summaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'kernel')
-rw-r--r--kernel/gsp_phys_booter.c124
-rw-r--r--kernel/gsp_sema_service.c17
2 files changed, 136 insertions, 5 deletions
diff --git a/kernel/gsp_phys_booter.c b/kernel/gsp_phys_booter.c
index 3ab4b49..5a30d40 100644
--- a/kernel/gsp_phys_booter.c
+++ b/kernel/gsp_phys_booter.c
@@ -5468,6 +5468,49 @@ static void gsp_phys_pbdma_fault_dump(u32 chid)
}
/*
+ * SESSION 153-CONTINUED-86: the fault-time register witness. The relayed
+ * errString names the fault; these reads add the machine state behind it at
+ * the earliest host observation point (the 0x1006 consume), before the
+ * FECS/GSP-RM clear the latches: MME_HWW_ESR (0x404490) + INFO (0x404494:
+ * PC_VALID/PC/MACRO_ADDRESS) + INFO2 (IR word), DS_HWW_ESR (0x405840) +
+ * ESR_2 (0x405848) + the SPH_INFO stage starts (0x405c00+si*4) that name the
+ * exact VA each failing pipeline stage fetched its shader program header
+ * from, the SPH program-region pair (0x405c1c/c20), and the trapped method
+ * address/data (0x400704/8). GR-class faults only (0xd graphics exception,
+ * 0x45 class error; PBDMA 0x20 has its own dump), bounded per boot so a fault
+ * storm cannot flood dmesg.
+ */
+static void gsp_phys_fault_regs_log(u32 except_type)
+{
+ static u32 frl_n;
+ void __iomem *bar0 = gsp_phys_gpu_bar0();
+ u32 esr, info, info2, ds, ds2, trap_a, trap_d, rr_a, rr_b, sph[6], si;
+
+ if (!bar0 || frl_n >= 48u)
+ return;
+ if (except_type != 0xdu && except_type != 0x45u)
+ return;
+ frl_n++;
+ esr = ioread32(bar0 + 0x00404490u);
+ info = ioread32(bar0 + 0x00404494u);
+ info2 = ioread32(bar0 + 0x00404498u);
+ ds = ioread32(bar0 + 0x00405840u);
+ ds2 = ioread32(bar0 + 0x00405848u);
+ for (si = 0; si < 6u; si++)
+ sph[si] = ioread32(bar0 + 0x00405c00u + si * 4u);
+ rr_a = ioread32(bar0 + 0x00405c1cu);
+ rr_b = ioread32(bar0 + 0x00405c20u);
+ trap_a = ioread32(bar0 + 0x00400704u);
+ trap_d = ioread32(bar0 + 0x00400708u);
+ pr_info("vgsp-fault: regs except=0x%x mme_esr=%08x(pcv=%u ill=%u miss=%u extra=%u) mme_info=%08x(pc=%u mac=0x%x) mme_ir=%08x ds=%08x/%08x sph=%08x,%08x,%08x,%08x,%08x,%08x rr=%08x,%08x trap=%08x data=%08x\n",
+ except_type, esr, (info >> 28) & 1u, (esr >> 2) & 1u,
+ esr & 1u, (esr >> 1) & 1u, info, info & 0xfffu,
+ (info >> 12) & 0xffu, info2, ds, ds2,
+ sph[0], sph[1], sph[2], sph[3], sph[4], sph[5],
+ rr_a, rr_b, trap_a, trap_d);
+}
+
+/*
* Note every consumed 0x1006 in the bounded last-4 ring, advance the fault
* epoch (the relay submit snapshot compares against it) and log the designed
* observation line when the fault relay is armed. Decoding and counting are
@@ -5483,10 +5526,12 @@ static void gsp_phys_fault_observe(const struct gsp_phys_rx_record *rec,
GSP_PHYS_FAULT_NOTE_MAX;
gsp_phys_fault_seen++;
gsp_phys_fault_epoch++;
- if (gsp_phys_fault_relay_enabled())
+ if (gsp_phys_fault_relay_enabled()) {
pr_info_ratelimited("vgsp-fault: func=0x1006 seq=%u exceptType=0x%x runlistId=%u chid=%u prevXid=0x%x errString=\"%s\"\n",
rec->seq_num, out->except_type, out->runlist_id,
out->chid, out->prev_xid, out->err);
+ gsp_phys_fault_regs_log(out->except_type);
+ }
if (out->except_type == 0x20u)
gsp_phys_pbdma_fault_dump(out->chid);
}
@@ -17827,6 +17872,40 @@ MODULE_PARM_DESC(sema_gl_mme_version,
"Emit SET_MME_VERSION=1 ahead of the replayed MME prelude (default 1; the Turing channel-init method the guest pushes once and the capture never carries)");
/*
+ * SESSION 153-CONTINUED-86: the missing SPH (shader-program-header) state.
+ *
+ * The executed beef launches fault `Graphics Exception: Shader Program
+ * Header 9/11/18 Error` + `DS_HWW_ESR 0x405840=0xa2040a00` (r1272): the DS
+ * unit validates the header of every pipeline program bound when a draw
+ * issues, including the SPH VERSION against the channel's programmed
+ * window. The Turing channel-init (the 3D driver's own
+ * _nv3dInitChannelTuring) writes the SPH version pair ONCE per channel:
+ *
+ * INC run @0x16a4, count 2:
+ * METHOD 0x16a4 (SET_SPH_VERSION) <- 4 | (4 << 16) = 0x00040004
+ * METHOD 0x16a8 (CHECK_SPH_VERSION) <- 0x00040004
+ *
+ * (fields: CURRENT 15:0, OLDEST_SUPPORTED 31:16; the value 4 is the SPH V4
+ * the Turing shader images carry). The replayed context never receives it:
+ * the capture families (MME prelude 0x114..0x124/0x234/0x550..0x568/
+ * 0x3400..0x34fc, attr prelude 0x1100..0x11fc/0x2000..0x205c) do not cover
+ * 0x16a4, and the captured 3D windows contain no such write (verified in the
+ * emitted-window decode and the raw guest-RAM stream). With the register
+ * unset (0/0) every fetched SPH fails its version window -> per-SPH error
+ * bits -> 0 GR-STATE retires and no stores. The client's own emitted init
+ * pair was located verbatim in the guest pushbuffer image (guest PA
+ * 0x8672d5b4: `200205a9 00040004 00040004`), so the launch builder emits
+ * exactly that run ahead of the window (right after SET_OBJECT, beside the
+ * MME version write). 3 words, idempotent; emitted on every replayed 3D
+ * window. Default 1; A/B with 0 reproduces the SPH fault.
+ */
+static bool gsp_phys_rmcall_gr_sph_version = true;
+module_param_named(sema_gl_sph_version, gsp_phys_rmcall_gr_sph_version,
+ bool, 0644);
+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-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
@@ -18146,7 +18225,7 @@ static u32 gsp_phys_rmcall_build_gr_launch(u32 *pb,
* off for this mode).
*/
if (gsp_phys_rmcall_gr_3d && req && win3d && win3d_n &&
- win3d_n + 2u + 8u <= GSP_PHYS_RMCALL_GR_METHOD_WORDS) {
+ win3d_n + 2u + 3u + 8u <= GSP_PHYS_RMCALL_GR_METHOD_WORDS) {
/*
* SESSION 153-CONTINUED-53: MME context-setup prelude (see the
* sema_gl_mme_prelude knob above). Preplay the captured client
@@ -18172,6 +18251,16 @@ static u32 gsp_phys_rmcall_build_gr_launch(u32 *pb,
block_cap > GSP_PHYS_RMCALL_GR_METHOD_WORDS)
block_cap = GSP_PHYS_RMCALL_GR_METHOD_WORDS;
/*
+ * SESSION 153-CONTINUED-86: harden the block cap against the
+ * emissions the block-cap arithmetic below does not fully
+ * count (the SA re-arm, 3 words per slot, up to 32 slots -
+ * see the MME-SA-REARM site). Clamping the cap keeps every
+ * combination inside the 4096-word method buffer; with the
+ * default 2048 cap this changes nothing.
+ */
+ if (block_cap > GSP_PHYS_RMCALL_GR_METHOD_WORDS - 128u)
+ block_cap = GSP_PHYS_RMCALL_GR_METHOD_WORDS - 128u;
+ /*
* SESSION 153-CONTINUED-63: MME START-ADDRESS RAM completion.
* The prelude capture is capped at 512 words, so the client's
* SA table (macro slot -> IR address) may be incomplete; on a
@@ -18454,6 +18543,22 @@ static u32 gsp_phys_rmcall_build_gr_launch(u32 *pb,
(GSP_PHYS_RMCALL_GR_SET_OBJECT >> 2);
*p++ = GSP_PHYS_RMCALL_CLASS_GR_3D;
/*
+ * SESSION 153-CONTINUED-86: the Turing channel-init SPH version
+ * pair (see the sema_gl_sph_version knob). Emitted on EVERY
+ * replayed 3D window (3 words, idempotent): the DS validates
+ * each bound program's SPH version against this window at draw
+ * time, and the replay context never received the client's
+ * once-per-channel write. Emitted before the prelude-room
+ * computations below so the live (p - pb) accounting covers
+ * it exactly.
+ */
+ if (READ_ONCE(gsp_phys_rmcall_gr_sph_version)) {
+ *p++ = ((u32)GSP_PHYS_RMCALL_METHOD_IMM << 29) |
+ (2u << 16) | (0x16a4u >> 2);
+ *p++ = 0x00040004u;
+ *p++ = 0x00040004u;
+ }
+ /*
* SESSION 153-CONTINUED-84: SET_MME_VERSION=1 (0x234).
*
* The Turing channel-init defaults push
@@ -22214,6 +22319,21 @@ static u32 gsp_phys_rmcall_gr_3d_patch_window(const u32 *in, u32 n, u32 *out,
*/
if (READ_ONCE(gsp_phys_rmcall_gr_sdm_drop) &&
hdr && (op == 0u || op == 2u || op == 6u)) {
+ /*
+ * SESSION 153-CONTINUED-86: name every dropped SDM
+ * entry (bounded) so the A/B arm can be audited: the
+ * "keep the drop only for entries proven unrelated"
+ * decision needs the actual words, not the count.
+ */
+ static u32 sdm_log;
+
+ if (sdm_log < 24u) {
+ sdm_log++;
+ pr_info("vgsp-gr: SDM-DROP in[%u]=%08x op=%u addr=%#x sub=%u cnt/val=%#x (span=%u)\n",
+ off, hdr, op, addr, sub,
+ (cnt ? cnt : ((hdr >> 16) & 0x1fffu)),
+ span);
+ }
dropped++;
sdm_drop++;
off += span;
diff --git a/kernel/gsp_sema_service.c b/kernel/gsp_sema_service.c
index 5224dad..12a7368 100644
--- a/kernel/gsp_sema_service.c
+++ b/kernel/gsp_sema_service.c
@@ -14662,12 +14662,23 @@ static u64 svc_attr_prelude_ptr[SVC_ATTR_PRELUDE_PTRS];
static u32 svc_attr_prelude_ptr_n;
module_param_named(sema_attr_prelude_cap, svc_attr_prelude_flag, uint, 0644);
MODULE_PARM_DESC(sema_attr_prelude_cap,
- "Capture the client's attr/pipeline method runs (0x1100..0x11fc, 0x2000..0x205c) from trusted beef pushes for the GR launch builder's preplay ahead of the first 3D window (default 1)");
+ "Capture the client's attr/pipeline method runs (0x1100..0x11fc, 0x2000..0x21fc) from trusted beef pushes for the GR launch builder's preplay ahead of the first 3D window (default 1)");
static bool svc_attr_setup_run_addr(u32 addr)
{
+ /*
+ * SESSION 153-CONTINUED-86: the pipeline family extends across ALL
+ * eight pipeline records (SET_PIPELINE_SHADER/BINDING/PROGRAM_ADDRESS
+ * for j=0..7 = 0x2000..0x21fc), not just j=0..1. The r1273 scrape of
+ * the client's own push image proved the guest driver binds stage 2
+ * (TESS_CONTROL, VA 0x4400200) and stage 5 (PIXEL, VA 0x4400000) with
+ * the same pair runs; the old 0x2060 cut-off dropped those binds, the
+ * replay channel's stages 2/5 kept stale/zero program addresses, and
+ * the draw's SPH validation failed for the stages it could not fetch
+ * ("Shader Program Header 9/11/18 Error", DS_HWW_ESR 0xa2040a00).
+ */
return (addr >= 0x1100u && addr < 0x1200u) ||
- (addr >= 0x2000u && addr < 0x2060u);
+ (addr >= 0x2000u && addr < 0x2200u);
}
const u32 *gsp_sema_attr_prelude_get(u32 *n, u32 *gen)
@@ -14745,7 +14756,7 @@ static void svc_attr_prelude_capture(const u8 *buf, u32 len, u64 push_va,
* lower(31:0)]: remember the program VA so its page can join
* the launch page set (see the header comment).
*/
- if (addr >= 0x2014u && addr < 0x2060u &&
+ if (addr >= 0x2014u && addr < 0x2200u &&
(addr & 0x3fu) == 0x14u && span >= 3u) {
u32 v0 = 0, v1 = 0;