diff options
| author | Ian Rogers <irogers@google.com> | 2026-09-25 23:19:44 -0700 |
|---|---|---|
| committer | Arnaldo Carvalho de Melo <acme@redhat.com> | 2026-09-26 20:49:28 +0200 |
| commit | 6ceccefad0751966ec63713e2855095caf296c54 (patch) | |
| tree | 68ab680e260e653069d0579130eb2e4316b2ba0e /tools/perf/tests/shell/test_mem_phys_addr_python.sh | |
| parent | 4425182d426b2180e98d0b537f46cdb03078876d (diff) | |
| download | linux-next-6ceccefad0751966ec63713e2855095caf296c54.tar.gz linux-next-6ceccefad0751966ec63713e2855095caf296c54.zip | |
perf python: Port mem-phys-addr to perf module
Port mem-phys-addr.py to a standalone script in tools/perf/python/
using the perf.session API to read perf.data files and profile physical
memory access types against /proc/iomem.
Improvements compared to the legacy script:
- Parse the full indentation hierarchy of /proc/iomem into a parent-child
tree of frozen IomemEntry dataclasses (instead of only top-level
indent-0 ranges), resolving physical addresses to the most specific
sub-range (such as Kernel code/data/bss inside System RAM) and rolling
child counts up into parent totals.
- Support profiling multiple memory events in a single perf.data session
(keyed by evsel name) instead of assuming a single global event.
- Add argparse CLI options (-i/--input and --iomem to allow supplying an
offline /proc/iomem snapshot from a target system).
Add a shell test (test_mem_phys_addr_python.sh) to verify the standalone
script.
Assisted-by: Antigravity:gemini-3.1-pro
Signed-off-by: Ian Rogers <irogers@google.com>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Diffstat (limited to 'tools/perf/tests/shell/test_mem_phys_addr_python.sh')
| -rwxr-xr-x | tools/perf/tests/shell/test_mem_phys_addr_python.sh | 102 |
1 files changed, 102 insertions, 0 deletions
diff --git a/tools/perf/tests/shell/test_mem_phys_addr_python.sh b/tools/perf/tests/shell/test_mem_phys_addr_python.sh new file mode 100755 index 000000000000..d094a0611a24 --- /dev/null +++ b/tools/perf/tests/shell/test_mem_phys_addr_python.sh @@ -0,0 +1,102 @@ +#!/bin/bash +# SPDX-License-Identifier: GPL-2.0 +# mem-phys-addr python test + +set -e + +shelldir=$(dirname "$0") +# shellcheck source=lib/setup_python.sh +. "${shelldir}"/lib/setup_python.sh + +# If we don't have the perf python module, we can't test +if ! "$PYTHON" -c 'import perf' > /dev/null 2>&1; then + echo "Skipping test, perf python module not found" + exit 2 +fi + +script_dir="$(dirname "$0")/../../python" +script_path="${script_dir}/mem-phys-addr.py" + +if [ ! -f "$script_path" ]; then + echo "Skipping test, mem-phys-addr.py not found at $script_path" + exit 2 +fi + +err=0 +temp_data="" +temp_iomem="" +temp_out="" + +cleanup() { + rm -f "${temp_data}" "${temp_iomem}" "${temp_out}" +} + +trap 'cleanup' EXIT TERM INT + +temp_data=$(mktemp /tmp/perf.data.XXXXXX) +temp_iomem=$(mktemp /tmp/perf.iomem.XXXXXX) +temp_out=$(mktemp /tmp/perf.out.XXXXXX) + +cat << 'EOF' > "${temp_iomem}" +00000000-ffffffffffffffff : System RAM + 00000000-7fffffffffffffff : Low RAM + 00001000-00ffffff : Kernel code + 8000000000000000-ffffffffffffffff : High RAM +EOF + +test_iomem_hierarchy() { + echo "Testing mem-phys-addr.py hierarchical iomem resolution..." + "$PYTHON" - "$script_path" "${temp_iomem}" << 'PYEOF' > "${temp_out}" +import importlib.util +import sys + +spec = importlib.util.spec_from_file_location("mem_phys_addr", sys.argv[1]) +mod = importlib.util.module_from_spec(spec) +sys.modules[spec.name] = mod +spec.loader.exec_module(mod) + +mod.parse_iomem(sys.argv[2]) +entry_kernel = mod.find_memory_type(0x100000) +entry_high = mod.find_memory_type(0x9000000000000000) +assert entry_kernel is not None and entry_kernel.label == "Kernel code" +assert entry_high is not None and entry_high.label == "High RAM" +mod.event_counts["cpu/mem-loads/"][entry_kernel] += 3 +mod.event_counts["cpu/mem-loads/"][entry_high] += 1 +mod.print_memory_type() +PYEOF + if ! grep -q "System RAM" "${temp_out}" || \ + ! grep -q "Kernel code" "${temp_out}" || \ + ! grep -q "High RAM" "${temp_out}"; then + echo "Hierarchical iomem resolution test failed." + err=1 + else + echo "Hierarchical iomem resolution test passed." + fi +} + +test_file_mode() { + echo "Testing mem-phys-addr.py file mode..." + + # Generate memory access events (try unprivileged user-space first, then system-wide) + if ! perf record --phys-data -d -o "${temp_data}" \ + -- perf test -w datasym >/dev/null 2>&1 && \ + ! perf record -d -o "${temp_data}" -- perf test -w datasym >/dev/null 2>&1 && \ + ! perf record -d -a -o "${temp_data}" -- sleep 0.2 >/dev/null 2>&1; then + echo "Skipping file mode record test, perf record -d not supported" + return 0 + fi + + # Run the script with custom --iomem + if ! "$PYTHON" "$script_path" -i "${temp_data}" --iomem "${temp_iomem}" > "${temp_out}" || \ + [ ! -s "${temp_out}" ]; then + echo "File mode test failed." + err=1 + else + echo "File mode test passed." + fi +} + +test_iomem_hierarchy +test_file_mode + +exit $err |
