summaryrefslogtreecommitdiffstats
path: root/tools/guest-diag
diff options
context:
space:
mode:
authorArthur Hanson Rasmusson <arthur@vgpu.io>2026-10-31 17:39:46 -0400
committerArthur Hanson Rasmusson <arthur@vgpu.io>2026-10-31 17:39:46 -0400
commit69b59a0d67d12e4767736a423bd307feeffef016 (patch)
tree3481f3763a2646188ffdf705bebcb4eda0d22738 /tools/guest-diag
parentbf8540b846631a234a20e6b404fc8fb607b93c1d (diff)
downloadopen-iov-69b59a0d67d12e4767736a423bd307feeffef016.tar.gz
open-iov-69b59a0d67d12e4767736a423bd307feeffef016.zip
diag: guest_pin_stream unknown-family demand anchors run kernel-vmap sweep first (union nv_vm_map_pages + os_alloc_mem vmalloc, phys/ioremap excluded, _window_accept full-parse gate, 8192 win/64 pages bound) - held push 0x3e4ccccc len=123916 proven NOT resolvable from any CPU-visible source (walk_probe PD1[1] rc=-2 on all 6 VASes; 8GB scan zero exact pairs; strict parse 0/8850+777 accepted); MME-CALL-DROP bits [34,39,40,48,51,57] exactly; next: discover beef channel's own hVASpace (log it, COPY_SERVER_PDES/VAS-candidate), then extend prelude>1024 + 3rd PB page cascade together - SESSION 153 r1156
Diffstat (limited to 'tools/guest-diag')
-rw-r--r--tools/guest-diag/guest_pin_stream.py100
1 files changed, 99 insertions, 1 deletions
diff --git a/tools/guest-diag/guest_pin_stream.py b/tools/guest-diag/guest_pin_stream.py
index ddc7098..a645a86 100644
--- a/tools/guest-diag/guest_pin_stream.py
+++ b/tools/guest-diag/guest_pin_stream.py
@@ -789,6 +789,87 @@ def resolve_va_client_mem(pid, ent_va, off, ln, out):
os.close(mfd)
+def _strict_kvm_sweep(kc, ent_va, off, ln, out):
+ """Kernel-vmap sweep for an anchor with no known-family page index.
+
+ SESSION 153-CONTINUED-74: mirrors the k == 0 known-family path (the
+ resolver that found the r1126 0x3200000 macro window) but works for ANY
+ anchor outside PB_GL_FAMILIES. Every candidate window passes the host's
+ own full parse (`_window_accept`) before a single pin is emitted, so a
+ false positive is impossible by construction; the cheap per-page prefix
+ walk rejects arbitrary data after a few words. Bounded: at most
+ 8192 candidate windows and at most 64 pages of a window (the same caps
+ as resolve_va_client_mem).
+
+ Areas swept: the nv_vm_map_pages vmap set (the historical resolver) plus
+ the nvidia os_alloc_mem vmalloc areas (`vpages`), which the r1156 probe
+ showed can be large (571 pages in one area) and are completely outside
+ _nv_vmap_areas' filter. A window is only emitted for an area whose pages
+ are all present in the CPU alias.
+ """
+ import re as _re
+
+ page = ent_va & ~0xFFF
+ need = (off + ln + 0xFFF) // 0x1000
+ if ln <= 0 or ln > 0x40000 or need > 64:
+ return False
+ areas = list(_nv_vmap_areas(kc))
+ try:
+ for line in open("/proc/vmallocinfo"):
+ if "[nvidia]" not in line or "vmalloc" not in line:
+ continue
+ if "nv_vm_map_pages" in line or "phys=" in line:
+ continue
+ if "os_map_kernel_space" in line or "ioremap" in line:
+ continue
+ m = _re.match(r'0x([0-9a-f]+)-0x([0-9a-f]+)\s+(\d+)', line)
+ if not m:
+ continue
+ lo = int(m.group(1), 16)
+ hi = int(m.group(2), 16)
+ pages = (hi - lo) >> 12
+ if pages >= need and lo < hi:
+ areas.append((lo, hi, pages))
+ except OSError:
+ pass
+ tried = 0
+ for (lo, _hi, pages) in areas:
+ for adj in range(0, max(1, pages - need + 1)):
+ tried += 1
+ if tried > 8192:
+ return False
+ cpu = lo + adj * 0x1000
+ first = kc.read(cpu, 0x1000)
+ if not first:
+ continue
+ if any(first) and not _prefix_walk_ok(first, off):
+ continue
+ buf = _read_window(kc, cpu, off, ln)
+ if buf is None:
+ continue
+ acc, mode = _window_accept(buf, ln)
+ if not acc:
+ continue
+ pas = []
+ for j in range(need):
+ vpa = kc.va_to_pa(cpu + j * 0x1000)
+ if vpa is None:
+ pas = None
+ break
+ pas.append(vpa)
+ if not pas:
+ continue
+ for j, vpa in enumerate(pas):
+ out.append("0x%x,0x%x,1\n" % (page + j * 0x1000, vpa))
+ dbg("demand-va: 0x%x -> pa=0x%x (%s vmap parse %u B ok"
+ " pages=%u area=0x%x adj=%+d)"
+ % (page, pas[0], mode, ln, need, lo, adj))
+ return True
+ dbg("demand-va: 0x%x strict vmap sweep failed (%u B, %u windows)"
+ % (page, ln, tried))
+ return False
+
+
def resolve_va_strict(kc, ent_va, off, ln, out, pid=None):
"""Demand pin validated by the host's exact full-parse of [ent_va, +ln).
@@ -811,12 +892,29 @@ def resolve_va_strict(kc, ent_va, off, ln, out, pid=None):
# SESSION 153-CONTINUED-64e: an anchor outside the known families
# (r1124: the hold moved to a 153600-byte push at 0x3200000) has no
# identity page index; only the client-mapping sweep can resolve it.
+ #
+ # SESSION 153-CONTINUED-74: the unknown-family branch skipped the
+ # kernel-vmap sweep entirely - the known-family path has always tried
+ # it, and it is the resolver that found the r1126 0x3200000 macro
+ # window (a KERNEL-mapped allocation no process pagemap covers). The
+ # r1156 held push (va=0x3e4ccccc, 123916 B) failed here after only
+ # the client-mem attempt ("strict unknown-family client-mem failed"),
+ # so a kernel-resident window could never be found for any anchor
+ # outside PB_GL_FAMILIES. Try the vmap sweep first (same full-parse
+ # gate; strictly additive - a failed sweep costs the bounded reads
+ # and falls through to the client-mem path unchanged).
+ try:
+ if _strict_kvm_sweep(kc, ent_va, off, ln, out):
+ return True
+ except Exception:
+ pass
try:
if resolve_va_client_mem(pid, ent_va, off, ln, out):
return True
except Exception:
pass
- dbg("demand-va: 0x%x strict unknown-family client-mem failed" % page)
+ dbg("demand-va: 0x%x strict unknown-family (vmap+client-mem) failed"
+ % page)
return False
gl_hi = next(hi for lo, hi in PB_GL_FAMILIES if lo <= page < hi)
k = (page - gl_base) >> 12