1#!/bin/bash 2# Check branch stack sampling 3 4# SPDX-License-Identifier: GPL-2.0 5# German Gomez <german.gomez@arm.com>, 2022 6 7shelldir=$(dirname "$0") 8# shellcheck source=lib/perf_has_symbol.sh 9. "${shelldir}"/lib/perf_has_symbol.sh 10 11# skip the test if the hardware doesn't support branch stack sampling 12# and if the architecture doesn't support filter types: any,save_type,u 13if ! perf record -o- --no-buildid --branch-filter any,save_type,u -- true > /dev/null 2>&1 ; then 14 echo "skip: system doesn't support filter types: any,save_type,u" 15 exit 2 16fi 17 18skip_test_missing_symbol brstack_bench 19 20err=0 21TMPDIR=$(mktemp -d /tmp/__perf_test.program.XXXXX) 22TESTPROG="perf test -w brstack" 23 24cleanup() { 25 rm -rf $TMPDIR 26 trap - EXIT TERM INT 27} 28 29trap_cleanup() { 30 set +e 31 echo "Unexpected signal in ${FUNCNAME[1]}" 32 cleanup 33 exit 1 34} 35trap trap_cleanup EXIT TERM INT 36 37test_user_branches() { 38 echo "Testing user branch stack sampling" 39 40 perf record -o "$TMPDIR/perf.data" --branch-filter any,save_type,u -- ${TESTPROG} > "$TMPDIR/record.txt" 2>&1 41 perf script -i "$TMPDIR/perf.data" --fields brstacksym > "$TMPDIR/perf.script" 42 43 # example of branch entries: 44 # brstack_foo+0x14/brstack_bar+0x40/P/-/-/0/CALL 45 46 expected=( 47 "^brstack_bench\+[^ ]*/brstack_foo\+[^ ]*/IND_CALL/.*$" 48 "^brstack_foo\+[^ ]*/brstack_bar\+[^ ]*/CALL/.*$" 49 "^brstack_bench\+[^ ]*/brstack_foo\+[^ ]*/CALL/.*$" 50 "^brstack_bench\+[^ ]*/brstack_bar\+[^ ]*/CALL/.*$" 51 "^brstack_bar\+[^ ]*/brstack_foo\+[^ ]*/RET/.*$" 52 "^brstack_foo\+[^ ]*/brstack_bench\+[^ ]*/RET/.*$" 53 "^brstack_bench\+[^ ]*/brstack_bench\+[^ ]*/COND/.*$" 54 "^brstack\+[^ ]*/brstack\+[^ ]*/UNCOND/.*$" 55 ) 56 for x in "${expected[@]}" 57 do 58 if ! tr -s ' ' '\n' < "$TMPDIR/perf.script" | grep -E -m1 -q "$x" 59 then 60 echo "Branches missing $x" 61 err=1 62 fi 63 done 64 # some branch types are still not being tested: 65 # IND COND_CALL COND_RET SYSCALL SYSRET IRQ SERROR NO_TX 66} 67 68# first argument <arg0> is the argument passed to "--branch-stack <arg0>,save_type,u" 69# second argument are the expected branch types for the given filter 70test_filter() { 71 test_filter_filter=$1 72 test_filter_expect=$2 73 74 echo "Testing branch stack filtering permutation ($test_filter_filter,$test_filter_expect)" 75 perf record -o "$TMPDIR/perf.data" --branch-filter "$test_filter_filter,save_type,u" -- ${TESTPROG} > "$TMPDIR/record.txt" 2>&1 76 perf script -i "$TMPDIR/perf.data" --fields brstack > "$TMPDIR/perf.script" 77 78 # fail if we find any branch type that doesn't match any of the expected ones 79 # also consider UNKNOWN branch types (-) 80 if [ ! -s "$TMPDIR/perf.script" ] 81 then 82 echo "Empty script output" 83 err=1 84 return 85 fi 86 # Look for lines not matching test_filter_expect ignoring issues caused 87 # by empty output 88 tr -s ' ' '\n' < "$TMPDIR/perf.script" | grep '.' | \ 89 grep -E -vm1 "^[^ ]*/($test_filter_expect|-|( *))/.*$" \ 90 > "$TMPDIR/perf.script-filtered" || true 91 if [ -s "$TMPDIR/perf.script-filtered" ] 92 then 93 echo "Unexpected branch filter in script output" 94 cat "$TMPDIR/perf.script" 95 err=1 96 return 97 fi 98} 99 100set -e 101 102test_user_branches 103 104test_filter "any_call" "CALL|IND_CALL|COND_CALL|SYSCALL|IRQ" 105test_filter "call" "CALL|SYSCALL" 106test_filter "cond" "COND" 107test_filter "any_ret" "RET|COND_RET|SYSRET|ERET" 108 109test_filter "call,cond" "CALL|SYSCALL|COND" 110test_filter "any_call,cond" "CALL|IND_CALL|COND_CALL|IRQ|SYSCALL|COND" 111test_filter "cond,any_call,any_ret" "COND|CALL|IND_CALL|COND_CALL|SYSCALL|IRQ|RET|COND_RET|SYSRET|ERET" 112 113cleanup 114exit $err 115