summaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'kernel')
-rw-r--r--kernel/gsp_phys_booter.c168
1 files changed, 167 insertions, 1 deletions
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
@@ -18061,6 +18061,61 @@ 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.
*
* The executed beef launches fault `Graphics Exception: Shader Program
@@ -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);