summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArthur Hanson Rasmusson <arthur@vgpu.io>2026-11-06 20:09:42 -0500
committerArthur Hanson Rasmusson <arthur@vgpu.io>2026-11-06 20:09:42 -0500
commit88e0b15326a7bacb6c02f351b26a4b28a7933ad8 (patch)
tree3701b1176742ece74f41d7db229a68bed1cb8aaa
parent630a8a9fbadc4e6be2f21b162071157ccfc12664 (diff)
downloadopen-iov-88e0b15326a7bacb6c02f351b26a4b28a7933ad8.tar.gz
open-iov-88e0b15326a7bacb6c02f351b26a4b28a7933ad8.zip
vgsp-gl: synthesized GS SPH image + map variants for the SPH18 gate
-rw-r--r--kernel/gsp_phys_booter.c93
-rw-r--r--kernel/gsp_phys_gpu.h14
-rw-r--r--kernel/gsp_sema_service.c83
3 files changed, 186 insertions, 4 deletions
diff --git a/kernel/gsp_phys_booter.c b/kernel/gsp_phys_booter.c
index 1dedf7c..fdd8e88 100644
--- a/kernel/gsp_phys_booter.c
+++ b/kernel/gsp_phys_booter.c
@@ -18610,6 +18610,53 @@ module_param_named(sema_gl_sph_stage_disable,
gsp_phys_rmcall_gr_sph_stage_disable, uint, 0644);
MODULE_PARM_DESC(sema_gl_sph_stage_disable,
"Per-stage synth-bind disable mask (bit j = synth slot j: 0=VSA,1=VSB,2=TCS,3=TES,4=GS,5=PS): emit the client's SET_PIPELINE_SHADER disable record for that stage and skip its synthesized bind (default 0; legacy bytes)");
+
+/*
+ * SESSION 155 CONT 11: the last DS latch bit in the r1562 replay is SPH18
+ * (GS check2, attribute map). r1562 proved the DS validates the GS stage
+ * even when the driver's own disable record (0x2100 <- 0x40) leaves it
+ * unbound: SPH18 latched with stage4 START=0. The client has no geometry
+ * program, so no GS SPH exists anywhere in its push. This knob binds a
+ * synthesized header-only GEOMETRY SPH (128 B, pass-through maps) to
+ * stage 4 while keeping SET_PIPELINE_SHADER(4) ENABLE=0, so the DS has a
+ * valid operand at SPH_INFO_STAGE4_START but the engine never executes
+ * it. The image is authored by the sema service at family+0x780 (same 4K
+ * page as the bound VTG/TCS/PS images) and the address pair below is
+ * relocated by the same window pass. Default 0 = legacy bytes.
+ */
+static bool gsp_phys_rmcall_gr_sph_gs_img;
+module_param_named(sema_gl_sph_gs_img, gsp_phys_rmcall_gr_sph_gs_img,
+ bool, 0644);
+MODULE_PARM_DESC(sema_gl_sph_gs_img,
+ "Bind a synthesized header-only GEOMETRY SPH to stage 4 with ENABLE=0 (family+0x780; satisfies the SPH18 GS attribute-map check; default 0)");
+
+bool gsp_phys_rmcall_gr_sph_gs_img_value(void)
+{
+ return READ_ONCE(gsp_phys_rmcall_gr_sph_gs_img);
+}
+
+/*
+ * SESSION 155 CONT 12: the synthesized GS SPH's attribute-map variant.
+ * The r1564 run proved the DS fetches the image (stage4 START nonzero)
+ * yet SPH18 persists and the VTG-class check2 bits return, so the map
+ * CONTENT is the discriminator:
+ * 0 = pass-through (IMAP = previous OMAP = POSITION+COLOR;
+ * OMAP = PS IMAP superset = POSITION+COLOR)
+ * 1 = all IMAP/OMAP zero (the mesh-dummy contract)
+ * 2 = PS-exact (IMAP = POSITION.W; OMAP = POSITION.XYZW)
+ * 3 = IMAP POSITION+COLOR, OMAP POSITION.XYZW only
+ * A/B live: the sema service reads this per capture.
+ */
+static u32 gsp_phys_rmcall_gr_sph_gs_maps;
+module_param_named(sema_gl_sph_gs_maps, gsp_phys_rmcall_gr_sph_gs_maps,
+ uint, 0644);
+MODULE_PARM_DESC(sema_gl_sph_gs_maps,
+ "Synth GS SPH attribute-map variant: 0=pass-through(POS+COLOR both), 1=zero maps, 2=PS-exact(POS.W/POS.XYZW), 3=IMAP POS+COLOR / OMAP POS.XYZW (default 0)");
+
+u32 gsp_phys_rmcall_gr_sph_gs_maps_value(void)
+{
+ return READ_ONCE(gsp_phys_rmcall_gr_sph_gs_maps);
+}
static bool gsp_phys_gr_mme_pairs_emitted; /* launch emitted a pair run */
static u32 gsp_phys_gr_mme_pairs_gen; /* gen whose pairs retired OK */
static u32 gsp_phys_gr_mme_launch_gen; /* last built launch's gen */
@@ -29659,6 +29706,15 @@ gr_page_unmapped:
(sph_bind_all || (sph_bind_mask & 0x01u));
bool emit_j4 = !(stage_disable_mask & 0x10u) &&
(sph_bind_all || (sph_bind_mask & 0x10u));
+ /*
+ * SESSION 155 CONT 11: synthesized GS image bind
+ * (see the sema_gl_sph_gs_img comment). Independent
+ * of the j4 slot mask: it replaces the disable-only
+ * GS state with a disabled stage that still has a
+ * valid SPH operand.
+ */
+ bool emit_gsimg =
+ READ_ONCE(gsp_phys_rmcall_gr_sph_gs_img);
/*
* SESSION 155 CONT 9: the prelude is prepended ahead of
@@ -29861,7 +29917,8 @@ gr_page_unmapped:
(emit_j0 ? (bind_binding ? 8u : 7u) : 0u) +
(emit_j2 ? (bind_binding ? 8u : 7u) : 0u) +
(emit_j4 ? (bind_binding ? 8u : 7u) : 0u) +
- (emit_j5 ? (bind_binding ? 8u : 7u) : 0u) <= 96u) {
+ (emit_j5 ? (bind_binding ? 8u : 7u) : 0u) +
+ (emit_gsimg ? 9u : 0u) <= 96u) {
/*
* SESSION 155 CONT 9: pair_safe emits each
* synthesized stage's SET_PIPELINE_SHADER
@@ -30053,8 +30110,38 @@ gr_page_unmapped:
in[nfin++] = 0x1au;
in[nfin++] = 0x0u;
/*
+ * SESSION 155 CONT 11: the synthesized
+ * header-only GEOMETRY SPH (128 B at
+ * family+0x780, authored by the sema
+ * service). Bind it to stage 4 and keep the
+ * stage disabled: the DS then validates a
+ * real GS SPH (its SPH18 check2 attribute
+ * map) while the engine does not execute the
+ * header-only image. Emitted after the
+ * stage-1 pair, before the address-pair
+ * census. The pair is the only relocatable
+ * run here (nrun++ below).
+ */
+ if (emit_gsimg) {
+ u64 gva = fam + 0x780u;
+
+ in[nfin++] = 0x20000000u | (1u << 16) |
+ (0x2100u >> 2);
+ in[nfin++] = 0x40u;
+ in[nfin++] = 0x20000000u | (1u << 16) |
+ (0x210cu >> 2);
+ in[nfin++] = 0x1au;
+ in[nfin++] = 0x20000000u | (2u << 16) |
+ (0x2114u >> 2);
+ in[nfin++] = (u32)(gva >> 32) & 0xffu;
+ in[nfin++] = (u32)gva & 0xfffffffcu;
+ in[nfin++] = 0x20000000u | (1u << 16) |
+ (0x2100u >> 2);
+ in[nfin++] = 0x40u;
+ }
+ /*
* nrun counts only the ADDRESS-bearing
- * binds above: the guard below matches it
+ * binds: the guard below matches it
* against the relocation pass's
* relocated-pair count, and the constant
* type runs can never be relocated.
@@ -30067,6 +30154,8 @@ gr_page_unmapped:
nrun++;
if (emit_j5)
nrun++;
+ if (emit_gsimg)
+ nrun++;
}
orel = gsp_phys_rmcall_gr_3d_patch_window(
in, nfin, out, &on, &odrop, req, &n_shadow,
diff --git a/kernel/gsp_phys_gpu.h b/kernel/gsp_phys_gpu.h
index 6e16062..6cb6aef 100644
--- a/kernel/gsp_phys_gpu.h
+++ b/kernel/gsp_phys_gpu.h
@@ -349,6 +349,20 @@ int gsp_phys_rmcall_gr_shadow_win0_value(void);
bool gsp_phys_rmcall_gr_sph_bind_value(void);
/*
+ * SESSION 155 CONT 11: bind a synthesized header-only GEOMETRY SPH to
+ * stage 4 with ENABLE=0 (sema_gl_sph_gs_img, default 0). The sema service
+ * uses this value to author the 128-byte image at family+0x780.
+ */
+bool gsp_phys_rmcall_gr_sph_gs_img_value(void);
+
+/*
+ * SESSION 155 CONT 12: attribute-map variant for the synthesized GS SPH
+ * (0=pass-through, 1=zero maps, 2=PS-exact, 3=IMAP POS+COLOR / OMAP
+ * POS.XYZW). The sema service reads this per capture.
+ */
+u32 gsp_phys_rmcall_gr_sph_gs_maps_value(void);
+
+/*
* r1512: the viewport state the 3D replay injects for the current launch
* (sema_gl_vp_prelude mode + its literal words). Read-only; used by the
* sema service's draw-coverage receipt.
diff --git a/kernel/gsp_sema_service.c b/kernel/gsp_sema_service.c
index dafbad6..d8aa4dc 100644
--- a/kernel/gsp_sema_service.c
+++ b/kernel/gsp_sema_service.c
@@ -10579,14 +10579,16 @@ static void svc_gl_flush(struct nv_vgpu_device *vgpu,
* channels only, and only when the window does not already
* bind that exact VA.
*/
- if (gsp_phys_rmcall_gr_sph_bind_value() &&
+ if ((gsp_phys_rmcall_gr_sph_bind_value() ||
+ gsp_phys_rmcall_gr_sph_gs_img_value()) &&
(ch->h_object & 0xfffff000u) == 0xbeef0000u &&
svc_gl.progs[0]) {
u64 fam = svc_gl.progs[0] &
~(u64)(SEMA_PAGE_SIZE - 1);
u32 k;
- for (k = 0; k < 2u && n_recs < SVC_GL_PROG_MAX; k++) {
+ for (k = 0; gsp_phys_rmcall_gr_sph_bind_value() &&
+ k < 2u && n_recs < SVC_GL_PROG_MAX; k++) {
u64 dst = fam + (k ? 0x200u : 0x0u);
const u8 *b = k ? svc_gl_vs : svc_gl_ps;
u32 bl = k ? svc_gl_vs_len : svc_gl_ps_len;
@@ -10619,6 +10621,83 @@ static void svc_gl_flush(struct nv_vgpu_device *vgpu,
get_unaligned_le32(prs[n_recs - 1].data));
}
}
+ /*
+ * SESSION 155 CONT 11: the synthesized header-only
+ * GEOMETRY SPH at family+0x780. The client never
+ * emits a geometry program, but the DS validates
+ * the GS stage anyway (SPH18 = GS check2 attribute
+ * map) even when the stage is disabled. The booter
+ * binds this page to stage 4 with ENABLE=0, so the
+ * engine does not execute it. SPH V4T1 header with
+ * SHADER_TYPE=GEOMETRY (4), SASS_VERSION=5 and
+ * pass-through maps (IMAP = the VTG OMAP =
+ * POSITION+COLOR; OMAP = the PS IMAP superset
+ * POSITION+COLOR). 128 bytes, same 4K family page
+ * as the bound VTG/TCS/PS images.
+ */
+ if (gsp_phys_rmcall_gr_sph_gs_img_value() &&
+ n_recs < SVC_GL_PROG_MAX) {
+ u32 gs_words[32] = {
+ 0x000a1081u, 0x00000000u,
+ 0x01000000u, 0x07000000u,
+ 0x00000003u, 0xf0000000u,
+ 0x00000000u, 0x00000000u,
+ 0x00000000u, 0x00000000u,
+ 0x0000000fu, 0x00000000u,
+ 0x00000000u, 0x0000f000u,
+ 0x00000000u, 0x00000000u,
+ 0x00000000u, 0x000f0000u,
+ 0x00000000u, 0x00000000u,
+ 0x00000000u, 0x00000000u,
+ 0x00000000u, 0x00000000u,
+ 0x00000000u, 0x00000000u,
+ 0x00000000u, 0x00000000u,
+ 0x00000000u, 0x00000000u,
+ 0x00000000u, 0x00000000u,
+ };
+ u32 gs_maps =
+ gsp_phys_rmcall_gr_sph_gs_maps_value();
+ u64 dst = fam + 0x780u;
+ bool dup = false;
+ u32 pi4;
+
+ /*
+ * SESSION 155 CONT 12: map A/B (see the
+ * sema_gl_sph_gs_maps comment). 0 keeps the
+ * pass-through header above.
+ */
+ if (gs_maps == 1u) {
+ gs_words[5] = 0u;
+ gs_words[10] = 0u;
+ gs_words[13] = 0u;
+ gs_words[17] = 0u;
+ } else if (gs_maps == 2u) {
+ gs_words[5] = 0x80000000u;
+ gs_words[10] = 0u;
+ gs_words[13] = 0x0000f000u;
+ gs_words[17] = 0u;
+ } else if (gs_maps == 3u) {
+ gs_words[17] = 0u;
+ }
+
+ for (pi4 = 0; pi4 < svc_gl.n_progs; pi4++)
+ if (svc_gl.progs[pi4] == dst)
+ dup = true;
+ if (!dup) {
+ memset(&prs[n_recs], 0,
+ sizeof(prs[n_recs]));
+ prs[n_recs].dst_va = dst;
+ prs[n_recs].len = 128u;
+ memcpy(prs[n_recs].data, gs_words,
+ sizeof(gs_words));
+ n_recs++;
+ if (gsp_sema_dbg &&
+ svc_gl_prog_log < 64)
+ pr_info("sema-gl: stage-image dst=0x%llx slot=4 len=128 maps=%u first=%08x w5=%08x w13=%08x\n",
+ dst, gs_maps, gs_words[0],
+ gs_words[5], gs_words[13]);
+ }
+ }
}
if (n_recs && gsp_sema_dbg && svc_gl_prog_log < 64) {
u32 pi2;