From 903ce168ca1ec9206a23aea66e9008346def74e2 Mon Sep 17 00:00:00 2001 From: Arthur Hanson Rasmusson Date: Tue, 29 Sep 2026 15:45:33 -0400 Subject: sema-svc: learn GR counter PA from pinned release VA (auto-register, publish puts) --- kernel/gsp_sema_service.c | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/kernel/gsp_sema_service.c b/kernel/gsp_sema_service.c index e21c997..d4cab22 100644 --- a/kernel/gsp_sema_service.c +++ b/kernel/gsp_sema_service.c @@ -2111,6 +2111,39 @@ static void svc_counter_release_apply(struct nv_vgpu_device *vgpu, u32 h, h, pa, payload, cur); } +/* + * Learn a GR channel's completion-counter guest PA from a release VA the + * push carried, so the publish path can advance the exact slot the client + * polls without any guest-side enumeration. Only a host-verified translation + * (pin/ipin) is trusted; the release VA of a GR push is the counter slot + * itself (0x20400fXX observed). No-op once registered. + */ +static void svc_counter_learn(u32 h, u64 sem_va) +{ + unsigned long flags; + u64 pa = 0; + int ap = SVC_APERTURE_SYS; + int i; + + if (!h || sem_va < 0x204000000ULL || sem_va >= 0x204100000ULL) + return; + if (svc_pin_lookup_any(sem_va, &pa, &ap) || ap != SVC_APERTURE_SYS) + return; + + spin_lock_irqsave(&svc.chan_lock, flags); + for (i = 0; i < SVC_MAX_CHANNELS; i++) { + if (svc.chan[i].valid && svc.chan[i].h_object == h) { + if (!svc.chan[i].counter_pa) { + svc.chan[i].counter_pa = pa & ~0x3ULL; + pr_info("sema-chan: counter learned h=0x%x pa=0x%llx (from release va=0x%llx)\n", + h, pa & ~0x3ULL, sem_va); + } + break; + } + } + spin_unlock_irqrestore(&svc.chan_lock, flags); +} + static void svc_decode_stream(struct nv_vgpu_device *vgpu, const u8 *buf, u32 len, u64 page_pa, bool allow_ops, u32 ch_h, u32 ch_eng, u64 push_va, @@ -2557,6 +2590,14 @@ static void svc_decode_stream(struct nv_vgpu_device *vgpu, const u8 *buf, * translation. Same forward-only guard as the * VA path. */ + /* + * GR pushes release the per-channel completion + * counter; learn its guest PA from the (pinned) + * release VA so the publish path can advance the + * exact slot the client polls. + */ + if (ch_eng == 0) + svc_counter_learn(ch_h, sem_va); svc_counter_release_apply(vgpu, ch_h, st.sem_payload); /* release ends the push */ -- cgit v1.2.3