From ebe1ed7717e55e5372d90ea56711d4073b5c9cd4 Mon Sep 17 00:00:00 2001 From: Arthur Hanson Rasmusson Date: Wed, 7 Oct 2026 11:35:52 -0400 Subject: 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). --- kernel/gsp_phys_booter.c | 117 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 117 insertions(+) (limited to 'kernel/gsp_phys_booter.c') 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 @@ -14411,6 +14411,121 @@ static int gsp_phys_rmcall_gr_sem_push_locked(void __iomem *bar0) return 0; } +/* + * 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 @@ -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; } -- cgit v1.2.3