summaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
authorArthur Hanson Rasmusson <arthur@vgpu.io>2026-10-07 15:36:35 -0400
committerArthur Hanson Rasmusson <arthur@vgpu.io>2026-10-07 15:36:35 -0400
commitf03249e1c928b2476f182953748fc5503b3d78cc (patch)
tree25d5186c40f0350b7e1245d90e3110eeebf214d1 /kernel
parentd9c2545fac3c37c57e56b892ed3d0e054d8f6816 (diff)
downloadopen-iov-f03249e1c928b2476f182953748fc5503b3d78cc.tar.gz
open-iov-f03249e1c928b2476f182953748fc5503b3d78cc.zip
vgsp: m114 - pre-commit bounce window for the kernel's data (native run w/ copy-in/out)
Decisive evidence: the SM walker resolves only the commit-time tree (every late write/install fails: m94, m99-m113; UNSET refused 0x1f). Plant a 112-page bounce window into the main small-PT at stage 3 (slots 0x110..0x17f - the proven win0 pattern), copy the launch's resolved data pages in, pointers are already rewritten to those VAs, and copy results back after the release. The mail message lives at bounce page 100 (c[0x4][0x0]=0x174000). Data cap 100 pages (440 KB), matching the shrunk victory_mail (3 x 128 KB).
Diffstat (limited to 'kernel')
-rw-r--r--kernel/gsp_phys_booter.c126
-rw-r--r--kernel/gsp_sema_service.c5
2 files changed, 111 insertions, 20 deletions
diff --git a/kernel/gsp_phys_booter.c b/kernel/gsp_phys_booter.c
index 86205d1..b03ac30 100644
--- a/kernel/gsp_phys_booter.c
+++ b/kernel/gsp_phys_booter.c
@@ -2160,6 +2160,20 @@ static struct gsp_phys_boot_stage {
u64 rmcall_gr_qmdwin_va; /* planted VA; 0 = guest destination */
/* m104: module page holding the injected mail_kernel message. */
struct gsp_phys_boot_chunk rmcall_gr_mail;
+ /*
+ * m114: pre-commit bounce window. 112 pages planted into the main
+ * small-PT at slots 0x110..0x17f during stage 3 (the proven win0
+ * pattern: the SM walker resolves the commit-time tree only). The
+ * launch copies the kernel's data pages in, rewrites the pointers to
+ * these VAs (reloc base 0x110000), and copies the results back after
+ * the release; page 100 (VA 0x174000) carries the mail message.
+ */
+ struct gsp_phys_boot_chunk rmcall_gr_bounce;
+ u32 rmcall_gr_bounce_used;
+#define GSP_PHYS_RMCALL_GR_BOUNCE_PAGES 112u
+#define GSP_PHYS_RMCALL_GR_BOUNCE_SLOT0 0x110u
+#define GSP_PHYS_RMCALL_GR_BOUNCE_VA0 0x110000ULL
+#define GSP_PHYS_RMCALL_GR_MAIL_SLOT 100u
/* m99: guest data identity-map table branches (see the PD*_MAX block). */
struct gsp_phys_boot_chunk
rmcall_gr_data_pd1[GSP_PHYS_RMCALL_GR_DATA_PD1_MAX];
@@ -9405,6 +9419,50 @@ static void gsp_phys_rmcall_pdb_build(void)
}
}
/*
+ * m114: allocate the bounce window and plant its PTEs into the main
+ * small-PT at slots 0x110..0x17f - pre-commit direct writes, the
+ * same pattern as the window-0 pool the SM provably reads. The mail
+ * message goes into bounce page GSP_PHYS_RMCALL_GR_MAIL_SLOT.
+ */
+ if (!boot_stage.rmcall_gr_bounce.pages) {
+ struct gsp_phys_boot_chunk *ptb =
+ &boot_stage.rmcall_chunks[GSP_PHYS_RMCALL_BUF_PT];
+ u32 i;
+
+ if (!gsp_phys_chunk_alloc(boot_stage.pdev,
+ &boot_stage.rmcall_gr_bounce,
+ GSP_PHYS_RMCALL_GR_BOUNCE_PAGES)) {
+ gsp_phys_chunk_zero(&boot_stage.rmcall_gr_bounce);
+ for (i = 0; i < GSP_PHYS_RMCALL_GR_BOUNCE_PAGES; i++)
+ put_unaligned_le64(gsp_phys_rmcall_pte(
+ (u64)gsp_phys_chunk_page_dma(
+ &boot_stage.rmcall_gr_bounce, i)),
+ (u8 *)gsp_phys_chunk_page_va(ptb, 0) +
+ (size_t)(GSP_PHYS_RMCALL_GR_BOUNCE_SLOT0 + i) * 8);
+ dma_wmb();
+ pr_info("vgsp-boot: rm-call: bounce window planted: %u pages at VA 0x%llx..0x%llx (main PT slots 0x%x..0x%x)\n",
+ GSP_PHYS_RMCALL_GR_BOUNCE_PAGES,
+ GSP_PHYS_RMCALL_GR_BOUNCE_VA0,
+ GSP_PHYS_RMCALL_GR_BOUNCE_VA0 +
+ (GSP_PHYS_RMCALL_GR_BOUNCE_PAGES - 1) *
+ GSP_PHYS_PAGE_SIZE,
+ GSP_PHYS_RMCALL_GR_BOUNCE_SLOT0,
+ GSP_PHYS_RMCALL_GR_BOUNCE_SLOT0 +
+ GSP_PHYS_RMCALL_GR_BOUNCE_PAGES - 1);
+ {
+ static const char mail[] =
+ "the little gpu man says you've got mail";
+ memcpy(gsp_phys_chunk_page_va(
+ &boot_stage.rmcall_gr_bounce,
+ GSP_PHYS_RMCALL_GR_MAIL_SLOT),
+ mail, sizeof(mail));
+ }
+ } else {
+ pr_err("vgsp-boot: rm-call: bounce window allocation failed\n");
+ }
+ }
+
+ /*
* 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
@@ -16672,15 +16730,13 @@ int gsp_phys_backend_guest_gr_submit(const struct gsp_phys_gr_submit *req,
boot_stage.rmcall_gr_data_pt
[GSP_PHYS_RMCALL_GR_DATA_WINS - 1].pages);
{
- u64 mva = 0x1f0000ULL;
+ u64 mva = GSP_PHYS_RMCALL_GR_BOUNCE_VA0 +
+ ((u64)GSP_PHYS_RMCALL_GR_MAIL_SLOT
+ << 12);
int mret = -EINVAL;
- if (boot_stage.rmcall_gr_mail.pages)
- mret = gsp_phys_rmcall_gr_data_map(
- bar0, mva,
- (u64)gsp_phys_chunk_page_dma(
- &boot_stage.rmcall_gr_mail, 0),
- boot_stage.rmcall_gr_submit_epoch);
+ if (boot_stage.rmcall_gr_bounce.pages)
+ mret = 0;
if (!mret) {
w[0] = (u32)mva;
w[1] = (u32)(mva >> 32);
@@ -17097,22 +17153,28 @@ gr_page_unmapped:
le32_to_cpu(iv[172]), le32_to_cpu(iv[173]));
}
}
- if (req->n_data) {
- u32 dmapped = 0, dfailed = 0, di;
+ if (req->n_data && boot_stage.rmcall_gr_bounce.pages) {
+ u32 dcopied = 0, dfailed = 0, di;
for (di = 0; di < req->n_data; di++) {
- if (gsp_phys_rmcall_gr_data_map(bar0,
- req->data[di].reloc_va ?
- req->data[di].reloc_va :
- req->data[di].va,
- req->data[di].hpa,
- boot_stage.rmcall_gr_submit_epoch))
+ u32 bi = (u32)((req->data[di].reloc_va -
+ GSP_PHYS_RMCALL_GR_BOUNCE_VA0) >>
+ 12);
+
+ if (bi >= GSP_PHYS_RMCALL_GR_MAIL_SLOT ||
+ !req->data[di].hpa) {
dfailed++;
- else
- dmapped++;
+ continue;
+ }
+ memcpy(gsp_phys_chunk_page_va(
+ &boot_stage.rmcall_gr_bounce, bi),
+ (u8 *)__va(req->data[di].hpa),
+ GSP_PHYS_PAGE_SIZE);
+ dcopied++;
}
- pr_info("vgsp-gr: guest data identity-map: %u pages in the engine tree, %u failed (pt pages=%u)\n",
- dmapped, dfailed, boot_stage.rmcall_gr_data_pt_n);
+ dma_wmb();
+ pr_info("vgsp-gr: bounce copy-in: %u pages, %u skipped\n",
+ dcopied, dfailed);
if (gsp_phys_rmcall_gr_recommit_value()) {
struct gsp_phys_rmcall_pdb_params rp;
struct {
@@ -17517,6 +17579,32 @@ gr_page_unmapped:
}
gsp_phys_gr_ok++;
+ /*
+ * m114: the kernel ran against the pre-commit bounce window; copy the
+ * results back to the guest's real pages (identity HPAs in the
+ * request). All mapped pages are written back; inputs are unchanged
+ * by the kernels, so copying them back is a no-op.
+ */
+ if (req->n_data && boot_stage.rmcall_gr_bounce.pages) {
+ u32 wbi, wrote = 0;
+
+ for (wbi = 0; wbi < req->n_data; wbi++) {
+ u32 bi = (u32)((req->data[wbi].reloc_va -
+ GSP_PHYS_RMCALL_GR_BOUNCE_VA0) >>
+ 12);
+
+ if (bi >= GSP_PHYS_RMCALL_GR_MAIL_SLOT ||
+ !req->data[wbi].hpa)
+ continue;
+ memcpy((u8 *)__va(req->data[wbi].hpa),
+ gsp_phys_chunk_page_va(
+ &boot_stage.rmcall_gr_bounce, bi),
+ GSP_PHYS_PAGE_SIZE);
+ wrote++;
+ }
+ pr_info("vgsp-gr: bounce copy-out: %u pages written back\n",
+ wrote);
+ }
poll = w1;
if (bar0)
pr_info("vgsp-gr: SKED readback (ok): HWW_ESR=0x%08x INFO2=0x%08x CWD_T0=0x%08x CWD_T1=0x%08x CWD_T2=0x%08x\n",
diff --git a/kernel/gsp_sema_service.c b/kernel/gsp_sema_service.c
index caaaae3..24b3adf 100644
--- a/kernel/gsp_sema_service.c
+++ b/kernel/gsp_sema_service.c
@@ -9562,6 +9562,9 @@ static bool svc_gr_page_inline_covers(u64 page)
* the demo buffers are small on the native path).
*/
#define SVC_GR_DATA_PAGES_PER_PTR 64u
+/* m114: total pages the pre-commit bounce window can carry (slot 100 is
+ * the mail message). */
+#define SVC_GR_DATA_BOUNCE_MAX 100u
static void svc_gr_data_fill(struct nv_vgpu_device *vgpu)
{
@@ -9633,7 +9636,7 @@ static void svc_gr_data_fill(struct nv_vgpu_device *vgpu)
continue; /* already mapped */
if (svc_resolve_va(vgpu, va, &pa, &ap))
break;
- if (svc_fwd_req.gr_n_data >= SVC_GR_DATA_MAX)
+ if (svc_fwd_req.gr_n_data >= SVC_GR_DATA_BOUNCE_MAX)
return;
rec = &svc_fwd_req.gr_data[svc_fwd_req.gr_n_data];
rec->va = va;