summaryrefslogtreecommitdiffstats
path: root/tools/guest-diag/wall2/find_ring_va.py
blob: c02ea40d9cc16ce99a4d0da6919c2d245aad102d (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
#!/usr/bin/env python3
# Guest-side: read the nv_vm_map_pages vmap areas via /proc/kcore and find the
# GPFIFO entry pattern (entry0 raw 0x0005980004480000 for va=0x4480000 len=1432).
import struct, sys
pat = bytes.fromhex("0000480400980500")  # 0x0005980004480000 LE
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()
areas = []
for line in open("/proc/vmallocinfo"):
    p = line.split()
    if len(p) < 2: continue
    if "nv_vm_map_pages" not in line: continue
    lo, hi = p[0].split("-")
    areas.append((int(lo, 16), int(hi, 16)))
print("nv_vm_map_pages areas:", len(areas))
for lo, hi in areas:
    size = hi - lo
    d = kc.read(lo, size)
    if not d:
        print("  0x%x-0x%x unreadable" % (lo, hi)); continue
    idx = d.find(pat)
    print("  0x%x-0x%x size=0x%x hit=%s" % (lo, hi, size, ("+0x%x -> VA 0x%x" % (idx, lo + idx)) if idx >= 0 else "no"))
    if idx >= 0:
        # dump the page around the hit
        base = lo + (idx & ~0xfff)
        page = kc.read(base, 0x100)
        print("     page head: %s" % page.hex())