summaryrefslogtreecommitdiffstats
path: root/tools/guest-diag/sem_slots.py
blob: 70d184cfdd679296704a4a202306752a6e340825 (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
#!/usr/bin/env python3
# sem_slots.py - read or write the per-channel u32 completion counters of a
# guest process (verification and fallback for the host's counter publish).
#
# Usage:
#   sudo python3 sem_slots.py <pid> <first-va> [count]              # read
#   sudo python3 sem_slots.py <pid> <first-va> [count] --write <v>  # write
#
# The slots are 16 bytes apart (one u32 per channel). Reading needs pagemap/
# mem access as root; writing uses /proc/<pid>/mem and mirrors the gdb poke
# used in earlier sessions (e.g. --write 1 to arm every waiter).
import os
import sys


def main():
    if len(sys.argv) < 3:
        print(__doc__)
        return 1
    pid = int(sys.argv[1])
    first = int(sys.argv[2], 16)
    count = 20
    write_val = None
    i = 3
    while i < len(sys.argv):
        if sys.argv[i] == '--write':
            write_val = int(sys.argv[i + 1], 0)
            i += 2
            continue
        count = int(sys.argv[i], 0)
        i += 1

    flags = os.O_RDWR if write_val is not None else os.O_RDONLY
    mem = os.open('/proc/%d/mem' % pid, flags)
    try:
        for n in range(count):
            va = first + n * 16
            if write_val is not None:
                os.pwrite(mem, write_val.to_bytes(4, 'little'), va)
                print('idx=%d VA=0x%x written=%u' % (n, va, write_val))
            else:
                v = int.from_bytes(os.pread(mem, 4, va), 'little')
                print('idx=%d VA=0x%x val=%u' % (n, va, v))
    finally:
        os.close(mem)
    return 0


if __name__ == '__main__':
    sys.exit(main())