summaryrefslogtreecommitdiffstats
path: root/tools/guest-diag
diff options
context:
space:
mode:
Diffstat (limited to 'tools/guest-diag')
-rw-r--r--tools/guest-diag/guest_pin_stream.py61
1 files changed, 39 insertions, 22 deletions
diff --git a/tools/guest-diag/guest_pin_stream.py b/tools/guest-diag/guest_pin_stream.py
index bed4728..ac4f72b 100644
--- a/tools/guest-diag/guest_pin_stream.py
+++ b/tools/guest-diag/guest_pin_stream.py
@@ -30,6 +30,12 @@ REGION = 0x200000
# ..0x45000) and the per-channel push allocations follow; 512 KB per 2 MB
# region covers both without scanning holes that hold nothing.
SPAN = int(os.environ.get("STREAM_SPAN", "0x80000"), 16)
+# CE push-buffer window: one 1 MB allocation per CE channel at
+# 0x120000000 + 0x100000*rank; SPAN2 covers the 1 MB boundary inside a
+# 2 MB region.
+LO2 = int(os.environ.get("STREAM_LO2", "0x120000000"), 16)
+HI2 = int(os.environ.get("STREAM_HI2", "0x120600000"), 16)
+SPAN2 = int(os.environ.get("STREAM_SPAN2", "0x180000"), 16)
TRACE = ("/sys/kernel/tracing/trace"
if os.path.exists("/sys/kernel/tracing/trace")
else "/sys/kernel/debug/tracing/trace")
@@ -108,6 +114,31 @@ def cdt_pid():
return None
+def scan_window(fd, lo, hi, span, out):
+ base = lo & ~(REGION - 1)
+ while base < hi:
+ va = max(base, lo) & ~0xFFF
+ end = min(base + span, hi)
+ while va < end:
+ n = min(BATCH, (end - va) // 0x1000)
+ if n <= 0:
+ break
+ os.lseek(fd, (va // 4096) * 8, 0)
+ data = os.read(fd, n * 8)
+ got = len(data) // 8
+ for i in range(got):
+ e = int.from_bytes(data[i * 8:i * 8 + 8], 'little')
+ if not ((e >> 63) & 1):
+ continue
+ pfn = e & ((1 << 55) - 1)
+ pa = pfn << 12
+ if not pa or (PAMAX and pa >= PAMAX):
+ continue
+ out[va + i * 0x1000] = pa
+ va += got * 0x1000
+ base += REGION
+
+
def scan(pid):
"""Present pages in the first SPAN bytes of every REGION, as {va: pa}.
@@ -115,32 +146,18 @@ def scan(pid):
aligned); scanning only the allocation heads keeps the per-loop page
table work small, which is what makes the stream fast while the client
is mapping and the guest is loaded.
+
+ Two windows: the GR window (rings/pushbuffers/counter page) and the CE
+ push-buffer window (0x120000000+, one 1 MB allocation per CE channel).
+ The CE window uses a wider span because the per-channel allocations are
+ 1 MB apart inside a 2 MB region.
"""
fd = os.open('/proc/%d/pagemap' % pid, os.O_RDONLY)
out = {}
try:
- base = LO & ~(REGION - 1)
- while base < HI:
- va = max(base, LO) & ~0xFFF
- end = min(base + SPAN, HI)
- while va < end:
- n = min(BATCH, (end - va) // 0x1000)
- if n <= 0:
- break
- os.lseek(fd, (va // 4096) * 8, 0)
- data = os.read(fd, n * 8)
- got = len(data) // 8
- for i in range(got):
- e = int.from_bytes(data[i * 8:i * 8 + 8], 'little')
- if not ((e >> 63) & 1):
- continue
- pfn = e & ((1 << 55) - 1)
- pa = pfn << 12
- if not pa or (PAMAX and pa >= PAMAX):
- continue
- out[va + i * 0x1000] = pa
- va += got * 0x1000
- base += REGION
+ scan_window(fd, LO, HI, SPAN, out)
+ if HI2 > LO2:
+ scan_window(fd, LO2, HI2, SPAN2, out)
finally:
os.close(fd)
return out