From f863cf8846a17fc53b75b1235dd2c1804e8efd27 Mon Sep 17 00:00:00 2001 From: Arthur Hanson Rasmusson Date: Tue, 29 Sep 2026 18:01:12 -0400 Subject: guest-diag: single-read counter sampler (kills phantom 4-of-20 view); vmrestart reaps stale watchers --- tools/guest-diag/track_waits.sh | 36 ++++++++++++++++++------------------ tools/guest-diag/vmrestart.sh | 5 +++++ 2 files changed, 23 insertions(+), 18 deletions(-) diff --git a/tools/guest-diag/track_waits.sh b/tools/guest-diag/track_waits.sh index 1e3cc91..54c4905 100644 --- a/tools/guest-diag/track_waits.sh +++ b/tools/guest-diag/track_waits.sh @@ -28,31 +28,31 @@ pid = int(sys.argv[1]); page = int(sys.argv[2], 16) count = int(sys.argv[3]); stride = int(sys.argv[4], 16); off = int(sys.argv[5], 16) pm = os.open('/proc/%d/pagemap' % pid, os.O_RDONLY) mem = os.open('/proc/%d/mem' % pid, os.O_RDONLY) +# Window dump start; slots live at [off, off+count*stride) inside the page. +WIN = 0x200 +WIN_BASE = page + 0xe00 +SLOT0 = off - 0xe00 while True: ts = time.strftime('%T') - vals = [] - for i in range(count): - va = page + off + i * stride - try: - os.lseek(pm, (va // 4096) * 8, 0) - e = int.from_bytes(os.read(pm, 8), 'little') - present = (e >> 63) & 1 - if present: - v = int.from_bytes(os.pread(mem, 4, va), 'little') - vals.append('%d:0x%x' % (i, v)) - else: - vals.append('%d:-' % i) - except OSError: - vals.append('%d:ERR' % i) - print('%s %s' % (ts, ' '.join(vals)), flush=True) - # Raw hex dump of the counter window: shows the true slot layout and any - # value a stride-16 sample would misread. try: os.lseek(pm, (page // 4096) * 8, 0) e = int.from_bytes(os.read(pm, 8), 'little') if (e >> 63) & 1: - raw = os.pread(mem, 0x200, page + 0xe00) + # One read for both views: per-slot values and the raw dump come + # from the same buffer, so they can never disagree. (The old + # 20-single-word reader plus a later bulk read produced a + # phantom "4 of 20 slots" pattern from a torn/remapped read.) + raw = os.pread(mem, WIN, WIN_BASE) + vals = [] + for i in range(count): + o = SLOT0 + i * stride + v = int.from_bytes(raw[o:o + 4], 'little') + vals.append('%d:0x%x' % (i, v)) + print('%s %s' % (ts, ' '.join(vals)), flush=True) print('%s RAW %s' % (ts, raw.hex()), flush=True) + else: + print('%s %s' % (ts, ' '.join('%d:-' % i for i in range(count))), + flush=True) except OSError: pass time.sleep(0.5) diff --git a/tools/guest-diag/vmrestart.sh b/tools/guest-diag/vmrestart.sh index dbe60ec..5d15852 100755 --- a/tools/guest-diag/vmrestart.sh +++ b/tools/guest-diag/vmrestart.sh @@ -6,6 +6,11 @@ set -u cd "$(dirname "$(readlink -f "$0")")/../.." sudo pkill -f qemu-system-x86_64 2>/dev/null +# Reap host-side watchers too: a pin_gr_stream/semfix pair left over from the +# previous boot holds the vsock port and the single QMP socket slot and will +# silently corrupt the next run (two QMP clients). +pkill -f "guest-diag/pin_gr_stream.py" 2>/dev/null +pkill -f "guest-diag/semfix_uvmt.py" 2>/dev/null sleep 4 sudo rm -f /tmp/qemu-guest-agent.sock /tmp/qemu-qmp.sock -- cgit v1.2.3