summaryrefslogtreecommitdiffstats
path: root/tools/guest-diag
diff options
context:
space:
mode:
Diffstat (limited to 'tools/guest-diag')
-rw-r--r--tools/guest-diag/guest_pin_stream.py47
1 files changed, 43 insertions, 4 deletions
diff --git a/tools/guest-diag/guest_pin_stream.py b/tools/guest-diag/guest_pin_stream.py
index 97c68f2..885a87e 100644
--- a/tools/guest-diag/guest_pin_stream.py
+++ b/tools/guest-diag/guest_pin_stream.py
@@ -639,6 +639,16 @@ def _kc_pb_fresh(kc, sem):
return False
if not st.get("page_va"):
return True
+ if not st.get("page_pa"):
+ # Unknown PA at store time: the manual page-table walk could not
+ # translate the vmap page (it may have been read before the kernel
+ # page tables were walkable). Treat the record as fresh instead of
+ # failing every check - a permanently-failing freshness test made
+ # the scanner drop the latch and re-resolve in a tight loop, and
+ # each failed re-resolution left the host with no pins at all
+ # (observed r131: "kc-chain stale: re-resolving" every second for
+ # five sems while smiley sat in cudaMalloc).
+ return True
pa = kc.va_to_pa(st["page_va"])
if pa is None or pa != st.get("page_pa"):
return False
@@ -1333,12 +1343,41 @@ def main():
except Exception:
_fresh = True
if not _fresh:
- _st = KC_PB_STATE.pop(sem, None)
+ # Re-resolve, but never lose the latch on a failed
+ # attempt: a dropped latch means the host keeps no
+ # pins for this channel at all, which is worse than
+ # a possibly-stale pin (the host content-checks the
+ # first page and now rejects all-FF continuation
+ # chunks, so stale pages are bounded). On failure
+ # keep the old state and defer the next attempt.
+ _st = KC_PB_STATE.get(sem)
if _st and _st.get("mem"):
RESOLVED_KC_PB.discard(_st["mem"])
- resolved_kc_pb.discard(sem)
- retry_at.pop(("pk", sem), None)
- dbg("kc-chain stale: re-resolving sem=0x%x" % sem)
+ got = []
+ try:
+ _found2 = resolve_pb_chain(kc, sem, got)
+ except Exception:
+ _found2 = False
+ got = []
+ if _found2 and got:
+ _new = KC_PB_STATE.get(sem)
+ _newmem = _new.get("mem") if _new else None
+ dbg("kc-chain stale: re-resolved sem=0x%x "
+ "new-mem=%s runs=%d"
+ % (sem, "yes" if _newmem !=
+ (_st.get("mem") if _st else None)
+ else "no", len(got)))
+ lines.extend(got)
+ added += len(got)
+ resolved_kc_pb.add(sem)
+ else:
+ if _st and _st.get("mem"):
+ RESOLVED_KC_PB.add(_st["mem"])
+ if sem not in KC_PB_STATE:
+ KC_PB_STATE[sem] = _st
+ kc_refresh_at[sem] = now_r + 5.0
+ dbg("kc-chain stale: keep old latch sem=0x%x"
+ % sem)
# CE push-buffer chain (second-client stall fix): resolve
# pool -> manager -> pushbuffer -> rm_mem directly, so the
# push-buffer pages never depend on the racy one-shot uvbp