From 262b3c0e9753f4320b8f84cd1ca408384b6f25ff Mon Sep 17 00:00:00 2001 From: Arthur Hanson Rasmusson Date: Wed, 30 Sep 2026 10:06:20 -0400 Subject: guest-diag: reset per-client pin state when a new client pid appears A new CUDA client allocates fresh channel pools at the same GPU VAs; the watcher kept the previous client's sem kptrs and seen-pin marks, so it pinned the previous (freed) pool pages and the new client's release writes went to dead memory. Clear the learned sems/marks on each pid change. --- tools/guest-diag/semfix_uvmt.py | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) (limited to 'tools') diff --git a/tools/guest-diag/semfix_uvmt.py b/tools/guest-diag/semfix_uvmt.py index b9f3ac9..636e1f4 100755 --- a/tools/guest-diag/semfix_uvmt.py +++ b/tools/guest-diag/semfix_uvmt.py @@ -69,6 +69,16 @@ class Stream: self.pbs = [] self.new_pbs = [] + def reset(self): + """Forget everything learned about the previous client. A new client + allocates its own channel pools; keeping the old sems/seen-pin marks + makes the watcher chase stale kernel pointers and pin the previous + client's (freed) pool pages - the stale-translation trap.""" + self.sems = [] + self.pbs = [] + self.pids = [] + self.new_pbs = [] + def poll(self): try: with open(self.path) as f: @@ -290,6 +300,17 @@ def main(): log("stream: new uvmt sem 0x%x" % s) for p in new_pids: log("stream: client pid %d" % p) + if last_pid is not None and p != last_pid: + stream.reset() + known_sems.clear() + seen_sem_pin.clear() + last_state.clear() + last_seen_t.clear() + pinned_ranges.clear() + seen_ch.clear() + seen_pb.clear() + counter_pids.clear() + log("semfix: new client pid %d - reset per-client pin state" % p) last_pid = p for pb in getattr(stream, "new_pbs", []): log("stream: new pushbuffer 0x%x" % pb) -- cgit v1.2.3