summaryrefslogtreecommitdiffstats
path: root/kernel/gsp_phys_booter.c
diff options
context:
space:
mode:
authorArthur Hanson Rasmusson <arthur@vgpu.io>2026-11-01 07:39:37 -0500
committerArthur Hanson Rasmusson <arthur@vgpu.io>2026-11-01 07:39:37 -0500
commit9cf8493f2435212aab1a5476ebdd46a19bb6657b (patch)
tree87126a027681301a662a77e4a14d1e9ba9704750 /kernel/gsp_phys_booter.c
parent52f676b4065ac82c5118c9e9716d90ab2875bfa1 (diff)
downloadopen-iov-9cf8493f2435212aab1a5476ebdd46a19bb6657b.tar.gz
open-iov-9cf8493f2435212aab1a5476ebdd46a19bb6657b.zip
vgsp: CONT-87 - sema_gl_sph_bind (window's own binds + client's missing TESS j=2 / PIXEL j=5 binds relocated by window pass; SPH version derives from loaded blob; INLINE-RB readback witness); stage-typed images at family VAs (TESS=vs image SHADER_TYPE->2), real-upload-wins record skip, gsp_sema_gl_sph_blob_version, prog_binds plumbing, pin-first arm - all three stages now fetch from authored VAs (sph=0,00620900,00620200,0,0,00620000); error 18 CLEARED (9/11/18->9/11); authored bytes engine-visible (INLINE-RB rb=000a0461); 9/11 survives every content A/B (V4 retag, SASS5, real w0 0x020a0481, REGISTER_COUNT, own-binds prelude, empty-blob) -> pipeline-state wall not content; real driver images in window inline writes dst=0x4350900 bytes=1536 + dst=0x4350f00 bytes=1408 (w0=0x020a0481 SPH V4) land in vGPU VRAM shadow NOT engine-read page; next: raise GSP_PHYS_GR_INLINE_BYTES 256->2048 + carry payloads in per-VA inline record or land svc_grce_inline_write via pin/fill - SESSION 153 r1276-r1281
Diffstat (limited to 'kernel/gsp_phys_booter.c')
-rw-r--r--kernel/gsp_phys_booter.c163
1 files changed, 161 insertions, 2 deletions
diff --git a/kernel/gsp_phys_booter.c b/kernel/gsp_phys_booter.c
index 5a30d40..5c1941a 100644
--- a/kernel/gsp_phys_booter.c
+++ b/kernel/gsp_phys_booter.c
@@ -17906,6 +17906,33 @@ MODULE_PARM_DESC(sema_gl_sph_version,
"Emit the Turing channel-init SET_SPH_VERSION/CHECK_SPH_VERSION pair (0x16a4/0x16a8 <- 0x00040004) ahead of each replayed 3D window (default 1; A/B with 0 reproduces the Shader Program Header 9/11/18 fault)");
/*
+ * SESSION 153-CONTINUED-87: the missing TESS_CONTROL/PIXEL program binds.
+ * The client's real channel state binds every pipeline stage once per
+ * context; the captured init-push image (guest RAM scrape) carries
+ * `20020825 [0, 04400200]` (j=2 TESS_CONTROL) and
+ * `20020855 [0, 04400000]` (j=5 PIXEL) beside the SPH version pair -
+ * but the captured per-frame window carries only the j=1 (VTG) pair
+ * (0x4400900/0x4400300). The DS validates the SPH of every pipeline
+ * stage the draw activates, so the unbound stages latch their header
+ * errors (DS_HWW_ESR 0xa2040a00 = SPH9|SPH11|SPH18) while the V3 blob
+ * passes wherever a stage IS bound. Emit both binds ahead of the
+ * window at the window's own program-family page (all four VAs share
+ * one 4K page: 0x4400000 j=5, 0x4400200 j=2, 0x4400300/0x4400900 j=1),
+ * pushed through the same relocation pass as the window - a MISS skips
+ * the bind entirely (never a raw client VA). Beef client channels only
+ * (the family layout is the client's). Default 1; A/B with 0.
+ */
+static bool gsp_phys_rmcall_gr_sph_bind = true;
+module_param_named(sema_gl_sph_bind, gsp_phys_rmcall_gr_sph_bind, bool, 0644);
+MODULE_PARM_DESC(sema_gl_sph_bind,
+ "Emit the client's missing TESS_CONTROL (j=2) and PIXEL (j=5) pipeline program binds ahead of replayed 3D windows (program-family page of the window's prog VA; default 1)");
+
+bool gsp_phys_rmcall_gr_sph_bind_value(void)
+{
+ return READ_ONCE(gsp_phys_rmcall_gr_sph_bind);
+}
+
+/*
* SESSION 153-CONTINUED-84: SET_MME_SHADOW_RAM_CONTROL mode before the
* window. The vendor comment (mesh shader bind path) is explicit:
* "MME filtering swallows them all if old and new state values are the
@@ -18553,10 +18580,27 @@ static u32 gsp_phys_rmcall_build_gr_launch(u32 *pb,
* it exactly.
*/
if (READ_ONCE(gsp_phys_rmcall_gr_sph_version)) {
+ /*
+ * SESSION 153-CONTINUED-87: the window's accepted
+ * version range must COVER the images the engine
+ * will fetch. The client's own init push writes
+ * 4|(4<<16), but our authored (V3) images are
+ * rejected by a 4/4 window (SPH9|11|18) while the
+ * r950-era acceptance - same V3 image - ran with
+ * NO version window. Emit oldest=V(blob),
+ * current=max(V(blob),4) so both the V3 image and
+ * a future V4 re-tag stay inside the range.
+ */
+ u32 bv = (u32)gsp_sema_gl_sph_blob_version();
+ u32 val = 0x00040004u;
+
+ if (bv >= 1u && bv <= 15u)
+ val = ((bv < 4u ? 4u : bv) << 16) | bv;
+
*p++ = ((u32)GSP_PHYS_RMCALL_METHOD_IMM << 29) |
(2u << 16) | (0x16a4u >> 2);
- *p++ = 0x00040004u;
- *p++ = 0x00040004u;
+ *p++ = val;
+ *p++ = val;
}
/*
* SESSION 153-CONTINUED-84: SET_MME_VERSION=1 (0x234).
@@ -23885,6 +23929,32 @@ int gsp_phys_backend_guest_gr_submit(const struct gsp_phys_gr_submit *req,
len >= 8 ? get_unaligned_le32(inl->data + 4) : 0u);
}
}
+ /*
+ * SESSION 153-CONTINUED-87: readback witness.
+ * For a stream3d window the engine's I-fetch
+ * walks the GUEST page (the inline bytes were
+ * just authored there above); read the exact
+ * engine-visible location back so the fetch
+ * content is provable from the log - if the DS
+ * still rejects the header, the bytes are known
+ * present at the VA it fetched.
+ */
+ if (stream3d && pg->hpa) {
+ static u32 inl_rb_log;
+ const u32 *gw = (const u32 *)
+ ((u8 *)__va(pg->hpa) +
+ (inl->dst_va &
+ (GSP_PHYS_PAGE_SIZE - 1)));
+
+ if (inl_rb_log < 12u) {
+ inl_rb_log++;
+ pr_info("vgsp-gr: INLINE-RB dst=0x%llx pa=0x%llx rb=%08x %08x %08x %08x %08x %08x %08x %08x\n",
+ inl->dst_va, pg->hpa,
+ gw[0], gw[1], gw[2],
+ gw[3], gw[4], gw[5],
+ gw[6], gw[7]);
+ }
+ }
copied++;
}
/*
@@ -24360,6 +24430,95 @@ gr_page_unmapped:
gsp_phys_rmcall_gr_3d_last_subdrop,
gsp_phys_rmcall_gr_3d_last_sdmdrop);
/*
+ * SESSION 153-CONTINUED-87: emit the client's missing
+ * pipeline-stage program binds (see the sema_gl_sph_bind
+ * comment). The window carries only the j=1 (VTG) pair; the
+ * real client state also binds j=2 (TESS_CONTROL at
+ * family+0x200) and j=5 (PIXEL at family+0x0) - both present
+ * verbatim in the init-push image scraped from guest RAM
+ * (`20020825 [0,04400200]`, `20020855 [0,04400000]`). Build
+ * the two runs and push them through the same window
+ * relocation pass (miss -> the pair stays raw and the whole
+ * bind is skipped, never a raw client VA to the engine),
+ * then prepend them ahead of the window. Beef client
+ * channels only: the family layout is that client's.
+ */
+ if (READ_ONCE(gsp_phys_rmcall_gr_sph_bind) &&
+ (req->h_object & 0xfffff000u) == 0xbeef0000u &&
+ req->prog_va &&
+ win3d_n + 40u + 13u <= GSP_PHYS_RMCALL_GR_METHOD_WORDS) {
+ static u32 sph_bind_log;
+ u64 fam = req->prog_va &
+ ~(u64)(GSP_PHYS_PAGE_SIZE - 1);
+ u32 in[40], out[40];
+ u32 nfin = 0, nrun = 0, on = 0, odrop = 0, orel;
+ u32 bi;
+
+ /*
+ * SESSION 153-CONTINUED-87 (second half): the window's
+ * OWN binds first. The captured per-frame window
+ * carries draws (BEGIN at word 93) BEFORE its program
+ * binds (j=1 pair at word 184): on real hardware the
+ * bind happened in an earlier push, but the replay
+ * channel's fresh context has nothing bound when the
+ * early draws validate their stages - the
+ * Shader-Program-Header poison (r1277+ 9/11). Re-emit
+ * every bind the window itself carries ahead of it.
+ */
+ for (bi = 0; bi < req->n_prog_binds && bi < 8u; bi++) {
+ u64 va = req->prog_bind_va[bi];
+ u32 sl = req->prog_bind_slot[bi] & 0x1fu;
+
+ if (!va || nfin + 3u > 40u)
+ continue;
+ in[nfin++] = 0x20000000u | (2u << 16) |
+ ((0x2014u + sl * 0x40u) >> 2);
+ in[nfin++] = (u32)(va >> 32) & 0xffu;
+ in[nfin++] = (u32)va & 0xfffffffcu;
+ nrun++;
+ }
+ /*
+ * Then the client's missing stage binds (see the
+ * sema_gl_sph_bind comment): TESS_CONTROL (j=2 at
+ * family+0x200) and PIXEL (j=5 at family+0x0), both
+ * present verbatim in the init-push image scraped
+ * from guest RAM (`20020825 [0,04400200]`,
+ * `20020855 [0,04400000]`).
+ */
+ if (nfin + 6u <= 40u) {
+ in[nfin++] = 0x20000000u | (2u << 16) |
+ (0x2094u >> 2);
+ in[nfin++] = (u32)((fam + 0x200u) >> 32) & 0xffu;
+ in[nfin++] = (u32)(fam + 0x200u) & 0xfffffffcu;
+ in[nfin++] = 0x20000000u | (2u << 16) |
+ (0x2154u >> 2);
+ in[nfin++] = (u32)(fam >> 32) & 0xffu;
+ in[nfin++] = (u32)fam & 0xfffffffcu;
+ nrun += 2;
+ }
+ orel = gsp_phys_rmcall_gr_3d_patch_window(
+ in, nfin, out, &on, &odrop, req, &n_shadow);
+ if (orel == nrun && on == nfin) {
+ memmove(&stream_patch[nfin], stream_patch,
+ (size_t)win3d_n * 4u);
+ memcpy(stream_patch, out, (size_t)nfin * 4u);
+ win3d_n += nfin;
+ if (sph_bind_log < 16u) {
+ sph_bind_log++;
+ pr_info("vgsp-gr: SPH-BIND emitted fam=0x%llx win-binds=%u j2=0x%llx j5=0x%llx win=%u h=0x%x push=0x%llx\n",
+ fam, req->n_prog_binds,
+ fam + 0x200u, fam,
+ win3d_n, req->h_object,
+ req->push_va);
+ }
+ } else if (sph_bind_log < 16u) {
+ sph_bind_log++;
+ pr_info("vgsp-gr: SPH-BIND skipped (reloc=%u/%u kept=%u/%u fam=0x%llx h=0x%x push=0x%llx)\n",
+ orel, nrun, on, nfin, fam,
+ req->h_object, req->push_va);
+ }
+ }
+ /*
* SESSION 153-CONTINUED-62: surface (render-target) prelude -
* see the gsp_phys_gr_surf_pre comment. Injected only when the
* window carries no usable colour-target bind of its own; the