summaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
Diffstat (limited to 'tools')
-rw-r--r--tools/guest-diag/fenceword_assist.py79
1 files changed, 79 insertions, 0 deletions
diff --git a/tools/guest-diag/fenceword_assist.py b/tools/guest-diag/fenceword_assist.py
new file mode 100644
index 0000000..3c45514
--- /dev/null
+++ b/tools/guest-diag/fenceword_assist.py
@@ -0,0 +1,79 @@
+#!/usr/bin/env python3
+# SPDX-License-Identifier: BSD-3-Clause
+# fenceword_assist.py - keep the Vulkan fence wait word of a live vk_frame120
+# client released (session 125).
+#
+# The client's fence wait polls a word in a 16 KB /dev/nvidiactl BO mapped
+# read-write into the client: the init wait word lives at +0x80 (the t122
+# "BW" chaser writes it once) and the per-submit fence word at +0x90 of the
+# SAME BO (GPU VA <base>+0x90, delivered by the submit push's INC-5 semaphore
+# group). While the emulation does not apply that group, this host assist
+# writes 1 to the +0x90 slot whenever it reads 0 - the direct predecessor of
+# the service-side fold (see Handoff SESSION 125).
+#
+# Usage (host, while a t122-driven client runs):
+# tools/guest-diag/fenceword_assist.py [seconds] [guest-pid]
+import os
+import subprocess
+import sys
+import time
+
+VMEXEC = os.path.normpath(os.path.join(os.path.dirname(os.path.abspath(__file__)),
+ "..", "..", "scripts", "vgpu_vm.py"))
+PY = r'''
+import struct, sys, time
+pids = [p for p in sys.argv[1:] if p]
+maps_of = {}
+def vma(pid, addr):
+ for line in open("/proc/%d/maps" % pid):
+ rng, perms = line.split(None, 2)[:2]
+ a, b = [int(x, 16) for x in rng.split("-")]
+ if a <= addr < b:
+ return line.strip()
+ return None
+found = {}
+for pid in pids:
+ try:
+ maps = [l for l in open("/proc/%d/maps" % pid) if "nvidia" in l and "rw-s" in l]
+ except OSError:
+ continue
+ for l in maps:
+ rng, perms, off = l.split(None, 3)[:3]
+ a, b = [int(x, 16) for x in rng.split("-")]
+ if b - a != 0x4000:
+ continue
+ try:
+ mem = open("/proc/%d/mem" % pid, "r+b", 0)
+ mem.seek(a + 0x80); init = mem.read(4)
+ mem.seek(a + 0x90); fw = mem.read(4)
+ except Exception:
+ continue
+ if init == b"\x01\x00\x00\x00" and fw == b"\x00\x00\x00\x00":
+ found[pid] = (a + 0x90, mem)
+ print("found pid=%s word=%#x" % (pid, a + 0x90), flush=True)
+end = time.time() + float(sys.argv[1])
+while time.time() < end:
+ for pid, (w, mem) in list(found.items()):
+ try:
+ mem.seek(w)
+ if mem.read(4) == b"\x00\x00\x00\x00":
+ mem.seek(w); mem.write(struct.pack("<I", 1)); mem.flush()
+ print("released pid=%s word=%#x" % (pid, w), flush=True)
+ except Exception:
+ del found[pid]
+ time.sleep(0.5)
+print("assist done", flush=True)
+'''
+
+
+def main():
+ dur = sys.argv[1] if len(sys.argv) > 1 else "300"
+ pid = sys.argv[2] if len(sys.argv) > 2 else ""
+ b64 = __import__("base64").b64encode(PY.encode()).decode()
+ subprocess.run([VMEXEC, "exec", "--timeout", str(int(dur) + 60),
+ "echo %s | base64 -d > /tmp/fwa.py; sudo python3 /tmp/fwa.py %s %s"
+ % (b64, dur, pid)])
+
+
+if __name__ == "__main__":
+ main()