From bbd3450baa544d8e25f2048cec6dee21bffac7b2 Mon Sep 17 00:00:00 2001 From: Arthur Hanson Rasmusson Date: Mon, 2 Nov 2026 15:22:04 -0500 Subject: vgsp: CONT-113 - clamp keep_mask to capture-covered slots (r1405 poison root cause) The r1405 priv-error wedge traced live: the draw window calls CALL_MME_MACRO(34)/(57) while the MME capture holds 13 SA slots (0..12, IR <= 0xe9); keep_mask=~0 exempted every slot from stubbing, so those calls ran, the MME fetched an instruction the packed program does not hold (info=badf1201 pc_valid=1 pc=513 mac=0x1f1 miss=1 ir=badf1201) and poisoned the lane; the second recovery's hard re-arm left the engine unresponsive (probe rc=-110, GP_GET frozen). Fix (one variable): gsp_phys_gr_slot_kept() - a keep_mask slot is only honored when the capture covers it (SA entry present AND its IR instruction entered the replay); otherwise the proven r1186 safe combination applies: SA stub + CALL-run drop, never a fetch of non-resident code. The decision reads the live SA table per window, so a later capture generation that covers the slot releases it automatically. Bounded MME-KEEP-CLAMP witness. Knob sema_gl_mme_keep_clamp (default 1; 0 = r1405 all-real A/B). --- kernel/gsp_phys_booter.c | 57 ++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 53 insertions(+), 4 deletions(-) diff --git a/kernel/gsp_phys_booter.c b/kernel/gsp_phys_booter.c index 6379894..2af384c 100644 --- a/kernel/gsp_phys_booter.c +++ b/kernel/gsp_phys_booter.c @@ -18180,6 +18180,31 @@ module_param_named(sema_gl_mme_keep_mask, gsp_phys_rmcall_gr_keep_mask, MODULE_PARM_DESC(sema_gl_mme_keep_mask, "Slots whose CALL_MME_MACRO/DATA runs are never dropped/stubbed (u64 bitmask; one slot at a time for macro re-enable)"); +/* + * SESSION 153-CONTINUED-113: clamp the keep mask to capture-covered slots. + * The r1405 poison anatomy (traced live): the draw window calls + * CALL_MME_MACRO(34) and CALL_MME_MACRO(57); the capture holds 13 SA slots + * (0..12, IR <= 0xe9) while keep_mask=~0 exempted every slot from stubbing, + * so the calls ran, the MME fetched a byte the packed program does not hold + * (`info=badf1201 pc_valid=1 pc=513 mac=0x1f1`, `miss=1`, ir=badf1201) and + * the priv-error wedge wiped the context; the second recovery's hard re-arm + * left the engine unresponsive (probe rc=-110) and GP_GET frozen for the + * boot. A kept slot the capture cannot serve can only ever fetch + * non-resident code: the CONT-80 r1186 note already pairs "drop the runs + + * stub SA[slot]" as the safe combination for a nop_drop slot - apply the + * same combination to any kept slot outside the capture's coverage. The + * decision reads the live SA table per window, so a later capture + * generation that covers the slot releases it automatically. Default 1 + * (keep_clamp); 0 = the r1405 all-real behavior (A/B). + */ +static bool gsp_phys_rmcall_gr_keep_clamp = true; +module_param_named(sema_gl_mme_keep_clamp, gsp_phys_rmcall_gr_keep_clamp, + bool, 0644); +MODULE_PARM_DESC(sema_gl_mme_keep_clamp, + "Clamp kept slots to capture-covered slots: a keep_mask slot with no captured SA entry (or uncovered IR) is stubbed + its CALL runs dropped instead of fetching non-resident code (default 1)"); + +static u32 gsp_phys_gr_keep_clamp_log; + /* * SESSION 153-CONTINUED-79: per-launch method-block word cap + prelude drain. * The r1172-r1175 A/B: every beef launch whose emitted block exceeded ~2000 @@ -18969,8 +18994,28 @@ MODULE_PARM_DESC(sema_gl_mme_sa_rearm, * 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 * instruction the entry names never entered the replay. A kept slot - * (sema_gl_mme_keep_mask) is never stubbed. + * (sema_gl_mme_keep_mask) is never stubbed - unless the capture cannot + * serve it at all (keep_clamp, see the CONT-113 param comment). */ +static bool gsp_phys_gr_slot_kept(u32 j, u64 sa_mask, const u32 *sa_ent) +{ + if (!(READ_ONCE(gsp_phys_rmcall_gr_keep_mask) & (1ull << j))) + return false; + if (READ_ONCE(gsp_phys_rmcall_gr_nop_drop) & (1ull << j)) + return false; + if (!READ_ONCE(gsp_phys_rmcall_gr_keep_clamp)) + return true; + if ((sa_mask & (1ull << j)) && gsp_sema_mme_ir_covered(sa_ent[j])) + return true; + if (gsp_phys_gr_keep_clamp_log < 16u) { + gsp_phys_gr_keep_clamp_log++; + pr_warn("vgsp-gr: MME-KEEP-CLAMP slot=%u (keep_mask set but capture has no SA entry/coverage; stubbed + calls dropped, never run) entry=0x%x covered=%u\n", + j, sa_ent[j], + (unsigned)gsp_sema_mme_ir_covered(sa_ent[j])); + } + return false; +} + static bool gsp_phys_gr_slot_stubbed(u32 j, u64 sa_mask, const u32 *sa_ent) { if (j >= 64u || !gsp_sema_gr_sa_stub_value()) @@ -18985,7 +19030,7 @@ static bool gsp_phys_gr_slot_stubbed(u32 j, u64 sa_mask, const u32 *sa_ent) */ if (READ_ONCE(gsp_phys_rmcall_gr_nop_drop) & (1ull << j)) return true; - if (READ_ONCE(gsp_phys_rmcall_gr_keep_mask) & (1ull << j)) + if (gsp_phys_gr_slot_kept(j, sa_mask, sa_ent)) return false; if (READ_ONCE(gsp_phys_rmcall_gr_sa_stub_all)) return true; @@ -19427,9 +19472,13 @@ static u32 gsp_phys_rmcall_build_gr_launch(u32 *pb, * client's own SA/IR uploads left it. * Logged in the covered list for the * census; no stub pair is emitted. + * SESSION 153-CONTINUED-113: unless + * the capture cannot serve it at all + * (keep_clamp) - then it falls into + * the stub + call-drop path below. */ - if (READ_ONCE(gsp_phys_rmcall_gr_keep_mask) & - (1ull << j)) { + if (gsp_phys_gr_slot_kept(j, sa_mask, + sa_ent)) { for (t = 0; t < sa_ncov; t++) if (sa_cov[t] == j) have = true; -- cgit v1.2.3