Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

perf test: Extend branch stack sampling test for Arm64 BRBE

BRBE emits IRQ and ERET branches for branching and returning from
trapped instructions. Add a test that loops on a trapped instruction
(MRS - Read special register) for this.

Extend the expected 'any_call' branches to include FAULT_DATA and
FAULT_INST as these are emitted by BRBE.

Reviewed-by: Ian Rogers <irogers@google.com>
Co-developed-by: German Gomez <german.gomez@arm.com>
Signed-off-by: German Gomez <german.gomez@arm.com>
Signed-off-by: James Clark <james.clark@linaro.org>
Cc: Adam Young <admiyo@os.amperecomputing.com>
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Anshuman Khandual <anshuman.khandual@arm.com>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Rob Herring <robh@kernel.org>
Cc: Will Deacon <will@kernel.org>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>

authored by

James Clark and committed by
Arnaldo Carvalho de Melo
9f0fa213 11e59335

+60 -1
+1
tools/perf/tests/builtin-test.c
··· 152 152 &workload__brstack, 153 153 &workload__datasym, 154 154 &workload__landlock, 155 + &workload__traploop, 155 156 }; 156 157 157 158 #define workloads__for_each(workload) \
+25 -1
tools/perf/tests/shell/test_brstack.sh
··· 34 34 } 35 35 trap trap_cleanup EXIT TERM INT 36 36 37 + is_arm64() { 38 + [ "$(uname -m)" = "aarch64" ]; 39 + } 40 + 37 41 check_branches() { 38 42 if ! tr -s ' ' '\n' < "$TMPDIR/perf.script" | grep -E -m1 -q "$1"; then 39 43 echo "Branches missing $1" ··· 80 76 err=1 81 77 fi 82 78 # some branch types are still not being tested: 83 - # IND COND_CALL COND_RET SYSRET IRQ SERROR NO_TX 79 + # IND COND_CALL COND_RET SYSRET SERROR NO_TX 84 80 } 85 81 82 + test_trap_eret_branches() { 83 + echo "Testing trap & eret branches" 84 + if ! is_arm64; then 85 + echo "skip: not arm64" 86 + else 87 + perf record -o $TMPDIR/perf.data --branch-filter any,save_type,u,k -- \ 88 + perf test -w traploop 1000 89 + perf script -i $TMPDIR/perf.data --fields brstacksym | \ 90 + tr ' ' '\n' > $TMPDIR/perf.script 91 + 92 + # BRBINF<n>.TYPE == TRAP are mapped to PERF_BR_IRQ by the BRBE driver 93 + check_branches "^trap_bench\+[^ ]+/[^ ]/IRQ/" 94 + check_branches "^[^ ]+/trap_bench\+[^ ]+/ERET/" 95 + fi 96 + } 86 97 87 98 test_kernel_branches() { 88 99 echo "Testing that k option only includes kernel source addresses" ··· 181 162 test_user_branches 182 163 test_syscall 183 164 test_kernel_branches 165 + test_trap_eret_branches 184 166 185 167 any_call="CALL|IND_CALL|COND_CALL|SYSCALL|IRQ" 168 + 169 + if is_arm64; then 170 + any_call="$any_call|FAULT_DATA|FAULT_INST" 171 + fi 186 172 187 173 test_filter "any_call" "$any_call" 188 174 test_filter "call" "CALL|SYSCALL"
+1
tools/perf/tests/tests.h
··· 239 239 DECLARE_WORKLOAD(brstack); 240 240 DECLARE_WORKLOAD(datasym); 241 241 DECLARE_WORKLOAD(landlock); 242 + DECLARE_WORKLOAD(traploop); 242 243 243 244 extern const char *dso_to_test; 244 245 extern const char *test_objdump_path;
+2
tools/perf/tests/workloads/Build
··· 7 7 perf-test-y += brstack.o 8 8 perf-test-y += datasym.o 9 9 perf-test-y += landlock.o 10 + perf-test-y += traploop.o 10 11 11 12 CFLAGS_sqrtloop.o = -g -O0 -fno-inline -U_FORTIFY_SOURCE 12 13 CFLAGS_leafloop.o = -g -O0 -fno-inline -fno-omit-frame-pointer -U_FORTIFY_SOURCE 13 14 CFLAGS_brstack.o = -g -O0 -fno-inline -U_FORTIFY_SOURCE 14 15 CFLAGS_datasym.o = -g -O0 -fno-inline -U_FORTIFY_SOURCE 16 + CFLAGS_traploop.o = -g -O0 -fno-inline -U_FORTIFY_SOURCE
+31
tools/perf/tests/workloads/traploop.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + #include <stdlib.h> 3 + #include "../tests.h" 4 + 5 + #define BENCH_RUNS 999999 6 + 7 + #ifdef __aarch64__ 8 + static void trap_bench(void) 9 + { 10 + unsigned long val; 11 + 12 + asm("mrs %0, ID_AA64ISAR0_EL1" : "=r" (val)); /* TRAP + ERET */ 13 + } 14 + #else 15 + static void trap_bench(void) { } 16 + #endif 17 + 18 + static int traploop(int argc, const char **argv) 19 + { 20 + int num_loops = BENCH_RUNS; 21 + 22 + if (argc > 0) 23 + num_loops = atoi(argv[0]); 24 + 25 + for (int i = 0; i < num_loops; i++) 26 + trap_bench(); 27 + 28 + return 0; 29 + } 30 + 31 + DEFINE_WORKLOAD(traploop);