From 7876ce047d1e60cae04babbdc6ffb4a00042ba38 Mon Sep 17 00:00:00 2001 From: Arthur Hanson Rasmusson Date: Sun, 8 Nov 2026 20:25:10 -0500 Subject: vgsp-sema: release the UVM channel tracker slot too r1642 gdbstub proved the guest polls pool map slot 1 while the push releases slot 0: rank-0 UVM channel's uvm_gpu_tracking_semaphore resolves map_base + index*4 (index=1) = 0x121000004 (PA 0x104ea2004), the release decoded from its push targets 0x121000000, and writing the payload into 0x104ea2004 cleared uvm_push_end_and_wait. When a CE channel releases the pool map page, also apply the forward-only value to map_base + 4*(rank+1) through the verified pool resolver (read-back proven), and log pool-tracker-wr. --- kernel/gsp_sema_service.c | 53 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) (limited to 'kernel/gsp_sema_service.c') diff --git a/kernel/gsp_sema_service.c b/kernel/gsp_sema_service.c index e16deb2..ca848c6 100644 --- a/kernel/gsp_sema_service.c +++ b/kernel/gsp_sema_service.c @@ -1293,6 +1293,7 @@ struct sema_svc { * (pin/walk disagreement; the * r538 init-stall class) */ u64 pool_dual_log; /* r539 fan-out log budget */ + u64 pool_tracker_log; /* r1642 tracker-slot budget */ u64 pool_residue; /* fresh-channel first releases whose * pool word read far ahead of the * payload (previous session's @@ -5567,6 +5568,56 @@ static bool svc_wait_pend_release(u64 va); static bool svc_gr_rel_match(u64 va, u32 *payload); static bool svc_gr_rel_inflight(u64 va, u32 *payload); +/* + * r1642: UVM's channel-pool semaphore map reserves slot 0 for the pool + * release; each channel's own tracking semaphore lives at map_base + + * 4*(rank+1). Gdbstub proof on the guest: the rank-0 UVM channel's + * uvm_gpu_tracking_semaphore polled map_base+4 while its push released + * map_base+0, and writing the payload into map_base+4 cleared the + * uvm_push_end_and_wait spin. When a CE channel releases the pool slot, + * apply the same forward-only value to its tracker slot as well. + */ +#define SVC_UVM_POOL_MAP_BASE 0x121000000ULL +static void svc_pool_tracker_apply(struct nv_vgpu_device *vgpu, u32 h, + u64 va, u32 val) +{ + u64 tva, addr = 0; + const char *src = NULL; + int ap = 0; + u32 cur = 0, back = 0; + int i; + + if (va < SVC_UVM_POOL_MAP_BASE || + va >= SVC_UVM_POOL_MAP_BASE + SEMA_PAGE_SIZE) + return; + for (i = 0; i < SVC_MAX_CHANNELS; i++) + if (svc.chan[i].valid && svc.chan[i].h_object == h && + svc.chan[i].engine_type) + break; + if (i == SVC_MAX_CHANNELS) + return; + tva = SVC_UVM_POOL_MAP_BASE + 4ULL * + ((u64)svc.chan[i].ce_index + 1); + if (tva == va) + return; + if (svc_pool_pa_resolve(vgpu, h, tva, &addr, &ap, &src)) + return; + if (svc_read_ap(vgpu, addr, svc_ap_of(ap), &cur, sizeof(cur))) + return; + if (cur >= val) + return; + if (svc_write_ap(vgpu, addr, svc_ap_of(ap), &val, sizeof(val))) + return; + if (svc_read_ap(vgpu, addr, svc_ap_of(ap), &back, sizeof(back)) || + back != val) + return; + if (svc.pool_tracker_log < 64) { + svc.pool_tracker_log++; + pr_info("sema-svc: pool-tracker-wr ch=0x%x rank=%u va=0x%llx pa=0x%llx val=%u\n", + h, svc.chan[i].ce_index, tva, addr, val); + } +} + static int svc_sem_write(struct nv_vgpu_device *vgpu, u32 h, u64 va, u32 val) { u64 addr = 0, old_addr; @@ -5677,6 +5728,7 @@ static int svc_sem_write(struct nv_vgpu_device *vgpu, u32 h, u64 va, u32 val) svc_pool_wr_note(h, va, addr, src, cur, val, "ok"); svc_pool_alt_apply(vgpu, h, va, val); svc_pool_boot_fanout(vgpu, h, va, val); + svc_pool_tracker_apply(vgpu, h, va, val); } return 0; } @@ -5717,6 +5769,7 @@ static int svc_sem_write(struct nv_vgpu_device *vgpu, u32 h, u64 va, u32 val) "advisory"); svc_pool_alt_apply(vgpu, h, va, val); svc_pool_boot_fanout(vgpu, h, va, val); + svc_pool_tracker_apply(vgpu, h, va, val); } return 0; /* the original write landed; read-back is advisory */ } -- cgit v1.2.3