diff options
| author | Arthur Hanson Rasmusson <arthur@vgpu.io> | 2026-10-06 15:41:01 -0400 |
|---|---|---|
| committer | Arthur Hanson Rasmusson <arthur@vgpu.io> | 2026-10-06 15:41:01 -0400 |
| commit | 49f1853c8dfd0ad576561540219d835227af4b31 (patch) | |
| tree | d7bed7e432338752c59f85bcb666b4f0a9dcdfef /kernel/gsp_phys_booter.c | |
| parent | c15be05319e00d0818d78d6fdf908e27f19c659f (diff) | |
| download | open-iov-49f1853c8dfd0ad576561540219d835227af4b31.tar.gz open-iov-49f1853c8dfd0ad576561540219d835227af4b31.zip | |
vgsp: m32 rank-2 qmdwin - relocate the inline-QMD destination to a proven ring-chunk page (compile-verified, untested)m32
Diffstat (limited to 'kernel/gsp_phys_booter.c')
| -rw-r--r-- | kernel/gsp_phys_booter.c | 110 |
1 files changed, 105 insertions, 5 deletions
diff --git a/kernel/gsp_phys_booter.c b/kernel/gsp_phys_booter.c index dc8e641..f15a117 100644 --- a/kernel/gsp_phys_booter.c +++ b/kernel/gsp_phys_booter.c @@ -888,6 +888,20 @@ bool gsp_phys_boot_requested(void) #define GSP_PHYS_RMCALL_VA_SEM (GSP_PHYS_RMCALL_VA_BASE + 4 * GSP_PHYS_PAGE_SIZE) /* + * Rank-2 qmdwin diagnostic (gsp_phys_rmcall_gr_qmdwin=1): dedicated module + * page for the forwarded inline-QMD destination inside the proven ladder + * window-0 small-PT line (slots 0x100..0x104 are GPFIFO/PB/SRC/DST/SEM). + * Slot 0x105/0x106 (VA 0x105000/0x106000) are owned by the legacy P6a + * guest-mem pre-build whenever a guest GPA is pinned, so the unused slot 0x107 + * is used; it lies in the same 128 B GMMU PTE fetch line already proven + * engine-reachable (and engine-writable: the REPORT_SEM writes land at + * 0x104000). Because the GMMU caches PTE fetch lines with no invalidate, the + * PTE is planted by gsp_phys_rmcall_pdb_build() at stage 3 - before the + * engine's first fetch of the line - and never at launch time. + */ +#define GSP_PHYS_RMCALL_VA_GR_QMDWIN (GSP_PHYS_RMCALL_VA_BASE + 0x7000) + +/* * P6a guest-memory windows (gsp_phys_guest_mem=1). Two more slots in the same * 2 MB PD0 slot / small-PT page as the five ladder pages, so VA_GUEST_W takes * PT slot 0x105 and VA_GUEST_R slot 0x106. These VAs are legacy: triggers 6/7 @@ -1898,6 +1912,14 @@ static struct gsp_phys_boot_stage { u32 rmcall_guest_pt_win_mask; /* Tier-2 scratch windows installed */ struct gsp_phys_boot_chunk rmcall_gr_pt[GSP_PHYS_RMCALL_GR_PT_PAGES]; struct gsp_phys_boot_chunk rmcall_gr_shadow; /* Tier-2 pages */ + /* + * Rank-2 qmdwin: dedicated module page for the forwarded inline-QMD + * destination, planted (PTE written) by gsp_phys_rmcall_pdb_build when + * gsp_phys_rmcall_gr_qmdwin=1; rmcall_gr_qmdwin_va stays 0 when off or + * when the plant failed. + */ + struct gsp_phys_boot_chunk rmcall_gr_qmdwin; + u64 rmcall_gr_qmdwin_va; /* planted VA; 0 = guest destination */ struct { u32 pde_index; u8 pt_slot; @@ -2528,6 +2550,9 @@ static void gsp_phys_rmcall_reset(void) memset(boot_stage.rmcall_gr_pt, 0, sizeof(boot_stage.rmcall_gr_pt)); memset(&boot_stage.rmcall_gr_shadow, 0, sizeof(boot_stage.rmcall_gr_shadow)); + memset(&boot_stage.rmcall_gr_qmdwin, 0, + sizeof(boot_stage.rmcall_gr_qmdwin)); + boot_stage.rmcall_gr_qmdwin_va = 0; memset(boot_stage.rmcall_gr_win, 0, sizeof(boot_stage.rmcall_gr_win)); for (i = 0; i < GSP_PHYS_RMCALL_BUF_COUNT; i++) { boot_stage.rmcall_mem_handles[i] = 0; @@ -8823,6 +8848,48 @@ static void gsp_phys_rmcall_pdb_build(void) (u8 *)gsp_phys_chunk_page_va(pt, 0) + (size_t)sem_idx * 8); /* + * Rank-2 qmdwin: plant the dedicated module page for the forwarded + * inline-QMD destination in this same small-PT line (slot 0x107, VA + * 0x107000; slots 0x105/0x106 stay the P6a guest slots below). This + * runs at stage 3, before the engine's first fetch of the 128 B PT + * line: the GMMU caches PTE fetch lines with no invalidate, so a + * launch-time PTE write into an already-fetched line would be + * invisible. Gated by the module parameter; with 0 the PT page is + * byte-identical (slot 0x107 stays zero from the stage-2 zeroing). + */ + if (gsp_phys_rmcall_gr_qmdwin_value()) { + struct gsp_phys_boot_chunk *qw = + &boot_stage.rmcall_gr_qmdwin; + u32 qw_idx = (u32)((GSP_PHYS_RMCALL_VA_GR_QMDWIN >> 12) & + 0x1ffu); + + if (!qw->pages) { + if (!boot_stage.pdev) { + pr_warn("vgsp-boot: rm-call: qmdwin plant skipped: no claimed pci_dev; launches keep the guest QMD destination\n"); + } else if (!gsp_phys_chunk_alloc(boot_stage.pdev, qw, 1u)) { + gsp_phys_chunk_zero(qw); + } else { + pr_warn("vgsp-boot: rm-call: qmdwin page allocation failed; launches keep the guest QMD destination\n"); + } + } + if (qw->pages) { + put_unaligned_le64(gsp_phys_rmcall_pte( + (u64)gsp_phys_chunk_page_dma(qw, 0)), + (u8 *)gsp_phys_chunk_page_va(pt, 0) + + (size_t)qw_idx * 8); + if (!boot_stage.rmcall_gr_qmdwin_va) + pr_info("vgsp-boot: rm-call: qmdwin module page planted VA=0x%llx ptSlot=0x%x pte=0x%016llx dma=0x%llx (before the engine's first fetch)\n", + GSP_PHYS_RMCALL_VA_GR_QMDWIN, qw_idx, + get_unaligned_le64( + (u8 *)gsp_phys_chunk_page_va( + pt, 0) + + (size_t)qw_idx * 8), + (u64)gsp_phys_chunk_page_dma(qw, 0)); + boot_stage.rmcall_gr_qmdwin_va = + GSP_PHYS_RMCALL_VA_GR_QMDWIN; + } + } + /* * P6a guest windows: start from explicit zero (invalid PTE) for both * slots, then, when the guest GPA is already pinned (it must be pinned * before stage 3 for this), pre-build both slots with the translated @@ -14151,6 +14218,8 @@ int gsp_phys_backend_guest_gr_submit(const struct gsp_phys_gr_submit *req, u32 qmd_win_pde = 0, qmd_win_installed = 0; int qmd_win_ret = 0; bool qmd_win_diag = false; + bool qmdwin_on = false; + char qmdwin_note[32] = ""; int ret = 0; if (out) @@ -14477,6 +14546,32 @@ gr_page_unmapped: } /* + * Rank-2 qmdwin (gsp_phys_rmcall_gr_qmdwin=1): relocate the inline-QMD + * destination to the dedicated module page planted in the ladder's + * window-0 small-PT line (VA 0x107000). The PTE was written by + * gsp_phys_rmcall_pdb_build before the engine's first fetch of that + * 128 B fetch line; the page is module-owned, so the prewrite and the + * post-mortem involve no guest page, and it shares the proven line the + * GPFIFO/PB/REPORT_SEM legs already use. The 2 MiB window is installed + * by the ladder itself, so no window ensure is sent for it (a + * pdeIndex-0 Tier-1 install would touch the ladder's own PDE). + */ + if (gsp_phys_rmcall_gr_qmdwin_value()) { + u8 *qw = boot_stage.rmcall_gr_qmdwin.pages ? + gsp_phys_chunk_page_va(&boot_stage.rmcall_gr_qmdwin, 0) : + NULL; + + if (boot_stage.rmcall_gr_qmdwin_va && qw) { + qmdwin_on = true; + qmd_dst = boot_stage.rmcall_gr_qmdwin_va; + qmd_dst_mem = qw; + pr_info("vgsp-gr: qmdwin: relocating inline-QMD dest 0x%llx -> 0x%llx (module ring chunk page)\n", + req->qmd_va, qmd_dst); + } else { + pr_warn("vgsp-gr: qmdwin=1 but no planted module page (stage-3 plant skipped or failed); using the guest QMD destination\n"); + } + } + /* * Inline-QMD destination: the CUDA driver points ADDRESS_A/B at its * own QMD buffer (turing_launch.c:1629) and the IQ2M copies the 64 * inline words there before scheduling. Map the guest QMD page and @@ -14485,7 +14580,7 @@ gr_page_unmapped: * alias keeps the launch runnable, and an unresolved page keeps the * module scratch VA. */ - if (req->qmd_hpa) { + if (!qmdwin_on && req->qmd_hpa) { u64 qmd_page = req->qmd_va & ~(u64)(GSP_PHYS_PAGE_SIZE - 1); u32 qmd_off = (u32)(req->qmd_va & (GSP_PHYS_PAGE_SIZE - 1)); bool dst_ok = false; @@ -14531,6 +14626,9 @@ gr_page_unmapped: pr_info("vgsp-gr: inline-QMD dest va=0x%llx hpa=0x%llx -> 0x%llx (shadow=%u)\n", req->qmd_va, req->qmd_hpa, qmd_dst, n_shadow); } + if (qmdwin_on) + scnprintf(qmdwin_note, sizeof(qmdwin_note), + " qmdwin=0x%llx", qmd_dst); /* * Channel release: author it into the guest semaphore page when the @@ -14596,13 +14694,13 @@ gr_page_unmapped: goto out; } - pr_info("vgsp-gr: GR LAUNCH submitted h=0x%x push=0x%llx len=%u pages=%u shadow=%u qmd_va=0x%llx slot=%u words=%u prelude=%d qmdvirt=%d token=0x%x; polling qmd_rel=%u ch_rel=0x%08x (<=%u ms)\n", + pr_info("vgsp-gr: GR LAUNCH submitted h=0x%x push=0x%llx len=%u pages=%u shadow=%u qmd_va=0x%llx slot=%u words=%u prelude=%d qmdvirt=%d token=0x%x; polling qmd_rel=%u ch_rel=0x%08x (<=%u ms)%s\n", req->h_object, req->push_va, req->push_len, req->n_pages, n_shadow, req->qmd_va, sub.slot, words, gsp_phys_rmcall_gr_prelude_value(), gsp_phys_rmcall_gr_qmdvirt_value(), boot_stage.rmcall_token, - qmd_rel, want_ch, GSP_PHYS_RMCALL_GR_POLL_MS); + qmd_rel, want_ch, GSP_PHYS_RMCALL_GR_POLL_MS, qmdwin_note); if (qmd_win_diag) pr_info("vgsp-gr: qmd dest va=0x%llx pdeIndex=%u installed=%u win_mask=0x%x ensure_ret=%d\n", qmd_dst, qmd_win_pde, qmd_win_installed, @@ -14689,12 +14787,13 @@ gr_page_unmapped: relw = READ_ONCE( *(u32 *)((u8 *)__va(qmd_rel_hpa) + qmd_rel_off)); - pr_info("vgsp-gr: post-mortem gpget=%u->%u qmd_page w0=%08x w1=%08x w23..25=%08x %08x %08x w63=%08x relw=%08x iq2m=%s\n", + pr_info("vgsp-gr: post-mortem gpget=%u->%u qmd_page w0=%08x w1=%08x w23..25=%08x %08x %08x w63=%08x relw=%08x iq2m=%s%s\n", sub.gpget, gpget_post, q0, q1, q23, q24, q25, q63, relw, q63 == GSP_PHYS_GR_QMD_SENTINEL ? "not-run (sentinel intact)" : - "ran (page overwritten)"); + "ran (page overwritten)", + qmdwin_note); } poll = w1; ret = -ETIMEDOUT; @@ -15535,6 +15634,7 @@ static void gsp_phys_rmcall_fini(struct pci_dev *pdev) for (i = 0; i < GSP_PHYS_RMCALL_GR_PT_PAGES; i++) gsp_phys_chunk_free(pdev, &boot_stage.rmcall_gr_pt[i]); gsp_phys_chunk_free(pdev, &boot_stage.rmcall_gr_shadow); + gsp_phys_chunk_free(pdev, &boot_stage.rmcall_gr_qmdwin); gsp_phys_chunk_free(pdev, &boot_stage.rmcall_patch); gsp_phys_chunk_free(pdev, &boot_stage.rmcall_pm); gsp_phys_chunk_free(pdev, &boot_stage.rmcall_fecs); |
