From ca944b45ba35f3c0dc63fa9f722067af13e97ab4 Mon Sep 17 00:00:00 2001 From: Arthur Hanson Rasmusson Date: Tue, 29 Sep 2026 14:38:44 -0400 Subject: tools: pin GR push-buffer window from guest pagemap per boot; widen injected-pin table The GR channel GPFIFO entries point at pushes in the client GPU VA window (observed 0x200400000 + stride, one allocation per channel) and the pump cannot read them: pushes_nomap grows and the tracking-semaphore releases they carry never land. The pushes are sysmem pages mapped into the client process, so /proc//pagemap in the guest gives the GPA. New guest helper guest_pmap_win.py batch-reads the pagemap of a VA range (512 entries per pread). New host tool pin_gr_window.py rescans the window on an interval, follows cdt pid changes, and injects VA->PA runs through sema_map_add (same mechanism as the counters and the CE pushbuffer pins). The injected-pin table grows 8k -> 32k slots so the CE pushbuffer (4096) plus the GR window pages fit without drops. --- tools/guest-diag/guest_pmap_win.py | 47 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 tools/guest-diag/guest_pmap_win.py (limited to 'tools/guest-diag/guest_pmap_win.py') diff --git a/tools/guest-diag/guest_pmap_win.py b/tools/guest-diag/guest_pmap_win.py new file mode 100644 index 0000000..a9b74a7 --- /dev/null +++ b/tools/guest-diag/guest_pmap_win.py @@ -0,0 +1,47 @@ +#!/usr/bin/env python3 +# guest_pmap_win.py - dump present pages of a process's VA range through the +# guest's own pagemap (root in the guest). Batched reads (512 entries per +# pread) so a 256 MB window takes about a second, not minutes. +# +# Usage: sudo python3 guest_pmap_win.py [max-pairs] [pa-max-hex] +# Output: one "0x,0x" line per present page (ascending VA), capped at +# max-pairs. PAs of 0 are skipped; pages above pa-max are skipped unless 0. +import os +import sys + +pid = int(sys.argv[1]) +lo = int(sys.argv[2], 16) & ~0xFFF +hi = int(sys.argv[3], 16) +maxp = int(sys.argv[4]) if len(sys.argv) > 4 else 20000 +pa_max = int(sys.argv[5], 16) if len(sys.argv) > 5 else 0 + +BATCH = 512 +out = [] +fd = os.open('/proc/%d/pagemap' % pid, os.O_RDONLY) +try: + va = lo + 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 + 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: + continue + if pa_max and pa >= pa_max: + continue + out.append('0x%x,0x%x' % (va + i * 0x1000, pa)) + if len(out) >= maxp: + print('\n'.join(out)) + sys.exit(0) + va += got * 0x1000 +finally: + os.close(fd) +print('\n'.join(out)) -- cgit v1.2.3