1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
|
#!/usr/bin/env python3
# unwait2.py - no-ptrace guest-side harness:
# (a) writes 1 to any zero u32 at +0x80 of every 0x4000-byte rw-s nvidia
# mapping of EVERY live vk_frame;
# (b) scans each live vk_frame's anonymous/heap rw-p mappings (16-byte
# aligned) for marker slots {u32@0==0, u16@+0xe==0xffff} and clears
# u16@+0xe to 0 (the instance-phase pending markers the t105 gdb used
# to clear). No ptrace anywhere.
import os, subprocess, sys, time
DUR = float(sys.argv[1]) if len(sys.argv) > 1 else 600
def pids():
try:
out = subprocess.run(["pgrep", "-x", "vk_frame"], capture_output=True).stdout
return [int(x) for x in out.split()]
except Exception:
return []
def rd(fd, off, n):
try:
os.lseek(fd, off, 0)
return os.read(fd, n)
except Exception:
return b""
def wr(fd, off, data):
try:
os.lseek(fd, off, 0)
os.write(fd, data)
return True
except Exception:
return False
wlog = set(); mlog = set()
end = time.time() + DUR
last_scan = 0.0
while time.time() < end:
for pid in pids():
try:
fd = os.open("/proc/%d/mem" % pid, os.O_RDWR)
except Exception:
continue
try:
for line in open("/proc/%d/maps" % pid):
p = line.split()
if len(p) < 6 or "nvidia" not in p[-1] or "rw-s" not in p[1]:
continue
lo, hi = [int(x, 16) for x in p[0].split("-")]
if hi - lo != 0x4000:
continue
wa = lo + 0x80
v = rd(fd, wa, 4)
if len(v) == 4 and v == b"\x00\x00\x00\x00":
if wr(fd, wa, b"\x01\x00\x00\x00"):
k = (pid, wa)
if k not in wlog:
wlog.add(k)
print("WORDWROTE pid=%d va=0x%x" % (pid, wa), flush=True)
except Exception:
pass
if time.time() - last_scan > 1.5:
budget = 64
try:
for line in open("/proc/%d/maps" % pid):
p = line.split()
if len(p) < 6 or p[1] != "rw-p":
continue
path = p[-1]
if path.startswith("/") and "nvidia" not in path and path != "[heap]":
continue
lo, hi = [int(x, 16) for x in p[0].split("-")]
if hi - lo > 0x10000000:
hi = lo + 0x10000000
off = lo
while off < hi:
chunk = rd(fd, off, 0x100000)
if len(chunk) < 32:
break
j = 0
while j + 16 <= len(chunk):
if chunk[j:j+4] == b"\x00\x00\x00\x00" and chunk[j+0xe:j+0x10] == b"\xff\xff":
wa = off + j + 0xe
if (pid, wa) not in mlog:
if wr(fd, wa, b"\x00\x00"):
mlog.add((pid, wa))
print("MARKCLR pid=%d va=0x%x" % (pid, wa), flush=True)
j += 16
off += 0x100000
budget -= 1
if budget <= 0:
break
if budget <= 0:
break
except Exception:
pass
last_scan = time.time()
os.close(fd)
time.sleep(0.4)
print("UNWAIT2-DONE", flush=True)
|