diff options
| author | Arthur Hanson Rasmusson <arthur@vgpu.io> | 2026-10-07 11:35:52 -0400 |
|---|---|---|
| committer | Arthur Hanson Rasmusson <arthur@vgpu.io> | 2026-10-07 11:35:52 -0400 |
| commit | ebe1ed7717e55e5372d90ea56711d4073b5c9cd4 (patch) | |
| tree | f3270c6fc8aae4598409656f5b2cd0937dfd8208 /kernel | |
| parent | 4541bae601a330d2a22a21d9e24d0fe879ebf618 (diff) | |
| download | open-iov-ebe1ed7717e55e5372d90ea56711d4073b5c9cd4.tar.gz open-iov-ebe1ed7717e55e5372d90ea56711d4073b5c9cd4.zip | |
vgsp: m84 - stage-4 CE read-back of the GR context image header and VEID0 subctx header
gsp_phys_rmcall_gr_img_probe=1: after the stage-4 GR sem proof the ladder
re-binds the rmcall channel to COPY0, copies image VA 0x2200000 and the subctx
header VA 0x22f3000 into the DST sysmem chunk through the real CE, dumps the
header pointers, and re-binds GR0. This is the missing read path for the
FBMEM context image (the GPC exception at QMD activation needs the image's
PATCH/PM/ZCULL/priv-map/global pointers and the subctx header content to be
compared against the expected VAs).
Diffstat (limited to 'kernel')
| -rw-r--r-- | kernel/gsp_phys_booter.c | 117 | ||||
| -rw-r--r-- | kernel/gsp_phys_gpu.c | 19 | ||||
| -rw-r--r-- | kernel/gsp_phys_gpu.h | 4 |
3 files changed, 140 insertions, 0 deletions
diff --git a/kernel/gsp_phys_booter.c b/kernel/gsp_phys_booter.c index 8bf94d8..de546d4 100644 --- a/kernel/gsp_phys_booter.c +++ b/kernel/gsp_phys_booter.c @@ -14412,6 +14412,121 @@ static int gsp_phys_rmcall_gr_sem_push_locked(void __iomem *bar0) } /* + * m84 diagnostic (gsp_phys_rmcall_gr_img_probe; default 0). Reads the first + * 4 KB of the GR MAIN context image (promoted at VA_GR_CTX, FBMEM) and of the + * per-VEID subcontext header (image + 0xf3000) through the real COPY engine. + * The rmcall channel is GR-bound in this mode, so the probe re-binds it to + * COPY0, submits one CE copy block per region into the DST sysmem chunk, + * polls the module semaphore, re-binds GR0 and dumps the image header + * pointers. Any rejection or timeout is logged and changes nothing else; + * the forwarded launch path then runs as usual. Must be called from stage 4 + * (gsp_phys_rm_lock held). + */ +static void gsp_phys_rmcall_ctx_image_probe(void __iomem *bar0) +{ + struct gsp_phys_boot_chunk *sem = + &boot_stage.rmcall_chunks[GSP_PHYS_RMCALL_BUF_SEM]; + struct gsp_phys_boot_chunk *dst = + &boot_stage.rmcall_chunks[GSP_PHYS_RMCALL_BUF_DST]; + struct gsp_phys_rmcall_ce_submit sub; + u64 regions[2]; + u32 bind_params; + int r; + + if (!boot_stage.rmcall_ctx_pa || boot_stage.rmcall_stage < 3) + return; + + bind_params = GSP_PHYS_RMCALL_ENGINE_COPY0; + { + u32 rpc_result = 0, status = 0; + + r = gsp_phys_rmcall_control(bar0, boot_stage.rmcall_channel, + GSP_PHYS_RMCALL_CTRL_BIND_CHANNEL, + &bind_params, sizeof(bind_params), 16, NULL, 0, + &rpc_result, &status, + "BIND_CHANNEL COPY0 (m84 image probe)"); + pr_info("vgsp-boot: rm-call: m84 image probe: BIND COPY0 status=0x%x rpc_result=0x%x ret=%d\n", + status, rpc_result, r); + } + + regions[0] = GSP_PHYS_RMCALL_VA_GR_CTX; /* image header */ + regions[1] = GSP_PHYS_RMCALL_VA_GR_CTX + 0xf3000ULL; /* subctx hdr VEID0 */ + if (!r) { + u32 k; + + for (k = 0; k < 2; k++) { + u32 rpc_result = 0, status = 0, poll = 0; + unsigned long deadline; + u8 *d; + + WRITE_ONCE(*(u32 *)gsp_phys_chunk_page_va(sem, 0), 0); + wmb(); + r = gsp_phys_rmcall_ce_submit_locked(bar0, + regions[k], GSP_PHYS_RMCALL_VA_DST, + GSP_PHYS_RMCALL_VA_SEM, + GSP_PHYS_PAGE_SIZE, + GSP_PHYS_RMCALL_SEM_PAYLOAD, false, + &sub); + (void)rpc_result; + (void)status; + if (r) { + pr_err("vgsp-boot: rm-call: m84 image probe: CE submit for region %u refused (%d)\n", + k, r); + break; + } + deadline = jiffies + + msecs_to_jiffies(GSP_PHYS_RMCALL_TIMEOUT_MS); + for (;;) { + poll = READ_ONCE(*(u32 *)gsp_phys_chunk_page_va(sem, 0)); + if (poll == GSP_PHYS_RMCALL_SEM_PAYLOAD) + break; + if (time_after_eq(jiffies, deadline)) { + pr_err("vgsp-boot: rm-call: m84 image probe: region %u CE copy TIMEOUT (sem=0x%08x) - an engine-side walk of VA 0x%llx failed or the CE did not run\n", + k, poll, regions[k]); + break; + } + msleep(GSP_PHYS_RMCALL_POLL_MS); + } + if (poll != GSP_PHYS_RMCALL_SEM_PAYLOAD) + break; + d = gsp_phys_chunk_page_va(dst, 0); + if (!d) + break; + pr_info("vgsp-boot: rm-call: m84 image probe: region %u VA=0x%llx copied OK\n", + k, regions[k]); + { + u32 i; + + for (i = 0; i < 0x80; i += 8) + pr_info("vgsp-ctximg[%u] [%03x] = %08x %08x %08x %08x %08x %08x %08x %08x\n", + k, i * 4, + get_unaligned_le32(d + i * 4), + get_unaligned_le32(d + (i + 1) * 4), + get_unaligned_le32(d + (i + 2) * 4), + get_unaligned_le32(d + (i + 3) * 4), + get_unaligned_le32(d + (i + 4) * 4), + get_unaligned_le32(d + (i + 5) * 4), + get_unaligned_le32(d + (i + 6) * 4), + get_unaligned_le32(d + (i + 7) * 4)); + } + } + } + + bind_params = GSP_PHYS_RMCALL_ENGINE_GR0; + { + u32 rpc_result = 0, status = 0; + + r = gsp_phys_rmcall_control(bar0, boot_stage.rmcall_channel, + GSP_PHYS_RMCALL_CTRL_BIND_CHANNEL, + &bind_params, sizeof(bind_params), 16, NULL, 0, + &rpc_result, &status, + "BIND_CHANNEL GR0 (m84 image probe)"); + pr_info("vgsp-boot: rm-call: m84 image probe: rebind GR0 status=0x%x rpc_result=0x%x ret=%d\n", + status, rpc_result, r); + } +} + +/* * P6a guest-memory CE helper: run one CE copy with explicit operand VAs on * the ladder channel and poll the module semaphore outside gsp_phys_rm_lock * (the same lock discipline as the P5 shadow API, so a guest copy can never @@ -17182,6 +17297,8 @@ static int gsp_phys_rmcall_stage4(void __iomem *bar0) if (ret) pr_err("vgsp-boot: rm-call: stage 4 GR path failed (%d); no retry\n", ret); + else if (gsp_phys_rmcall_gr_img_probe_value()) + gsp_phys_rmcall_ctx_image_probe(bar0); return ret; } diff --git a/kernel/gsp_phys_gpu.c b/kernel/gsp_phys_gpu.c index f094d36..e3ca2e8 100644 --- a/kernel/gsp_phys_gpu.c +++ b/kernel/gsp_phys_gpu.c @@ -796,6 +796,25 @@ unsigned int gsp_phys_rmcall_gr_lmem_tpc_size_value(void) EXPORT_SYMBOL_GPL(gsp_phys_rmcall_gr_lmem_tpc_size_value); /* + * m84 ctx-image probe (gsp_phys_rmcall_gr_img_probe; default 0). After the + * stage-4 GR sem proof the ladder re-binds the rmcall channel to COPY0, + * copies the first 4 KB of the MAIN context image and of the VEID0 subctx + * header into the DST sysmem chunk through the real CE, dumps them, and + * re-binds GR0. Diagnostic only; each failure is logged and ignored. + */ +static int gsp_phys_rmcall_gr_img_probe_param; +module_param_named(gsp_phys_rmcall_gr_img_probe, + gsp_phys_rmcall_gr_img_probe_param, int, 0644); +MODULE_PARM_DESC(gsp_phys_rmcall_gr_img_probe, + "Stage-4 CE read-back of the GR context image header + VEID0 subctx header (default 0)"); + +int gsp_phys_rmcall_gr_img_probe_value(void) +{ + return gsp_phys_rmcall_gr_img_probe_param; +} +EXPORT_SYMBOL_GPL(gsp_phys_rmcall_gr_img_probe_value); + +/* * m83 sysmem error notifier (gsp_phys_rmcall_gr_notifier_sys; default 0). * The mode-35 V7 error notifier is normally a server FBMEM class-0x40 memory * object (unreadable). With 1 it is a host sysmem chunk registered as the diff --git a/kernel/gsp_phys_gpu.h b/kernel/gsp_phys_gpu.h index 9bd5624..1b0bac3 100644 --- a/kernel/gsp_phys_gpu.h +++ b/kernel/gsp_phys_gpu.h @@ -366,6 +366,10 @@ int gsp_phys_rmcall_gr_lane_skip_value(void); * records are readable (default 0 = server FBMEM). */ int gsp_phys_rmcall_gr_notifier_sys_value(void); +/* m84: stage-4 CE read-back of the GR context image header + subctx header + * (default 0). */ +int gsp_phys_rmcall_gr_img_probe_value(void); + /* * Ladder VAS ownership selector (gsp_phys_rmcall_vas_shared; default 0). * 0 = FERMI_VASPACE_A is allocated IS_EXTERNALLY_OWNED (historical ladder |
