diff options
Diffstat (limited to 'tools/guest-diag/guest_pin_stream.py')
| -rw-r--r-- | tools/guest-diag/guest_pin_stream.py | 43 |
1 files changed, 41 insertions, 2 deletions
diff --git a/tools/guest-diag/guest_pin_stream.py b/tools/guest-diag/guest_pin_stream.py index 3b7d9b1..f89ed4a 100644 --- a/tools/guest-diag/guest_pin_stream.py +++ b/tools/guest-diag/guest_pin_stream.py @@ -40,6 +40,12 @@ SPAN = int(os.environ.get("STREAM_SPAN", "0x80000"), 16) LO2 = int(os.environ.get("STREAM_LO2", "0x120000000"), 16) HI2 = int(os.environ.get("STREAM_HI2", "0x121400000"), 16) SPAN2 = int(os.environ.get("STREAM_SPAN2", "0x180000"), 16) +# UVM semaphore pool window: the tracker pool word lives at +# 0x121000000 + 4*idx, above the CE window head span (LO2+SPAN2 = +# 0x120180000), so scan_window never reaches it. Scan every 4 KB page of +# [POOL_LO, POOL_HI) directly - cheap (16 pages) and host-visible as pins. +POOL_LO = int(os.environ.get("STREAM_POOL_LO", "0x121000000"), 16) +POOL_HI = int(os.environ.get("STREAM_POOL_HI", "0x121010000"), 16) # UVM system-memory AVMAs: the client's sysmem buffers (the DtoH staging # buffer among them) are /dev/zero mappings at high GPU VAs (e.g. # 0x79c21c800000). They are not inside the two fixed windows, and only the @@ -128,7 +134,7 @@ def new_sems(seen): def cdt_pid(): prefixes = tuple(p for p in os.environ.get("CLIENT_PREFIXES", - "cdt,va").split(",") if p) + "cdt,va,victory").split(",") if p) for d in os.listdir('/proc'): if not d.isdigit(): continue @@ -167,6 +173,35 @@ def scan_window(fd, lo, hi, span, out): base += REGION +def scan_range(fd, lo, hi, out): + """Present pages of one explicit VA range, every 4 KB page. + + Same pagemap present/PFN/PAMAX filtering as scan_window, but with no + REGION alignment or head-span limit: walks [lo, hi) directly. Used for + the UVM semaphore pool window, which sits past the CE head span. + """ + va = lo & ~0xFFF + while va < hi: + n = min(BATCH, (hi - va) // 0x1000) + if n <= 0: + break + os.lseek(fd, (va // 4096) * 8, 0) + data = os.read(fd, n * 8) + got = len(data) // 8 + if got <= 0: + break + for i in range(got): + e = int.from_bytes(data[i * 8:i * 8 + 8], 'little') + if not ((e >> 63) & 1): + continue + pfn = e & ((1 << 55) - 1) + pa = pfn << 12 + if not pa or (PAMAX and pa >= PAMAX): + continue + out[va + i * 0x1000] = pa + va += got * 0x1000 + + def scan_vmas(fd, pid, out): """Present pages of the client's high-VA nvidia//dev/zero mappings. @@ -237,6 +272,8 @@ def scan(pid): scan_window(fd, LO, HI, SPAN, out) if HI2 > LO2: scan_window(fd, LO2, HI2, SPAN2, out) + if POOL_HI > POOL_LO: + scan_range(fd, POOL_LO, POOL_HI, out) if VMA_EVERY and scan.loop % VMA_EVERY == 0: scan_vmas(fd, pid, out) finally: @@ -304,7 +341,7 @@ def main(): if cpa and (not PAMAX or cpa < PAMAX): cur[0x20400f000] = cpa new = [(va, pa) for va, pa in cur.items() if seen.get(va) != pa] - seen = cur + pending_cur = cur lines = [] for ctl in tracer.drain(): if ctl.startswith("#sem"): @@ -321,6 +358,7 @@ def main(): except OSError: pass if not new and not lines: + seen = pending_cur time.sleep(INTERVAL) continue if new: @@ -350,6 +388,7 @@ def main(): continue try: sock.sendall(payload) + seen = pending_cur except OSError: sock.close() sock = None |
