diff options
| author | Peter Maydell <peter.maydell@linaro.org> | 2024-09-19 21:31:35 +0100 |
|---|---|---|
| committer | Peter Maydell <peter.maydell@linaro.org> | 2024-09-19 21:31:35 +0100 |
| commit | a5dd9ee060b0ad65239889a62e93a33276055981 (patch) | |
| tree | 5f9d51119f09f671b1430b60d82599e0023533c0 /tests/tcg/multiarch/system/validate-memory-counts.py | |
| parent | 01dc65a3bc262ab1bec8fe89775e9bbfa627becb (diff) | |
| parent | 8148fb56c753908fcc41d52846f9d8e6ae5f7daf (diff) | |
| download | focaccia-qemu-a5dd9ee060b0ad65239889a62e93a33276055981.tar.gz focaccia-qemu-a5dd9ee060b0ad65239889a62e93a33276055981.zip | |
Merge tag 'pull-tcg-plugin-memory-190924-1' of https://gitlab.com/stsquad/qemu into staging
TCG plugin memory instrumentation updates - deprecate plugins on 32 bit hosts - deprecate plugins with TCI - extend memory API to save value - add check-tcg tests to exercise new memory API - fix timer deadlock with non-changing timer - add basic block vector plugin to contrib - add cflow plugin to contrib - extend syscall plugin to dump write memory - validate ips plugin arguments meet minimum slice value # -----BEGIN PGP SIGNATURE----- # # iQEzBAABCgAdFiEEZoWumedRZ7yvyN81+9DbCVqeKkQFAmbsPCUACgkQ+9DbCVqe # KkTm1gf9Hs5Zfdng0E+7sr5Dpa5F+cJOXU9QJhoTWJ4XC16CygWByqMXbyeX/kvm # HXJEm6OnkADJhikIUCoBko8uK4/96iWSrDL0sEdzASX4SM/tXu684KeL+j9G/Ql8 # iqxm6tIjaJqmbSZRMp0l5jD+ZBltRMCzBNdK1suJR2ppQgqfKj3qMLVLtq2hhqPH # qPgwKm44hk9BEpHYqXaivzSWN5GKCgvp5ECcFXCBhDcM+8W7Dl3Mv6X0pWOpYcKZ # d2a5KUt+Xp7WB2jkOgJYr0zKCOQCiCjGSfm/30qRDOUnwiLRWbfamRI9jUDNUtfy # RYR+GaspurGCwSkwICdlvj+vFp/16Q== # =5wfo # -----END PGP SIGNATURE----- # gpg: Signature made Thu 19 Sep 2024 15:58:45 BST # gpg: using RSA key 6685AE99E75167BCAFC8DF35FBD0DB095A9E2A44 # gpg: Good signature from "Alex Bennée (Master Work Key) <alex.bennee@linaro.org>" [full] # Primary key fingerprint: 6685 AE99 E751 67BC AFC8 DF35 FBD0 DB09 5A9E 2A44 * tag 'pull-tcg-plugin-memory-190924-1' of https://gitlab.com/stsquad/qemu: contrib/plugins: avoid hanging program plugins: add option to dump write argument to syscall plugin plugins: add plugin API to read guest memory contrib/plugins: Add a plugin to generate basic block vectors util/timer: avoid deadlock when shutting down tests/tcg: add a system test to check memory instrumentation tests/tcg: ensure s390x-softmmu output redirected tests/tcg: only read/write 64 bit words on 64 bit systems tests/tcg: clean up output of memory system test tests/tcg/multiarch: add test for plugin memory access tests/tcg/plugins/mem: add option to print memory accesses tests/tcg: allow to check output of plugins tests/tcg: add mechanism to run specific tests with plugins plugins: extend API to get latest memory value accessed plugins: save value during memory accesses contrib/plugins: control flow plugin deprecation: don't enable TCG plugins by default with TCI deprecation: don't enable TCG plugins by default on 32 bit hosts Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'tests/tcg/multiarch/system/validate-memory-counts.py')
| -rwxr-xr-x | tests/tcg/multiarch/system/validate-memory-counts.py | 130 |
1 files changed, 130 insertions, 0 deletions
diff --git a/tests/tcg/multiarch/system/validate-memory-counts.py b/tests/tcg/multiarch/system/validate-memory-counts.py new file mode 100755 index 0000000000..5b8bbf3ef3 --- /dev/null +++ b/tests/tcg/multiarch/system/validate-memory-counts.py @@ -0,0 +1,130 @@ +#!/usr/bin/env python3 +# +# validate-memory-counts.py: check we instrumented memory properly +# +# This program takes two inputs: +# - the mem plugin output +# - the memory binary output +# +# Copyright (C) 2024 Linaro Ltd +# +# SPDX-License-Identifier: GPL-2.0-or-later + +import sys +from argparse import ArgumentParser + +def extract_counts(path): + """ + Load the output from path and extract the lines containing: + + Test data start: 0x40214000 + Test data end: 0x40218001 + Test data read: 2522280 + Test data write: 262111 + + From the stream of data. Extract the values for use in the + validation function. + """ + start_address = None + end_address = None + read_count = 0 + write_count = 0 + with open(path, 'r') as f: + for line in f: + if line.startswith("Test data start:"): + start_address = int(line.split(':')[1].strip(), 16) + elif line.startswith("Test data end:"): + end_address = int(line.split(':')[1].strip(), 16) + elif line.startswith("Test data read:"): + read_count = int(line.split(':')[1].strip()) + elif line.startswith("Test data write:"): + write_count = int(line.split(':')[1].strip()) + return start_address, end_address, read_count, write_count + + +def parse_plugin_output(path, start, end): + """ + Load the plugin output from path in the form of: + + Region Base, Reads, Writes, Seen all + 0x0000000040004000, 31093, 0, false + 0x0000000040214000, 2522280, 278579, true + 0x0000000040000000, 137398, 0, false + 0x0000000040210000, 54727397, 33721956, false + + And extract the ranges that match test data start and end and + return the results. + """ + total_reads = 0 + total_writes = 0 + seen_all = False + + with open(path, 'r') as f: + next(f) # Skip the header + for line in f: + + if line.startswith("Region Base"): + continue + + parts = line.strip().split(', ') + if len(parts) != 4: + continue + + region_base = int(parts[0], 16) + reads = int(parts[1]) + writes = int(parts[2]) + + if start <= region_base < end: # Checking if within range + total_reads += reads + total_writes += writes + seen_all = parts[3] == "true" + + return total_reads, total_writes, seen_all + +def main() -> None: + """ + Process the arguments, injest the program and plugin out and + verify they match up and report if they do not. + """ + parser = ArgumentParser(description="Validate memory instrumentation") + parser.add_argument('test_output', + help="The output from the test itself") + parser.add_argument('plugin_output', + help="The output from memory plugin") + parser.add_argument('--bss-cleared', + action='store_true', + help='Assume bss was cleared (and adjusts counts).') + + args = parser.parse_args() + + # Extract counts from memory binary + start, end, exp_reads, exp_writes = extract_counts(args.test_output) + + # Some targets clear BSS before running but the test doesn't know + # that so we adjust it by the size of the test region. + if args.bss_cleared: + exp_writes += 16384 + + if start is None or end is None: + print("Failed to test_data boundaries from output.") + sys.exit(1) + + # Parse plugin output + preads, pwrites, seen_all = parse_plugin_output(args.plugin_output, + start, end) + + if not seen_all: + print("Fail: didn't instrument all accesses to test_data.") + sys.exit(1) + + # Compare and report + if preads == exp_reads and pwrites == exp_writes: + sys.exit(0) + else: + print("Fail: The memory reads and writes count does not match.") + print(f"Expected Reads: {exp_reads}, Actual Reads: {preads}") + print(f"Expected Writes: {exp_writes}, Actual Writes: {pwrites}") + sys.exit(1) + +if __name__ == "__main__": + main() |