summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--kernel/gsp_sema_service.c39
-rwxr-xr-xtools/guest-diag/semfix_uvmt.py8
-rw-r--r--tools/guest-diag/semfix_watch.py7
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
@@ -2506,6 +2506,32 @@ static void svc_decode_stream(struct nv_vgpu_device *vgpu, const u8 *buf,
}
/*
+ * 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.
* Execute it here, independently of whether the
@@ -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):