#!/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). # # SUPERSEDED (SESSION 126, commit 95e7f57e): the service now authors these # releases itself. The `sema_gr_ahead` fence fold sweeps the channel's # pre-built ring continuation beyond GP_PUT through the ring's validated # GPFIFO translation, decodes the INC-5 RELEASE groups it finds (addr 0x5c # count>=5) and queues them in the standard pending ledger; r717 evidence: # `sema-ahead: h=0xbeec0100 put=11 swept=10 rels=4` followed 30 ms later by # `sema-svc: deferred release va=0x45ba090 payload=1 (was cur=0)`, with # VKFRAME seq/DONE and NO assist running (see # backups/evidence-20261002-victory/r717-fencefold/). Keep this tool only as # the A/B fallback for boots that predate the fold (or with # sema_gr_ahead=0). # # 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 +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/126). # # 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(" 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()