summaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authorArthur Hanson Rasmusson <arthur@vgpu.io>2026-09-30 03:34:33 -0400
committerArthur Hanson Rasmusson <arthur@vgpu.io>2026-09-30 03:34:33 -0400
commit9b6d5521bfde18e80207ca9f7d0230f8df47eb3c (patch)
treee2be0798175666922a88345b2f7e2cfb4e446a11 /tools
parent2f264a02e530624f7547a611619464888a2a50e6 (diff)
downloadopen-iov-9b6d5521bfde18e80207ca9f7d0230f8df47eb3c.tar.gz
open-iov-9b6d5521bfde18e80207ca9f7d0230f8df47eb3c.zip
guest-diag: bpz20 - watchpoint on ds+0xe94 to catch the zeroing write
Diffstat (limited to 'tools')
-rw-r--r--tools/guest-diag/bpz20.py78
-rwxr-xr-xtools/guest-diag/push_guest_tools.sh1
2 files changed, 79 insertions, 0 deletions
diff --git a/tools/guest-diag/bpz20.py b/tools/guest-diag/bpz20.py
new file mode 100644
index 0000000..cf8ee8c
--- /dev/null
+++ b/tools/guest-diag/bpz20.py
@@ -0,0 +1,78 @@
+# gdb script: catch the write that ZEROES ds+0xe94 after the CASE1 body set
+# it to 0x18. Run via run_cycle.sh gdb-launch (device init happens during
+# cuInit, before the CDT_PAUSE).
+#
+# bpz18 showed: CASE1 (0x32e8be) hit at t=0.24; at FUN_003e3e80 (t=72.9)
+# ds+0xe94 == 0. Set a hardware watchpoint at the CASE1 hit and log every
+# write with a backtrace.
+import gdb
+import time
+
+gdb.execute("set pagination off")
+gdb.execute("set confirm off")
+gdb.execute("set environment CDT_PAUSE=60")
+gdb.execute("set environment CDT_HOLD=900")
+gdb.execute("catch load libcuda.so")
+gdb.execute("run")
+out = gdb.execute("info proc mappings", to_string=True)
+base = None
+for line in out.splitlines():
+ if "libcuda" in line and "r-xp" in line:
+ f = line.split()
+ base = int(f[0], 16) - int(f[3], 16)
+ break
+print("BASE=0x%x" % (base or 0))
+if base is None:
+ raise SystemExit
+
+CASE1 = base + 0x32e8be
+TERM = base + 0x2e3e80
+CALLER_RET = base + 0xd0eae1
+gdb.execute("break *0x%x" % CASE1)
+gdb.execute("break *0x%x" % TERM)
+
+def rd(addr, n=4, fmt="unsigned int"):
+ try:
+ return int(gdb.parse_and_eval("*(%s*)0x%x" % (fmt, addr))) & ((1 << (8 * n)) - 1)
+ except Exception:
+ return None
+
+t0 = time.time()
+watched = False
+for hit in range(200):
+ try:
+ gdb.execute("continue")
+ except gdb.error as e:
+ print("CONTINUE_END %s" % e)
+ break
+ rip = int(gdb.parse_and_eval("$rip")) & 0xffffffffffffffff
+ if rip == CASE1 and not watched:
+ rc = int(gdb.parse_and_eval("$rcx")) & 0xffffffffffffffff
+ gdb.execute("delete 1")
+ gdb.execute("set $wpaddr = 0x%x" % (rc + 0xe94))
+ gdb.execute("watch *(int*)$wpaddr")
+ watched = True
+ print("WATCH set on ds=0x%x +0xe94 (t=%.3f)" % (rc, time.time() - t0))
+ continue
+ if rip == TERM:
+ ret = rd(int(gdb.parse_and_eval("$rsp")), 8, "unsigned long")
+ if ret != CALLER_RET:
+ continue
+ rdi = int(gdb.parse_and_eval("$rdi")) & 0xffffffffffffffff
+ ds = rd(rdi + 0x40, 8, "unsigned long")
+ print("TERMINATOR t=%.3f ds=0x%x e94=0x%x c4c=0x%x" %
+ (time.time() - t0, ds or 0, rd(ds + 0xe94) or 0, rd(ds + 0xc4c) or 0))
+ break
+ # watchpoint hit
+ addr = int(gdb.parse_and_eval("$wpaddr")) & 0xffffffffffffffff
+ val = rd(addr) or 0
+ print("WP hit t=%.3f pc=+0x%x val=0x%x" % (time.time() - t0, rip - base, val))
+ try:
+ print(gdb.execute("bt 6", to_string=True))
+ except Exception:
+ pass
+
+try:
+ gdb.execute("detach")
+except Exception:
+ pass
diff --git a/tools/guest-diag/push_guest_tools.sh b/tools/guest-diag/push_guest_tools.sh
index 9014144..ad1f310 100755
--- a/tools/guest-diag/push_guest_tools.sh
+++ b/tools/guest-diag/push_guest_tools.sh
@@ -44,6 +44,7 @@ push_b64 "$HERE/bpz13.py" /tmp/bpz13.py
push_b64 "$HERE/bpz14.py" /tmp/bpz14.py
push_b64 "$HERE/bpz16.py" /tmp/bpz16.py
push_b64 "$HERE/bpz18.py" /tmp/bpz18.py
+push_b64 "$HERE/bpz20.py" /tmp/bpz20.py
push_b64 "$HERE/bpz19.py" /tmp/bpz19.py
push_b64 "$HERE/invd.py" /tmp/invd.py
push_b64 "$HERE/bpwait.py" /tmp/bpwait.py