summaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'kernel')
-rw-r--r--kernel/gsp_phys_booter.c286
-rw-r--r--kernel/gsp_sema_service.c79
-rw-r--r--kernel/gsp_sema_service.h10
3 files changed, 362 insertions, 13 deletions
diff --git a/kernel/gsp_phys_booter.c b/kernel/gsp_phys_booter.c
index eba0305..7f41df6 100644
--- a/kernel/gsp_phys_booter.c
+++ b/kernel/gsp_phys_booter.c
@@ -5047,6 +5047,7 @@ static void gsp_phys_pbdma_fault_dump(u32 chid)
u32 trig;
const char *trig_src;
s64 off_words = -1;
+ s64 voff = -1;
if (!intr0 && !pbf && !hdrsh && !pbhd)
continue;
@@ -5073,8 +5074,20 @@ static void gsp_phys_pbdma_fault_dump(u32 chid)
fetch64 < gsp_phys_gr_last_pb_dma +
(u64)gsp_phys_gr_last_words * 4u)
off_words = (s64)(fetch64 - gsp_phys_gr_last_pb_dma) / 4;
- pr_info("vgsp-gr: PB-FAULT-DUMP P%u intr0=%08x gpf=%u pbfetch=0x%llx len=%u off=%lld hdr=%08x(%s m=0x%x cnt=%u sub=%u) cnt=%08x data0=%08x shadow=%08x pbhd=%08x(type=%s) TRIG=%08x(%s)\n",
- i, intr0, gpf, fetch64, pbfhi >> 11, off_words,
+ /*
+ * SESSION 153-CONTINUED-59: the SAME offset computed against
+ * the GPU VA the engine fetches (the r1102 WINPROBE/PB-FAULT
+ * agreement: pbfetch 0x101ebc with pb_va 0x101000 and 943
+ * words = exactly the block end). voff >= words is the
+ * past-the-block-end prefetch position.
+ */
+ voff = (s64)-1;
+ if (pb_va && fetch64 >= pb_va &&
+ fetch64 < pb_va + (u64)GSP_PHYS_PAGE_SIZE)
+ voff = (s64)(fetch64 - pb_va) / 4;
+ pr_info("vgsp-gr: PB-FAULT-DUMP P%u intr0=%08x gpf=%u pbfetch=0x%llx len=%u off=%lld voff=%lld/%u hdr=%08x(%s m=0x%x cnt=%u sub=%u) cnt=%08x data0=%08x shadow=%08x pbhd=%08x(type=%s) TRIG=%08x(%s)\n",
+ i, intr0, gpf, fetch64, pbfhi >> 11, off_words, voff,
+ gsp_phys_gr_last_words,
hdrsh, gsp_phys_pbdma_type_name(hdrsh >> 29),
(hdrsh & 0x1fffu) << 2,
(hdrsh >> 16) & 0xfffu, (hdrsh >> 13) & 7u,
@@ -5105,6 +5118,34 @@ static void gsp_phys_pbdma_fault_dump(u32 chid)
w + 12 < n ? pw[w + 12] : 0, w + 13 < n ? pw[w + 13] : 0,
w + 14 < n ? pw[w + 14] : 0, w + 15 < n ? pw[w + 15] : 0);
}
+ /*
+ * SESSION 153-CONTINUED-59: the block TAIL and the
+ * words PAST the block end (the r1102 fault fetch
+ * sits exactly at the end - voff == words). The past
+ * words are what a prefetching PBDMA decodes next;
+ * the tail shows whether the block itself ends at an
+ * entry boundary.
+ */
+ {
+ u32 words = gsp_phys_gr_last_words;
+ u32 lo = words > 48u ? words - 48u : 0u;
+ u32 hi = words + 32u;
+
+ if (hi > 1024u)
+ hi = 1024u;
+ for (w = lo; w < hi; w += 16) {
+ pr_info("vgsp-gr: PB-FAULT-DUMP %s[%3u]= %08x %08x %08x %08x %08x %08x %08x %08x %08x %08x %08x %08x %08x %08x %08x %08x\n",
+ w < words ? "tail" : "past", w,
+ pw[w], w + 1 < 1024u ? pw[w + 1] : 0,
+ w + 2 < 1024u ? pw[w + 2] : 0, w + 3 < 1024u ? pw[w + 3] : 0,
+ w + 4 < 1024u ? pw[w + 4] : 0, w + 5 < 1024u ? pw[w + 5] : 0,
+ w + 6 < 1024u ? pw[w + 6] : 0, w + 7 < 1024u ? pw[w + 7] : 0,
+ w + 8 < 1024u ? pw[w + 8] : 0, w + 9 < 1024u ? pw[w + 9] : 0,
+ w + 10 < 1024u ? pw[w + 10] : 0, w + 11 < 1024u ? pw[w + 11] : 0,
+ w + 12 < 1024u ? pw[w + 12] : 0, w + 13 < 1024u ? pw[w + 13] : 0,
+ w + 14 < 1024u ? pw[w + 14] : 0, w + 15 < 1024u ? pw[w + 15] : 0);
+ }
+ }
}
}
}
@@ -17110,6 +17151,31 @@ 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-59: drop single-word SDM-type entries (SEC_OP 0
+ * SSDM / 2 STORE_SDM / 6 USE_SDM, tu102 dev_esched_pbdma.h type map) from
+ * every replayed stream: the 3D window patch, the MME prelude and the attr
+ * prelude emission. The r1102 PBENTRY first-sighting forensics localized
+ * the fault decode point to the MME prelude head (WINPROBE/PB-FAULT-DUMP
+ * P0 HDR_SHADOW=04666d14 = prelude[2], PB_DATA0=04646d00 = prelude[3],
+ * pbfetch=0x101ebc = block end after the whole 943-word block was
+ * prefetched, intr0 bit 18 in the guest relay): the client's setup push
+ * carries a 21-word run of `04666d00 04666d10 04666d14 04646d00 ...`
+ * (SDM-family single-word encodings, method fields 0x3400/0x3440/0x3450)
+ * that svc_mme_prelude_capture stored verbatim; the physical PBDMA refuses
+ * them ("invalid method encoding used in method", NV_PPBDMA_INTR_0
+ * PBENTRY), which also explains why the whole block was fetched but the
+ * REPORT_SEMAPHORE never retired. The guest-vGPU parts (subdevice masks)
+ * are meaningless on the single-subdevice ladder channel - the same call
+ * the sub!=0 multi-word drop makes. Zero words are kept (benign padding).
+ * Default 1; A/B with 0.
+ */
+static bool gsp_phys_rmcall_gr_sdm_drop = true;
+module_param_named(sema_gl_sdm_drop, gsp_phys_rmcall_gr_sdm_drop, bool,
+ 0644);
+MODULE_PARM_DESC(sema_gl_sdm_drop,
+ "Drop single-word SDM-type entries (SEC_OP 0/2/6) from 3D window replays, the MME prelude and the attr 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
@@ -17236,18 +17302,50 @@ static u32 gsp_phys_rmcall_build_gr_launch(u32 *pb,
(GSP_PHYS_RMCALL_GR_SET_OBJECT >> 2);
*p++ = GSP_PHYS_RMCALL_CLASS_GR_3D;
if (emit_prelude) {
- u32 g0 = pl_gen, g1 = 0;
+ u32 g0 = pl_gen, g1 = 0, sdrop = 0, pwords = pl_n;
- memcpy(p, pl, (size_t)pl_n * 4);
- p += pl_n;
+ if (READ_ONCE(gsp_phys_rmcall_gr_sdm_drop)) {
+ u32 r = 0, w = 0;
+
+ /*
+ * SESSION 153-CONTINUED-59: SDM sanitize (see the
+ * gsp_phys_rmcall_gr_sdm_drop comment). Walk the
+ * prelude verbatim but drop single-word SDM-family
+ * encodings; they are the r1102 PBENTRY offenders.
+ */
+ 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 (h && (op == 0u || op == 2u ||
+ op == 6u)) {
+ sdrop++;
+ r += span;
+ continue;
+ }
+ memcpy(&p[w], &pl[r], (size_t)span * 4u);
+ w += span;
+ r += span;
+ }
+ p += w;
+ pwords = w;
+ } else {
+ 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);
+ pr_info("vgsp-gr: MME-PRELUDE emitted gen=%u words=%u window=%u h=0x%x push=0x%llx sdm_drop=%u\n",
+ g0, pwords, win3d_n, req->h_object,
+ req->push_va, sdrop);
} 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);
@@ -17286,6 +17384,18 @@ static u32 gsp_phys_rmcall_build_gr_launch(u32 *pb,
if (off + span > attr_pre_n)
span = attr_pre_n - off;
+ /*
+ * SESSION 153-CONTINUED-59: the same SDM
+ * sanitize as the MME prelude (see
+ * gsp_phys_rmcall_gr_sdm_drop); the cursor
+ * still advances so the drop is permanent.
+ */
+ if (READ_ONCE(gsp_phys_rmcall_gr_sdm_drop) &&
+ hdr && (op == 0u || op == 2u ||
+ op == 6u)) {
+ off += span;
+ continue;
+ }
if (copied + span > avail)
break;
memcpy(&p[copied], &attr_pre[off],
@@ -19793,6 +19903,23 @@ static u64 gsp_phys_gr_surf_dummy_dma_locked(void)
* verbatim (it faults later and is named in the drain). Called with
* gsp_phys_rm_lock held.
*/
+/*
+ * SESSION 153-CONTINUED-59: window/attr operand-miss state for the
+ * pre-doorbell abort (see gsp_phys_rmcall_gr_3d_reloc's level-2 fallback
+ * and the MISS-ABORT site in gsp_phys_backend_guest_gr_submit). Reset at
+ * the start of each 3D-window patch pass; a nonzero count at the submit
+ * point means the emitted block still carries a raw client VA the physical
+ * engine cannot resolve, which is the r1104/r1105 lane-killing class.
+ * sema_gl_miss_abort=0 restores the historical submit-anyway behaviour.
+ */
+static u32 gsp_phys_rmcall_gr_3d_miss_n;
+static bool gsp_phys_rmcall_gr_miss_abort = true;
+static u64 gsp_phys_gr_miss_abort_n;
+module_param_named(sema_gl_miss_abort, gsp_phys_rmcall_gr_miss_abort, bool,
+ 0644);
+MODULE_PARM_DESC(sema_gl_miss_abort,
+ "Abort a 3D-window launch before the doorbell while a window/attr operand relocation MISSes (page demanded via the pin path; retried on the next forward; fail-open after 3000 aborts). Default 1");
+
static bool gsp_phys_rmcall_gr_3d_reloc(u32 *up_w, u32 *lo_w,
const struct gsp_phys_gr_submit *req,
u32 *n_shadow)
@@ -19841,6 +19968,40 @@ static bool gsp_phys_rmcall_gr_3d_reloc(u32 *up_w, u32 *lo_w,
*up_w = (*up_w & ~0xffu) | ((u32)(sh >> 32) & 0xffu);
return true;
}
+ /*
+ * SESSION 153-CONTINUED-59: level-2 late resolution, the same trusted
+ * chain the MME payload branch uses (ipin/pin/lat/map/walk then shadow
+ * map). The r1104 first beat window MISSed the program pair 0x2054
+ * (va=0x4350900) and the r1105 windows MISSed the index-buffer pairs
+ * (0x17c8, va=0x44fedf0...) whose pages were not in the launch page
+ * set at build time; the raw guest VA then let the engine fault the
+ * MMU (HUBCLIENT_PD) and the guest driver reset the channel. Resolve
+ * the page here if any stage knows it, so a MISS only survives when
+ * every source fails; a surviving MISS is recorded for the pin demand
+ * set and counts toward the pre-doorbell abort.
+ */
+ {
+ struct gsp_sema_gr_reloc r;
+ u32 line2 = 0;
+
+ if (!gsp_sema_gr_reloc_resolve(va, &r) && r.hpa &&
+ *n_shadow < GSP_PHYS_RMCALL_GR_SHADOW_PAGES &&
+ !gsp_phys_rmcall_gr_map_shadow_locked(*n_shadow, r.hpa,
+ &sh, &line2)) {
+ if (line2 != 0xffffffffu)
+ (*n_shadow)++;
+ sh |= va & (GSP_PHYS_PAGE_SIZE - 1);
+ *lo_w = (*lo_w & 0x3u) | ((u32)sh & 0xfffffffcu);
+ *up_w = (*up_w & ~0xffu) | ((u32)(sh >> 32) & 0xffu);
+ return true;
+ }
+ }
+ /*
+ * Unresolvable: demand the page for the pin path and count the miss
+ * (the submit path aborts pre-doorbell while the count is nonzero).
+ */
+ gsp_phys_rmcall_gr_3d_miss_n++;
+ gsp_sema_demand_note(page);
return false;
}
@@ -20190,13 +20351,14 @@ static bool gsp_phys_rmcall_gr_win_patch_find(u32 addr, u32 *out_data)
}
static u32 gsp_phys_rmcall_gr_3d_last_subdrop;
+static u32 gsp_phys_rmcall_gr_3d_last_sdmdrop;
static u32 gsp_phys_rmcall_gr_3d_patch_window(const u32 *in, u32 n, u32 *out,
u32 *out_n, u32 *n_dropped,
const struct gsp_phys_gr_submit *req,
u32 *n_shadow)
{
- u32 off = 0, wout = 0, reloc = 0, dropped = 0, subdrop = 0;
+ u32 off = 0, wout = 0, reloc = 0, dropped = 0, subdrop = 0, sdm_drop = 0;
*out_n = n;
*n_dropped = 0;
@@ -20237,6 +20399,21 @@ static u32 gsp_phys_rmcall_gr_3d_patch_window(const u32 *in, u32 n, u32 *out,
off += span;
continue;
}
+ /*
+ * SESSION 153-CONTINUED-59: single-word SDM-type entries
+ * (SEC_OP 0/2/6, see gsp_phys_rmcall_gr_sdm_drop). The
+ * retiring X-family windows never yield one; this guards a
+ * window that carries the client's SDM markers (the
+ * 0x1fff0-class marker words or the prelude 0x046x6dXX
+ * family), which the physical PBDMA refuses with PBENTRY.
+ */
+ if (READ_ONCE(gsp_phys_rmcall_gr_sdm_drop) &&
+ hdr && (op == 0u || op == 2u || op == 6u)) {
+ dropped++;
+ sdm_drop++;
+ off += span;
+ continue;
+ }
if (gsp_phys_rmcall_gr_win_drop_match(addr) ||
gsp_phys_rmcall_gr_win_drop_auto_match(addr)) {
dropped++;
@@ -20553,6 +20730,7 @@ static u32 gsp_phys_rmcall_gr_3d_patch_window(const u32 *in, u32 n, u32 *out,
*out_n = wout;
*n_dropped = dropped;
gsp_phys_rmcall_gr_3d_last_subdrop = subdrop;
+ gsp_phys_rmcall_gr_3d_last_sdmdrop = sdm_drop;
return reloc;
}
@@ -22029,15 +22207,19 @@ gr_page_unmapped:
*/
gsp_phys_gr_surface_alias_scan_locked(req->stream,
req->stream_n, req);
+ /* SESSION 153-CONTINUED-59: fresh miss census for this pass
+ * (window + attr patch below both feed it). */
+ gsp_phys_rmcall_gr_3d_miss_n = 0;
nrel = gsp_phys_rmcall_gr_3d_patch_window(
req->stream, req->stream_n, stream_patch, &win_n,
&ndrop, req, &n_shadow);
win3d = stream_patch;
win3d_n = win_n;
- pr_info("vgsp-gr: 3D window relocated %u operand pair(s) to shadow VAs (window=%u shadow=%u dropped=%u subdrop=%u)\n",
+ pr_info("vgsp-gr: 3D window relocated %u operand pair(s) to shadow VAs (window=%u shadow=%u dropped=%u subdrop=%u sdmdrop=%u)\n",
nrel, win3d_n, n_shadow, ndrop,
- gsp_phys_rmcall_gr_3d_last_subdrop);
+ gsp_phys_rmcall_gr_3d_last_subdrop,
+ gsp_phys_rmcall_gr_3d_last_sdmdrop);
/*
* SESSION 153-CONTINUED-57: patch the attr/pipeline prelude for
* this launch (relocation exactly like the window: the
@@ -22086,6 +22268,39 @@ gr_page_unmapped:
}
}
/*
+ * SESSION 153-CONTINUED-59: pre-doorbell MISS abort (see the
+ * gsp_phys_rmcall_gr_miss_abort comment). A window/attr
+ * operand whose relocation stayed a raw client VA after the
+ * level-2 resolver would make the physical engine read an
+ * unmapped page (r1104 MMU Fault HUBCLIENT_PD @0x4350000 ->
+ * guest channel reset; r1105 index-buffer misses). Ride the
+ * same failure path as RELOC-GAP-STRICT: the launch is not
+ * submitted, the caller falls back and authors the software
+ * release, the page is already in the pin demand set, and
+ * the next forward retries. Bounded: after 3000 aborts the
+ * check fails open so a page the resolver can never see
+ * cannot livelock the lane forever.
+ */
+ if (READ_ONCE(gsp_phys_rmcall_gr_miss_abort) &&
+ gsp_phys_rmcall_gr_3d_miss_n &&
+ gsp_phys_gr_miss_abort_n < 3000u) {
+ static u32 miss_abort_log;
+
+ gsp_phys_gr_miss_abort_n++;
+ if (miss_abort_log < 16u ||
+ !(gsp_phys_gr_miss_abort_n % 256u)) {
+ miss_abort_log++;
+ pr_info("vgsp-gr: MISS-ABORT h=0x%x push=0x%llx miss=%u n=%llu (operand page unresolvable; demanded via pin path, launch not submitted - retry next forward)\n",
+ req->h_object, req->push_va,
+ gsp_phys_rmcall_gr_3d_miss_n,
+ gsp_phys_gr_miss_abort_n);
+ }
+ mutex_unlock(&gsp_phys_rm_lock);
+ gsp_phys_gr_refused++;
+ ret = -EAGAIN;
+ goto out;
+ }
+ /*
* SESSION 153-CONTINUED-56: bounded RAW (pre-drop, pre-reloc)
* window dump so the emitted window can be diffed against the
* client's authentic bytes. r1091 faulted at method 0x1168
@@ -22753,6 +22968,55 @@ gr_page_unmapped:
w0 = READ_ONCE(*(u32 *)sem_va);
}
/*
+ * SESSION 153-CONTINUED-59: PBENTRY first-sighting watch.
+ * The r1102 fault was only captured via the GSP's 0x1006
+ * relay (seconds later, intr0 already cleared by the RM):
+ * here every 5 ms poll of a 3D-stream launch scans the 12
+ * PBDMA instances for NV_PPBDMA_INTR_0 bit 18 (PBENTRY) and
+ * on the FIRST sighting dumps the live PB_HEADER / PB_COUNT
+ * / PB_DATA0 / HDR_SHADOW set plus the raw 0x100..0x120
+ * block for the faulting instance, before any re-arm or RM
+ * clear can overwrite them. Bounded (8 lines per boot);
+ * read-only, no behavior change to the launch.
+ */
+ if (stream3d && bar0) {
+ static u32 pbentry_log;
+ u32 pi2;
+
+ for (pi2 = 0; pi2 < 12 && pbentry_log < 8; pi2++) {
+ u32 b2 = 0x40000u + pi2 * 0x2000u;
+ u32 i0 = ioread32(bar0 + b2 + 0x108u);
+
+ if (!(i0 & 0x00040000u))
+ continue;
+ pbentry_log++;
+ pr_warn("vgsp-gr: PBENTRY-FIRST-SIGHTING P%u intr0=%08x gpf=%u pbfetch=0x%llx hdr=%08x cnt=%08x data0=%08x pbhd=%08x h=%x push=0x%llx words=%u tick=%u\n",
+ pi2, i0,
+ ioread32(bar0 + b2 + 0x050u),
+ ((u64)(ioread32(bar0 + b2 + 0x058u) &
+ 0xffu) << 32) |
+ (ioread32(bar0 + b2 + 0x054u) &
+ ~3u),
+ ioread32(bar0 + b2 + 0x118u),
+ ioread32(bar0 + b2 + 0x088u),
+ ioread32(bar0 + b2 + 0x08cu),
+ ioread32(bar0 + b2 + 0x084u),
+ req->h_object, req->push_va, words,
+ sked_tick);
+ pr_info("vgsp-gr: PBENTRY-FIRST-SIGHTING P%u raw[0x100]=%08x [104]=%08x [10c]=%08x [110]=%08x [114]=%08x [11c]=%08x [120]=%08x\n",
+ pi2,
+ ioread32(bar0 + b2 + 0x100u),
+ ioread32(bar0 + b2 + 0x104u),
+ ioread32(bar0 + b2 + 0x10cu),
+ ioread32(bar0 + b2 + 0x110u),
+ ioread32(bar0 + b2 + 0x114u),
+ ioread32(bar0 + b2 + 0x11cu),
+ ioread32(bar0 + b2 + 0x120u));
+ gsp_phys_pbdma_fault_dump(0xffffffffu);
+ break;
+ }
+ }
+ /*
* SESSION 153-CONTINUED-13: early PBDMA fetch probe for a 3D
* stream launch - where is the front end while a DRAW window
* does not retire? One shot per launch at ~150 ms and ~1.2 s
diff --git a/kernel/gsp_sema_service.c b/kernel/gsp_sema_service.c
index b7897d8..11f4f46 100644
--- a/kernel/gsp_sema_service.c
+++ b/kernel/gsp_sema_service.c
@@ -1591,6 +1591,20 @@ static void svc_setup_demand_record(u64 va)
}
/*
+ * SESSION 153-CONTINUED-59: cross-file entry for the GR launch builder (see
+ * gsp_sema_service.h). Records the page of a VA whose window/attr operand
+ * relocation MISSed, so the pin demand path fetches it before the next
+ * forward; the builder then either resolves it (RELOC level-2 fallback) or
+ * aborts the launch pre-doorbell instead of letting the engine read a raw
+ * unmapped guest VA (the r1104 MMU Fault HUBCLIENT_PD class).
+ */
+void gsp_sema_demand_note(u64 va)
+{
+ if (va)
+ svc_setup_demand_record(va & ~(u64)0xfffu);
+}
+
+/*
* Read-only view of the setup-hold demand set for the pin tool:
* # sema setup-hold demand VAs (page-aligned): N
* 0x4021000
@@ -14215,6 +14229,18 @@ static void svc_attr_prelude_note_ptr(u64 va)
(va & ~(u64)0xfffu))
return;
svc_attr_prelude_ptr[svc_attr_prelude_ptr_n++] = va;
+ /*
+ * SESSION 153-CONTINUED-59: demand the program page NOW. The r1104
+ * first beat window MISSed its 0x2054 pair operand (va=0x4350900)
+ * because the page did not resolve at the launch fill; the engine
+ * read it raw -> MMU Fault HUBCLIENT_PD @0x4350000 -> the guest
+ * driver reset the channel and the lane died for the boot. Recording
+ * the page in the pin-demand set here (at capture time, often
+ * minutes before the first launch) lets pin_gr_stream demand it in
+ * the guest so the launch fill's note resolves. See also the
+ * sema_attr_settle_ms launch gate.
+ */
+ svc_setup_demand_record(va & ~(u64)0xfffu);
}
static void svc_attr_prelude_capture(const u8 *buf, u32 len, u64 push_va,
@@ -31162,12 +31188,61 @@ static unsigned long svc_gr_prelude_gate_j;
static u64 svc_gr_prelude_gate_defer;
static u64 svc_gr_prelude_gate_exp;
-static bool svc_gr_prelude_gate_active(const struct svc_channel *ch)
+/*
+ * SESSION 153-CONTINUED-59: attr-program settle gate. The first beat
+ * window of a capture generation binds program pairs (method 0x2014/0x2054)
+ * whose operand pages must be IN the launch page set or the builder's
+ * shadow relocation MISSes and the emitted address stays a raw client VA
+ * the engine cannot fetch (r1104: `pair addr=0x2054 va=0x4350900 -> MISS`
+ * -> MMU Fault HUBCLIENT_PD @0x4350000 -> guest channel reset). The pages
+ * resolve through the pin demand path with a multi-second latency, so a
+ * launch that runs within a second of the attr prelude's program-VA set
+ * last growing races that resolution. This gate withholds beef forwards
+ * for sema_attr_settle_ms after the set last grew (bounded by the same
+ * gate window as the prelude gate), giving the pins time; the busy-defer
+ * keeps the candidate so the launch goes out once settled.
+ */
+static unsigned gsp_sema_attr_settle_ms = 8000u;
+module_param_named(sema_attr_settle_ms, gsp_sema_attr_settle_ms, uint, 0644);
+MODULE_PARM_DESC(sema_attr_settle_ms,
+ "Withhold beef GR forwards for this long after the attr prelude program-VA set last grew, so window pair pages resolve before the first launch (default 8000, 0 = off)");
+static unsigned long svc_attr_settle_j;
+static u32 svc_attr_settle_n;
+
+static bool svc_gr_attr_settle_wait(void)
{
- if (!READ_ONCE(svc_mme_prelude_flag) || !gsp_sema_gr_prelude_gate_ms)
+ u32 apn = 0;
+
+ if (!gsp_sema_attr_settle_ms)
+ return false;
+ (void)gsp_sema_attr_prelude_ptrs(&apn);
+ if (!apn)
return false;
+ if (apn != svc_attr_settle_n) {
+ svc_attr_settle_n = apn;
+ svc_attr_settle_j = jiffies;
+ }
+ if (!svc_gr_prelude_gate_j)
+ svc_gr_prelude_gate_j = jiffies;
+ if (time_after(jiffies, svc_gr_prelude_gate_j +
+ msecs_to_jiffies(gsp_sema_gr_prelude_gate_ms)))
+ return false; /* overall fail-open with the prelude gate */
+ return time_before(jiffies, svc_attr_settle_j +
+ msecs_to_jiffies(gsp_sema_attr_settle_ms));
+}
+
+static bool svc_gr_prelude_gate_active(const struct svc_channel *ch)
+{
if ((ch->h_object & 0xfffff000u) != 0xbeef0000u)
return false;
+ /*
+ * SESSION 153-CONTINUED-59: attr-program settle first (fires even
+ * with the MME prelude already mature - that is the r1104 state).
+ */
+ if (svc_gr_attr_settle_wait())
+ return true;
+ if (!READ_ONCE(svc_mme_prelude_flag) || !gsp_sema_gr_prelude_gate_ms)
+ return false;
if (gsp_sema_mme_prelude_mature())
return false;
if (!svc_gr_prelude_gate_j)
diff --git a/kernel/gsp_sema_service.h b/kernel/gsp_sema_service.h
index 7a9feb7..6b7922a 100644
--- a/kernel/gsp_sema_service.h
+++ b/kernel/gsp_sema_service.h
@@ -450,6 +450,16 @@ struct gsp_sema_gr_reloc {
int gsp_sema_gr_reloc_resolve(u64 va, struct gsp_sema_gr_reloc *out);
/*
+ * SESSION 153-CONTINUED-59: record one VA (page-aligned internally) in the
+ * pin-demand set exposed at /sys/kernel/debug/vgsp/sema_setup_demand, so
+ * pin_gr_stream demands its page in the guest. The GR launch builder calls
+ * this when a window/attr operand page cannot be resolved at build time
+ * (the r1104/r1105 MISS -> MMU-fault class); the demand gives the next
+ * forward a resolvable page instead of a lane-killing raw guest VA.
+ */
+void gsp_sema_demand_note(u64 va);
+
+/*
* SESSION 153-CONTINUED-53: MME context-setup prelude accessor for the GR
* launch builder. Returns the captured setup runs (C597 MME family
* 0x114..0x124/0x234/0x550..0x568/0x3400..0x34fc, verbatim, first-