summaryrefslogtreecommitdiffstats
path: root/tools/guest-diag
diff options
context:
space:
mode:
authorArthur Hanson Rasmusson <arthur@vgpu.io>2026-09-30 03:15:57 -0400
committerArthur Hanson Rasmusson <arthur@vgpu.io>2026-09-30 03:15:57 -0400
commit8b0f657ec4683f2e332d72ed82cc5f94765b0837 (patch)
tree097110579eff62d53b6fe77f5b82306fb7eb1a0b /tools/guest-diag
parent57ea6ed69189f69c3a3d3a47972da0411bc92e91 (diff)
downloadopen-iov-8b0f657ec4683f2e332d72ed82cc5f94765b0837.tar.gz
open-iov-8b0f657ec4683f2e332d72ed82cc5f94765b0837.zip
guest-diag: bpz16 - live-probe chip-info vtable + 0xc48/0xc4c at the failing call
Diffstat (limited to 'tools/guest-diag')
-rw-r--r--tools/guest-diag/bpz16.py71
-rwxr-xr-xtools/guest-diag/push_guest_tools.sh1
2 files changed, 72 insertions, 0 deletions
diff --git a/tools/guest-diag/bpz16.py b/tools/guest-diag/bpz16.py
new file mode 100644
index 0000000..c67175d
--- /dev/null
+++ b/tools/guest-diag/bpz16.py
@@ -0,0 +1,71 @@
+# gdb script: probe the guest's chip-info vtable call (ds->[0x4d38]) and the
+# 0xc48/0xc4c fields at the FUN_003e3e80 call from FUN_00e0e970.
+#
+# Host oracle: FUN_00338f70(ChipId=0x160, Rev=4) -> out (0xc48=6, 0xc4c=0x27,
+# 0xc50=7, 0xc54=5). Guest FAILS the 0xc4c switch -> 0xe94 stays 0.
+# This calls ds->[0x4d38] in-process to see what the guest returns.
+#
+# Run: sudo gdb -p <cdt-pid> -batch -x /tmp/bpz16.py
+import gdb
+import time
+
+out = gdb.execute("info proc mappings", to_string=True)
+base = None
+lo = hi = 0
+for line in out.splitlines():
+ if "libcuda" in line:
+ f = line.split()
+ b = int(f[0], 16)
+ lo, hi = b, b + int(f[1], 16)
+ if "r-xp" in line:
+ base = b - int(f[3], 16)
+print("BASE=0x%x libcuda=[0x%x,0x%x)" % (base or 0, lo, hi))
+if base is None:
+ raise SystemExit
+
+gdb.execute("set pagination off")
+gdb.execute("set confirm off")
+CALLER_RET = base + 0xd0eae1
+gdb.execute("break *0x%x" % (base + 0x2e3e80))
+
+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()
+for hit in range(300):
+ try:
+ gdb.execute("continue")
+ except gdb.error as e:
+ print("CONTINUE_END %s" % e)
+ break
+ 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("FUN_003e3e80 dev=0x%x ds=0x%x t=%.3f" % (rdi, ds or 0, time.time() - t0))
+ for off in [0xc48, 0xc4c, 0xc50, 0xc54, 0xe94, 0xf5c, 0x5330]:
+ print(" ds+0x%x = 0x%x" % (off, rd(ds + off) or 0))
+ fn = rd(ds + 0x4d38, 8, "unsigned long")
+ print(" ds->[0x4d38] = 0x%x in_libcuda=%s" % (fn or 0, lo <= (fn or 0) < hi))
+ if fn and lo <= fn < hi:
+ sp = (int(gdb.parse_and_eval("$rsp")) - 0x200) & ~0xf
+ try:
+ gdb.execute("set $chip = 0x%x" % (sp + 0x10))
+ gdb.execute("set $rev = 0x%x" % (sp + 0x20))
+ res = int(gdb.parse_and_eval(
+ "((unsigned int (*)(unsigned long, unsigned long, unsigned long))0x%x)(0x%x, $chip, $rev)"
+ % (fn, ds)))
+ print(" CALL ret=0x%x chip=0x%x rev=0x%x" %
+ (res, rd(sp + 0x10) or 0xdead, rd(sp + 0x20) or 0xdead))
+ except Exception as e:
+ print(" CALL failed: %s" % e)
+ break
+
+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 68d4e64..ffb9b29 100755
--- a/tools/guest-diag/push_guest_tools.sh
+++ b/tools/guest-diag/push_guest_tools.sh
@@ -42,6 +42,7 @@ push_b64 "$HERE/bpz11.py" /tmp/bpz11.py
push_b64 "$HERE/bpz12.py" /tmp/bpz12.py
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/invd.py" /tmp/invd.py
push_b64 "$HERE/bpwait.py" /tmp/bpwait.py
push_b64 "$HERE/ctx999.py" /tmp/ctx999.py