diff options
Diffstat (limited to 'tools/perf/tests/shell/test_brstack.sh')
-rwxr-xr-x | tools/perf/tests/shell/test_brstack.sh | 106 |
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 |