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.c80
1 files changed, 78 insertions, 2 deletions
diff --git a/kernel/gsp_phys_booter.c b/kernel/gsp_phys_booter.c
index 96d4c59..bb75a8c 100644
--- a/kernel/gsp_phys_booter.c
+++ b/kernel/gsp_phys_booter.c
@@ -16789,8 +16789,12 @@ EXPORT_SYMBOL_GPL(gsp_phys_backend_guest_ce_copy);
#define GSP_PHYS_RMCALL_PRI_SKED_DEBUG_1 0x00407040u
#define GSP_PHYS_RMCALL_PRI_SKED_DEBUG_1_EN_CWD_SLOT_COUNT 0x800u
/* Method block bound: init(152) + inline run(67) + PCAS(4) + REPORT_SEM(8) +
- * the optional QMD-virt pair(2). */
-#define GSP_PHYS_RMCALL_GR_METHOD_WORDS 512u
+ * the optional QMD-virt pair(2). Raised 512 -> 1024 (SESSION 153-
+ * CONTINUED-53) so a 3D stream replay can carry the captured MME setup
+ * prelude (<=512 words) ahead of the largest chunked window (<=448) in one
+ * block; the block still lands inside the one 4 KB chunk page it is copied
+ * to. */
+#define GSP_PHYS_RMCALL_GR_METHOD_WORDS 1024u
static u64 gsp_phys_gr_submitted;
static u64 gsp_phys_gr_ok;
@@ -17106,6 +17110,26 @@ MODULE_PARM_DESC(gsp_phys_rmcall_gr_3d,
"Replay a captured raw C597 method window verbatim instead of the compute prelude (default 1)");
/*
+ * SESSION 153-CONTINUED-53: MME context-setup prelude. The r1073-r1077
+ * in-flight capture proved the draw-window replay raises a real MME
+ * ILLEGAL_OPCODE on CALL_MME_MACRO(2)=0x3810 (mme_pc=0, mme_ir=1, mme_mac
+ * =2) because the ladder context never received the client's macro
+ * program. The client does upload it (0x11c/0x114 pointer pairs, 0x118
+ * code, 0x120 entry addresses, 0x124 shadow control; see
+ * svc_mme_prelude_capture); with this knob the launch builder preplays
+ * those captured runs verbatim - once per capture generation - right
+ * after the SET_OBJECT C597 bind and ahead of the window, so the macros
+ * the window calls are resident. Declared before build_gr_launch (its
+ * reader); the matching capture-side knob is sema_mme_prelude_cap.
+ * Default 1; A/B with 0.
+ */
+static bool gsp_phys_rmcall_gr_mme_prelude = true;
+module_param_named(sema_gl_mme_prelude, gsp_phys_rmcall_gr_mme_prelude, bool,
+ 0644);
+MODULE_PARM_DESC(sema_gl_mme_prelude,
+ "Preplay the captured client MME context-setup runs once per capture generation ahead of the first 3D window replay (default 1)");
+
+/*
* GR launch method block: the inline QMD run at its original shape and the
* channel REPORT_SEMAPHORE release. The stock guest push does NOT emit
* SET_OBJECT before the inline run (the compute class is bound on the
@@ -17137,10 +17161,59 @@ static u32 gsp_phys_rmcall_build_gr_launch(u32 *pb,
*/
if (gsp_phys_rmcall_gr_3d && req && win3d && win3d_n &&
win3d_n + 2u + 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
+ * setup runs once per capture generation, right after the
+ * SET_OBJECT C597 bind and ahead of the window, so
+ * CALL_MME_MACRO() runs execute against a loaded macro
+ * program instead of pc=0 -> ILLEGAL_OPCODE. The read is
+ * seqchecked (generation before/after): a concurrent append
+ * only defers emission to the next launch. A window too large
+ * to also carry the prelude replays without it (logged) - the
+ * emission then happens on the next launch that fits.
+ */
+ static u32 mme_prelude_emitted_gen;
+ bool emit_prelude = false;
+ const u32 *pl = NULL;
+ u32 pl_n = 0, pl_gen = 0;
+
+ if (READ_ONCE(gsp_phys_rmcall_gr_mme_prelude)) {
+ pl = gsp_sema_mme_prelude_get(&pl_n, &pl_gen);
+ if (pl && pl_n && pl_gen &&
+ pl_gen != READ_ONCE(mme_prelude_emitted_gen)) {
+ if (win3d_n + 2u + 8u + pl_n <=
+ GSP_PHYS_RMCALL_GR_METHOD_WORDS) {
+ emit_prelude = true;
+ } else {
+ pr_info("vgsp-gr: MME-PRELUDE deferred (window=%u prelude=%u exceeds block; replaying window alone) h=0x%x\n",
+ win3d_n, pl_n, req->h_object);
+ }
+ }
+ }
+
*p++ = ((u32)GSP_PHYS_RMCALL_METHOD_IMM << 29) | (1u << 16) |
(0u << 13) |
(GSP_PHYS_RMCALL_GR_SET_OBJECT >> 2);
*p++ = GSP_PHYS_RMCALL_CLASS_GR_3D;
+ if (emit_prelude) {
+ u32 g0 = pl_gen, g1 = 0;
+
+ memcpy(p, pl, (size_t)pl_n * 4);
+ p += pl_n;
+ /* 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);
+ if (g1 == g0) {
+ WRITE_ONCE(mme_prelude_emitted_gen, g0);
+ pr_info("vgsp-gr: MME-PRELUDE emitted gen=%u words=%u window=%u h=0x%x push=0x%llx\n",
+ g0, pl_n, win3d_n, req->h_object,
+ req->push_va);
+ } else {
+ pr_info("vgsp-gr: MME-PRELUDE copy raced an append (gen %u->%u); emitted words=%u, will re-emit next launch\n",
+ g0, g1, pl_n);
+ }
+ }
memcpy(p, win3d, (size_t)win3d_n * 4);
p += win3d_n;
p = gsp_phys_rmcall_push_gr(p,
@@ -19728,6 +19801,9 @@ module_param_named(sema_gl_mme_reloc, gsp_phys_rmcall_gr_mme_reloc, bool, 0644);
MODULE_PARM_DESC(sema_gl_mme_reloc,
"Relocate CALL_MME_MACRO/DATA(j) run payload words whose page resolves in the launch page set to shadow VAs in 3D replays (default 0 = off)");
+/* (SESSION 153-CONTINUED-53 MME prelude knob is declared before
+ * gsp_phys_rmcall_build_gr_launch, its reader.) */
+
/*
* SESSION 153-CONTINUED-48: ladder-wedge recovery. CONT-47 measured that
* the FIRST beef launch per boot whose window carries an unresolvable raw