diff options
Diffstat (limited to 'kernel/gsp_phys_booter.c')
| -rw-r--r-- | kernel/gsp_phys_booter.c | 105 |
1 files changed, 99 insertions, 6 deletions
diff --git a/kernel/gsp_phys_booter.c b/kernel/gsp_phys_booter.c index 8de8408..611a128 100644 --- a/kernel/gsp_phys_booter.c +++ b/kernel/gsp_phys_booter.c @@ -996,6 +996,17 @@ bool gsp_phys_boot_requested(void) #define GSP_PHYS_RMCALL_VA_SRC (GSP_PHYS_RMCALL_VA_BASE + 2 * GSP_PHYS_PAGE_SIZE) #define GSP_PHYS_RMCALL_VA_DST (GSP_PHYS_RMCALL_VA_BASE + 3 * GSP_PHYS_PAGE_SIZE) #define GSP_PHYS_RMCALL_VA_SEM (GSP_PHYS_RMCALL_VA_BASE + 4 * GSP_PHYS_PAGE_SIZE) +/* + * m69: window-0 shadow pool - 8 module pages at VAs 0x108000..0x10f000 + * (small-PT slots 0x108..0x10f, the same 128 B PTE fetch line as the + * GPFIFO/PB/QMDWIN slots, planted before the engine's first fetch). The + * Tier-2 copies of the QMD's program/param pages are placed here so the GR + * engine never has to read through the window-1 scratch VA range whose PT + * chain (DMA_UPDATE_PDE_2 pdeIndex=1) has never been proven engine-readable. + */ +#define GSP_PHYS_RMCALL_VA_GR_SHADOW0_BASE \ + (GSP_PHYS_RMCALL_VA_BASE + 8 * GSP_PHYS_PAGE_SIZE) +#define GSP_PHYS_RMCALL_GR_SHADOW0_SLOTS 8u /* * Rank-2 qmdwin diagnostic (gsp_phys_rmcall_gr_qmdwin=1): dedicated module @@ -2107,6 +2118,17 @@ static struct gsp_phys_boot_stage { 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 */ /* + * m69: window-0 shadow pool (gsp_phys_rmcall_gr_shadow_win0=1). + * Eight module pages whose PTEs are planted in the proven window-0 + * PT line at slots 0x108..0x10f (VAs 0x108000..0x10f000) by + * gsp_phys_rmcall_pdb_build, before the engine's first fetch (same + * pattern as the qmdwin slot). The launch copies the QMD's + * program/param page content into them and rewrites the QMD pointers + * there, so the GR engine never reads the window-1 scratch range. + */ + struct gsp_phys_boot_chunk rmcall_gr_shadow_win0; + u32 rmcall_gr_shadow_win0_used; + /* * 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 @@ -2747,6 +2769,9 @@ static void gsp_phys_rmcall_reset(void) 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_shadow_win0, 0, + sizeof(boot_stage.rmcall_gr_shadow_win0)); + boot_stage.rmcall_gr_shadow_win0_used = 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; @@ -9205,6 +9230,47 @@ static void gsp_phys_rmcall_pdb_build(void) } } /* + * m69: plant the window-0 shadow pool PTEs (slots 0x108..0x10f) in the + * same proven small-PT line, before the engine's first fetch. The + * launch copies the QMD's program/param page content into these pages + * and rewrites the QMD pointers to these VAs, so the GR engine never + * reads the window-1 scratch range (whose DMA_UPDATE_PDE_2 PT chain + * has never been proven engine-readable). + */ + if (gsp_phys_rmcall_gr_shadow_win0_value()) { + struct gsp_phys_boot_chunk *w0 = + &boot_stage.rmcall_gr_shadow_win0; + + if (!w0->pages && boot_stage.pdev) { + if (!gsp_phys_chunk_alloc(boot_stage.pdev, w0, + GSP_PHYS_RMCALL_GR_SHADOW0_SLOTS)) + gsp_phys_chunk_zero(w0); + else + pr_warn("vgsp-boot: rm-call: shadow-win0 pool allocation failed; the launch keeps the window-1 shadow path\n"); + } + if (w0->pages) { + u32 s; + + for (s = 0; s < GSP_PHYS_RMCALL_GR_SHADOW0_SLOTS; s++) { + u64 va = GSP_PHYS_RMCALL_VA_GR_SHADOW0_BASE + + (u64)s * GSP_PHYS_PAGE_SIZE; + u32 idx = (u32)((va >> 12) & 0x1ffu); + + put_unaligned_le64(gsp_phys_rmcall_pte( + (u64)gsp_phys_chunk_page_dma(w0, s)), + (u8 *)gsp_phys_chunk_page_va(pt, 0) + + (size_t)idx * 8); + } + dma_wmb(); + pr_info("vgsp-boot: rm-call: shadow-win0 pool planted %u pages at VA 0x%llx..0x%llx (small-PT slots 0x108..0x10f, before first fetch)\n", + GSP_PHYS_RMCALL_GR_SHADOW0_SLOTS, + GSP_PHYS_RMCALL_VA_GR_SHADOW0_BASE, + GSP_PHYS_RMCALL_VA_GR_SHADOW0_BASE + + (GSP_PHYS_RMCALL_GR_SHADOW0_SLOTS - 1) * + GSP_PHYS_PAGE_SIZE); + } + } + /* * 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 @@ -15964,12 +16030,39 @@ int gsp_phys_backend_guest_gr_submit(const struct gsp_phys_gr_submit *req, if (copied) { u32 sh_line = boot_stage.rmcall_guest_pt_next_line; - - ret = gsp_phys_rmcall_gr_map_shadow_locked( - n_shadow, - (u64)gsp_phys_chunk_page_dma(sh, - n_shadow), - &sh_va); + bool win0 = (pg->qmd_word == 32u || + pg->qmd_word == 48u) && + gsp_phys_rmcall_gr_shadow_win0_value() && + boot_stage.rmcall_gr_shadow_win0.pages && + boot_stage.rmcall_gr_shadow_win0_used < + GSP_PHYS_RMCALL_GR_SHADOW0_SLOTS; + + if (win0) { + u8 *dst = gsp_phys_chunk_page_va( + &boot_stage.rmcall_gr_shadow_win0, + boot_stage.rmcall_gr_shadow_win0_used); + + if (!dst) { + ret = -EIO; + } else { + memcpy(dst, sh_page, + GSP_PHYS_PAGE_SIZE); + sh_va = + GSP_PHYS_RMCALL_VA_GR_SHADOW0_BASE + + (u64)boot_stage.rmcall_gr_shadow_win0_used * + GSP_PHYS_PAGE_SIZE; + boot_stage.rmcall_gr_shadow_win0_used++; + ret = 0; + pr_info("vgsp-gr: qmd_word %u page copied to window-0 shadow VA=0x%llx (proven PT line)\n", + pg->qmd_word, sh_va); + } + } else { + ret = gsp_phys_rmcall_gr_map_shadow_locked( + n_shadow, + (u64)gsp_phys_chunk_page_dma(sh, + n_shadow), + &sh_va); + } if (!ret) { /* * Preserve the original pointer's page |
