diff options
| author | Arthur Hanson Rasmusson <arthur@vgpu.io> | 2026-09-29 15:24:31 -0400 |
|---|---|---|
| committer | Arthur Hanson Rasmusson <arthur@vgpu.io> | 2026-09-29 15:24:31 -0400 |
| commit | 8d45a99fe54cb2b19b3024fd975ab11574611c3e (patch) | |
| tree | 43615ee128d2687b2f7093f95597cf9379484c4a /tools/guest-diag/semfix_uvmt.py | |
| parent | 1895679334371c5a89dd5cb715c980ade6559c72 (diff) | |
| download | open-iov-8d45a99fe54cb2b19b3024fd975ab11574611c3e.tar.gz open-iov-8d45a99fe54cb2b19b3024fd975ab11574611c3e.zip | |
guest-diag: stream uvmt sems over vsock (no guest-agent race); dump channel last release VA; larger push log budget
Diffstat (limited to 'tools/guest-diag/semfix_uvmt.py')
| -rwxr-xr-x | tools/guest-diag/semfix_uvmt.py | 89 |
1 files changed, 81 insertions, 8 deletions
diff --git a/tools/guest-diag/semfix_uvmt.py b/tools/guest-diag/semfix_uvmt.py index 0d31394..fb0e92e 100755 --- a/tools/guest-diag/semfix_uvmt.py +++ b/tools/guest-diag/semfix_uvmt.py @@ -41,6 +41,53 @@ DLOG = os.environ.get("UVMT_DMESG", "1") == "1" VMEXEC = os.path.normpath(os.path.join(HERE, "..", "..", "scripts", "vgpu_vm.py")) COUNTER_LO = int(os.environ.get("COUNTER_LO", "0x20400f000"), 16) COUNTER_HI = int(os.environ.get("COUNTER_HI", "0x204010000"), 16) +SEMSTREAM = os.environ.get("SEM_STREAM_FILE", "/tmp/opencode/sem_stream.txt") +TRACE_EVERY = int(os.environ.get("UVMT_TRACE_EVERY", "5")) + + +class Stream: + """Tail the guest scanner's control lines mirrored by pin_gr_stream.py. + + The guest emits "#pid <n>" and "#sem 0x<k>" over vsock; the listener + appends them here. This replaces per-loop guest-agent trace reads, which + were too slow to catch short-lived tracking semaphores. + """ + + def __init__(self, path): + self.path = path + self.off = 0 + self.sems = [] + self.pids = [] + + def poll(self): + try: + with open(self.path) as f: + f.seek(0, os.SEEK_END) + size = f.tell() + if size < self.off: + self.off = 0 + f.seek(self.off) + data = f.read() + self.off = f.tell() + except OSError: + return [], [] + new_sems, new_pids = [], [] + for line in data.splitlines(): + if line.startswith("#sem"): + m = re.search(r"0x([0-9a-fA-F]+)", line) + if m: + v = int(m.group(1), 16) + if v not in self.sems: + self.sems.append(v) + new_sems.append(v) + elif line.startswith("#pid"): + m = re.search(r"(\d+)", line) + if m: + v = int(m.group(1)) + if v not in self.pids: + self.pids.append(v) + new_pids.append(v) + return new_sems, new_pids def log(msg): @@ -191,6 +238,8 @@ def main(): dseen = set() counter_pids = set() last_pid = None + stream = Stream(SEMSTREAM) + loop = 0 def pin_range_once(gpu_vas, cpu, gpa, size=0): key = tuple(gpu_vas), cpu, size @@ -200,7 +249,30 @@ def main(): pin_pushbuffer(q, gpu_vas, cpu, gpa, size) while True: - sems, pbs, chans = guest_trace() + loop += 1 + sems = set() + pbs = set() + chans = set() + + new_sems, new_pids = stream.poll() + for s in new_sems: + log("stream: new uvmt sem 0x%x" % s) + for p in new_pids: + log("stream: client pid %d" % p) + last_pid = p + sems.update(stream.sems) + + # The guest-agent trace read is slow under client load; use it only + # as a fallback for channel/pushbuffer discovery and to recover sems + # the scanner may have missed. + if loop % TRACE_EVERY == 0: + try: + t_sems, t_pbs, t_chans = guest_trace() + except Exception: + t_sems, t_pbs, t_chans = set(), set(), set() + sems.update(t_sems) + pbs.update(t_pbs) + chans.update(t_chans) # Poll every sem ever seen: the client's final wait may only appear in # the trace once, and the trace ring wraps while it spins. @@ -293,14 +365,15 @@ def main(): dmesg_releases(dseen) # Pin the completion-counter page of a newly started client, before its - # first GR pushes decode their releases. - pid = cdt_pid() - if pid and pid != last_pid: - last_pid = pid - log("counter: client pid %d" % pid) - if pid and pid not in counter_pids: + # first GR pushes decode their releases. The pid comes from the guest + # scanner; the guest-agent fallback is only a safety net. + if last_pid is None and loop % TRACE_EVERY == 0: + last_pid = cdt_pid() + if last_pid: + log("counter: client pid %d (agent)" % last_pid) + if last_pid and last_pid not in counter_pids: try: - pin_counter_page(pid, counter_pids) + pin_counter_page(last_pid, counter_pids) except Exception as e: log("counter: pin failed: %s" % e) |
