Commit 9f0fa213 authored by James Clark's avatar James Clark Committed by Arnaldo Carvalho de Melo
Browse files

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: default avatarIan Rogers <irogers@google.com>
Co-developed-by: default avatarGerman Gomez <german.gomez@arm.com>
Signed-off-by: default avatarGerman Gomez <german.gomez@arm.com>
Signed-off-by: default avatarJames 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: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
parent 11e59335
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -152,6 +152,7 @@ static struct test_workload *workloads[] = {
	&workload__brstack,
	&workload__datasym,
	&workload__landlock,
	&workload__traploop,
};

#define workloads__for_each(workload) \
+25 −1
Original line number Diff line number Diff line
@@ -34,6 +34,10 @@ trap_cleanup() {
}
trap trap_cleanup EXIT TERM INT

is_arm64() {
	[ "$(uname -m)" = "aarch64" ];
}

check_branches() {
	if ! tr -s ' ' '\n' < "$TMPDIR/perf.script" | grep -E -m1 -q "$1"; then
		echo "Branches missing $1"
@@ -76,9 +80,24 @@ test_user_branches() {
		err=1
	fi
	# some branch types are still not being tested:
	# IND COND_CALL COND_RET SYSRET IRQ SERROR NO_TX
	# IND COND_CALL COND_RET SYSRET SERROR NO_TX
}

test_trap_eret_branches() {
	echo "Testing trap & eret branches"
	if ! is_arm64; then
		echo "skip: not arm64"
	else
		perf record -o $TMPDIR/perf.data --branch-filter any,save_type,u,k -- \
			perf test -w traploop 1000
		perf script -i $TMPDIR/perf.data --fields brstacksym | \
			tr ' ' '\n' > $TMPDIR/perf.script

		# BRBINF<n>.TYPE == TRAP are mapped to PERF_BR_IRQ by the BRBE driver
		check_branches "^trap_bench\+[^ ]+/[^ ]/IRQ/"
		check_branches "^[^ ]+/trap_bench\+[^ ]+/ERET/"
	fi
}

test_kernel_branches() {
	echo "Testing that k option only includes kernel source addresses"
@@ -162,9 +181,14 @@ set -e
test_user_branches
test_syscall
test_kernel_branches
test_trap_eret_branches

any_call="CALL|IND_CALL|COND_CALL|SYSCALL|IRQ"

if is_arm64; then
	any_call="$any_call|FAULT_DATA|FAULT_INST"
fi

test_filter "any_call" "$any_call"
test_filter "call"	"CALL|SYSCALL"
test_filter "cond"	"COND"
+1 −0
Original line number Diff line number Diff line
@@ -239,6 +239,7 @@ DECLARE_WORKLOAD(sqrtloop);
DECLARE_WORKLOAD(brstack);
DECLARE_WORKLOAD(datasym);
DECLARE_WORKLOAD(landlock);
DECLARE_WORKLOAD(traploop);

extern const char *dso_to_test;
extern const char *test_objdump_path;
+2 −0
Original line number Diff line number Diff line
@@ -7,8 +7,10 @@ perf-test-y += sqrtloop.o
perf-test-y += brstack.o
perf-test-y += datasym.o
perf-test-y += landlock.o
perf-test-y += traploop.o

CFLAGS_sqrtloop.o         = -g -O0 -fno-inline -U_FORTIFY_SOURCE
CFLAGS_leafloop.o         = -g -O0 -fno-inline -fno-omit-frame-pointer -U_FORTIFY_SOURCE
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
+31 −0
Original line number Diff line number Diff line
// SPDX-License-Identifier: GPL-2.0
#include <stdlib.h>
#include "../tests.h"

#define BENCH_RUNS 999999

#ifdef __aarch64__
static void trap_bench(void)
{
	unsigned long val;

	asm("mrs %0, ID_AA64ISAR0_EL1" : "=r" (val));   /* TRAP + ERET */
}
#else
static void trap_bench(void) { }
#endif

static int traploop(int argc, const char **argv)
{
	int num_loops = BENCH_RUNS;

	if (argc > 0)
		num_loops = atoi(argv[0]);

	for (int i = 0; i < num_loops; i++)
		trap_bench();

	return 0;
}

DEFINE_WORKLOAD(traploop);