summaryrefslogtreecommitdiffstats
path: root/kernel/gsp_sema_service.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/gsp_sema_service.c')
-rw-r--r--kernel/gsp_sema_service.c83
1 files changed, 81 insertions, 2 deletions
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;