From 74fb010669c351eb9eeba733fae6e000fdff34dd Mon Sep 17 00:00:00 2001 From: Arthur Hanson Rasmusson Date: Tue, 29 Sep 2026 15:34:18 -0400 Subject: sema-svc: apply releases before push memsets; poller: bypass read cache --- kernel/gsp_sema_service.c | 39 ++++++++++++++++++++++++++------------- tools/guest-diag/semfix_uvmt.py | 8 ++++---- tools/guest-diag/semfix_watch.py | 7 ++++--- 3 files changed, 34 insertions(+), 20 deletions(-) diff --git a/kernel/gsp_sema_service.c b/kernel/gsp_sema_service.c index a04a3c2..0c0e85b 100644 --- a/kernel/gsp_sema_service.c +++ b/kernel/gsp_sema_service.c @@ -2505,6 +2505,32 @@ static void svc_decode_stream(struct nv_vgpu_device *vgpu, const u8 *buf, pending = 1; } + /* + * Apply the release BEFORE running the push's + * collected work. The client's tracker only + * observes the release, and its context-init + * deadline is what the whole run races against; + * running the memsets first added their full + * execution time to every push's visible + * completion latency. Ordering is still safe: + * this is the only writer of both the semaphore + * and the vidmem shadow, and the next push is + * not decoded until this call returns. + */ + if (pending) { + svc.pushes_pending++; + if (DMA_SEM_REDUCTION_EN(dma) && + DMA_SEM_REDUCTION(dma) == + SEM_REDUCTION_INC) + cur += st.sem_payload; + else + cur = st.sem_payload; + if (!svc_sem_write(vgpu, sem_va, cur)) { + svc.releases_applied++; + svc.post_hint_until = jiffies + 10 * HZ; + } + } + /* * The push's collected work always runs on real * hardware; the release only orders observers. @@ -2521,19 +2547,6 @@ static void svc_decode_stream(struct nv_vgpu_device *vgpu, const u8 *buf, svc.ring_ops++; ops_runs++; } - if (pending) { - svc.pushes_pending++; - if (DMA_SEM_REDUCTION_EN(dma) && - DMA_SEM_REDUCTION(dma) == - SEM_REDUCTION_INC) - cur += st.sem_payload; - else - cur = st.sem_payload; - if (!svc_sem_write(vgpu, sem_va, cur)) { - svc.releases_applied++; - svc.post_hint_until = jiffies + 10 * HZ; - } - } /* * Exact-slot fallback: the releasing channel's diff --git a/tools/guest-diag/semfix_uvmt.py b/tools/guest-diag/semfix_uvmt.py index fb0e92e..02d4f9e 100755 --- a/tools/guest-diag/semfix_uvmt.py +++ b/tools/guest-diag/semfix_uvmt.py @@ -109,21 +109,21 @@ def uvmt_state(q, sem): cpu_va + idx*4 (its GPU alias is gpu_va + idx*4, the VA the releasing push writes). """ - vals = q.read64(sem, 12) + vals = q.read64(sem, 12, cache=False) if len(vals) < 2 or not is_kern(vals[0]): return None - pv = q.read64(vals[0]) + pv = q.read64(vals[0], cache=False) if not pv or not is_kern(pv[0]): return None mem = pv[0] - vas = q.read64(mem + 0x10, 16) + vas = q.read64(mem + 0x10, 16, cache=False) cpu = next((v for v in vas if is_kern(v)), None) gpu = [v for v in vas if is_gpu(v)] idx = vals[1] & 0xffff payload = None word_pa = None if cpu is not None: - w = q.read64(cpu + idx * 4) + w = q.read64(cpu + idx * 4, cache=False) payload = w[0] if w else None word_pa = q.gva2gpa(cpu + idx * 4) word_va = (gpu[0] + idx * 4) if gpu else None diff --git a/tools/guest-diag/semfix_watch.py b/tools/guest-diag/semfix_watch.py index 1fc6b01..1c33de6 100644 --- a/tools/guest-diag/semfix_watch.py +++ b/tools/guest-diag/semfix_watch.py @@ -96,16 +96,17 @@ class Qmp: def hmp(self, line): return self.cmd("human-monitor-command", **{"command-line": line}).get("return", "") - def read64(self, addr, n=1): + def read64(self, addr, n=1, cache=True): key = (addr, n) - if key in self._cache: + if cache and key in self._cache: return self._cache[key] out = self.hmp("x/%dgx 0x%x" % (n, addr)) m = re.search(r":(.*)$", out, re.S) if not m: return [] vals = [int(x, 16) for x in re.findall(r"0x([0-9a-fA-F]+)", m.group(1))][:n] - self._cache[key] = vals + if cache: + self._cache[key] = vals return vals def gva2gpa(self, va): -- cgit v1.2.3