From 51e50d937800db01bd95010ad54ef2c4ea140b75 Mon Sep 17 00:00:00 2001 From: Arthur Hanson Rasmusson Date: Fri, 23 Oct 2026 09:11:55 -0400 Subject: vgsp-sema: prefer the client's page tables over a disagreeing pool pin (moved-but-readable pool) The pool resolver trusted an injected pin after a read-back proof. That proof does not catch a pool page that MOVED: the old page is still readable, so the release write lands on the old page while the client polls the new one. Observed: 'pending release starved va=0x12100000x tries=64' for ~45 s with the stale pin (pa=0x120b30000) readable, until the fresh pin (pa=0x130e9d000) arrived; the client's tracker never woke and its init hung (multikernel battery timeout, copies stuck rc=-2). The client's own page tables are the GPU/UVM ground truth for where the tracker reads, so when a structural walk resolves a different page than the pin (and it is not a degenerate identity), the walk wins - both sources are read-back proven at the exact offset. --- kernel/gsp_sema_service.c | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) (limited to 'kernel') diff --git a/kernel/gsp_sema_service.c b/kernel/gsp_sema_service.c index 2634220..dcce4b5 100644 --- a/kernel/gsp_sema_service.c +++ b/kernel/gsp_sema_service.c @@ -3622,11 +3622,50 @@ static int svc_pool_pa_resolve(struct nv_vgpu_device *vgpu, u32 h, u64 va, * the injected page is readable before trusting it; a failed * proof falls through to the read-back-validated cache, the * structural walk and the targeted rm_mem record. + * + * r536: the read-back proof does NOT catch a moved pool whose + * OLD page is still readable - the write then lands on the old + * page while the client polls the new one and the tracker + * starves (observed: "pending release starved va=0x12100000x + * tries=64" for ~45 s after the pool moved, with the stale pin + * pa=0x120b30000 still readable; the fresh pin pa=0x130e9d000 + * arrived 45 s later). The client's OWN page tables are the + * GPU/UVM ground truth for where the tracker reads, so when a + * structural walk resolves a DIFFERENT page than the pin, the + * walk wins (both are read-back proven at the exact offset). */ u32 probe = 0; if (!svc_read_ap(vgpu, pa, svc_ap_of(a), &probe, sizeof(probe))) { + u64 wpa = 0; + int wap = SVC_APERTURE_SYS; + bool walk_hit = false; + + if (!svc_walk_discovered(vgpu, page, &wpa, &wap) || + !svc_walk_vaspaces(vgpu, page, &wpa, &wap)) + walk_hit = true; + if (walk_hit && + (wpa & ~(u64)(SEMA_PAGE_SIZE - 1)) != + (pa & ~(u64)(SEMA_PAGE_SIZE - 1)) && + !svc_pool_pa_identity(va, wpa)) { + u32 wprobe = 0; + u64 exact = (wpa & ~(u64)(SEMA_PAGE_SIZE - 1)) | + (va & (SEMA_PAGE_SIZE - 1)); + + if (!svc_read_ap(vgpu, exact, svc_ap_of(wap), + &wprobe, sizeof(wprobe))) { + svc_pool_pa_store(va, exact, wap); + svc_tr_clear_failure(page); + if (src) + *src = "walk-over-pin"; + svc_pool_pa_note(h, va, exact, + "walk-over-pin"); + *addr = exact; + *ap = wap; + return 0; + } + } svc_tr_clear_failure(page); if (src) *src = "pin"; -- cgit v1.2.3