From 32ec1ca305fe60da413cfe7262e2fbb4bc199a1d Mon Sep 17 00:00:00 2001 From: Arthur Hanson Rasmusson Date: Mon, 2 Nov 2026 11:59:31 -0500 Subject: guest-diag: strict-anchor pagemap window fallback un-deadlocks the GL setup-push family A strict demand anchor (the host's exact [entry_va,+len) read window, e.g. the 60 216 B setup push) whose full-window content parse fails on every candidate used to set strict_pending, and the pend_bases rule then skipped every loose demand VA of the same GL family for as long as the anchor was pending - the host demanded the push's pages individually, the guest suppressed them, and the entry stayed unreadable for the whole generation (r1396: entry 8 unreadable=1 on all generations while its sibling entries read fine; generations churn every ~12 s, the content sweeps take longer). Add _pagemap_window_pin(): on a failed strict resolve, pin the anchor window's pages directly from the client's /proc/pid/pagemap (the r586 mechanism already proven for the non-family draws). The anchor VA is the host's own GPFIFO entry VA, so a present client page is by definition its translation; no content gate and no family learn, so no k/(area,adj) risk. Partial presence heals on the ~2 s anchor resend. A 'strict-pagemap:' log line reports present/total pages either way (0 present => kernel-resident, the fallback cannot help). SESSION 153 r1397; scan: r1397 offline brief Change 1. --- tools/guest-diag/guest_pin_stream.py | 57 ++++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) (limited to 'tools/guest-diag/guest_pin_stream.py') diff --git a/tools/guest-diag/guest_pin_stream.py b/tools/guest-diag/guest_pin_stream.py index e98d851..3222a90 100644 --- a/tools/guest-diag/guest_pin_stream.py +++ b/tools/guest-diag/guest_pin_stream.py @@ -2201,6 +2201,42 @@ def scan_range(fd, lo, hi, out): va += got * 0x1000 +def _pagemap_window_pin(pid, ev, off, ln, out): + """Direct client-pagemap pin for [ev, ev+ln) (window-wide r586 fallback). + + SESSION 153-r1397: a strict anchor whose full-window content parse fails + (both the kernel-vmap candidates and the client-mem scan) used to set + strict_pending and thereby stall EVERY loose demand VA of its family via + the pend_bases deferral - the 60 216 B setup push's pages were demanded + individually by the host but suppressed, so the entry stayed unreadable + for the whole generation (r1396: entry 8 unreadable=1 on all gens while + its sibling entries read fine). The anchor VA is the host's own GPFIFO + entry VA: when the client maps the pushbuffer at the same VA (rw-s + /dev/nvidia mappings - the same premise as the r586 single-page pagemap + fallback proven for the non-family draws), a present page IS the + translation the host needs; no content gate and no family learn (so no + k/(area,adj) risk, no r1120 poisoning class). Partial presence is fine: + the anchor resend (~2 s) re-tries and the missing pages heal late. + """ + pfd = os.open('/proc/%d/pagemap' % pid, os.O_RDONLY) + try: + sub = {} + vpg = ev & ~0xFFF + end = vpg + ((off + ln + 0xFFF) // 0x1000) * 0x1000 + scan_range(pfd, vpg, end, sub) + if not sub: + dbg('strict-pagemap: 0x%x no present page (%u pages)' + % (vpg, (end - vpg) >> 12)) + return False + for v, p in sorted(sub.items()): + out.append('0x%x,0x%x,1\n' % (v, p)) + dbg('strict-pagemap: 0x%x -> %u/%u pages pinned' + % (vpg, len(sub), (end - vpg) >> 12)) + return True + finally: + os.close(pfd) + + def scan_vmas(fd, pid, out): """Present pages of the client's high-VA nvidia//dev/zero mappings. @@ -2522,6 +2558,27 @@ def main(): ok = False if ok: got = got2 + if not ok and pid and eln: + # SESSION 153-r1397: a failed content parse must + # not make the anchor's pages (and, via + # pend_bases, every loose demand VA of its + # family) unpinnable. Fall back to the direct + # client-pagemap window pin - the VA is the + # host's own entry VA, so a present page is by + # definition its translation (see + # _pagemap_window_pin). This un-deadlocks the + # family: on success the anchor counts as + # resolved and the deferral lifts; on failure + # the 'strict-pagemap:' line says the pages are + # not client-pagemap-present (kernel-resident). + got2 = [] + try: + ok = _pagemap_window_pin(pid, ev, eoff, eln, + got2) + except Exception: + ok = False + if ok: + got = got2 if ok and got: lines.extend(got) for g in got: -- cgit v1.2.3