diff options
| author | Arthur Hanson Rasmusson <arthur@vgpu.io> | 2026-10-03 14:05:38 -0400 |
|---|---|---|
| committer | Arthur Hanson Rasmusson <arthur@vgpu.io> | 2026-10-03 14:05:38 -0400 |
| commit | cc79b478843f0230fe6aa8ecd822de7ba71c891e (patch) | |
| tree | 5de760ddec4e45cc23d39ce7502635f5c0711217 /tools/guest-diag | |
| parent | 40351167dd209012ab485e6164ce94f0b8965422 (diff) | |
| download | open-iov-cc79b478843f0230fe6aa8ecd822de7ba71c891e.tar.gz open-iov-cc79b478843f0230fe6aa8ecd822de7ba71c891e.zip | |
vgsp: host CUDA bridge + sema release recovery; greeneye simulator wave
- kernel: gsp_cuda_bridge (QMD launch capture, debugfs job/out/done, param+output resolution cached from inline writes), sema drain fixes (never hold/starve a channel), GR ring autopin + counter autoreg, per-page push reads, counter-derive gate; module builds clean
- tools/cuda-bridge: CUDA driver-API daemon executing mail/vadd kernels on the physical GPU, CUBB2/CBD2 v2 protocol, layout check + self-tests
- tools/guest-diag + tools/cuda-ab: scanner/pin fixes, victory push-only mode
- debug/risc-v-gsp-rm-vm: Phase S simulator wave (GSP device model, boot ladder, triage/re-demo harnesses, docs 30-41), GPGPU-sim scaffolding
- STATE-CURRENT/docs updates
Diffstat (limited to 'tools/guest-diag')
| -rw-r--r-- | tools/guest-diag/guest_pin_stream.py | 43 | ||||
| -rw-r--r-- | tools/guest-diag/pin_gr_stream.py | 36 |
2 files changed, 63 insertions, 16 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 diff --git a/tools/guest-diag/pin_gr_stream.py b/tools/guest-diag/pin_gr_stream.py index d8b6b61..7f8e4b8 100644 --- a/tools/guest-diag/pin_gr_stream.py +++ b/tools/guest-diag/pin_gr_stream.py @@ -58,6 +58,8 @@ def _start_cmd(): with open(GUEST_SCRIPT) as f: b64 = subprocess.run(["base64", "-w0"], stdin=f, capture_output=True, text=True).stdout + prefixes = os.environ.get("CLIENT_PREFIXES", "cdt,va,victory") + vma_every = os.environ.get("STREAM_VMA_EVERY", "1") return ("echo '%s' | base64 -d > /tmp/guest_pin_stream.py; " "if [ -f /tmp/guest_pin_stream.pid ]; then " "p=$(cat /tmp/guest_pin_stream.pid 2>/dev/null); " @@ -65,10 +67,12 @@ def _start_cmd(): "/proc/$p/cmdline 2>/dev/null && sudo kill $p 2>/dev/null; " "fi; " "sudo rm -f /tmp/guest_pin_stream.pid; " - "sudo setsid nohup python3 /tmp/guest_pin_stream.py %d %d %s %s %s " + "sudo setsid nohup env CLIENT_PREFIXES='%s' " + "STREAM_VMA_EVERY='%s' " + "python3 /tmp/guest_pin_stream.py %d %d %s %s %s " ">/tmp/guest_pin_stream.log 2>&1 & sleep 2; " "sudo cat /tmp/guest_pin_stream.pid 2>/dev/null" - % (b64, 2, PORT, LO, HI, PAMAX)) + % (b64, prefixes, vma_every, 2, PORT, LO, HI, PAMAX)) def install_and_start(): @@ -189,18 +193,22 @@ def _flush(runs, seen): "echo 'FAIL 0x%x 0x%x 0x%x'" % (va, pa, n * 0x1000, PARAM, va, pa, n * 0x1000)) failed = set() - try: - r = subprocess.run(["sudo", "-n", "sh", "-c", "\n".join(script)], - capture_output=True, text=True, timeout=60) - for line in r.stdout.splitlines(): - m = re.match(r"FAIL (0x[0-9a-f]+) (0x[0-9a-f]+) (0x[0-9a-f]+)", - line.strip()) - if m: - failed.add((int(m.group(1), 16), int(m.group(2), 16), - int(m.group(3), 16) // 0x1000)) - except Exception as e: - log("batch inject failed: %s" % e) - failed = set(todo) + CHUNK = 200 + for start in range(0, len(script), CHUNK): + batch = script[start:start + CHUNK] + try: + r = subprocess.run(["sudo", "-n", "sh", "-c", "\n".join(batch)], + capture_output=True, text=True, timeout=60) + for line in r.stdout.splitlines(): + m = re.match(r"FAIL (0x[0-9a-f]+) (0x[0-9a-f]+) (0x[0-9a-f]+)", + line.strip()) + if m: + failed.add((int(m.group(1), 16), int(m.group(2), 16), + int(m.group(3), 16) // 0x1000)) + except Exception as e: + log("batch inject failed: %s" % e) + for va, pa, n in todo[start:start + CHUNK]: + failed.add((va, pa, n)) pages = 0 for va, pa, n in todo: |
