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.c134
1 files changed, 132 insertions, 2 deletions
diff --git a/kernel/gsp_phys_booter.c b/kernel/gsp_phys_booter.c
index 5ca854d..effff74 100644
--- a/kernel/gsp_phys_booter.c
+++ b/kernel/gsp_phys_booter.c
@@ -17645,6 +17645,34 @@ MODULE_PARM_DESC(sema_gl_mme_nop_drop,
"Slots whose call runs are dropped entirely (proven-safe retire, SA[slot] stubbed) instead of retargeted to the CALL_MME_DATA port (u64 bitmask; default 0)");
/*
+ * SESSION 153-CONTINUED-82: hold real CALL runs until the prelude latch.
+ * The r1220 (all-real, nop_drop=1<<57, sa_stub_all=N) wedge: the window's
+ * real CALL runs executed in the SAME launch that emitted only the first
+ * PART of a fresh capture generation (`MME-PRELUDE part gen=3 off=1776
+ * words=1776/3083 ... (continuation next launch)`), so the called macros
+ * fetched IR code that was not resident yet - `MME-FAST launch ...
+ * pc_valid=1 pc=513`, priv-error poison, `Shader Program Header 18 Error`,
+ * `Class Error ... Offset 0000238c, Data 00020020` (the r1116 lane-poison
+ * class) and the boot wedged. The prelude latch (gsp_phys_gr_mme_prelude_*
+ * gen/h) is set only when the FINAL part has gone out; with this knob the
+ * launch builder holds (elides, the proven-safe drop shape) every remaining
+ * CALL_MME_MACRO/DATA run of the emitted window while EITHER the latch for
+ * this generation+channel is not set after this launch, OR this launch
+ * uploaded generation code for the first time (latch invalid before the
+ * emission). The r1222 all-real boot proved the second clause necessary:
+ * the drain-completing launch (part-2 IR uploads + window real calls in the
+ * SAME block, latch set by its own emission) still hit ILLEGAL_OPCODE -
+ * real calls resume on the next launch, when only the idempotent keep-forced
+ * re-emission of the already-resident prefix is in flight. Default 1 (the
+ * fix); A/B with 0 to reproduce the r1209/r1220/r1222 wedge.
+ */
+static bool gsp_phys_rmcall_gr_mme_hold_calls = true;
+module_param_named(sema_gl_mme_hold_calls, gsp_phys_rmcall_gr_mme_hold_calls,
+ bool, 0644);
+MODULE_PARM_DESC(sema_gl_mme_hold_calls,
+ "Hold (elide) window CALL_MME_MACRO/DATA runs until the MME prelude latches for the current generation+channel (default 1; 0 = legacy, real calls run against a partial prelude)");
+
+/*
* The same stubbed-slot predicate the launch builder applies (see the
* sa_stub emit decision): a slot is stubbed when stubbing is on and either
* the all-slots knob is set, the capture holds no SA entry, or the IR
@@ -17939,6 +17967,9 @@ static u32 gsp_phys_rmcall_build_gr_launch(u32 *pb,
*/
bool emit_prelude = false;
bool pre_done = false;
+ bool mme_hold_calls = false;
+ bool latch_before = false;
+ u32 pre_words_out = 0;
const u32 *pl = NULL;
u32 pl_n = 0, pl_gen = 0, pl_room = 0;
u32 block_cap = READ_ONCE(gsp_phys_rmcall_gr_block_cap);
@@ -18159,6 +18190,23 @@ static u32 gsp_phys_rmcall_build_gr_launch(u32 *pb,
*/
u32 fixed = 2u + sa_block + win3d_n + 8u;
+ /*
+ * SESSION 153-CONTINUED-82: latch state BEFORE
+ * this launch's emission (see the hold decision
+ * below). A launch that first uploads a
+ * generation's MME code must not run real CALL
+ * runs in the same block (the r1222 evidence:
+ * the drain-completing launch bundled part-2's
+ * IR uploads with the window's real calls and
+ * hit ILLEGAL_OPCODE even though the latch was
+ * set by its own emission step).
+ */
+ latch_before =
+ (pl_gen == READ_ONCE(
+ gsp_phys_gr_mme_prelude_gen) &&
+ req->h_object == READ_ONCE(
+ gsp_phys_gr_mme_prelude_h));
+
pl_room = (fixed + 24u <= block_cap) ?
block_cap - fixed : 0u;
if (pl_room > pl_n)
@@ -18251,6 +18299,7 @@ static u32 gsp_phys_rmcall_build_gr_launch(u32 *pb,
}
WRITE_ONCE(gsp_phys_gr_mme_pre_emit_off, doff);
pre_done = (doff >= pl_n);
+ pre_words_out = pwords;
/* seqcheck: a mid-copy append must not be recorded as
* emitted (the copy may be a torn prefix). */
gsp_sema_mme_prelude_get(NULL, &g1);
@@ -18308,6 +18357,36 @@ static u32 gsp_phys_rmcall_build_gr_launch(u32 *pb,
}
}
/*
+ * SESSION 153-CONTINUED-82: hold real CALL runs until the
+ * prelude latch for this generation+channel is set (see the
+ * sema_gl_mme_hold_calls comment). Evaluated AFTER the
+ * emission step above, so a launch that completed the drain
+ * in this same block has just written the latch. Real calls
+ * stay held when EITHER
+ * - the latch for this generation+channel is not valid after
+ * this launch (partial drain, raced append, or a fresh
+ * generation whose code is not fully resident), or
+ * - this launch uploaded generation code for the FIRST time
+ * (emitted words with the latch invalid before the step) -
+ * the r1222 evidence: the drain-completing launch bundled
+ * part-2's IR uploads with the window's real calls and hit
+ * ILLEGAL_OPCODE even though its own emission set the
+ * latch. A later launch (latch already valid, only the
+ * idempotent keep-forced re-emission of the prefix) runs
+ * the real calls against the now-resident program.
+ */
+ if (pl && pl_n && pl_gen &&
+ READ_ONCE(gsp_phys_rmcall_gr_mme_prelude) &&
+ READ_ONCE(gsp_phys_rmcall_gr_mme_hold_calls)) {
+ u32 lg = READ_ONCE(gsp_phys_gr_mme_prelude_gen);
+ u32 lh = READ_ONCE(gsp_phys_gr_mme_prelude_h);
+ bool latch_after = (pl_gen == lg &&
+ req->h_object == lh);
+
+ mme_hold_calls = !latch_after ||
+ (pre_words_out && !latch_before);
+ }
+ /*
* SESSION 153-CONTINUED-63: emit the SA-RAM completion computed
* above - a one-instruction end-noop stub in the IR plus one
* ONE_INC 0x11c run loading [slot, stub] for every called slot
@@ -18481,8 +18560,59 @@ static u32 gsp_phys_rmcall_build_gr_launch(u32 *pb,
}
}
}
- memcpy(p, win3d, (size_t)win3d_n * 4);
- p += win3d_n;
+ if (mme_hold_calls) {
+ /*
+ * SESSION 153-CONTINUED-82: the prelude latch for
+ * this generation+channel is not set - elide every
+ * remaining CALL_MME_MACRO/DATA run of the window
+ * (the proven-safe drop shape; see the
+ * sema_gl_mme_hold_calls comment). Runs touching
+ * the MME macro method space 0x3800..0x39fc are the
+ * ones that execute a macro; the drop decision is
+ * the same walk gsp_phys_gr_mme_drop_calls uses.
+ */
+ u32 r = 0, w = 0, held = 0;
+
+ while (r < win3d_n) {
+ u32 h = win3d[r];
+ u32 op = (h >> 29) & 7u;
+ u32 cnt = (h >> 16) & 0xfffu;
+ u32 span = 1u;
+ bool iscall = false;
+ u32 k;
+
+ if ((op == 1u || op == 3u || op == 5u) &&
+ cnt && r + 1u + cnt <= win3d_n)
+ span = 1u + cnt;
+ for (k = 0; k < span; k++) {
+ u32 m = ((h & 0xfffu) << 2) +
+ 4u * k;
+
+ if (k && op != 1u && op != 3u)
+ break;
+ if (m >= 0x3800u && m <= 0x39fcu) {
+ iscall = true;
+ break;
+ }
+ }
+ if (iscall) {
+ held += span;
+ r += span;
+ continue;
+ }
+ memcpy(&p[w], &win3d[r], (size_t)span * 4u);
+ w += span;
+ r += span;
+ }
+ if (held)
+ pr_info("vgsp-gr: MME-CALL-HOLD %u word(s) of real CALL runs held (prelude gen=%u not latched for h=0x%x; window=%u->%u) push=0x%llx\n",
+ held, pl_gen, req->h_object,
+ win3d_n, w, req->push_va);
+ p += w;
+ } else {
+ memcpy(p, win3d, (size_t)win3d_n * 4);
+ p += win3d_n;
+ }
p = gsp_phys_rmcall_push_gr(p,
GSP_PHYS_RMCALL_GR_SET_REPORT_SEMAPHORE_A,
(u32)(sem_va >> 32));