On linux-next tree 'perf test 95' ("Check branch stack sampling") was
added recently.
s390 does not support branch sampling at all and the test case fails
despite for checking branch support before hand.
The check for support of branching uses the software event named "dummy",
as seen in the line:
perf record -b -o- -e dummy -B true > /dev/null 2>&1 || exit 2
However when the branch recording is actually done, a different event is
used, as seen in the line:
perf record -o $TMPDIR/... --branch-filter any,save_type,u -- ...
The event is omitted and for "perf record" the default event is cycles,
which is not supported by s390 and this fails when executed on s390:
# perf record --branch-filter any,save_type,u -- /tmp/__perf_test.program.iDSmQ/a.out
Error:
cycles: PMU Hardware or event type doesn't support branch stack sampling.
#
Therefore fix this and use the same event cycles for testing support
and actually running the test.
Output before:
# ./perf test -Fv 95
95: Check branch stack sampling :
--- start ---
Testing user branch stack sampling
---- end ----
Check branch stack sampling: FAILED!
#
Output after:
# ./perf test -Fv 95
95: Check branch stack sampling :
--- start ---
---- end ----
Check branch stack sampling: Skip
#
Fixes: b55878c90a
("perf test: Add test for branch stack sampling")
Reviewed-by: James Clark <james.clark@arm.com>
Signed-off-by: Thomas Richter <tmricht@linux.ibm.com>
Acked-by: German Gomez <german.gomez@arm.com>
Cc: German Gomez <german.gomez@arm.com>
Cc: Heiko Carstens <hca@linux.ibm.com>
Cc: Sumanth Korikkar <sumanthk@linux.ibm.com>
Cc: Sven Schnelle <svens@linux.ibm.com>
Cc: Vasily Gorbik <gor@linux.ibm.com>
Link: https://lore.kernel.org/r/20220727141439.712582-1-tmricht@linux.ibm.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
114 lines
3.2 KiB
Bash
Executable file
114 lines
3.2 KiB
Bash
Executable file
#!/bin/sh
|
|
# Check branch stack sampling
|
|
|
|
# SPDX-License-Identifier: GPL-2.0
|
|
# German Gomez <german.gomez@arm.com>, 2022
|
|
|
|
# we need a C compiler to build the test programs
|
|
# so bail if none is found
|
|
if ! [ -x "$(command -v cc)" ]; then
|
|
echo "failed: no compiler, install gcc"
|
|
exit 2
|
|
fi
|
|
|
|
# skip the test if the hardware doesn't support branch stack sampling
|
|
perf record -b -o- -B true > /dev/null 2>&1 || exit 2
|
|
|
|
TMPDIR=$(mktemp -d /tmp/__perf_test.program.XXXXX)
|
|
|
|
cleanup() {
|
|
rm -rf $TMPDIR
|
|
}
|
|
|
|
trap cleanup exit term int
|
|
|
|
gen_test_program() {
|
|
# generate test program
|
|
cat << EOF > $1
|
|
#define BENCH_RUNS 999999
|
|
int cnt;
|
|
void bar(void) {
|
|
} /* return */
|
|
void foo(void) {
|
|
bar(); /* call */
|
|
} /* return */
|
|
void bench(void) {
|
|
void (*foo_ind)(void) = foo;
|
|
if ((cnt++) % 3) /* branch (cond) */
|
|
foo(); /* call */
|
|
bar(); /* call */
|
|
foo_ind(); /* call (ind) */
|
|
}
|
|
int main(void)
|
|
{
|
|
int cnt = 0;
|
|
while (1) {
|
|
if ((cnt++) > BENCH_RUNS)
|
|
break;
|
|
bench(); /* call */
|
|
} /* branch (uncond) */
|
|
return 0;
|
|
}
|
|
EOF
|
|
}
|
|
|
|
test_user_branches() {
|
|
echo "Testing user branch stack sampling"
|
|
|
|
gen_test_program "$TEMPDIR/program.c"
|
|
cc -fno-inline -g "$TEMPDIR/program.c" -o $TMPDIR/a.out
|
|
|
|
perf record -o $TMPDIR/perf.data --branch-filter any,save_type,u -- $TMPDIR/a.out > /dev/null 2>&1
|
|
perf script -i $TMPDIR/perf.data --fields brstacksym | xargs -n1 > $TMPDIR/perf.script
|
|
|
|
# example of branch entries:
|
|
# foo+0x14/bar+0x40/P/-/-/0/CALL
|
|
|
|
set -x
|
|
egrep -m1 "^bench\+[^ ]*/foo\+[^ ]*/IND_CALL$" $TMPDIR/perf.script
|
|
egrep -m1 "^foo\+[^ ]*/bar\+[^ ]*/CALL$" $TMPDIR/perf.script
|
|
egrep -m1 "^bench\+[^ ]*/foo\+[^ ]*/CALL$" $TMPDIR/perf.script
|
|
egrep -m1 "^bench\+[^ ]*/bar\+[^ ]*/CALL$" $TMPDIR/perf.script
|
|
egrep -m1 "^bar\+[^ ]*/foo\+[^ ]*/RET$" $TMPDIR/perf.script
|
|
egrep -m1 "^foo\+[^ ]*/bench\+[^ ]*/RET$" $TMPDIR/perf.script
|
|
egrep -m1 "^bench\+[^ ]*/bench\+[^ ]*/COND$" $TMPDIR/perf.script
|
|
egrep -m1 "^main\+[^ ]*/main\+[^ ]*/UNCOND$" $TMPDIR/perf.script
|
|
set +x
|
|
|
|
# some branch types are still not being tested:
|
|
# IND COND_CALL COND_RET SYSCALL SYSRET IRQ SERROR NO_TX
|
|
}
|
|
|
|
# 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() {
|
|
local filter=$1
|
|
local expect=$2
|
|
|
|
echo "Testing branch stack filtering permutation ($filter,$expect)"
|
|
|
|
gen_test_program "$TEMPDIR/program.c"
|
|
cc -fno-inline -g "$TEMPDIR/program.c" -o $TMPDIR/a.out
|
|
|
|
perf record -o $TMPDIR/perf.data --branch-filter $filter,save_type,u -- $TMPDIR/a.out > /dev/null 2>&1
|
|
perf script -i $TMPDIR/perf.data --fields brstack | xargs -n1 > $TMPDIR/perf.script
|
|
|
|
# fail if we find any branch type that doesn't match any of the expected ones
|
|
# also consider UNKNOWN branch types (-)
|
|
if egrep -vm1 "^[^ ]*/($expect|-|( *))$" $TMPDIR/perf.script; then
|
|
return 1
|
|
fi
|
|
}
|
|
|
|
set -e
|
|
|
|
test_user_branches
|
|
|
|
test_filter "any_call" "CALL|IND_CALL|COND_CALL|SYSCALL|IRQ"
|
|
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"
|