From e0e96fe151e9bf690dd215e46da135da1dcc2317 Mon Sep 17 00:00:00 2001 From: Arthur Hanson Rasmusson Date: Mon, 5 Oct 2026 21:34:36 -0400 Subject: vgsp: alias-map indirect high-VA GR pages and fix up shadow pointers The mail kernel's output buffer has no QMD pointer word; the engine reaches it through a pointer inside the parameter bank, so the Tier-1 refusal at its high VA killed the launch. Alias-map such a page's guest HPA at a fresh ladder line and rewrite every matching 8-byte pointer inside the shadowed copy pages (param/program) to the alias, so engine writes land in the guest's own page and the guest's DtoH sees them. --- kernel/gsp_phys_booter.c | 64 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) (limited to 'kernel') diff --git a/kernel/gsp_phys_booter.c b/kernel/gsp_phys_booter.c index 2200b4f..b95bd81 100644 --- a/kernel/gsp_phys_booter.c +++ b/kernel/gsp_phys_booter.c @@ -13128,7 +13128,9 @@ int gsp_phys_backend_guest_gr_submit(const struct gsp_phys_gr_submit *req, u64 guest_va; /* base guest VA of the shadowed range */ u64 shadow_va; /* line base VA (PTE0) */ u32 line; /* scratch PT pool line index */ + u32 slot; /* member host page in the shadow chunk */ u32 npte; /* mapped pages so far */ + bool copy; /* true = copy, false = guest HPA alias */ } sh_rec[8]; u32 n_sh_rec = 0; @@ -13144,6 +13146,8 @@ int gsp_phys_backend_guest_gr_submit(const struct gsp_phys_gr_submit *req, goto out; } pg_va = pg->guest_va & ~(u64)(GSP_PHYS_PAGE_SIZE - 1); + pr_info("vgsp-gr: page[%u] va=0x%llx hpa=0x%llx qmd_word=%u\n", + i, pg->guest_va, pg->hpa, pg->qmd_word); if (pg->hpa) { ret = gsp_phys_rmcall_gr_map_va_locked(bar0, pg_va, pg->hpa, epoch); @@ -13182,6 +13186,66 @@ int gsp_phys_backend_guest_gr_submit(const struct gsp_phys_gr_submit *req, break; } } + /* + * Indirect high-VA write/read target (no QMD pointer of its + * own; e.g. the kernel's output buffer, referenced from the + * parameter bank): alias-map the guest page's HPA at a fresh + * ladder line and rewrite matching pointers inside the + * already-shadowed copy pages (param/program) to the alias, + * so engine accesses land in the guest's own page. + */ + if (!mapped && pg->hpa && + pg->qmd_word == GSP_PHYS_GR_QMD_WORD_NONE) { + u32 sh_line = boot_stage.rmcall_guest_pt_next_line; + + if (n_shadow < GSP_PHYS_RMCALL_GR_SHADOW_PAGES && + !gsp_phys_rmcall_gr_map_shadow_locked( + n_shadow, pg->hpa, &sh_va)) { + u32 k, slot = n_shadow; + + mapped = true; + n_shadow++; + if (n_sh_rec < ARRAY_SIZE(sh_rec)) { + sh_rec[n_sh_rec].guest_va = pg_va; + sh_rec[n_sh_rec].shadow_va = sh_va; + sh_rec[n_sh_rec].line = sh_line; + sh_rec[n_sh_rec].slot = slot; + sh_rec[n_sh_rec].npte = 1; + sh_rec[n_sh_rec].copy = false; + n_sh_rec++; + } + for (k = 0; k < n_sh_rec; k++) { + u8 *cp; + u32 off; + + if (!sh_rec[k].copy) + continue; + cp = gsp_phys_chunk_page_va( + &boot_stage.rmcall_gr_shadow, + sh_rec[k].slot); + if (!cp) + continue; + for (off = 0; off + 8 <= + GSP_PHYS_PAGE_SIZE; + off += 8) { + u64 v = get_unaligned_le64( + cp + off); + + if ((v & ~(u64)(GSP_PHYS_PAGE_SIZE + - 1)) != pg_va) + continue; + put_unaligned_le64( + sh_va + (v & + (u64)(GSP_PHYS_PAGE_SIZE + - 1)), + cp + off); + } + } + dma_wmb(); + pr_info("vgsp-gr: indirect page va=0x%llx aliased at 0x%llx (shadow slot %u); copy pointers fixed up\n", + pg->guest_va, sh_va, slot); + } + } if (!mapped && pg->qmd_word != GSP_PHYS_GR_QMD_WORD_NONE && pg->qmd_word + 1 < GSP_PHYS_GR_QMD_WORDS) { struct gsp_phys_boot_chunk *sh = -- cgit v1.2.3