diff options
| author | Arthur Hanson Rasmusson <arthur@vgpu.io> | 2026-10-27 10:26:38 -0400 |
|---|---|---|
| committer | Arthur Hanson Rasmusson <arthur@vgpu.io> | 2026-10-27 10:26:38 -0400 |
| commit | bd1f27476fc11dc0bc45eb1aa666e352f34a0168 (patch) | |
| tree | c6542466394f637a077d8e89f4d5f12b3cc5825f /kernel/gsp_sema_service.c | |
| parent | cb1653d62f521943497e5705803f461ab7041dda (diff) | |
| download | open-iov-bd1f27476fc11dc0bc45eb1aa666e352f34a0168.tar.gz open-iov-bd1f27476fc11dc0bc45eb1aa666e352f34a0168.zip | |
vgsp: client-session boundary fixes - WD ring scan gate + forced session flush
Two changes from the r839/r840 multi-client forensics (session 147):
1. The guest-RAM content scan for a GR ring must not run for the kernel
RC-watchdog channel (h=0x31415900). Its ring is a plain kernel allocation
always resolvable through the driver-published VAS walk; on r840 the walk
lost a registration race, the scan latched a foreign garbage page, and
the bad latch poisoned the driver's DMA test ('Failed to initialize DMA',
Xorg died). Gated, the walk retries per pass; r841 Xorg#1 passes DMA
(DMAFAIL=0) where r840 failed.
2. sema_force_flush module parameter + gsp_sema_service_sess_flush_force():
execute the ISSUE-0002 client-session flush even with live channels. The
channel-close trigger never fires on real boots (driver-global channels
stay valid), so later client sessions inherited stale discovery state.
Verified on r841: flush executes mid-boot, Xorg survives it and
re-registers its channels.
Remaining wall (addendum 9): GR client channels' pushbuffer reads return
all-zero through the trusted translation (va=0x4000000-class, src=4), so
first entries never complete and GL clients never render.
Diffstat (limited to 'kernel/gsp_sema_service.c')
| -rw-r--r-- | kernel/gsp_sema_service.c | 51 |
1 files changed, 48 insertions, 3 deletions
diff --git a/kernel/gsp_sema_service.c b/kernel/gsp_sema_service.c index f6ad3b2..9c72b4b 100644 --- a/kernel/gsp_sema_service.c +++ b/kernel/gsp_sema_service.c @@ -678,6 +678,9 @@ static u32 svc_ring_n; */ static u8 svc_sess_flush; static u8 svc_guest_reset_req; /* m177: guest RM reload; wiped on svc thread */ +static u8 svc_sess_flush_forced; /* execute the next flush past the live-channel skip + * (ISSUE-0002 client-session boundary aid; see + * gsp_sema_service_sess_flush_force) */ static u8 svc_sess_active; /* a channel of a session has registered (until flush) */ static u32 svc_sess_gen; /* m176: bumped by every executed session flush; * stamps channels/scrubbers so per-session learned @@ -13415,6 +13418,7 @@ static void svc_session_flush(void) */ { bool live = false; + bool forced = READ_ONCE(svc_sess_flush_forced); spin_lock_irqsave(&svc.chan_lock, flags); for (i = 0; i < SVC_MAX_CHANNELS; i++) @@ -13423,10 +13427,15 @@ static void svc_session_flush(void) break; } spin_unlock_irqrestore(&svc.chan_lock, flags); - if (live) { + if (live && !forced) { pr_info("sema-svc: session flush skipped: live channel(s) present (deferred flush raced a new session registration)\n"); return; } + if (forced) { + svc_sess_flush_forced = 0; + pr_info("sema-svc: session flush (forced) executing with live=%d channel(s)\n", + live); + } } svc_gr_diag_reset(); /* m150: per-session diagnostic budgets */ @@ -17532,8 +17541,24 @@ static void svc_gr_ring_autopin(struct nv_vgpu_device *vgpu, * entry and pushbuffer reads resolve. Sliced so the service thread * stays responsive; gives up per channel after * SVC_GR_RAM_PASS_MAX slices. - */ - if (ch->gr_ram_passes < SVC_GR_RAM_PASS_MAX && + * + * SESSION 147 (r840 evidence): the scan must NOT run for the kernel + * RC-watchdog channel (h=0x31415900). Its ring is a plain kernel + * allocation whose VA is always resolvable through the driver- + * published VAS walk - the walk is the correct, deterministic + * source. On r840 the walk lost a registration race, the scan ran + * first and latched a FOREIGN page (pa=0x101cc3000, garbage + * entries: raw=0xffff88f10403e000), and the bad latch poisoned + * every later entry/push read: the driver's DMA test never saw its + * push complete and Xorg died with "Failed to initialize DMA" + * (the same boot passed on r835/836/838 where the trusted walk + * won the race). Gating the scan keeps the per-pass walk retry + * alive for the watchdog; the walk landing late is indistinguishable + * from the r838 flow, and never landing is no worse than a poisoned + * latch. + */ + if (ch->h_object != 0x31415900u && + ch->gr_ram_passes < SVC_GR_RAM_PASS_MAX && !test_bit(ch->gr_index, &svc_gr_ring_done)) { u64 hit_pa = 0; @@ -30684,6 +30709,26 @@ static void svc_stall_watch_check(void) svc_force_consume = 4; } +/* + * ISSUE-0002 client-session boundary aid: force a session flush that + * executes even while channels are live. The channel-close trigger only + * fires when the table empties, which never happens on a guest where the + * driver-global kernel channels (RC watchdog 0x31415900, the tiny notifier + * channel) stay valid; later client sessions then inherit the previous + * session's map/pin/pool discovery state and wedge (false translations -> + * failed rescues -> driver DMA-init timeout). Raised through the + * sema_force_flush module parameter so the boundary can be tested before + * wiring automatic detection. + */ +void gsp_sema_service_sess_flush_force(void) +{ + WRITE_ONCE(svc_sess_flush_forced, 1); + WRITE_ONCE(svc_sess_flush, 1); + if (READ_ONCE(svc.task)) + wake_up_process(svc.task); + pr_info("sema-svc: forced session flush requested\n"); +} + static int svc_thread(void *arg) { struct nv_vgpu_device *vgpus[SVC_MAX_GUESTS]; |
