From f2a4adc091a43d73eca4388df84fd1a67fb4007f Mon Sep 17 00:00:00 2001 From: Arthur Hanson Rasmusson Date: Fri, 16 Oct 2026 21:05:05 -0400 Subject: vgsp: m167 session flush never wipes a live session (r169: deferred flush fired with smiley's channels live 7s after registration, dropped its queued launch release, client spun in uvm_channel_is_value_completed) + m164 hardening: GR no-capture hold applies only to fresh entries, never replays (old-session pushes were held and re-counted) --- kernel/gsp_sema_service.c | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) (limited to 'kernel/gsp_sema_service.c') diff --git a/kernel/gsp_sema_service.c b/kernel/gsp_sema_service.c index d6b9617..ad03f5f 100644 --- a/kernel/gsp_sema_service.c +++ b/kernel/gsp_sema_service.c @@ -7335,6 +7335,35 @@ static void svc_session_flush(void) unsigned long flags; u32 i; + /* + * m167: never wipe a LIVE session. The flush is requested when a + * channel close leaves the table empty, but that transition fires + * during ordinary UVM channel cycling and the deferred execution can + * land after the same client (or the next client, when its chan_add + * raced the requested flush) has registered channels again - r169: + * the flush executed 2.5 s after smiley's launch with its channels + * live (registered 7 s earlier), wiped the queued completion releases, + * and the client spun forever in uvm_channel_is_value_completed + * (release never applied; pool word frozen). A live channel's session + * owns the tables - skipping is always safe because a genuine session + * end re-arms the flush when its own channels close. + */ + { + bool live = false; + + spin_lock_irqsave(&svc.chan_lock, flags); + for (i = 0; i < SVC_MAX_CHANNELS; i++) + if (svc.chan[i].valid) { + live = true; + break; + } + spin_unlock_irqrestore(&svc.chan_lock, flags); + if (live) { + pr_info("sema-svc: session flush skipped: live channel(s) present (deferred flush raced a new session registration)\n"); + return; + } + } + svc_gr_diag_reset(); /* m150: per-session diagnostic budgets */ svc.map_n = 0; svc_pb_n = 0; @@ -14899,6 +14928,7 @@ static void svc_pump_channels(struct nv_vgpu_device *vgpu) if (!ch->engine_type && va && len && gsp_phys_gr_forward_enabled() && svc_gr_qmd_seen > 0 && + !entry_replay && !(svc_gr_cand.valid && svc_gr_cand.h_object == ch->h_object && -- cgit v1.2.3