summaryrefslogtreecommitdiffstats
path: root/tools/guest-diag
diff options
context:
space:
mode:
authorArthur Hanson Rasmusson <arthur@vgpu.io>2026-10-25 17:53:37 -0400
committerArthur Hanson Rasmusson <arthur@vgpu.io>2026-10-25 17:53:37 -0400
commit4ae5090563a3e1ab5277eb949eed36fe47316410 (patch)
tree988d1acc92c31aa412948ff025a32abce3f02ce3 /tools/guest-diag
parent50e293e39fc322fce3221c01a2a7219d49f618d1 (diff)
downloadopen-iov-4ae5090563a3e1ab5277eb949eed36fe47316410.tar.gz
open-iov-4ae5090563a3e1ab5277eb949eed36fe47316410.zip
vgsp-sema/wall2: host-triggered VAS pdb discovery (sema_pdb_discover va,pa -> verify the parked COPY_SERVER_PDES candidates against a content-verified ring pair, then fall back to the vidmem walk-root sweep) and a runtime-tunable candidate age-out (sema_vas_cand_ms; the default 15 s ages the client's candidate out exactly when its channels first register); tools: fasttick.py (triggers on the GR0 ring resolution line) and pdbtick.py (content-locates the ring page and triggers) - r706/r707 evidence: three parked candidates (0x11cd3d000/0x11cd48000/0x11cd50000 entries=4), the ring pair appears only at channel registration (the same second as the age-out), ring resolution is racy across runs (r706 rc=0 / r707 rc=-2), the skip starts 145-194 rescues (~8-10 s) after the submit; next run: keep candidates parked + trigger within the window
Diffstat (limited to 'tools/guest-diag')
-rw-r--r--tools/guest-diag/wall2/fasttick.py44
-rw-r--r--tools/guest-diag/wall2/pdbtick.py55
2 files changed, 99 insertions, 0 deletions
diff --git a/tools/guest-diag/wall2/fasttick.py b/tools/guest-diag/wall2/fasttick.py
new file mode 100644
index 0000000..413d3ba
--- /dev/null
+++ b/tools/guest-diag/wall2/fasttick.py
@@ -0,0 +1,44 @@
+#!/usr/bin/env python3
+# fasttick.py - watch the service log for the GR0 channel's ring resolution
+# (sema-chan: h=0xbeec0100 ... ring rc=0 pa=0x...) and immediately hand the
+# verified {ring VA -> ring PA} pair to the service (sema_pdb_discover), so
+# the parked VAS pdb candidate can be verified before/at age-out.
+import re, subprocess, sys, time
+
+PARAM = "/sys/module/vgsp/parameters/sema_pdb_discover"
+RING_VA = 0x4cc0000
+
+def main():
+ dur = float(sys.argv[1]) if len(sys.argv) > 1 else 120
+ end = time.time() + dur
+ fired = set()
+ seen_pdbs = set()
+ print("# fasttick start (%.0fs)" % dur, flush=True)
+ while time.time() < end:
+ out = subprocess.run(["sudo", "dmesg"], capture_output=True).stdout.decode(errors="ignore")
+ tail = out.splitlines()[-120:]
+ for ln in tail:
+ m = re.search(r"sema-chan: h=0xbeec0100 eng=\d+ cid=\d+ gpfifo=0x([0-9a-f]+) ent=\d+ userd=0x[0-9a-f]+ as=\d+ put=\d+ get=\d+ ring rc=0 pa=0x([0-9a-f]+)", ln)
+ if m:
+ ring_va = int(m.group(1), 16)
+ ring_pa = int(m.group(2), 16)
+ key = (ring_va, ring_pa)
+ if key not in fired:
+ fired.add(key)
+ cmd = "echo 0x%x,0x%x > %s" % (ring_va, ring_pa, PARAM)
+ r = subprocess.run(["sudo", "sh", "-c", cmd], capture_output=True)
+ print("[%s] TRIGGER va=0x%x pa=0x%x rc=%d" % (
+ time.strftime("%H:%M:%S"), ring_va, ring_pa, r.returncode), flush=True)
+ m2 = re.search(r"page directory (?:registered UNVERIFIED after \d+ ms parked \()?pdb=0x([0-9a-f]+) entries=(\d+)", ln)
+ if not m2:
+ m2 = re.search(r"VA space 0x[0-9a-f]+ page directory 0x([0-9a-f]+) entries=(\d+)", ln)
+ if m2:
+ key = int(m2.group(1), 16)
+ if key not in seen_pdbs:
+ seen_pdbs.add(key)
+ print("[%s] PDB candidate 0x%x entries=%s" % (
+ time.strftime("%H:%M:%S"), key, m2.group(2)), flush=True)
+ time.sleep(0.3)
+ print("# fasttick end", flush=True)
+
+main()
diff --git a/tools/guest-diag/wall2/pdbtick.py b/tools/guest-diag/wall2/pdbtick.py
new file mode 100644
index 0000000..35b9ab8
--- /dev/null
+++ b/tools/guest-diag/wall2/pdbtick.py
@@ -0,0 +1,55 @@
+#!/usr/bin/env python3
+# pdbtick.py - content-locate the GR0 ring page (deterministic first three
+# GPFIFO entries) in the guest RAM file, then hand the verified
+# {ring VA -> ring PA} pair to the service (sema_pdb_discover), which
+# verifies the parked COPY_SERVER_PDES candidates and falls back to the
+# vidmem walk-root sweep. Runs while the client is alive.
+import mmap, struct, subprocess, sys, threading, time
+
+F = "/dev/shm/vgpu-guest-ram"
+PARAM = "/sys/module/vgsp/parameters/sema_pdb_discover"
+PAT = struct.pack("<QQQ", 0x0005980004ca0000, 0x8000040004ca0598,
+ 0x0003d00004ca059c)
+RING_VA = 0x4cc0000
+
+def gpa_of(x):
+ return x if x < 0x80000000 else x - 0x80000000 + 0x100000000
+
+def main():
+ fobj = open(F, "rb")
+ mm = mmap.mmap(fobj.fileno(), 0, access=mmap.ACCESS_READ)
+ size = len(mm)
+ nthr = 8
+ step = size // nthr
+ res = []
+ lock = threading.Lock()
+ def worker(a, b):
+ CH = 8 << 20
+ off = a
+ while off < b:
+ d = mm[off:off + CH]
+ i = d.find(PAT)
+ while i >= 0:
+ with lock:
+ res.append(off + i)
+ i = d.find(PAT, i + 1)
+ off += CH - 64
+ ts = []
+ for k in range(nthr):
+ a = k * step
+ b = (k + 1) * step if k < nthr - 1 else size
+ t = threading.Thread(target=worker, args=(a, b)); t.start(); ts.append(t)
+ for t in ts: t.join()
+ if not res:
+ print("RING NOT FOUND"); return 1
+ # prefer the most recently written: check which page's entries beyond the
+ # first three match this run's full 16-entry sequence; else take the last
+ hits = [gpa_of(x) for x in res]
+ print("ring candidates:", [hex(h) for h in hits])
+ for gpa in hits:
+ cmd = "echo 0x%x,0x%x > %s" % (RING_VA, gpa, PARAM)
+ r = subprocess.run(["sudo", "sh", "-c", cmd], capture_output=True)
+ print("sema_pdb_discover 0x%x,0x%x rc=%d" % (RING_VA, gpa, r.returncode))
+ return 0
+
+sys.exit(main())