[PATCH v3 13/14] perf tests: Check CoreSight abort entry and exit
Leo Yan
leo.yan at arm.com
Fri Oct 30 08:13:20 PDT 2026
Add page_fault_loop to repeatedly discard an anonymous page with
MADV_DONTNEED and read it again. Each demand fault is resolved without
signal delivery, so the load must be retried at the same PC.
For example, an expected int/iret pair is:
int 5ccadc => ffff800080010c00 insn: 00 00 40 39
...
iret ffff800080012284 => 5ccadc insn: e0 03 9f d6
The LDRB W0, [X0] at 0x5ccadc faults before completing. After resolving
the page fault, the kernel returns via ERET to the same PC to retry it.
Reviewed-by: James Clark <james.clark at linaro.org>
Signed-off-by: Leo Yan <leo.yan at arm.com>
---
tools/perf/tests/builtin-test.c | 1 +
.../perf/tests/shell/coresight/abort_entry_exit.sh | 32 +++++++++++++++++++
tools/perf/tests/tests.h | 1 +
tools/perf/tests/workloads/Build | 2 ++
tools/perf/tests/workloads/page_fault_loop.c | 37 ++++++++++++++++++++++
5 files changed, 73 insertions(+)
diff --git a/tools/perf/tests/builtin-test.c b/tools/perf/tests/builtin-test.c
index 24e095d4d20cee6a6aae7cfda364fb237ef74b30..86698b86657f45b094755583800062c37e16ca8b 100644
--- a/tools/perf/tests/builtin-test.c
+++ b/tools/perf/tests/builtin-test.c
@@ -192,6 +192,7 @@ static struct test_workload *workloads[] = {
&workload__landlock,
&workload__traploop,
&workload__branch_not_taken_loop,
+ &workload__page_fault_loop,
&workload__inlineloop,
&workload__jitdump,
&workload__context_switch_loop,
diff --git a/tools/perf/tests/shell/coresight/abort_entry_exit.sh b/tools/perf/tests/shell/coresight/abort_entry_exit.sh
new file mode 100755
index 0000000000000000000000000000000000000000..98aeb2b1068e9847d87e3b25aeabf6da114c6ae2
--- /dev/null
+++ b/tools/perf/tests/shell/coresight/abort_entry_exit.sh
@@ -0,0 +1,32 @@
+#!/bin/bash
+# SPDX-License-Identifier: GPL-2.0
+# CoreSight abort entry and exit (exclusive)
+
+. "$(dirname "$0")/../lib/coresight_exception.sh"
+
+test_abort_entry_exit()
+{
+ local attempt result
+
+ # A demand page fault retries the load at the same PC after resolution.
+ for attempt in 1 2 3; do
+ echo "Recording page faults (attempt $attempt/3)"
+ if ! record_trace page_fault_loop; then
+ cat "$tmpdir/record.log"
+ echo "Failed to record the page fault workload"
+ return 1
+ fi
+ decode_trace || return 1
+ check_exception_pairs "int" "iret" 0
+ result=$?
+ if [ "$result" -ne 2 ]; then
+ return "$result"
+ fi
+ done
+
+ echo "FAIL: No complete abort pair after three recordings"
+ return 1
+}
+
+setup_exception_test || exit $?
+test_abort_entry_exit
diff --git a/tools/perf/tests/tests.h b/tools/perf/tests/tests.h
index 989208fcd417a676d03e2372e8a71ecf2059b9c6..8c399840a735910d4344eba928075e3ec6b1f81c 100644
--- a/tools/perf/tests/tests.h
+++ b/tools/perf/tests/tests.h
@@ -265,6 +265,7 @@ DECLARE_WORKLOAD(datasym);
DECLARE_WORKLOAD(landlock);
DECLARE_WORKLOAD(traploop);
DECLARE_WORKLOAD(branch_not_taken_loop);
+DECLARE_WORKLOAD(page_fault_loop);
DECLARE_WORKLOAD(inlineloop);
DECLARE_WORKLOAD(jitdump);
DECLARE_WORKLOAD(context_switch_loop);
diff --git a/tools/perf/tests/workloads/Build b/tools/perf/tests/workloads/Build
index d3030bd9c0752a5bc8743a4539a0ac365d215719..43cc4da6fb0786de8bb5c52717c2ad5fdbaa639c 100644
--- a/tools/perf/tests/workloads/Build
+++ b/tools/perf/tests/workloads/Build
@@ -10,6 +10,7 @@ perf-test-y += datasym.o
perf-test-y += landlock.o
perf-test-y += traploop.o
perf-test-y += branch_not_taken_loop.o
+perf-test-y += page_fault_loop.o
perf-test-y += inlineloop.o
perf-test-y += jitdump.o
perf-test-y += context_switch_loop.o
@@ -28,6 +29,7 @@ CFLAGS_brstack.o = -g -O0 -fno-inline -U_FORTIFY_SOURCE
CFLAGS_datasym.o = -g -O0 -fno-inline -U_FORTIFY_SOURCE
CFLAGS_traploop.o = -g -O0 -fno-inline -U_FORTIFY_SOURCE
CFLAGS_branch_not_taken_loop.o = -g -O0 -fno-inline -U_FORTIFY_SOURCE
+CFLAGS_page_fault_loop.o = -g -O0 -fno-inline -U_FORTIFY_SOURCE
CFLAGS_inlineloop.o = -g -O2
CFLAGS_deterministic.o = -g -O0 -fno-inline -U_FORTIFY_SOURCE
CFLAGS_named_threads.o = -g -O0 -fno-inline -U_FORTIFY_SOURCE
diff --git a/tools/perf/tests/workloads/page_fault_loop.c b/tools/perf/tests/workloads/page_fault_loop.c
new file mode 100644
index 0000000000000000000000000000000000000000..4afbc4ab0a55400360facdc3a99ea5a5a9d52596
--- /dev/null
+++ b/tools/perf/tests/workloads/page_fault_loop.c
@@ -0,0 +1,37 @@
+// SPDX-License-Identifier: GPL-2.0
+#include <linux/compiler.h>
+#include <stdio.h>
+#include <sys/mman.h>
+#include <unistd.h>
+#include "../tests.h"
+
+static int page_fault_loop(int argc __maybe_unused, const char **argv __maybe_unused)
+{
+ size_t size = getpagesize();
+ char *page;
+ int ret = 1;
+
+ page = mmap(NULL, size, PROT_READ, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+ if (page == MAP_FAILED) {
+ perror("mmap");
+ return 1;
+ }
+
+ for (int i = 0; i < 256; i++) {
+ /* Drop the PTE so the kernel must resolve a fault on each read. */
+ if (madvise(page, size, MADV_DONTNEED)) {
+ perror("madvise");
+ goto out;
+ }
+ if (READ_ONCE(*page)) {
+ fprintf(stderr, "Anonymous page is not zero-filled\n");
+ goto out;
+ }
+ }
+ ret = 0;
+out:
+ munmap(page, size);
+ return ret;
+}
+
+DEFINE_WORKLOAD(page_fault_loop);
--
2.34.1
More information about the linux-arm-kernel
mailing list