diff options
Diffstat (limited to 'tools/guest-diag/guest_pmap_win.py')
| -rw-r--r-- | tools/guest-diag/guest_pmap_win.py | 38 |
1 files changed, 31 insertions, 7 deletions
diff --git a/tools/guest-diag/guest_pmap_win.py b/tools/guest-diag/guest_pmap_win.py index a9b74a7..f6ca85c 100644 --- a/tools/guest-diag/guest_pmap_win.py +++ b/tools/guest-diag/guest_pmap_win.py @@ -4,8 +4,9 @@ # pread) so a 256 MB window takes about a second, not minutes. # # Usage: sudo python3 guest_pmap_win.py <pid> <lo-hex> <hi-hex> [max-pairs] [pa-max-hex] -# Output: one "0x<va>,0x<pa>" line per present page (ascending VA), capped at -# max-pairs. PAs of 0 are skipped; pages above pa-max are skipped unless 0. +# Output: one "0x<va>,0x<pa>,<npages>" line per contiguous run (ascending VA), +# capped at max-pairs pages. PAs of 0 are skipped; pages at/above pa-max are +# skipped unless pa-max is 0. import os import sys @@ -17,6 +18,16 @@ pa_max = int(sys.argv[5], 16) if len(sys.argv) > 5 else 0 BATCH = 512 out = [] +run_va = run_pa = None +run_n = 0 +pairs = 0 + + +def flush(): + if run_n: + out.append('0x%x,0x%x,%d' % (run_va, run_pa, run_n)) + + fd = os.open('/proc/%d/pagemap' % pid, os.O_RDONLY) try: va = lo @@ -29,19 +40,32 @@ try: got = len(data) // 8 for i in range(got): e = int.from_bytes(data[i * 8:i * 8 + 8], 'little') + page_va = va + i * 0x1000 if not ((e >> 63) & 1): + flush() + run_va = run_pa = None + run_n = 0 continue pfn = e & ((1 << 55) - 1) pa = pfn << 12 - if not pa: - continue - if pa_max and pa >= pa_max: + if not pa or (pa_max and pa >= pa_max): + flush() + run_va = run_pa = None + run_n = 0 continue - out.append('0x%x,0x%x' % (va + i * 0x1000, pa)) - if len(out) >= maxp: + if (run_va is not None and page_va == run_va + run_n * 0x1000 + and pa == run_pa + run_n * 0x1000): + run_n += 1 + else: + flush() + run_va, run_pa, run_n = page_va, pa, 1 + pairs += 1 + if pairs >= maxp: + flush() print('\n'.join(out)) sys.exit(0) va += got * 0x1000 finally: os.close(fd) +flush() print('\n'.join(out)) |
