From 8002b3b4d4b56dfc2423d556bc86c7f278bfd065 Mon Sep 17 00:00:00 2001 From: Arthur Hanson Rasmusson Date: Mon, 9 Nov 2026 12:45:24 -0500 Subject: vgsp-sema: derive and register the guest scrubber finish-payload words The X DDX's NV_ESC_RM_VID_HEAP_CONTROL (ioctl 0x4a) allocates scrubbed pages through the guest PMA's CeUtils scrubber channel; it waits on the channel buffer's finish payload (channelWaitForFinishPayload), which the host's svc_scrub_pass was supposed to author but never did because the guest scanner had not registered fin_pa/hsem_pa (pa_ok=0 in every run). The channel buffer is pb + GPFIFO + sema + finish, and the scrubber's GPFIFO VA is pb + pbSize, so the host semaphore is gpfifo_va + entries*8 and the finish payload is that +4. Resolve that VA through the learned map or the VAS walk at the first pass and register the PAs in place (SYS aperture only). r1665: `scrub geometry hsem_va=0x12006c000 fin_va=0x12006c004 -> hsem_pa=0x10f46a000 fin_pa=0x10f46a004`, then `scrub author put=1..11` and the X server left the kernel scrub spin entirely: perf on Xorg is now 100 % in nvidia_drv.so+0xaee70 (a DDX userspace loop, next wall) with no _nv018351rm/_nv015102rm samples. --- kernel/gsp_sema_service.c | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/kernel/gsp_sema_service.c b/kernel/gsp_sema_service.c index f98fa98..1b77ea0 100644 --- a/kernel/gsp_sema_service.c +++ b/kernel/gsp_sema_service.c @@ -45330,6 +45330,39 @@ static void svc_scrub_pass(struct nv_vgpu_device *vgpu) if (!s) return; + /* + * r1665: the guest scanner never registered the scrubber's finish + * payload, so the X DDX's vidheap scrub wait (channelFillPbFastScrub + * / channelWaitForFinishPayload) never completed. The channel buffer + * is pb (0x64000) + GPFIFO (entries*8) + sema (4) + finish (4); the + * scrubber's gpfifo VA = pb + pbSize, so hsem = gpfifo_va + + * entries*8 and fin = hsem + 4. Resolve them through the learned map + * or the VAS walk and register in place. + */ + if (s->userd_ok && !s->pa_ok && s->gpfifo_va && s->entries) { + u64 hva = s->gpfifo_va + (u64)s->entries * 8; + u64 pa = 0; + int ap = SVC_APERTURE_SYS; + + if (svc_lookup(vgpu, hva, &pa, &ap) || !pa) { + if (svc_walk_vaspaces(vgpu, hva, &pa, &ap) || !pa) + pa = 0; + } + /* The scrub words are guest RAM; an FB translation is not. */ + if (pa && svc_ap_of(ap) != SVC_APERTURE_SYS) + pa = 0; + if (pa) { + s->hsem_pa = pa; + s->fin_pa = pa + 4; + s->pa_ok = true; + if (s->log_budget < 16) { + s->log_budget++; + pr_info("sema-svc: scrub geometry hsem_va=0x%llx fin_va=0x%llx -> hsem_pa=0x%llx fin_pa=0x%llx\n", + hva, hva + 4, s->hsem_pa, + s->fin_pa); + } + } + } if (!s->userd_ok || !s->pa_ok || !s->entries) { /* m112b: silent-return diagnostic (bounded per boot). */ if (s->log_budget < 8) { -- cgit v1.2.3