summaryrefslogtreecommitdiffstats
path: root/tools/guest-diag/wall2/wall2_recscan.py
diff options
context:
space:
mode:
Diffstat (limited to 'tools/guest-diag/wall2/wall2_recscan.py')
-rw-r--r--tools/guest-diag/wall2/wall2_recscan.py70
1 files changed, 70 insertions, 0 deletions
diff --git a/tools/guest-diag/wall2/wall2_recscan.py b/tools/guest-diag/wall2/wall2_recscan.py
new file mode 100644
index 0000000..7bc4e2c
--- /dev/null
+++ b/tools/guest-diag/wall2/wall2_recscan.py
@@ -0,0 +1,70 @@
+#!/usr/bin/env python3
+# wall2_recscan.py - scan the guest RAM for the RM's low-aperture window
+# records and their memdesc PAs.
+#
+# Record layout (verified r685/r686): 0x40-byte stride
+# {u64 tag; u64 VA; u64 SIZE; u64 0; u32 0x7461696c ("tail" as a u32 -
+# on disk the BYTES are "liat"); u32 0}
+# The tag is NOT the byte string "tail" - searching for b'tail' finds
+# nothing; search for the 4-byte pattern 6c 69 61 74 (struct '<I'
+# 0x7461696c) at record+0x20 and decode {tag,VA,SIZE} at -0x20/-0x18/-0x10.
+#
+# Usage: wall2_recscan.py [VA_prefix_or_full_VA]
+# Prints every record and the size-matching memdesc {SIZE,0x03008000,PA}
+# found in the same page, and dumps the first words of each memdesc page so
+# semaphore windows can be identified by the release payload values.
+import struct, sys
+
+RAM = "/dev/shm/vgpu-guest-ram"
+TAG = struct.pack("<I", 0x7461696c)
+
+def off2gpa(off):
+ return off if off < 0x80000000 else 0x100000000 + (off - 0x80000000)
+
+def gpa2off(pa):
+ if pa < 0x80000000:
+ return pa
+ if pa < 0x180000000:
+ return 0x80000000 + (pa - 0x100000000)
+ return None
+
+def main():
+ want = None
+ if len(sys.argv) > 1:
+ want = int(sys.argv[1], 0)
+ img = open(RAM, "rb", buffering=0)
+ img.seek(0, 2); fsz = img.tell()
+ recs = []
+ pos = 0; CH = 64 << 20
+ while pos < fsz:
+ img.seek(pos); buf = img.read(min(CH, fsz - pos))
+ st = 0
+ while True:
+ i = buf.find(TAG, st)
+ if i < 0:
+ break
+ st = i + 1
+ if i >= 0x20:
+ tag, va, sz, z = struct.unpack_from("<QQQQ", buf, i - 0x20)
+ if 0x4000000 <= va < 0x100000000 and \
+ 0x1000 <= sz <= 0x1000000 and (sz & 0xfff) == 0 and z == 0:
+ if want is None or va == want or (va & ~0xfffff) == (want & ~0xfffff):
+ recs.append((off2gpa(pos + i - 0x20), tag, va, sz))
+ pos += CH
+ for gpa, tag, va, sz in sorted(recs, key=lambda r: r[2]):
+ page = gpa & ~0xfff
+ img.seek(gpa2off(page)); d = img.read(0x1000)
+ descs = []
+ for o in range(0, 0x1000 - 24, 8):
+ s2, f2 = struct.unpack_from("<QQ", d, o)
+ pa = struct.unpack_from("<Q", d, o + 16)[0]
+ if f2 == 0x03008000 and s2 == sz and 0x100000000 <= pa < 0x180000000:
+ descs.append(pa)
+ print("rec gpa=0x%x tag=0x%x va=0x%x size=0x%x" % (gpa, tag, va, sz))
+ for pa in descs:
+ img.seek(gpa2off(pa)); pd = img.read(0x20)
+ print(" desc pa=0x%x head=%s" % (pa, pd.hex(" ")))
+ return 0
+
+if __name__ == "__main__":
+ sys.exit(main())