diff options
| author | Arthur Hanson Rasmusson <arthur@vgpu.io> | 2026-09-29 08:53:11 -0400 |
|---|---|---|
| committer | Arthur Hanson Rasmusson <arthur@vgpu.io> | 2026-09-29 08:53:11 -0400 |
| commit | 26fce4914011914bb1e2ee520fe62e790326877e (patch) | |
| tree | 1151ba10251bbad9cd127abdf8a5ecf39b2d2947 /tools/guest-diag/read_va.py | |
| parent | 64bcfd6fd72546a2758d664bea39354604babcda (diff) | |
| download | open-iov-26fce4914011914bb1e2ee520fe62e790326877e.tar.gz open-iov-26fce4914011914bb1e2ee520fe62e790326877e.zip | |
tools: durable guest counter enumeration/injection and VA reader
The counter enumeration/injection workflow lived in the guest's /tmp and was
lost on every restart. Make it durable under tools/guest-diag:
- sem_counters.py: translate a process's per-channel u32 completion counters
(16-byte stride in the /dev/nvidiactl counter page) to guest PAs through
/proc/<pid>/pagemap; --pairs emits handle,va,pa triples.
- sem_slots.py: read/write the counter slots via /proc/<pid>/mem (fallback
for the host counter publish).
- read_va.py: hex dump a process VA (UVM sysmem GPU VAs are usually valid
CPU VAs in the owning process); --u32 for method streams.
- inject_counters.sh: host-side one-shot: push the tool, take the GR handles
from the live chan_dump, enumerate, then register each counter with
sema_counter and pin its VA with sema_map_add.
- push_guest_tools.sh: push the new tools after every VM start.
- launch_qemu_direct.sh: parameterized mdev UUID/paths instead of a stale
hardcoded one; committed so it survives checkouts.
Diffstat (limited to 'tools/guest-diag/read_va.py')
| -rwxr-xr-x | tools/guest-diag/read_va.py | 61 |
1 files changed, 61 insertions, 0 deletions
diff --git a/tools/guest-diag/read_va.py b/tools/guest-diag/read_va.py new file mode 100755 index 0000000..fca3994 --- /dev/null +++ b/tools/guest-diag/read_va.py @@ -0,0 +1,61 @@ +#!/usr/bin/env python3 +# read_va.py - dump a guest process's memory at a VA (GPU VAs of UVM sysmem +# objects are usually also valid CPU VAs in the owning process). +# +# Usage: +# sudo python3 read_va.py <pid> <va-hex> [len] [--u32] +# +# --u32 prints one little-endian u32 per line (method-stream friendly). +import os +import sys + + +def main(): + if len(sys.argv) < 3: + print(__doc__) + return 1 + pid = int(sys.argv[1]) + va = int(sys.argv[2], 16) + ln = 256 + as_u32 = False + for a in sys.argv[3:]: + if a == '--u32': + as_u32 = True + else: + ln = int(a, 0) + + found = False + with open('/proc/%d/maps' % pid) as f: + for line in f: + rng = line.split()[0] + a, b = rng.split('-') + if int(a, 16) <= va < int(b, 16): + print('MAP: %s' % line.strip()) + found = True + break + if not found: + print('VA 0x%x not in maps' % va) + + mem = os.open('/proc/%d/mem' % pid, os.O_RDONLY) + try: + data = os.pread(mem, ln, va) + except OSError as e: + print('read error: %s' % e) + return 1 + finally: + os.close(mem) + + if as_u32: + for i in range(0, len(data) - 3, 4): + print('+0x%03x: 0x%08x' % + (i, int.from_bytes(data[i:i + 4], 'little'))) + else: + for i in range(0, len(data), 16): + chunk = data[i:i + 16] + hexs = ' '.join('%02x' % b for b in chunk) + print('+0x%03x: %s' % (i, hexs)) + return 0 + + +if __name__ == '__main__': + sys.exit(main()) |
