summaryrefslogtreecommitdiffstats
path: root/tools/guest-diag/wall2/vmap_watch2.py
blob: 194b0d6345bf472ebfe7f2c7c9a831e3db058a9f (plain)
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
#!/usr/bin/env python3
# Guest-side live watcher v2: scan ALL vmallocinfo areas via /proc/kcore for
# (a) GR ring entry patterns, (b) pages starting with a small INC_METHOD header.
import struct, time
ENTRIES = [bytes.fromhex("0000480400980500"), bytes.fromhex("8000040004480598"), bytes.fromhex("0003d0000448059c")]
class Kcore:
    def __init__(self):
        self.fd = open("/proc/kcore", "rb")
        hdr = self.fd.read(64)
        e_phoff = struct.unpack_from("<Q", hdr, 32)[0]
        e_phentsize, e_phnum = struct.unpack_from("<HH", hdr, 54)
        self.segs = []
        for i in range(e_phnum):
            self.fd.seek(e_phoff + i * e_phentsize)
            ph = self.fd.read(56)
            p_type, _fl, p_off, p_va, _pa, p_sz = struct.unpack_from("<IIQQQQ", ph, 0)
            if p_type == 1:
                self.segs.append((p_va, p_va + p_sz, p_off))
    def read(self, va, n):
        for lo, hi, off in self.segs:
            if lo <= va and va + n <= hi:
                self.fd.seek(off + (va - lo))
                return self.fd.read(n)
        return None
kc = Kcore()
def areas():
    out = []
    for line in open("/proc/vmallocinfo"):
        p = line.split()
        if len(p) < 2 or "-" not in p[0]: continue
        try:
            lo, hi = p[0].split("-")
            lo, hi = int(lo,16), int(hi,16)
        except Exception:
            continue
        out.append((lo, hi, line.strip()[-60:]))
    return out
def hdr_ok(page):
    v = struct.unpack_from("<I", page, 0)[0]
    op = (v >> 29) & 7
    cnt = (v >> 16) & 0xfff
    return op == 1 and 1 <= cnt <= 8
print("vmap_watch2 start", flush=True)
found = set()
t0 = time.time()
it = 0
while time.time() - t0 < 300:
    it += 1
    nareas = 0
    for lo, hi, tag in areas():
        size = hi - lo
        if size > 8 << 20: continue
        nareas += 1
        d = kc.read(lo, size)
        if not d: continue
        for pat in ENTRIES:
            i = d.find(pat)
            if i >= 0:
                key = (lo, i & ~0xfff, pat.hex())
                if key not in found:
                    found.add(key)
                    print("%.2f RING %s VA 0x%x (+0x%x) %s" % (time.time()-t0, pat.hex(), lo+(i&~0xfff), i&~0xfff, tag), flush=True)
        for off in range(0, size - 0x1000, 0x1000):
            page = d[off:off+0x1000]
            if hdr_ok(page):
                key = (lo, off, "h")
                if key not in found:
                    found.add(key)
                    print("%.2f HDR VA 0x%x (+0x%x) %s head=%s" % (time.time()-t0, lo+off, off, tag, page[:0x30].hex()), flush=True)
    if it % 10 == 0:
        print("%.1f iter %d areas %d" % (time.time()-t0, it, nareas), flush=True)
    time.sleep(0.2)
print("vmap_watch2 done", flush=True)