summaryrefslogtreecommitdiffstats
path: root/kernel/gsp_sema_service.c
diff options
context:
space:
mode:
authorArthur Hanson Rasmusson <arthur@vgpu.io>2026-11-10 15:13:31 -0500
committerArthur Hanson Rasmusson <arthur@vgpu.io>2026-11-10 15:13:31 -0500
commitdf6e71bb5188bdc762ca0fbc73352f9067572589 (patch)
tree0598532da068ec59d950eff00d11154b718666b7 /kernel/gsp_sema_service.c
parent72c7e2e6d4443457807d947f38ec650b3b8fb75a (diff)
downloadopen-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).
Diffstat (limited to 'kernel/gsp_sema_service.c')
-rw-r--r--kernel/gsp_sema_service.c31
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));
}