summaryrefslogtreecommitdiff
path: root/tools/perf/tests/shell/test_brstack.sh
diff options
context:
space:
mode:
Diffstat (limited to 'tools/perf/tests/shell/test_brstack.sh')
-rwxr-xr-xtools/perf/tests/shell/test_brstack.sh106
1 files changed, 97 insertions, 9 deletions
diff --git a/tools/perf/tests/shell/test_brstack.sh b/tools/perf/tests/shell/test_brstack.sh
index 9138fa83bf36..85233d435be6 100755
--- a/tools/perf/tests/shell/test_brstack.sh
+++ b/tools/perf/tests/shell/test_brstack.sh
@@ -34,6 +34,17 @@ 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"
+ err=1
+ fi
+}
+
test_user_branches() {
echo "Testing user branch stack sampling"
@@ -55,14 +66,67 @@ test_user_branches() {
)
for x in "${expected[@]}"
do
- if ! tr -s ' ' '\n' < "$TMPDIR/perf.script" | grep -E -m1 -q "$x"
- then
- echo "Branches missing $x"
- err=1
- fi
+ check_branches "$x"
done
+
+ # Dump addresses only this time
+ perf script -i "$TMPDIR/perf.data" --fields brstack | \
+ tr ' ' '\n' > "$TMPDIR/perf.script"
+
+ # There should be no kernel addresses with the u option, in either
+ # source or target addresses.
+ if grep -E -m1 "0x[89a-f][0-9a-f]{15}" $TMPDIR/perf.script; then
+ echo "ERROR: Kernel address found in user mode"
+ err=1
+ fi
# some branch types are still not being tested:
- # IND COND_CALL COND_RET SYSCALL 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"
+
+ if ! perf record --branch-filter any,k -o- -- true > /dev/null; then
+ echo "skip: not enough privileges"
+ else
+ perf record -o $TMPDIR/perf.data --branch-filter any,k -- \
+ perf bench syscall basic --loop 1000
+ perf script -i $TMPDIR/perf.data --fields brstack | \
+ tr ' ' '\n' > $TMPDIR/perf.script
+
+ # Example of branch entries:
+ # "0xffffffff93bda241/0xffffffff93bda20f/M/-/-/..."
+ # Source addresses come first and target address can be either
+ # userspace or kernel even with k option, as long as the source
+ # is in kernel.
+
+ #Look for source addresses with top bit set
+ if ! grep -E -m1 "^0x[89a-f][0-9a-f]{15}" $TMPDIR/perf.script; then
+ echo "ERROR: Kernel branches missing"
+ err=1
+ fi
+ # Look for no source addresses without top bit set
+ if grep -E -m1 "^0x[0-7][0-9a-f]{0,15}" $TMPDIR/perf.script; then
+ echo "ERROR: User branches found with kernel filter"
+ err=1
+ fi
+ fi
}
# first argument <arg0> is the argument passed to "--branch-stack <arg0>,save_type,u"
@@ -97,18 +161,42 @@ test_filter() {
fi
}
+test_syscall() {
+ echo "Testing syscalls"
+ # skip if perf doesn't have enough privileges
+ if ! perf record --branch-filter any,k -o- -- true > /dev/null; then
+ echo "skip: not enough privileges"
+ else
+ perf record -o $TMPDIR/perf.data --branch-filter \
+ any_call,save_type,u,k -c 10000 -- \
+ perf bench syscall basic --loop 1000
+ perf script -i $TMPDIR/perf.data --fields brstacksym | \
+ tr ' ' '\n' > $TMPDIR/perf.script
+
+ check_branches "getppid[^ ]*/SYSCALL/"
+ fi
+}
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" "CALL|IND_CALL|COND_CALL|SYSCALL|IRQ"
+test_filter "any_call" "$any_call"
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" "$any_call|COND"
+test_filter "any_call,cond,any_ret" "$any_call|COND|RET|COND_RET"
cleanup
exit $err