diff options
| author | Arthur Hanson Rasmusson <arthur@vgpu.io> | 2026-09-29 13:18:00 -0400 |
|---|---|---|
| committer | Arthur Hanson Rasmusson <arthur@vgpu.io> | 2026-09-29 13:18:00 -0400 |
| commit | e4ef588ad0536095aed852acaa765a115edcb75d (patch) | |
| tree | 0ac5e8bf4d2f023678d1d413a4684c5cfbcb38fd /tools/guest-diag | |
| parent | 4c591d2579f97d25609368222f0a3c95eed413c4 (diff) | |
| download | open-iov-e4ef588ad0536095aed852acaa765a115edcb75d.tar.gz open-iov-e4ef588ad0536095aed852acaa765a115edcb75d.zip | |
guest-diag: resolve pushbuffer from uvpbf kprobe pointer (deterministic)
Diffstat (limited to 'tools/guest-diag')
| -rw-r--r-- | tools/guest-diag/semfix_watch.py | 45 |
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: |
