summaryrefslogtreecommitdiffstats
path: root/tools/guest-diag/pin_gr_stream.py
diff options
context:
space:
mode:
authorArthur Hanson Rasmusson <arthur@vgpu.io>2026-10-31 08:14:08 -0400
committerArthur Hanson Rasmusson <arthur@vgpu.io>2026-10-31 08:14:08 -0400
commit520ad3e2f99b4e15c8778874e1b4b188c6d16b77 (patch)
tree36167c2e02ef74dbdffc69f66d08d908ec42324d /tools/guest-diag/pin_gr_stream.py
parentf8f0a86a07949f913e546de4459c779a9ccbc3f3 (diff)
downloadopen-iov-520ad3e2f99b4e15c8778874e1b4b188c6d16b77.tar.gz
open-iov-520ad3e2f99b4e15c8778874e1b4b188c6d16b77.zip
vgsp+diag: anchored demand record (sema_setup_demand prints VA/off/len), ipin-table eviction (32768 slots silently dropped demand pins; nodrop + alt stash), MME prelude 512->1024 words + SIGS 512; guest_pin_stream resolve_va_strict (host svc_stream_parse port + client-mem /proc/pid/mem+pagemap), pin_gr_stream chunked script push (MAX_ARG_STRLEN) - setup-push read NOW SUCCEEDS (plausible=1 ipin=1 unreadable=0, pa=0x2387b9000), SA table captured, MME-PRELUDE gen=3 words=443, GR LAUNCH words=934, retire 0/903 pages (no writes); new wall: NO 0x114 instruction-RAM upload in any parseable window (code=0) - prelude immature; next: bind setup-hold to the entry carrying the 0x114 uploads - SESSION 153 r1121-r1124
Diffstat (limited to 'tools/guest-diag/pin_gr_stream.py')
-rw-r--r--tools/guest-diag/pin_gr_stream.py90
1 files changed, 75 insertions, 15 deletions
diff --git a/tools/guest-diag/pin_gr_stream.py b/tools/guest-diag/pin_gr_stream.py
index 7a9bb66..35c2ea3 100644
--- a/tools/guest-diag/pin_gr_stream.py
+++ b/tools/guest-diag/pin_gr_stream.py
@@ -131,11 +131,29 @@ def _demand_send(vas):
pass
-def _start_cmd():
+def _push_guest_script():
+ """Push the scanner into the guest in argv-safe chunks.
+
+ SESSION 153-CONTINUED-64: the one-shot `echo <b64> | base64 -d >` form
+ put the whole ~135 KB base64 of the (grown) scanner on vgpu_vm.py's
+ argv, and the host's MAX_ARG_STRLEN (128 KB) rejected the exec before
+ it ever reached the guest ('OSError: Argument list too long'), so no
+ scanner started and the boot streamed zero pins. Push 60 KB chunks and
+ print the guest-side md5 for verification.
+ """
with open(GUEST_SCRIPT) as f:
b64 = subprocess.run(["base64", "-w0"], stdin=f,
capture_output=True, text=True,
- timeout=10).stdout
+ timeout=10).stdout.strip()
+ vexec("rm -f /tmp/gps.b64", 30)
+ for off in range(0, len(b64), 60000):
+ vexec("printf %%s '%s' >> /tmp/gps.b64" % b64[off:off + 60000], 30)
+ return vexec("base64 -d /tmp/gps.b64 > /tmp/guest_pin_stream.py && "
+ "rm -f /tmp/gps.b64 && md5sum /tmp/guest_pin_stream.py "
+ "&& echo PUSH_OK", 60) or ""
+
+
+def _start_cmd():
prefixes = os.environ.get("CLIENT_PREFIXES",
"cdt,va,victory,Xorg,X,glxgears,gzdoom")
vma_every = os.environ.get("STREAM_VMA_EVERY", "1")
@@ -151,14 +169,13 @@ def _start_cmd():
# failed silently (r149).
return ("P=$(printf '^python3 /tmp/guest_pin_%%s.py' stream); "
"sudo pkill -f \"$P\" 2>/dev/null; sleep 1; "
- "echo '%s' | base64 -d > /tmp/guest_pin_stream.py; "
"sudo rm -f /tmp/guest_pin_stream.pid; "
"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, prefixes, vma_every, 2, PORT, LO, HI, PAMAX))
+ % (prefixes, vma_every, 2, PORT, LO, HI, PAMAX))
def install_and_start():
@@ -167,6 +184,14 @@ def install_and_start():
# a boot without the scanner streams no pins and the client then hangs.
for attempt in range(5):
_heartbeat()
+ try:
+ out_push = _push_guest_script()
+ if "PUSH_OK" not in (out_push or ""):
+ log("WARN: scanner push attempt %d incomplete: %s"
+ % (attempt + 1, (out_push or "")[-120:]))
+ except Exception as e:
+ log("WARN: scanner push attempt %d failed: %s"
+ % (attempt + 1, e))
out = vexec(_start_cmd(), 60)
if any(ch.isdigit() for ch in out):
return True
@@ -230,6 +255,13 @@ def _demand_loop():
expiry) as the stalled-VA class.
"""
track = {} # va -> [first_seen, last_sent]
+ # SESSION 153-CONTINUED-64: strict demand anchors (entry va -> [first,
+ # last_sent]) from the anchored debugfs lines. The guest validates the
+ # exact [entry_va, +len) read window with the host's full stream parse
+ # before pinning, so the setup-push pin can never land on a page whose
+ # bytes the host's read will reject. Resent fast (2 s) while the hold
+ # is up; the loose cadence (20 s) is too slow for the client's churn.
+ strict_track = {}
it = 0
while True:
# SESSION 153-CONTINUED-57: the 3 s pass was the losing half of the
@@ -296,30 +328,58 @@ def _demand_loop():
"/sys/kernel/debug/vgsp/sema_setup_demand"],
capture_output=True, text=True, timeout=10)
if rr.returncode == 0:
- for m in re.finditer(r"0x[0-9a-f]+", rr.stdout or ""):
- sva = int(m.group(0), 16) & ~0xfff
- if sva:
- track.setdefault(sva, [now, 0.0])
+ for line in (rr.stdout or "").splitlines():
+ ma = re.match(
+ r"\s*0x([0-9a-f]+)\s+0x([0-9a-f]+)\s+(\d+)\s*$",
+ line)
+ if ma:
+ ev = int(ma.group(1), 16)
+ off = int(ma.group(2), 16)
+ ln = int(ma.group(3))
+ if ev and 0 < ln <= 0x40000:
+ strict_track.setdefault(ev, [now, 0.0,
+ off, ln])
+ continue
+ for m in re.finditer(r"0x[0-9a-f]+", line):
+ sva = int(m.group(0), 16) & ~0xfff
+ if sva:
+ track.setdefault(sva, [now, 0.0])
except Exception:
pass
for va in list(track):
first, last = track[va]
if now - first > 300.0:
del track[va]
+ for ev in list(strict_track):
+ first, last, off, ln = strict_track[ev]
+ if now - first > 300.0:
+ del strict_track[ev]
+ cmds = []
todo = [va for va, (f, l) in track.items() if now - l > 20.0]
- if not todo:
+ if todo:
+ todo = todo[:48]
+ cmds.append(_demand_write_cmd(todo))
+ stodo = [ev for ev, (f, l, o, ln) in strict_track.items()
+ if now - l > 2.0]
+ if stodo:
+ stodo = stodo[:16]
+ cmds.append("; ".join(
+ "echo S 0x%x 0x%x %d >> /tmp/guest_want_vas.txt"
+ % (ev, strict_track[ev][2], strict_track[ev][3])
+ for ev in stodo))
+ if not cmds:
continue
- # CONT-51: bound one batch's command size (a page-expanded push
- # range can add many pages; the remainder goes next cycle).
- todo = todo[:48]
- cmd = _demand_write_cmd(todo)
try:
- vexec(cmd, 30)
+ vexec("; ".join(cmds), 30)
except Exception:
continue
for va in todo:
track[va][1] = now
- log("demand: sent %d stalled VA(s) to guest" % len(todo))
+ for ev in stodo:
+ strict_track[ev][1] = now
+ log("demand: sent %d stalled VA(s)%s to guest" %
+ (len(todo),
+ " + %d strict anchor(s)" % len(stodo) if stodo else ""))
_DEMAND_STARTED = False