/* control.c — control-write SEAM ONLY (this never writes guest memory). * * The actual write is performed elsewhere, by a component that holds read-write * access to the region; this only builds the desired vgpu_control_t image from * the intent and computes the GVA + offset/length of the significant field range * for that atomic write under the ctrl_gen seqlock. There is no gva_write here * and there must not be — the source is a RO fd that would fault on a store anyway. * * The reported out_ctrl_gva is a GVA in the PRODUCER's user address space * (region base + VGPU_CONTROL_OFFSET, cached as r->ctrl_gva): the external write * MUST be performed under r->proc_cr3, NOT the System kcr3. */ #include "perception-internal.h" int vgpup_build_control_write(vgpup_region* r, const vgpup_control_intent* in, vgpu_control_t* out_frame, uint64_t* out_ctrl_gva, uint32_t* out_off, uint32_t* out_len) { if (!r || !in || !out_frame || !out_ctrl_gva || !out_off || !out_len) { return -1; } /* Fill the desired control image. ctrl_gen stays 0: the writer owns it under * the seqlock. consumer_tick/attached carry separate heartbeat/intent * semantics and are not part of this intent. */ memset(out_frame, 0, sizeof *out_frame); out_frame->desired_state = in->desired_state; out_frame->target_fps = in->target_fps; out_frame->draw_cursor = in->draw_cursor; out_frame->full_frame_req = in->full_frame_req; *out_ctrl_gva = r->ctrl_gva; /* region base + VGPU_CONTROL_OFFSET (cached) */ /* Significant range: desired_state .. full_frame_req (contiguous in the ABI), * i.e. offsetof(desired_state) through the end of full_frame_req. */ *out_off = (uint32_t)offsetof(vgpu_control_t, desired_state); *out_len = (uint32_t)(offsetof(vgpu_control_t, full_frame_req) + sizeof(uint32_t) - offsetof(vgpu_control_t, desired_state)); return 0; }