From 66d95894742780b42c58f4d01aec3f70519a6ee5 Mon Sep 17 00:00:00 2001 From: Arthur Hanson Rasmusson Date: Sun, 1 Nov 2026 20:16:02 -0500 Subject: vgsp: CONT-99 - sema_gl_mme_prelude_ir_only + sema_gl_mme_prelude_pack (partitioned IR: each SA region its own upload run clipped at next SA entry; SA pairs + one contiguous 0x114 ONE_INC run ~1270 words so SA+IR+calls ship in same <=2048-word block; static gsp_phys_gr_mme_ir_pack[4096]) - decisive offline: capture is sum of OVERLAPPING per-macro upload runs; run 34 (ptr=0x265, 75 words) == driver mmeCodeOGL_C597_DRAW_IAB word-for-word (0/75 diffs) but later runs overwrite its tail so capture-order image differs at 50/75 words; r1343/44 packed same-launch: MME-PRELUDE pack ir_words=937 runs=55 sa=54, held launch retires words=1515, first call-bearing launch words=1633 STILL POISONS in 8.7ms; unified failure 6 boots: MME-FAST end events=1 (poison) + ILLEGAL_OPCODE + ESR 0x404490=0x80000004 (bit2 NV_PGRAPH_PRI_MME_HWW_ESR, dev_graphics_nobundle.h:2046); r1340 nop_drop {48,51,57} 40x drops still faults {0,2,34,39,40}; r1341 block_cap=4096 words=3441/3623 never retire (block ceiling); sema_gl_mme_version=0 identical (version exonerated); GATE1 black 0/900 pages; next: macros' runtime STATE wrong - they branch on MME shadow-RAM STATE (slot-57 reads 0xd04..0xd2a) replay leaves zero + prelude's 6 non-SA/IR scratch writes (0x3470/0x34a8/0x3484) + client 0x124 mode not established; capture golden MME ctx state from real run and replay before calls; fallback per-boot nop_drop bisect {0,2,34,39,40} to name faulting macro then read g_tu100mmecode.h - SESSION 153 r1340-r1344 --- kernel/gsp_phys_booter.c | 168 ++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 167 insertions(+), 1 deletion(-) (limited to 'kernel') diff --git a/kernel/gsp_phys_booter.c b/kernel/gsp_phys_booter.c index 3d0aae2..114751d 100644 --- a/kernel/gsp_phys_booter.c +++ b/kernel/gsp_phys_booter.c @@ -18060,6 +18060,61 @@ module_param_named(sema_gl_mme_version, gsp_phys_rmcall_gr_mme_version, 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-99: IR-only prelude drain. The call-bearing launch + * must carry the macros' SA pairs + IR words IN THE SAME BLOCK as the + * CALL_MME_MACRO runs: the split drain ships the full 3083-word capture + * across two launches (r1337 W1/W2), so the calls only ever ran on a launch + * whose block held part of the program - and every such launch faults MME + * ILLEGAL_OPCODE (relayed ESR 0x404490=0x80000004) the moment the first + * CALL executes (r1336/r1337/r1339/r1340, four boots; with {48,51,57} + * dropped in r1340 the remaining {0,2,34,39,40} calls fault identically). + * Shipping the FULL capture in one block does not work either: the 3441- + * and 3623-word blocks of r1341 never retired at all (MME-FAST begin + * grfifo=0d0d0001/00000001, no ch_rel, timeout ladder). The SA pairs + + * IR-load runs of the whole capture are only ~1277 of the 3083 words; the + * remainder is the setup family the macros do not fetch. With this knob the + * drain emits ONLY the runs targeting the MME SA/IR ports (0x114/0x118/ + * 0x11c/0x120), whole runs, so a single <=2048-word block can carry SA+IR + * (1277) + SA re-arm + window and the calls execute against the program + * the same launch uploaded. Default 0 (A/B; the r1337 drain behavior). + */ +static bool gsp_phys_rmcall_gr_mme_prelude_ir_only; +module_param_named(sema_gl_mme_prelude_ir_only, + gsp_phys_rmcall_gr_mme_prelude_ir_only, bool, 0644); +MODULE_PARM_DESC(sema_gl_mme_prelude_ir_only, + "Emit only the MME SA/IR port runs (0x114/0x118/0x11c/0x120) from the prelude drain so SA+IR fit one working-size block (default 0)"); + +/* + * SESSION 153-CONTINUED-99b: packed (partitioned) prelude. The captured + * prelude buffer is the sum of the client's overlapping MME upload runs: + * each run writes its macro's body at its SA entry, and the runs overlap + * (runs for later slots rewrite shared tail regions). Replaying them + * verbatim in capture order therefore leaves the IR in a state where a + * macro's own body tail has been overwritten with the NEXT macro's bytes - + * executing it fetches non-code and the MME raises ILLEGAL_OPCODE + * (relayed ESR 0x404490=0x80000004; r1336/r1337/r1339/r1340/r1342, five + * boots). Verified against the driver's own generated macro source: the + * slot-34 run equals mmeCodeOGL_C597_DRAW_IAB word-for-word (75/75) but + * the capture-order final image differs at 50 of them. + * + * This knob rebuilds the program the way the engine must see it: each IR + * address takes the value from the run of the slot whose SA region owns it + * (run j clipped at the next SA entry), then emits the whole IR as ONE + * contiguous 0x114 ONE_INC run plus the full SA table as [slot, entry] + * pairs - about 1270 words, so a single <=2048-word block carries SA+IR + + * SA re-arm + window and the window's CALL_MME_MACRO runs execute against + * the program the same launch uploaded. Default 0 (capture-order drain). + */ +static bool gsp_phys_rmcall_gr_mme_prelude_pack; +module_param_named(sema_gl_mme_prelude_pack, + gsp_phys_rmcall_gr_mme_prelude_pack, bool, 0644); +MODULE_PARM_DESC(sema_gl_mme_prelude_pack, + "Rebuild the MME IR as the partitioned program (each SA region from its own run) and emit it compactly with the SA table (default 0)"); + +/* Packed IR image; indexed by IR word address (<= 0x420 in captures). */ +static u32 gsp_phys_gr_mme_ir_pack[4096]; + /* * SESSION 153-CONTINUED-86: the missing SPH (shader-program-header) state. * @@ -19133,7 +19188,100 @@ static u32 gsp_phys_rmcall_build_gr_launch(u32 *pb, * single-word entries skipped exactly like the legacy * sanitize (see gsp_phys_rmcall_gr_sdm_drop). */ - while (doff < pl_n && pwords + 1u <= room) { + /* + * SESSION 153-CONTINUED-99b: packed emission (see the + * sema_gl_mme_prelude_pack comment). Rebuild the + * partitioned IR, then emit the SA table + one + * contiguous 0x114 run; the drain loop is skipped. + */ + bool packed = false; + + if (READ_ONCE(gsp_phys_rmcall_gr_mme_prelude_pack)) { + u32 sa_ent[64]; + u64 sa_mask = gsp_sema_mme_sa_get(sa_ent, 64); + u32 maxa = 0, r = 0, nruns = 0, npair = 0; + u32 need, kk; + u32 *pp; + + memset(gsp_phys_gr_mme_ir_pack, 0, + sizeof(gsp_phys_gr_mme_ir_pack)); + while (r < pl_n) { + u32 h = pl[r]; + u32 op = (h >> 29) & 7u; + u32 cnt = (h >> 16) & 0xfffu; + u32 span = ((op == 1u || op == 3u || + op == 5u) && cnt && + r + 1u + cnt <= pl_n) ? + 1u + cnt : 1u; + + if (r + span > pl_n) + span = pl_n - r; + if (op == 5u && + ((h & 0x1fffu) << 2) == 0x114u && + cnt >= 2u) { + u32 ptr = pl[r + 1u]; + u32 blen = cnt - 1u; + u32 nxt = 0, k; + + for (kk = 0; kk < 64u; kk++) + if ((sa_mask & (1ull << kk)) && + sa_ent[kk] > ptr && + (!nxt || + sa_ent[kk] < nxt)) + nxt = sa_ent[kk]; + if (nxt && ptr + blen > nxt) + blen = nxt - ptr; + for (k = 0; k < blen && + ptr + k < 4096u; k++) + gsp_phys_gr_mme_ir_pack[ptr + k] = + pl[r + 2u + k]; + if (ptr + blen > maxa) + maxa = ptr + blen; + nruns++; + } + r += span; + } + for (kk = 0; kk < 64u; kk++) + if ((sa_mask & (1ull << kk)) && + sa_ent[kk]) + npair++; + need = 2u + maxa + 3u * npair; + if (maxa >= 3u && need <= room) { + pp = p; + for (kk = 0; kk < 64u; kk++) { + if (!(sa_mask & (1ull << kk)) || + !sa_ent[kk]) + continue; + *pp++ = ((u32) + GSP_PHYS_RMCALL_METHOD_IMM + << 29) | + (2u << 16) | + (0x11cu >> 2); + *pp++ = kk; + *pp++ = sa_ent[kk]; + } + *pp++ = ((u32) + GSP_PHYS_RMCALL_METHOD_ONEINC + << 29) | + ((maxa + 1u) << 16) | + (0x114u >> 2); + *pp++ = 0u; + memcpy(pp, + gsp_phys_gr_mme_ir_pack, + (size_t)maxa * 4u); + pp += maxa; + pwords = (u32)(pp - p); + p = pp; + doff = pl_n; + packed = true; + pr_info("vgsp-gr: MME-PRELUDE pack ir_words=%u runs=%u sa=%u h=0x%x push=0x%llx\n", + maxa, nruns, npair, + req->h_object, + req->push_va); + } + } + while (!packed && doff < pl_n && + pwords + 1u <= room) { u32 h = pl[doff]; u32 op = (h >> 29) & 7u; u32 cnt = (h >> 16) & 0xfffu; @@ -19150,6 +19298,24 @@ static u32 gsp_phys_rmcall_build_gr_launch(u32 *pb, doff += span; continue; } + /* + * SESSION 153-CONTINUED-99: IR-only drain (see + * the sema_gl_mme_prelude_ir_only comment). + * Keep only the runs aimed at the MME SA/IR + * ports; skip everything else with the same + * run-aligned accounting as the SDM drop. + */ + if (READ_ONCE( + gsp_phys_rmcall_gr_mme_prelude_ir_only)) { + u32 ma = (h & 0x1fffu) << 2; + + if (ma != 0x114u && ma != 0x118u && + ma != 0x11cu && ma != 0x120u) { + sdrop += span; + doff += span; + continue; + } + } if (pwords + span > room) break; memcpy(p, &pl[doff], (size_t)span * 4u); -- cgit v1.2.3