diff options
| author | Arthur Hanson Rasmusson <arthur@vgpu.io> | 2026-11-01 06:46:40 -0500 |
|---|---|---|
| committer | Arthur Hanson Rasmusson <arthur@vgpu.io> | 2026-11-01 06:46:40 -0500 |
| commit | 52f676b4065ac82c5118c9e9716d90ab2875bfa1 (patch) | |
| tree | 9e58ea7b5302672439fcbf1fc9a0df1ccf098746 /kernel | |
| parent | b7f4f7a5fb5a0130aa999034646936c8db80e7d4 (diff) | |
| download | open-iov-52f676b4065ac82c5118c9e9716d90ab2875bfa1.tar.gz open-iov-52f676b4065ac82c5118c9e9716d90ab2875bfa1.zip | |
vgsp: CONT-86 - sema_gl_sph_version (emits Turing channel-init pair 200205a9 00040004 00040004 after SET_OBJECT on replayed 3D windows); gsp_phys_fault_regs_log (MME_HWW_ESR/INFO/IR + DS_HWW_ESR/ESR_2 + SPH stage starts beside every GR-class 0x1006); SDM-DROP forensic log; block-cap hardening <=4096-128; attr-prelude capture range 0x2000..0x2200 (8 pipeline records) - fault witness: failing SPH stage1 fetched from relocated shadow VA 0x620900; minimal V3 blobs rejected STRUCTURALLY (V4 retag no help); SDM drops all 0001fff0 SET_SUB_DEV_MASK legit; missing binds: j=2 va=0x4300200 TESS + j=5 va=0x4300000 PIXEL never in windows/preludes; next: author client's REAL SPH+SASS bytes at relocated program VAs (VA 0x4300900-family from unreplayed init push) as sema_gl_vs_hex/ps_hex + replay stage-2/5 binds - SESSION 153 r1273-r1275
Diffstat (limited to 'kernel')
| -rw-r--r-- | kernel/gsp_phys_booter.c | 124 | ||||
| -rw-r--r-- | kernel/gsp_sema_service.c | 17 |
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; |
