From 380469ee70dc4d3f1f695f807da0b0bfe7d5d3ba Mon Sep 17 00:00:00 2001 From: Arthur Hanson Rasmusson Date: Wed, 21 Oct 2026 00:24:11 -0400 Subject: sema: r391f once-only GRCE inline writes - the sum=0 class root cause A REPLAYED ring entry must not re-run its LOAD_INLINE_DATA writes. The fill/copy ops were already gated by allow_ops (cleared for entry_replay), but the inline-write gate was 'trusted || allow_ops' and a replay is trusted by construction, so every re-decode of an already-processed push re-wrote its inline bytes into the vidmem shadow. victory_reduce's cudaMemset(d_sum, 0, 8) is exactly such an inline write. Observed on r396: 'sema-grce: inline write dst=0x7845ef000000 -> pa=0x7c00000 ap=vidmem bytes=8 data8=0000000000000000' fired 86 us before the D2H readback of the same VA - zeroing the accumulator the launch had just written (OUT-PAGE-POST val8=0000008000080000 = the correct sum) so the client read zeros (sum=0, bad=1). The same replay rewrote the page repeatedly (482 inline writes/boot). The r383 replay-capture path only needs to CAPTURE the launch; the inline bytes were authored on the first (non-replay) pass. --- kernel/gsp_sema_service.c | 22 +++++++++++++++++++++- 1 file changed, 21 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 40a8867..41a5c58 100644 --- a/kernel/gsp_sema_service.c +++ b/kernel/gsp_sema_service.c @@ -8776,7 +8776,27 @@ static void svc_decode_stream(struct nv_vgpu_device *vgpu, const u8 *buf, if (slot_bytes > 0x8000 - 4) slot_bytes = 0x8000 - 4; } - if ((trusted || allow_ops) && !gsp_sema_skip_ops && + /* + * r391f once-only (the sum=0 class): a REPLAYED + * entry must not re-run its inline writes. The ops + * are already gated by allow_ops (entry_replay + * clears it), but the inline-write gate used + * `trusted || allow_ops` - and a replay is trusted + * by construction - so every re-decode of an + * already-processed push re-wrote its inline data + * into the vidmem shadow. victory_reduce's + * cudaMemset(d_sum,0,8) is exactly such an inline + * write (observed: `inline write + * dst=0x7845ef000000 -> pa=0x7c00000 bytes=8 + * data8=0` firing 86 us before the D2H readback, + * zeroing the accumulator the launch had just + * written - the readback then reads zeros). The + * r383 replay-capture path only needs to CAPTURE + * the launch; the inline bytes were authored on the + * first (non-replay) pass. + */ + if ((trusted || allow_ops) && !replay && + !gsp_sema_skip_ops && st.have_out && st.line_length) { u32 bytes = slot_run ? slot_bytes : st.line_length * -- cgit v1.2.3