Commit faba2f17 authored by James Clark's avatar James Clark Committed by Junhao He
Browse files

perf: test: Extend branch stack sampling test for Arm64 BRBE

maillist inclusion
category: feature
bugzilla: https://gitee.com/openeuler/kernel/issues/I8EC9K
CVE: NA

Reference: https://lore.kernel.org/linux-arm-kernel/20240613061731.3109448-1-anshuman.khandual@arm.com/



--------------------------------

Add Arm64 BRBE-specific testing to the existing branch stack sampling test.
The test currently passes on the Arm FVP RevC model, but no hardware has
been tested yet.

Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Arnaldo Carvalho de Melo <acme@kernel.org>
Cc: linux-perf-users@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
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@arm.com>
Signed-off-by: default avatarAnshuman Khandual <anshuman.khandual@arm.com>
Signed-off-by: default avatarJunhao He <hejunhao3@huawei.com>
parent e9c94f8a
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -139,6 +139,7 @@ static struct test_workload *workloads[] = {
	&workload__sqrtloop,
	&workload__brstack,
	&workload__datasym,
	&workload__traploop
};

static int num_subtests(const struct test_suite *t)
+39 −3
Original line number Diff line number Diff line
@@ -47,12 +47,43 @@ test_user_branches() {
	grep -E -m1 "^brstack_foo\+[^ ]*/brstack_bench\+[^ ]*/RET/.*$"	$TMPDIR/perf.script
	grep -E -m1 "^brstack_bench\+[^ ]*/brstack_bench\+[^ ]*/COND/.*$"	$TMPDIR/perf.script
	grep -E -m1 "^brstack\+[^ ]*/brstack\+[^ ]*/UNCOND/.*$"		$TMPDIR/perf.script

	if is_arm64; then
		# in arm64 with BRBE, we get IRQ entries that correspond
		# to any point in the process
		grep -m1 "/IRQ/"					$TMPDIR/perf.script
	fi
	set +x

	# some branch types are still not being tested:
	# IND COND_CALL COND_RET SYSCALL SYSRET IRQ SERROR NO_TX
}

test_arm64_trap_eret_branches() {
	echo "Testing trap & eret branches (arm64 brbe)"
	perf record -o $TMPDIR/perf.data --branch-filter any,save_type,u -- \
		perf test -w traploop 250
	perf script -i $TMPDIR/perf.data --fields brstacksym | tr ' ' '\n' > $TMPDIR/perf.script
	set -x
	# BRBINF<n>.TYPE == TRAP are mapped to PERF_BR_SYSCALL by the BRBE driver
	grep -E -m1 "^trap_bench\+[^ ]*/\[unknown\][^ ]*/SYSCALL/" $TMPDIR/perf.script
	grep -E -m1 "^\[unknown\][^ ]*/trap_bench\+[^ ]*/ERET/"	$TMPDIR/perf.script
	set +x
}

test_arm64_kernel_branches() {
	echo "Testing kernel branches (arm64 brbe)"
	# skip if perf doesn't have enough privileges
	if ! perf record --branch-filter any,k -o- -- true > /dev/null; then
		echo "[skipped: not enough privileges]"
		return 0
	fi
	perf record -o $TMPDIR/perf.data --branch-filter any,k -- uname -a
	perf script -i $TMPDIR/perf.data --fields brstack | tr ' ' '\n' > $TMPDIR/perf.script
	grep -E -m1 "0xffff[0-9a-f]{12}" $TMPDIR/perf.script
	! egrep -E -m1 "0x0000[0-9a-f]{12}" $TMPDIR/perf.script
}

# first argument <arg0> is the argument passed to "--branch-stack <arg0>,save_type,u"
# second argument are the expected branch types for the given filter
test_filter() {
@@ -75,11 +106,16 @@ set -e

test_user_branches

test_filter "any_call"	"CALL|IND_CALL|COND_CALL|SYSCALL|IRQ"
if is_arm64; then
	test_arm64_trap_eret_branches
	test_arm64_kernel_branches
fi

test_filter "any_call"	"CALL|IND_CALL|COND_CALL|SYSCALL|IRQ|FAULT_DATA|FAULT_INST"
test_filter "call"	"CALL|SYSCALL"
test_filter "cond"	"COND"
test_filter "any_ret"	"RET|COND_RET|SYSRET|ERET"

test_filter "call,cond"		"CALL|SYSCALL|COND"
test_filter "any_call,cond"		"CALL|IND_CALL|COND_CALL|IRQ|SYSCALL|COND"
test_filter "cond,any_call,any_ret"	"COND|CALL|IND_CALL|COND_CALL|SYSCALL|IRQ|RET|COND_RET|SYSRET|ERET"
test_filter "any_call,cond"		"CALL|IND_CALL|COND_CALL|IRQ|SYSCALL|COND|FAULT_DATA|FAULT_INST"
test_filter "cond,any_call,any_ret"	"COND|CALL|IND_CALL|COND_CALL|SYSCALL|IRQ|RET|COND_RET|SYSRET|ERET|FAULT_DATA|FAULT_INST"
+1 −0
Original line number Diff line number Diff line
@@ -205,6 +205,7 @@ DECLARE_WORKLOAD(leafloop);
DECLARE_WORKLOAD(sqrtloop);
DECLARE_WORKLOAD(brstack);
DECLARE_WORKLOAD(datasym);
DECLARE_WORKLOAD(traploop);

extern const char *dso_to_test;

+2 −0
Original line number Diff line number Diff line
@@ -6,8 +6,10 @@ perf-y += leafloop.o
perf-y += sqrtloop.o
perf-y += brstack.o
perf-y += datasym.o
perf-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
+39 −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

static volatile int cnt;

#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]);

	while (1) {
		if ((cnt++) > num_loops)
			break;

		trap_bench();
	}
	return 0;
}

DEFINE_WORKLOAD(traploop);