diff options
| author | Arthur Hanson Rasmusson <arthur@vgpu.io> | 2026-11-12 20:01:04 -0500 |
|---|---|---|
| committer | Arthur Hanson Rasmusson <arthur@vgpu.io> | 2026-11-12 20:01:04 -0500 |
| commit | 725898e44666b4def396f7f3c5e50712fd37aa33 (patch) | |
| tree | 261bba910db49036624cc2cf89baac6554a6f58d /tools/guest-diag/gpa.py | |
| parent | 800c108f9d2463066a221a0e4ff56867304551a6 (diff) | |
| download | open-iov-725898e44666b4def396f7f3c5e50712fd37aa33.tar.gz open-iov-725898e44666b4def396f7f3c5e50712fd37aa33.zip | |
vgsp: stop fabricating 0xFFFF into the nvPush error notifier; add r1780 GL ops tooling
The uncommitted keep-alive change wrote 0xFFFF into slot 0's status field
(u16 at notifier+0x0e) on the X DDX / GLX kick-idle channel families. Ground
truth (570.144 reference sources + stock nvidia_drv.so disassembly): slot 0
of an nvPush notifier block is the ERROR notifier; nvPushCheckChannelError
reads that status and 0xFFFF aborts every nvPushWaitForNotifier/idle wait as
a channel error. There is no pb_kickIfIdle in 570.144 - the DDX DMA-idle
test reads the progress-tracker semaphore word, not this slot. Leave slot 0
untouched; keep the 0x8000->0 completion ack for the remaining slots and the
r864 0xFFFF/0x8000 completion on the RC-watchdog/beef families. Correct the
CONT.408/409 comments accordingly.
New host/guest tooling: gpa.py (QMP gva2gpa), tick_gen.py (guest-RM timer
BO tick), guest_mode.sh (shared nvClip modeNum reader), gl_verify.sh
(X/GLX bring-up with ScreenInit-lottery retries), push_gl_tools.sh, the
gzdoom_pbuf_run.sh guest recipe and the test_tri SDL2 harness validation
program; ignore tools/guest-diag/build/.
Diffstat (limited to 'tools/guest-diag/gpa.py')
| -rwxr-xr-x | tools/guest-diag/gpa.py | 82 |
1 files changed, 82 insertions, 0 deletions
diff --git a/tools/guest-diag/gpa.py b/tools/guest-diag/gpa.py new file mode 100755 index 0000000..61ba27b --- /dev/null +++ b/tools/guest-diag/gpa.py @@ -0,0 +1,82 @@ +#!/usr/bin/env python3 +# SPDX-License-Identifier: BSD-3-Clause +# Copyright (c) 2026 Open-IOV contributors +# gpa.py - translate a guest virtual address to a guest physical address via +# the QEMU monitor's HMP `gva2gpa`, reusing the QMP client in semfix_watch.py. +# +# Usage: sudo python3 tools/guest-diag/gpa.py <gva_hex> [--offset] +# <gva_hex> guest VA, e.g. 0xffffc90000000000 or 0x7f... +# --offset also print the /dev/shm/vgpu-guest-ram file offset +# (gpa - 0x80000000) +# +# The monitor's `gva2gpa` translates with the selected CPU's CR3; while a CPU +# runs user code under PTI the kernel half is hidden, so retry across CPUs +# exactly like semfix_watch.Qmp.gva2gpa does. On failure the raw monitor text +# is printed so the operator can see the reason (unmapped VA, no guest, ...). +import argparse +import os +import re +import sys + +HERE = os.path.dirname(os.path.abspath(__file__)) +sys.path.insert(0, HERE) +from semfix_watch import Qmp # noqa: E402 + +QMP_SOCK = os.environ.get("QMP_SOCK", "/tmp/qemu-qmp.sock") +RAM_BASE = 0x80000000 + + +def parse_va(text): + text = text.strip() + try: + return int(text, 0) + except ValueError: + return int(text, 16) + + +def translate(q, va): + """Return (gpa, raw_hmp_text) or (None, last_raw_text).""" + last = "" + for cpu in q._cpu_order(): + q._set_cpu(cpu) + out = q.hmp("gva2gpa 0x%x" % va) + last = out.strip() + m = re.search(r"gpa:\s*0x([0-9a-fA-F]+)", out) + if m: + return int(m.group(1), 16), last + return None, last + + +def main(): + ap = argparse.ArgumentParser(add_help=True) + ap.add_argument("gva", help="guest virtual address (hex, 0x prefix optional)") + ap.add_argument("--offset", action="store_true", + help="also print gpa - 0x80000000 (guest RAM file offset)") + ap.add_argument("--qmp", default=QMP_SOCK, help="QMP socket path") + args = ap.parse_args() + + va = parse_va(args.gva) + if not os.path.exists(args.qmp): + print("gpa: QMP socket not found: %s" % args.qmp, file=sys.stderr) + return 2 + try: + q = Qmp(args.qmp) + except Exception as exc: # noqa: BLE001 - diagnostic surface + print("gpa: cannot connect to %s: %s" % (args.qmp, exc), file=sys.stderr) + return 2 + + gpa, text = translate(q, va) + if gpa is None: + print("gpa: gva2gpa 0x%x failed" % va, file=sys.stderr) + if text: + print(text, file=sys.stderr) + return 1 + + print("GPA 0x%x" % gpa) + if args.offset: + print("OFFSET 0x%x" % (gpa - RAM_BASE)) + return 0 + + +if __name__ == "__main__": + sys.exit(main()) |
