From 6ebc7cd40b09b6c922e8b87209a74da60f347739 Mon Sep 17 00:00:00 2001 From: Arthur Hanson Rasmusson Date: Thu, 12 Nov 2026 22:46:46 -0500 Subject: vgsp: display engine re-seeds GET on a driver ring wrap (fixes the nvidia-modeset GET-past-PUT wedge) Root cause of the post-ScreenInit Xorg kernel-mode spin (sysrq-t: Xorg R-state inside nvKmsIoctl -> nvkms_yield, utime frozen, stime 100%): the emulated display engine (core channel c57d) held GET=0xcd8 PAST PUT=0xcc8 for 50 s. gsp_disp_run only publishes GET when the parse reaches PUT exactly (by design, per its r1630 comment), so when the guest driver wraps/resets its push ring (PUT steps backward via nvEvoMakeRoom) the stale consumed can never resync and NVKMS spins forever. When put < s->consumed (wrap/reset), re-seed consumed=0/last_put=0 and republish GET=0 so the wrapped pushes are re-parsed from the ring base; the driver's PUT is authoritative. Validated c160 (rich args): bar0 channels now read PUT==GET (core 0x590, window c57e 0xe2c) with no wedge and flips parse (UPDATE armed=1 -> FINISHED posts=32..34); X advances past the spin and served xdpyinfo once. Remaining walls (next): the push-buffer 0x51 NV_ERR_NO_MEMORY allocation lottery and 'Flip event timeout on head 0' (Xorg D in nv_drm_atomic_commit). --- kernel/gsp_display_engine.c | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) (limited to 'kernel/gsp_display_engine.c') diff --git a/kernel/gsp_display_engine.c b/kernel/gsp_display_engine.c index 98f85fe..c522a93 100644 --- a/kernel/gsp_display_engine.c +++ b/kernel/gsp_display_engine.c @@ -1418,6 +1418,30 @@ void gsp_disp_engine_pump(struct nv_vgpu_device *vgpu) put = gsp_disp_bar0_read(vgpu, s->ctl_off + GSP_DISP_REG_PUT) & 0xffc; + /* + * Ring wrap / reset resync (eng4, 2026-11-12). nvEvoMakeRoom + * resets the driver's push pointer to the ring base when it + * wraps (writes a JUMP at the head, sets putOffset = 0), so the + * channel's PUT steps BACKWARD below our consumed. gsp_disp_run + * deliberately only publishes a GET that reached PUT exactly + * (see its r1630 comment), so a stale consumed left AHEAD of PUT + * can never resync: the parse from the old consumed hits the + * wrapped tail and never lands on the new PUT, GET stays past + * PUT forever, and nvidia-modeset's nvEvoMakeRoom / + * nvEvoPollForEmptyChannel spin (they break only on GET == + * put_offset). Seen live as core c57d PUT=0xcc8 GET=0xcd8 held + * for minutes with Xorg 100% in-kernel (nvkms_yield) and xdpyinfo + * unanswered. Re-seed consumed to the ring base and republish + * GET so the wrapped pushes are parsed from 0 (the driver's + * authoritative write pointer is PUT). + */ + if (put < s->consumed) { + s->consumed = 0; + s->last_put = 0; + gsp_disp_bar0_write(vgpu, + s->ctl_off + GSP_DISP_REG_GET, 0); + } + /* * Raster line for the window channels: NVC57E_GET_LINE at * 0x208. Bit 15 set = blanking, 14:0 = line. A free-running -- cgit v1.2.3