summaryrefslogtreecommitdiffstats
path: root/tools/guest-diag/wall2/trace_push674.py
blob: ced41680b3dcfdc9810558bfd4508c7da0d29e87 (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
#!/usr/bin/env python3
# r674: find every reference to the push VA 0x4480000 and follow RM structures
# (direct-map pointers: PA = ptr - page_offset_base) toward a page list.
import numpy as np, struct, os, time, sys

RAM="/dev/shm/vgpu-guest-ram"
VA=0x4480000
BASE=0xffff8916c0000000   # r674 page_offset_base (from dmesg rebuild #15)
img=open(RAM,"rb"); fsz=os.path.getsize(RAM)
def gpa2off(pa):
    if pa<0x80000000: return pa
    if pa<0x180000000: return 0x80000000+(pa-0x100000000)
    return None
def off2gpa(off):
    return off if off<0x80000000 else 0x100000000+(off-0x80000000)
def rd(pa,n):
    off=gpa2off(pa)
    if off is None or off+n>fsz: return None
    img.seek(off); return img.read(n)
def ptr2pa(v):
    if BASE<=v<BASE+0x180000000:
        return v-BASE
    return None

CH=64<<20
hits=[]
t0=time.time()
for pos in range(0,fsz,CH):
    img.seek(pos); d=img.read(min(CH,fsz-pos))
    n=len(d)//8
    a=np.frombuffer(d[:n*8],dtype=np.uint64)
    idx=np.nonzero(a==np.uint64(VA))[0]
    for i in idx: hits.append(off2gpa(pos+int(i)*8))
print("VA hits:", len(hits), "(%.1fs)" % (time.time()-t0))

def tag(v):
    bs=struct.pack("<Q",v)
    return bs.decode() if all(32<=c<127 for c in bs) else ""

for gpa in hits:
    page=gpa&~0xfff
    d=rd(page,0x1000)
    if not d: continue
    ro=gpa-page
    print("== hit gpa=0x%x page=0x%x off=0x%x ==" % (gpa,page,ro))
    # print 0x60 before, 0x80 after
    s=max(0,ro-0x60); e=min(0x1000,ro+0x80)
    for o in range(s,e,0x10):
        a,b=struct.unpack_from("<QQ",d,o)
        print("   +0x%03x: %016x %016x %s %s" % (o,a,b,tag(a),tag(b)))
    # follow direct-map pointers in this page
    for o in range(0,0x1000-8,8):
        v=struct.unpack_from("<Q",d,o)[0]
        pa=ptr2pa(v)
        if pa is None: continue
        dd=rd(pa&~0xfff,0x1000)
        if not dd: continue
        # search that page for PA runs (>=8 page-aligned RAM PAs ascending/descending)
        runs=[]; cur=[]
        for oo in range(0,0xff8,8):
            vv=struct.unpack_from("<Q",dd,oo)[0]
            if 0x100000000<=vv<0x180000000 and (vv&0xfff)==0:
                cur.append((oo,vv))
            else:
                if len(cur)>=8: runs.append(cur)
                cur=[]
        if len(cur)>=8: runs.append(cur)
        if runs:
            print("   ptr +0x%03x -> pa=0x%x has %d PA-run(s):" % (o,pa&~0xfff,len(runs)))
            for r in runs[:4]:
                print("      run at +0x%x: %d pages first=0x%x last=0x%x" % (r[0][0],len(r),r[0][1],r[-1][1]))