From 03ee5bbe4a60c80627e21d3446b6b787d6eae004 Mon Sep 17 00:00:00 2001 From: Arthur Hanson Rasmusson Date: Sat, 31 Oct 2026 12:31:56 -0400 Subject: vgsp: stub IR write real encoding SEC_OP_ONE_INC=5 (op=1 walked 0x114->0x118/0x11c/0x120 clobbering SA[0]=1 = r1131 MISSING_MACRO_DATA), stub PC at IR-end, byte-exact END body, coverage-aware stubbing, ONE_INC ghost CALL fix (18->6 real), MME-WINRUN dump, prelude latch keyed (generation,h_object); mme_ir_end/ir_cov bitmap + USERD adopt latch clear - ATTRIBUTION ANSWERED: non-retire is NONE of the attachments (window-only also ILLEGAL_OPCODE 0/901; all-macro-noop sa_stub_all=1 still ILLEGAL_OPCODE 0/902); r1111 retire was a different frame class (5016B no-CALL) vs draw-class (7148B CALL_MME_MACRO(0)); next: MME reg sample BEFORE WEDGE-RECOVER reset + stub landing verify (stub_pc 0xf0 test) - SESSION 153 r1132-r1141 --- kernel/gsp_sema_service.c | 87 ++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 86 insertions(+), 1 deletion(-) (limited to 'kernel/gsp_sema_service.c') diff --git a/kernel/gsp_sema_service.c b/kernel/gsp_sema_service.c index 748eae9..2b8b422 100644 --- a/kernel/gsp_sema_service.c +++ b/kernel/gsp_sema_service.c @@ -14212,6 +14212,18 @@ static void svc_mme_census(const u8 *buf, u32 len, u64 push_va, u32 h_object) * next window re-preplays. The writer is the single service thread and * appends strictly in order; the generation only increments after a * capture that appended, giving the booter a seqcheck against torn views. + * + * SESSION 153-CONTINUED-68: the capture can DROP runs once the buffer is + * full ("buffer full=N words=1023" on r1126) - e.g. a second GL program + * whose content never entered the replay - while the SA table (recorded + * unbounded, last-wins) still points slots at those never-replayed IR + * addresses; a call then fetches macro data that is not there (Graphics + * Exception: MISSING_MACRO_DATA). The coverage bitmap + * (svc_mme_ir_cov, instruction granularity) records exactly which IR + * instructions the REPLAY holds so the launch builder can stub every + * called slot whose entry is outside that set (see + * gsp_sema_mme_ir_covered). The buffer cap itself stays 1024 words: the + * launch method block is 2048 words and must also carry the window. */ #define SVC_MME_PRELUDE_WORDS 1024u #define SVC_MME_PRELUDE_SIGS 512u @@ -14253,6 +14265,39 @@ static u64 svc_mme_sa_present; static u32 svc_mme_sa_entry[64]; static u32 svc_mme_sa_log; +/* + * SESSION 153-CONTINUED-68: furthest IR instruction any CAPTURED 0x114 + * upload covers (pc + ceil(code words / 3); the client's upload addresses + * are instruction units - slot N's pc equals slot N-1's pc + its code + * instructions, verified across the r1099/r1116 captures). The launch + * builder's MME stub must land BEYOND the replayed program: a fixed stub + * PC inside a captured macro's body would clobber that macro's code (the + * window calls covered slots too). Recorded only for runs that entered the + * replay buffer, so the value always describes the replayed IR extent. + */ +static u32 svc_mme_ir_end; + +u32 gsp_sema_mme_ir_end_get(void) +{ + return READ_ONCE(svc_mme_ir_end); +} + +/* + * SESSION 153-CONTINUED-68: instruction-granular coverage of the IR the + * REPLAY buffer actually holds (marked for every 0x114 run that entered + * svc_mme_prelude_buf). Values >= SVC_MME_IR_BITS are treated as covered + * "elsewhere" so an overflow cannot force every slot to be stubbed. + */ +#define SVC_MME_IR_BITS 8192u +static u8 svc_mme_ir_cov[SVC_MME_IR_BITS / 8u]; + +bool gsp_sema_mme_ir_covered(u32 pc) +{ + if (pc >= SVC_MME_IR_BITS) + return true; + return !!(svc_mme_ir_cov[pc >> 3] & (1u << (pc & 7u))); +} + u64 gsp_sema_mme_sa_get(u32 *entries, u32 n) { u32 i; @@ -14378,9 +14423,31 @@ static void svc_mme_prelude_capture(const u8 *buf, u32 len, u64 push_va, * the 0x114 instruction-RAM uploads are the only runs that * make the prelude functionally complete; the maturity gate * keys on them. + * + * SESSION 153-CONTINUED-68: also track the furthest covered + * IR instruction (see svc_mme_ir_end) so the builder's stub + * lands beyond the replayed program. */ - if (addr == 0x114u && span > 1u) + if (addr == 0x114u && span > 1u) { + u32 pc = 0, code_words = span - 2u, ir_end, k; + + if (span >= 2u) + memcpy(&pc, buf + off + 4u, 4); + ir_end = pc + (code_words + 2u) / 3u; + if (ir_end > READ_ONCE(svc_mme_ir_end)) + WRITE_ONCE(svc_mme_ir_end, ir_end); + /* + * SESSION 153-CONTINUED-68: mark the instructions this + * replayed run covers (see svc_mme_ir_cov). + */ + for (k = 0; k < (code_words + 2u) / 3u; k++) { + u32 a = pc + k; + + if (a < SVC_MME_IR_BITS) + svc_mme_ir_cov[a >> 3] |= 1u << (a & 7u); + } svc_mme_prelude_code_words += span - 1u; + } svc_mme_prelude_n += span; svc_mme_prelude_sigs[svc_mme_prelude_sig_n++] = sig; added++; @@ -21152,6 +21219,24 @@ static int svc_chan_userd(struct nv_vgpu_device *vgpu, struct svc_channel *ch, ch->userd_ok = true; *put = best_put; *get = best_get; + /* + * SESSION 153-CONTINUED-68: deliberately do NOT + * seed the speculative latch here. Seeding + * armed the pump's judge on channels that + * previously accepted the VRAM candidate + * quietly; a pool block whose PUT advances in + * jumps (r1133: 219 -> 996) or a stale seed + * from an earlier RAM-scan candidate (r1132: + * latch=2 vs put=6) then rejected on every + * pass - adopt/reject spin at ~10 Hz (4638 + * REJECTED lines on r1132, the guest's Xorg + * soft-locked, glxgears starved). The r1129- + * r1131 good boots show the intended shape: + * VRAM adopts logged, no rejects, ring + * consumption via the walk. + */ + ch->gr_ram_userd_latch_at = 0; + ch->gr_ram_userd_confirmed = false; pr_info("sema-chan: GR USERD h=0x%x rank=%u found by VRAM shape scan at fb 0x%llx (put=%u get=%u%s, ring-validated)\n", ch->h_object, ch->gr_index, best, best_put, best_get, -- cgit v1.2.3