From 131d44e083925f35f842114b6f7b6db546f28368 Mon Sep 17 00:00:00 2001 From: Arthur Hanson Rasmusson Date: Wed, 11 Nov 2026 00:23:21 -0500 Subject: vgsp: all-ones scrub release for registered waits; walk-page registration; GL frame publisher (CONT.416-417) - gsp_sema_service: merge a scanner registration arriving after the stash record instead of dropping it (a dropped registration let the next authoring pass write the blocking pair into the page the guest was polling, so the wait never ended); author the finish word all-ones for every registered record while the sema word stays put-based once real submissions were observed (CONT.416/417). - scrub_pin_qmp (host scanner): accept an unstable-but-live wait page instead of skipping it, and register the walk-resolved scrubber channel page - first the walk summary, then the per-VAS kernel row (h=0xc) when the summary path fails - so the release is armed before the guest polls (r1762/r1764 evidence). - guest-diag: add gl_frames, the direct-GL (GLX pbuffer) frame publisher; with it the stack produced the first non-black GPU-rendered frames (40/40, 640x480, animated) through pbuffer -> sysmem -> ivshmem -> host frame_reader. - gsp_rm_emulation: log the display-shim request words for triage. --- kernel/gsp_sema_service.c | 51 ++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 46 insertions(+), 5 deletions(-) (limited to 'kernel/gsp_sema_service.c') diff --git a/kernel/gsp_sema_service.c b/kernel/gsp_sema_service.c index 7bd1b26..be91f6d 100644 --- a/kernel/gsp_sema_service.c +++ b/kernel/gsp_sema_service.c @@ -47066,7 +47066,29 @@ static void svc_scrub_one(struct nv_vgpu_device *vgpu, struct svc_scrub *s) if (svc_scrubs[j].registered && !svc_scrubs[j].userd_ok && svc_scrubs[j].hsem_pa == s->hsem_pa) { - pr_info("sema-svc: scrub dedup slot %d (stash owns hsem_pa=0x%llx)\n", + /* + * CONT.416: merge the scanner + * registration onto the stash + * record instead of dropping it. + * Dropping it left this record + * registered=false, so the next + * authoring pass wrote the + * blocking pair (sema=entries-1, + * fin=0) to the very page the + * guest waited on (r1749/r1752: + * Xorg's PMA scrub wait never + * ended). The wait needs the + * all-ones release, which only + * registered records author. + */ + if (!s->registered || + s->fin_pa != svc_scrubs[j].fin_pa) { + s->registered = true; + s->fin_pa = svc_scrubs[j].fin_pa; + s->pa_gen++; + s->seeded = false; + } + pr_info("sema-svc: scrub dedup slot %d (stash owns hsem_pa=0x%llx; registration merged)\n", j, s->hsem_pa); memset(&svc_scrubs[j], 0, sizeof(svc_scrubs[j])); @@ -47162,7 +47184,7 @@ static void svc_scrub_one(struct nv_vgpu_device *vgpu, struct svc_scrub *s) s->consumed = put ? put - 1 : s->entries - 1; } else if (s->submitted == s->authored && s->authored_gen == s->pa_gen && - !(s->registered && !s->submitted)) { + !s->registered) { /* * CONT.414: re-author the release pair every pass while a * scanner-registered buffer has no observed submissions, so a @@ -47202,10 +47224,29 @@ static void svc_scrub_one(struct nv_vgpu_device *vgpu, struct svc_scrub *s) * and the folded finish counter is at its maximum. */ { - bool release = s->registered && !s->submitted; + /* + * CONT.416: a scanner-registered record always takes the + * all-ones release. The PMA scrub wait (mem_scrub + * _scrubWaitAndSave; finish word at vmap+0x6c004) has no + * timeout, and the registered page is by definition the one + * the guest polled. The put-based values remain for + * stash-only records (no scanner registration). + * + * CONT.417 (reboot #2 cold-boot decision, previously "candidate" + * in the CONT.416 note): the finish word is all-ones for EVERY + * registered record (not just submitted==0), because the finish + * wait accepts only fin >= lastSeen+itemsToSave and the + * emulation never executes the memsets; the sema word stays + * put-based once real submissions were observed so an active + * scrubber still sees forward progress. 0xffffffff can never + * equal a putIndex below the ring size, so the free-entry wait + * cannot block either way. + */ + bool rel_sema = s->registered && !s->submitted; + bool rel_fin = s->registered; u32 idle = 0xffffffffu; - u32 sema = release ? idle : s->consumed; - u32 fin = release ? idle : (u32)s->submitted; + u32 sema = rel_sema ? idle : s->consumed; + u32 fin = rel_fin ? idle : (u32)s->submitted; svc_write_ap(vgpu, s->hsem_pa, SVC_APERTURE_SYS, &sema, sizeof(sema)); -- cgit v1.2.3