From d0ae432ade6941a705875b9db2a9d26b23c23b59 Mon Sep 17 00:00:00 2001 From: Arthur Hanson Rasmusson Date: Fri, 9 Oct 2026 21:44:24 -0400 Subject: vgsp-sema: gate the pool-residue rule on the first translated pool read, not submissions (ISSUE-0002) r70 c3 proved the submissions gate wrong: the content-rescue path consumes entry 0 (submissions++) while the pool page is still untranslated (rrc=-2), then the scanner's pin batch rewinds last_get (SVC_PIN_REWIND) and the entry is decoded again - this time with cur=134 residue, pay=1, but submissions already 1, so the residue branch was skipped, the hold branch deferred the release, and the pending retry dropped it (payload <= cur). The client's first tracker wait then never completed. Replace the freshness gate with a per-channel pool_rel_seen flag set on the first translated pool read (rrc2 == 0), persisted in the pump write-back. The residue rule now fires exactly on that first read, exactly once per channel per session. --- kernel/gsp_sema_service.c | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) (limited to 'kernel') diff --git a/kernel/gsp_sema_service.c b/kernel/gsp_sema_service.c index d69be19..075a429 100644 --- a/kernel/gsp_sema_service.c +++ b/kernel/gsp_sema_service.c @@ -168,6 +168,18 @@ struct svc_channel { * last_get to slot 0 so the live first push is * processed instead of skipped. */ bool logged; /* one state log per channel */ + bool pool_rel_seen; /* ISSUE-0002 r70: a pool release word for + * this channel has been read through a + * translated source at least once in this + * session. The residue rule (first release of + * a fresh channel whose word reads far ahead + * of the payload) must fire on the FIRST + * translated read only: the rescue path can + * consume entry 0 (submissions++) before the + * pool pin lands, the pin batch then rewinds + * last_get, and the re-decode is no longer a + * fresh channel by submissions - but it still + * is by this flag. */ u64 instance_pa; u64 notifier_pa; /* error notifier: NvNotification slots */ u32 notifier_as; @@ -6504,7 +6516,7 @@ static void svc_decode_stream(struct nv_vgpu_device *vgpu, const u8 *buf, SEM_REDUCTION_INC) ? 1 : 0); } else if (svc_pool_sem_va(sem_va) && ch && ch->engine_type && - !ch->submissions && + !ch->pool_rel_seen && cur > st.sem_payload) { /* * ISSUE-0002 (r63/r64): the @@ -6589,6 +6601,19 @@ static void svc_decode_stream(struct nv_vgpu_device *vgpu, const u8 *buf, if (st.sem_payload > cur) pending = 1; } + /* + * ISSUE-0002 r70: the residue rule + * applies to the first translated + * pool read of the session only. + * The rescue path can consume entry 0 + * before the pool pin lands and the + * pin batch then rewinds last_get, + * so a submissions-based freshness + * test misses the re-decode; this + * flag does not. + */ + if (!rrc2 && svc_pool_sem_va(sem_va) && ch) + ch->pool_rel_seen = true; } /* @@ -14359,6 +14384,7 @@ static void svc_pump_channels(struct nv_vgpu_device *vgpu) bitmap_copy(svc.chan[k].rel_done, ch->rel_done, SVC_GPFIFO_MAX_BITS); svc.chan[k].last_rel_va = ch->last_rel_va; + svc.chan[k].pool_rel_seen = ch->pool_rel_seen; svc.chan[k].rescue_last = ch->rescue_last; svc.chan[k].rescue_fail = ch->rescue_fail; svc.chan[k].push_hold_until = ch->push_hold_until; -- cgit v1.2.3