diff options
| author | Arthur Hanson Rasmusson <arthur@vgpu.io> | 2026-09-28 13:27:31 -0400 |
|---|---|---|
| committer | Arthur Hanson Rasmusson <arthur@vgpu.io> | 2026-09-28 13:27:31 -0400 |
| commit | f3a10d9a117bbc1eeec121fe6f726e9199a3c89a (patch) | |
| tree | 03f27c985bffbd4fe3281a931388bee29c1b3f43 | |
| parent | 6ac574eb67b478cb48ddfbd6e77f4613698020c7 (diff) | |
| download | open-iov-f3a10d9a117bbc1eeec121fe6f726e9199a3c89a.tar.gz open-iov-f3a10d9a117bbc1eeec121fe6f726e9199a3c89a.zip | |
guest-diag: ctx999.py (scanner/ctx gdb capture); fix pinner exact-VA match
ctx999.py arms the scanner entry/returns plus cuCtxCreate and dumps the
ctx->mgr->reg->record chain at the stop. First live capture: the scanner is
called with param_2=1 during normal context creation and correctly returns 0
on a zero record (mgr[+0], the channel handle, and the record walk are now
confirmed live). pin_miss_pages.sh must match the exact VA pmapall printed:
guest_pmap_all.py returns the first nvidia page at-or-above va-min, so a page
that is not present resolves to an unrelated mapping (it pinned a UVM page
for 0x20400f000).
| -rw-r--r-- | tools/guest-diag/ctx999.py | 102 | ||||
| -rwxr-xr-x | tools/guest-diag/pin_miss_pages.sh | 2 |
2 files changed, 103 insertions, 1 deletions
diff --git a/tools/guest-diag/ctx999.py b/tools/guest-diag/ctx999.py new file mode 100644 index 0000000..e5472c8 --- /dev/null +++ b/tools/guest-diag/ctx999.py @@ -0,0 +1,102 @@ +# gdb script: catch where a hanging/failing cuCtxCreate goes. +# +# Arms the libcuda 999-scanner sites (FUN_0054fa00 entry/999/0x2cf returns) +# plus cuCtxCreate (symbol), then: +# - at the first stop: dump RIP, backtrace and, if it is a scanner frame, +# the RM error record chain (rdi -> ctx -> ctx[0x1291] -> +0x10 -> +0x10); +# - then `finish` to capture the return value (rax) of whatever frame it +# stopped in, and a backtrace of the caller. +# Use with a cdt that holds on failure (CDT_HOLD=<s>) so the state survives. +# Run: sudo gdb -p <cdt-pid> -batch -x /tmp/ctx999.py +import gdb + +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: + print("NO_LIBCUDA_MAPPING") + raise SystemExit +gdb.execute("set pagination off") +gdb.execute("set confirm off") +for off in (0x44fa00, 0x44fb80, 0x44fb6c): + gdb.execute("break *0x%x" % (base + off)) +try: + gdb.execute("break cuCtxCreate") +except gdb.error as e: + print("break cuCtxCreate: %s" % e) +try: + gdb.execute("continue") +except gdb.error as e: + print("CONTINUE_ERR %s" % e) +print("STOPPED") +try: + rip = int(gdb.parse_and_eval("$rip")) & 0xffffffffffffffff + print("RIP=0x%x off=0x%x" % (rip, rip - base)) +except Exception as e: + print("rip_fail %s" % e) +try: + print(gdb.execute("info registers rdi rsi rax", to_string=True)) +except Exception: + pass +try: + print(gdb.execute("bt 12", to_string=True)) +except Exception as e: + print("bt_fail %s" % e) + + +def rd64(addr): + try: + return int(gdb.parse_and_eval("*(unsigned long *)0x%x" % addr)) & 0xffffffffffffffff + except Exception: + return None + + +def rd32(addr): + try: + return int(gdb.parse_and_eval("*(unsigned int *)0x%x" % addr)) & 0xffffffff + except Exception: + return None + + +try: + p1 = int(gdb.parse_and_eval("$rdi")) & 0xffffffffffffffff + ctx = rd64(p1) + print("param_1=0x%x ctx=0x%x" % (p1, ctx or 0)) + if ctx: + mgr = rd64(ctx + 0x1291 * 8) + print("mgr=0x%x" % (mgr or 0)) + if mgr: + for mo in (0x0, 0x8, 0x10, 0x18, 0x38): + print(" mgr[+0x%x]=0x%x" % (mo, rd64(mgr + mo) or 0)) + reg = rd64(mgr + 0x10) + print("reg=0x%x" % (reg or 0)) + if reg: + rec = rd64(reg + 0x10) + print("rec=0x%x" % (rec or 0)) + if rec: + for i in range(0, 0x28, 4): + print(" rec[+0x%02x]=0x%08x" % (i, rd32(rec + i) or 0)) +except Exception as e: + print("record_dump_fail %s" % e) + +try: + gdb.execute("finish") + print("FINISHED") + print(gdb.execute("info registers rax", to_string=True)) +except gdb.error as e: + print("finish_err %s" % e) +except Exception as e: + print("finish_other %s" % e) +try: + print(gdb.execute("bt 12", to_string=True)) +except Exception: + pass +try: + gdb.execute("detach") +except Exception: + pass diff --git a/tools/guest-diag/pin_miss_pages.sh b/tools/guest-diag/pin_miss_pages.sh index 80b8c77..77268ef 100755 --- a/tools/guest-diag/pin_miss_pages.sh +++ b/tools/guest-diag/pin_miss_pages.sh @@ -43,7 +43,7 @@ for ((i = 1; i <= MAXMIN * 4; i++)); do *" $page "*) continue ;; esac line=$(EXEC "sudo python3 /tmp/pmapall.py $pid $page 1" | - grep -aE '^0x[0-9a-f]+,0x[0-9a-f]+$' | head -1) + grep -aE "^$page,0x[0-9a-f]+$" | head -1) if [ -n "$line" ]; then echo "$line,0x1000,1" | sudo tee /sys/module/open_iov_vfio/parameters/sema_map_add >/dev/null echo "[$((i * 15))s] pinned $line (pid $pid)" |
