summaryrefslogtreecommitdiffstats
path: root/kernel/gsp_phys_booter.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/gsp_phys_booter.c')
-rw-r--r--kernel/gsp_phys_booter.c124
1 files changed, 114 insertions, 10 deletions
diff --git a/kernel/gsp_phys_booter.c b/kernel/gsp_phys_booter.c
index cf3107f..e43ba23 100644
--- a/kernel/gsp_phys_booter.c
+++ b/kernel/gsp_phys_booter.c
@@ -5280,7 +5280,7 @@ MODULE_PARM_DESC(sema_mme_post_ms,
*/
static u32 gsp_phys_mme_shadow_read(void __iomem *bar0, u32 nvclass, u32 mthd)
{
- iowrite32(nvclass | ((mthd & 0xfffu) << 16) | (1u << 30),
+ iowrite32(nvclass | (((mthd >> 2) & 0xfffu) << 16) | (1u << 30),
bar0 + 0x00404488u);
return ioread32(bar0 + 0x0040448cu);
}
@@ -19957,6 +19957,35 @@ module_param_named(sema_sph_bind_mask, gsp_phys_rmcall_gr_sph_bind_mask,
MODULE_PARM_DESC(sema_sph_bind_mask,
"Synth SPH-BIND slot mask (bit j = slot j; 0x20 = PS only, 0x01/0x10 = VSA/GS VTG image, 0x25 = VSA+PS) used when sema_gl_sph_bind=0");
+/*
+ * eng51 (CONT.512): the synthesized VSA/GS (j0/j4) bind the VTG SPH image.
+ * The historical address was family+0x900, but the live direct-GL family
+ * page reads zero there (c716: DS 0x86040624 with stage=01df0900,...).
+ * family+0x600 was tried as the VTG image (INLINE-WRITER: 0x020a0481), but
+ * the engine-visible alias shadow at +0x600 is the client's SASS upload
+ * (0x0b0b7208), so binding it poisons the DS (c718/c720: badf1201 with the
+ * j1 override off too). Default 0 = keep the historical +0x900 zero page
+ * until a real VTG SPH is authored at an engine-visible VA; A/B with 1.
+ */
+static bool gsp_phys_rmcall_gr_sph_vtg600;
+module_param_named(sema_gl_sph_vtg600, gsp_phys_rmcall_gr_sph_vtg600,
+ bool, 0644);
+MODULE_PARM_DESC(sema_gl_sph_vtg600,
+ "Bind the synthesized VSA/GS (j0/j4) stages to family+0x600 instead of the historical family+0x900 page (default 0: the live +0x600 alias shadow is SASS and poisons the DS)");
+
+/*
+ * eng51 A/B (c718): overriding the window's own slot-1 bind (j1) with the
+ * family+0x600 image is a separate question. c718 (override on) poisoned the
+ * DS (badf1201) while c716 (j0/j4 at 0x900, j1 at the client's 0x300 SASS
+ * pointer) reached 0x86040624, so the j1 override is default OFF until a
+ * same-boot A/B says otherwise.
+ */
+static bool gsp_phys_rmcall_gr_sph_vtg_j1;
+module_param_named(sema_gl_sph_vtg_j1, gsp_phys_rmcall_gr_sph_vtg_j1,
+ bool, 0644);
+MODULE_PARM_DESC(sema_gl_sph_vtg_j1,
+ "Also point the window's own slot-1 (VTG) bind at family+0x600 instead of the client's captured bind (default 0; c718 poison A/B)");
+
bool gsp_phys_rmcall_gr_sph_bind_value(void)
{
return READ_ONCE(gsp_phys_rmcall_gr_sph_bind);
@@ -30660,6 +30689,8 @@ gr_page_unmapped:
static u32 sph_bind_log;
u64 fam = req->prog_va &
~(u64)(GSP_PHYS_PAGE_SIZE - 1);
+ u64 vtg_va = READ_ONCE(gsp_phys_rmcall_gr_sph_vtg600) ?
+ (fam + 0x600u) : (fam + 0x900u);
u32 in[96], out[96];
u32 nfin = 0, nrun = 0, on = 0, odrop = 0, orel;
u32 bi;
@@ -30960,6 +30991,16 @@ gr_page_unmapped:
if (!va || nfin + 3u > 96u)
continue;
+ /*
+ * eng51: the window's own slot-1 bind can be
+ * a SASS pointer (c716: family+0x300 starts
+ * 0x0d0d7623); the VTG SPH image is at
+ * family+0x600. Point the VTG slot at the
+ * real image when the knob is on.
+ */
+ if (sl == 1u &&
+ READ_ONCE(gsp_phys_rmcall_gr_sph_vtg_j1))
+ va = vtg_va;
in[nfin++] = 0x20000000u | (2u << 16) |
((0x2014u + sl * 0x40u) >> 2);
in[nfin++] = (u32)(va >> 32) & 0xffu;
@@ -30981,9 +31022,7 @@ gr_page_unmapped:
(emit_j5 ? (bind_binding ? 8u : 7u) : 0u) +
(emit_gsimg ? (9u + ((gs_mode & 1u) ? 11u : 0u) +
((gs_ctx & 1u) ? 2u : 0u) +
- ((gs_ctx & 2u) ? 2u : 0u)) : 0u) +
- (emit_raster ? 17u : 0u) +
- (emit_raster_extra ? 16u : 0u)
+ ((gs_ctx & 2u) ? 2u : 0u)) : 0u)
<= 96u) {
/*
* SESSION 155 CONT 9: pair_safe emits each
@@ -31043,14 +31082,14 @@ gr_page_unmapped:
if (emit_j0) {
in[nfin++] = 0x20000000u | (2u << 16) |
(0x2014u >> 2);
- in[nfin++] = (u32)((fam + 0x900u) >> 32) & 0xffu;
- in[nfin++] = (u32)(fam + 0x900u) & 0xfffffffcu;
+ in[nfin++] = (u32)(vtg_va >> 32) & 0xffu;
+ in[nfin++] = (u32)vtg_va & 0xfffffffcu;
}
if (emit_j4) {
in[nfin++] = 0x20000000u | (2u << 16) |
(0x2114u >> 2);
- in[nfin++] = (u32)((fam + 0x900u) >> 32) & 0xffu;
- in[nfin++] = (u32)(fam + 0x900u) & 0xfffffffcu;
+ in[nfin++] = (u32)(vtg_va >> 32) & 0xffu;
+ in[nfin++] = (u32)vtg_va & 0xfffffffcu;
}
if (emit_j2) {
in[nfin++] = 0x20000000u | (2u << 16) |
@@ -31259,6 +31298,19 @@ gr_page_unmapped:
nrun++;
if (emit_gsimg)
nrun++;
+ } else if (sph_bind_log < 64u) {
+ /*
+ * eng51 (CONT.512): name the silent budget
+ * skip. Before this receipt the stage block
+ * (j0/j2/j4/j5/gsimg) could vanish while the
+ * prelude still emitted with only the j1 bind,
+ * leaving VSA/TCS/GS unbound and the DS latch
+ * at the a2040a04 class.
+ */
+ sph_bind_log++;
+ pr_info("vgsp-gr: SPH-BIND-STAGE-SKIP reason=budget nfin=%u mask=0x%x h=0x%x push=0x%llx\n",
+ nfin, sph_bind_mask, req->h_object,
+ req->push_va);
}
orel = gsp_phys_rmcall_gr_3d_patch_window(
in, nfin, out, &on, &odrop, req, &n_shadow,
@@ -31272,8 +31324,8 @@ gr_page_unmapped:
sph_bind_log++;
pr_info("vgsp-gr: SPH-BIND emitted fam=0x%llx win-binds=%u j0=0x%llx j2=0x%llx j4=0x%llx j5=0x%llx j1-type=0x11 rc=0x1a initblk=17 win=%u (pre=%u) h=0x%x push=0x%llx\n",
fam, req->n_prog_binds,
- fam + 0x900u, fam + 0x200u,
- fam + 0x900u, fam,
+ vtg_va, fam + 0x200u,
+ vtg_va, fam,
win3d_n, nfin,
req->h_object,
req->push_va);
@@ -37250,6 +37302,52 @@ static const struct file_operations gsp_phys_init_push_fops = {
};
/*
+ * eng51 (CONT.512): gsp-phys-last-push - the most recent >=4 KiB beef push
+ * (the direct-GL draw stream; c714: 0x4250110). Same text format as the
+ * init-push dump so the RT bind / draw methods can be decoded offline after
+ * the guest recycles its pushbuffer.
+ */
+static int gsp_phys_last_push_show(struct seq_file *m, void *unused)
+{
+ const u8 *buf;
+ u32 len, h, off;
+ u64 va;
+
+ buf = gsp_sema_last_cap_get(&len, &h, &va);
+ if (!len) {
+ seq_puts(m, "vgsp-last-push: empty (no later >=4 KiB beef push captured yet)\n");
+ return 0;
+ }
+ seq_printf(m, "vgsp-last-push: h=0x%x va=0x%llx len=%u\n", h, va, len);
+ for (off = 0; off + 4u <= len; off += 16u) {
+ u32 k, n = min_t(u32, 4u, (len - off) / 4u);
+
+ seq_printf(m, "%06x:", off);
+ for (k = 0; k < n; k++) {
+ u32 w;
+
+ memcpy(&w, buf + off + k * 4u, 4);
+ seq_printf(m, " %08x", w);
+ }
+ seq_putc(m, '\n');
+ }
+ return 0;
+}
+
+static int gsp_phys_last_push_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, gsp_phys_last_push_show, NULL);
+}
+
+static const struct file_operations gsp_phys_last_push_fops = {
+ .owner = THIS_MODULE,
+ .open = gsp_phys_last_push_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
+
+/*
* SESSION 153-CONTINUED-95: gsp-phys-ctx-dump - raw binary readback of the
* engine context buffer (see gsp_phys_ctx_readback_try). Empty until the
* first launch of the boot has run the CE readback.
@@ -37483,6 +37581,12 @@ int gsp_phys_boot_debugfs_init(void)
&gsp_phys_init_push_fops);
if (IS_ERR_OR_NULL(file))
pr_warn("vgsp-boot: debugfs file gsp-phys-init-push creation failed (init-push capture unavailable)\n");
+ /* eng51 (CONT.512): the most recent large beef push (direct-GL draw). */
+ file = debugfs_create_file("gsp-phys-last-push", 0444,
+ gsp_phys_debugfs_root, NULL,
+ &gsp_phys_last_push_fops);
+ if (IS_ERR_OR_NULL(file))
+ pr_warn("vgsp-boot: debugfs file gsp-phys-last-push creation failed (last-push capture unavailable)\n");
/*
* SESSION 153-CONTINUED-95: raw binary dump of the engine context
* buffer readback (64 KB from GSP_PHYS_RMCALL_VA_GR_CTX, taken once