diff options
| author | Arthur Hanson Rasmusson <arthur@vgpu.io> | 2026-11-10 15:13:31 -0500 |
|---|---|---|
| committer | Arthur Hanson Rasmusson <arthur@vgpu.io> | 2026-11-10 15:13:31 -0500 |
| commit | df6e71bb5188bdc762ca0fbc73352f9067572589 (patch) | |
| tree | 0598532da068ec59d950eff00d11154b718666b7 | |
| parent | 72c7e2e6d4443457807d947f38ec650b3b8fb75a (diff) | |
| download | open-iov-df6e71bb5188bdc762ca0fbc73352f9067572589.tar.gz open-iov-df6e71bb5188bdc762ca0fbc73352f9067572589.zip | |
vgsp: author the scrub release pair for scanner-registered waits (CONT.414)
The X DDX vidheap scrub wait polls the finish payload at channel buffer
+0x6c004 while the host still reads USERD GP_PUT=0, so put-based forward
authoring wrote sema=entries-1 / fin=0: exactly the values that leave
channelWaitForFreeEntry and channelWaitForFinishPayload blocked. Xorg then
held the NVRM RM API write lock inside NV_ESC_RM_VID_HEAP_CONTROL, and the
GL thread and nvidia-modeset both sat D-state on os_acquire_rwlock_write.
A scanner-registered buffer with no observed submissions now gets the
proven all-ones release pair (sema=fin=0xffffffff) and is re-authored every
pass so a guest rewrite cannot re-block the wait. Put-driven records keep
forward-only authoring.
Result: the GL thread leaves D-state and a glClear+glFinish+glReadPixels
probe returns rc=0 with pixel=ff0000ff (a real red readback).
| -rw-r--r-- | kernel/gsp_sema_service.c | 31 |
1 files changed, 25 insertions, 6 deletions
diff --git a/kernel/gsp_sema_service.c b/kernel/gsp_sema_service.c index 8e6401d..7bd1b26 100644 --- a/kernel/gsp_sema_service.c +++ b/kernel/gsp_sema_service.c @@ -47161,7 +47161,13 @@ static void svc_scrub_one(struct nv_vgpu_device *vgpu, struct svc_scrub *s) s->put_last = put; s->consumed = put ? put - 1 : s->entries - 1; } else if (s->submitted == s->authored && - s->authored_gen == s->pa_gen) { + s->authored_gen == s->pa_gen && + !(s->registered && !s->submitted)) { + /* + * CONT.414: re-author the release pair every pass while a + * scanner-registered buffer has no observed submissions, so a + * guest rewrite of the polled word cannot re-block the wait. + */ return; /* nothing new; no guest writes */ } @@ -47181,15 +47187,28 @@ static void svc_scrub_one(struct nv_vgpu_device *vgpu, struct svc_scrub *s) */ svc_write_ap(vgpu, s->userd_pa + SVC_USERD_GP_GET, s->userd_as, &put, sizeof(put)); + /* + * CONT.414: a scanner-registered channel buffer with no observed + * USERD GP_PUT submissions is the X DDX's vidheap scrub wait: the + * guest RM polls the finish payload at channel buffer + 0x6c004 + * (channelWaitForFinishPayload) while the host still reads GP_PUT=0, + * so the put-based forward authoring would write sema=entries-1 and + * fin=0 - the exact values that leave channelWaitForFreeEntry and + * channelWaitForFinishPayload blocked (r1729: Xorg holds the NVRM + * RM API write lock in that wait, glxgears and nvidia-modeset D on + * os_acquire_rwlock_write). Author the proven all-ones release pair + * (CONT.408/409) until a real put advance gives us progress to + * mirror; 0xffffffff can never equal a putIndex below the ring size + * and the folded finish counter is at its maximum. + */ { - u32 sema = s->consumed; + bool release = s->registered && !s->submitted; + u32 idle = 0xffffffffu; + u32 sema = release ? idle : s->consumed; + u32 fin = release ? idle : (u32)s->submitted; svc_write_ap(vgpu, s->hsem_pa, SVC_APERTURE_SYS, &sema, sizeof(sema)); - } - { - u32 fin = (u32)s->submitted; - svc_write_ap(vgpu, s->fin_pa, SVC_APERTURE_SYS, &fin, sizeof(fin)); } |
