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