summaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authorArthur Hanson Rasmusson <arthur@vgpu.io>2026-09-29 13:18:00 -0400
committerArthur Hanson Rasmusson <arthur@vgpu.io>2026-09-29 13:18:00 -0400
commite4ef588ad0536095aed852acaa765a115edcb75d (patch)
tree0ac5e8bf4d2f023678d1d413a4684c5cfbcb38fd /tools
parent4c591d2579f97d25609368222f0a3c95eed413c4 (diff)
downloadopen-iov-e4ef588ad0536095aed852acaa765a115edcb75d.tar.gz
open-iov-e4ef588ad0536095aed852acaa765a115edcb75d.zip
guest-diag: resolve pushbuffer from uvpbf kprobe pointer (deterministic)
Diffstat (limited to 'tools')
-rw-r--r--tools/guest-diag/semfix_watch.py45
1 files changed, 39 insertions, 6 deletions
diff --git a/tools/guest-diag/semfix_watch.py b/tools/guest-diag/semfix_watch.py
index 0de5cad..8fd534d 100644
--- a/tools/guest-diag/semfix_watch.py
+++ b/tools/guest-diag/semfix_watch.py
@@ -87,16 +87,34 @@ def is_gpu(v):
return v and GPU_VA_LO <= v < GPU_VA_HI
-def guest_sems():
- """Kernel pointers of tracking semaphores the client is spinning on."""
+def guest_trace():
+ """(sem kptrs, pushbuffer kptrs) from the trace ring, then clear it."""
cmd = ("sudo sh -c 'echo > /sys/kernel/tracing/trace; sleep 2; "
- "grep uvmt /sys/kernel/tracing/trace | tail -4'")
+ "grep -E \"uvmt|uvpb\" /sys/kernel/tracing/trace | tail -8'")
try:
out = subprocess.run([VMEXEC, "exec", cmd], capture_output=True,
text=True, timeout=90).stdout
except Exception:
- return set()
- return {int(m, 16) for m in re.findall(r"sem=0x([0-9a-fA-F]+)", out)}
+ return set(), set()
+ sems = {int(m, 16) for m in re.findall(r"sem=0x([0-9a-fA-F]+)", out)}
+ pbs = {int(m, 16) for m in re.findall(r"pb=0x([0-9a-fA-F]+)", out)}
+ return sems, pbs
+
+
+def resolve_pb_ptr(q, pb):
+ """pushbuffer pointer -> rm_mem -> vas[] -> (gpu_vas, cpu, gpa)."""
+ mem = q.read64(pb + 8)
+ if not mem or not is_kern(mem[0]):
+ return [], None, None
+ vas = q.read64(mem[0] + 0x10, 16)
+ gpu_vas = [v for v in vas if PUSHBUF_VA_LO <= v < PUSHBUF_VA_HI]
+ cpu = next((v for v in vas if is_kern(v)), None)
+ if not gpu_vas or not cpu:
+ return [], None, None
+ gpa = q.gva2gpa(cpu)
+ if not gpa:
+ return [], None, None
+ return gpu_vas, cpu, gpa
def pin(va, pa):
@@ -201,10 +219,25 @@ def main():
interval = float(sys.argv[1]) if len(sys.argv) > 1 else 3.0
q = Qmp(QMP_SOCK)
seen = set()
+ seen_pb = set()
pb_done = False
print("semfix: watching (interval %.1fs)" % interval, flush=True)
while True:
- for sem in guest_sems() - seen:
+ sems, pbs = guest_trace()
+ if not pb_done:
+ for pb in pbs - seen_pb:
+ seen_pb.add(pb)
+ try:
+ gpu_vas, cpu, gpa = resolve_pb_ptr(q, pb)
+ except Exception as e:
+ print("semfix: pb=0x%x resolve failed: %s" % (pb, e), flush=True)
+ continue
+ if gpu_vas:
+ pin_pushbuffer(q, gpu_vas, cpu, gpa)
+ pb_done = True
+ break
+ print("semfix: pb=0x%x no pushbuffer rm_mem (retry)" % pb, flush=True)
+ for sem in sems - seen:
try:
pairs = resolve_sem_pool(q, sem)
except Exception as e: