1#!/bin/bash 2# SPDX-License-Identifier: GPL-2.0 3# perf record LBR tests 4 5set -e 6 7shelldir=$(dirname "$0") 8. "${shelldir}"/lib/perf_record.sh 9 10ParanoidAndNotRoot() { 11 [ "$(id -u)" != 0 ] && [ "$(cat /proc/sys/kernel/perf_event_paranoid)" -gt $1 ] 12} 13 14if [ ! -f /sys/bus/event_source/devices/cpu/caps/branches ] && 15 [ ! -f /sys/bus/event_source/devices/cpu_core/caps/branches ] 16then 17 echo "Skip: only x86 CPUs support LBR" 18 exit 2 19fi 20 21err=0 22perfdata=$(mktemp /tmp/__perf_test.perf.data.XXXXX) 23 24cleanup() { 25 rm -rf "${perfdata}" 26 rm -rf "${perfdata}".old 27 rm -rf "${perfdata}".txt 28 perf_record_cleanup 29 30 trap - EXIT TERM INT 31} 32 33trap_cleanup() { 34 echo "Unexpected signal in ${FUNCNAME[1]}" 35 cleanup 36 exit 1 37} 38trap trap_cleanup EXIT TERM INT 39 40 41check_lbr_callgraph() { 42 perf report --stitch-lbr -i "${perfdata}" > "${perfdata}".txt 2>&1 43} 44 45lbr_callgraph_test() { 46 test="LBR callgraph" 47 48 echo "$test" 49 set +e 50 perf_record_with_retry "${perfdata}" "check_lbr_callgraph" "perf test -w thloop" \ 51 -e cycles --call-graph lbr 52 local ret=$? 53 set -e 54 55 if [ $ret -eq 2 ]; then 56 echo "$test [Failed support missing]" 57 if [ $err -eq 0 ] 58 then 59 err=2 60 fi 61 return 62 elif [ $ret -eq 1 ]; then 63 cat "${perfdata}".txt 64 echo "$test [Failed in perf report]" 65 err=1 66 return 67 fi 68 69 echo "$test [Success]" 70} 71 72check_lbr_samples() { 73 local out 74 out=$(perf report -D -i "${perfdata}" 2> /dev/null | grep -A1 'PERF_RECORD_SAMPLE') 75 [ "$(echo "$out" | grep -c 'PERF_RECORD_SAMPLE' || true)" -gt 0 ] 76} 77 78lbr_test() { 79 local branch_flags=$1 80 local test="LBR $2 test" 81 local threshold=$3 82 local out 83 local sam_nr 84 local bs_nr 85 local zero_nr 86 local r 87 88 echo "$test" 89 set +e 90 perf_record_with_retry "${perfdata}" "check_lbr_samples" "perf test -w thloop" \ 91 -e cycles $branch_flags 92 local ret=$? 93 set -e 94 95 if [ $ret -eq 2 ]; then 96 echo "$test [Failed support missing]" 97 if [ $err -eq 0 ] 98 then 99 err=2 100 fi 101 return 102 elif [ $ret -eq 1 ]; then 103 echo "$test [Failed no samples captured]" 104 err=1 105 return 106 fi 107 108 out=$(perf report -D -i "${perfdata}" 2> /dev/null | grep -A1 'PERF_RECORD_SAMPLE') 109 sam_nr=$(echo "$out" | grep -c 'PERF_RECORD_SAMPLE' || true) 110 echo "$test: $sam_nr samples" 111 112 bs_nr=$(echo "$out" | grep -c 'branch stack: nr:' || true) 113 if [ $sam_nr -ne $bs_nr ] 114 then 115 echo "$test [Failed samples missing branch stacks]" 116 err=1 117 return 118 fi 119 120 zero_nr=$(echo "$out" | grep -A3 'branch stack: nr:0' | grep thread | grep -cv swapper || true) 121 r=$(($zero_nr * 100 / $bs_nr)) 122 if [ $r -gt $threshold ]; then 123 echo "$test [Failed empty br stack ratio exceed $threshold%: $r%]" 124 err=1 125 return 126 fi 127 128 echo "$test [Success]" 129} 130 131parallel_lbr_test() { 132 err=0 133 perfdata=$(mktemp /tmp/__perf_test.perf.data.XXXXX) 134 lbr_test "$1" "$2" "$3" 135 cleanup 136 exit $err 137} 138 139lbr_callgraph_test 140 141# Sequential 142lbr_test "-b" "any branch" 2 143lbr_test "-j any_call" "any call" 2 144lbr_test "-j any_ret" "any ret" 2 145lbr_test "-j ind_call" "any indirect call" 2 146lbr_test "-j ind_jmp" "any indirect jump" 100 147lbr_test "-j call" "direct calls" 2 148lbr_test "-j ind_call,u" "any indirect user call" 100 149if ! ParanoidAndNotRoot 1 150then 151 lbr_test "-a -b" "system wide any branch" 2 152 lbr_test "-a -j any_call" "system wide any call" 2 153fi 154 155# Parallel 156parallel_lbr_test "-b" "parallel any branch" 100 & 157pid1=$! 158parallel_lbr_test "-j any_call" "parallel any call" 100 & 159pid2=$! 160parallel_lbr_test "-j any_ret" "parallel any ret" 100 & 161pid3=$! 162parallel_lbr_test "-j ind_call" "parallel any indirect call" 100 & 163pid4=$! 164parallel_lbr_test "-j ind_jmp" "parallel any indirect jump" 100 & 165pid5=$! 166parallel_lbr_test "-j call" "parallel direct calls" 100 & 167pid6=$! 168parallel_lbr_test "-j ind_call,u" "parallel any indirect user call" 100 & 169pid7=$! 170if ParanoidAndNotRoot 1 171then 172 pid8= 173 pid9= 174else 175 parallel_lbr_test "-a -b" "parallel system wide any branch" 100 & 176 pid8=$! 177 parallel_lbr_test "-a -j any_call" "parallel system wide any call" 100 & 178 pid9=$! 179fi 180 181for pid in $pid1 $pid2 $pid3 $pid4 $pid5 $pid6 $pid7 $pid8 $pid9 182do 183 set +e 184 wait $pid 185 child_err=$? 186 set -e 187 if ([ $err -eq 2 ] && [ $child_err -eq 1 ]) || [ $err -eq 0 ] 188 then 189 err=$child_err 190 fi 191done 192 193cleanup 194exit $err 195