1#!/bin/bash 2# perf stat tests 3# SPDX-License-Identifier: GPL-2.0 4 5set -e 6 7err=0 8test_default_stat() { 9 echo "Basic stat command test" 10 if ! perf stat true 2>&1 | grep -E -q "Performance counter stats for 'true':" 11 then 12 echo "Basic stat command test [Failed]" 13 err=1 14 return 15 fi 16 echo "Basic stat command test [Success]" 17} 18 19test_null_stat() { 20 echo "Null stat command test" 21 if ! perf stat --null true 2>&1 | grep -E -q "Performance counter stats for 'true':" 22 then 23 echo "Null stat command test [Failed]" 24 err=1 25 return 26 fi 27 echo "Null stat command test [Success]" 28} 29 30find_offline_cpu() { 31 for i in $(seq 1 4096) 32 do 33 if [[ ! -f /sys/devices/system/cpu/cpu$i/online || \ 34 $(cat /sys/devices/system/cpu/cpu$i/online) == "0" ]] 35 then 36 echo $i 37 return 38 fi 39 done 40 echo "Failed to find offline CPU" 41 exit 1 42} 43 44test_offline_cpu_stat() { 45 cpu=$(find_offline_cpu) 46 echo "Offline CPU stat command test (cpu $cpu)" 47 if ! perf stat "-C$cpu" -e cycles true 2>&1 | grep -E -q "No supported events found." 48 then 49 echo "Offline CPU stat command test [Failed]" 50 err=1 51 return 52 fi 53 echo "Offline CPU stat command test [Success]" 54} 55 56test_stat_record_report() { 57 echo "stat record and report test" 58 if ! perf stat record -e task-clock -o - true | perf stat report -i - 2>&1 | \ 59 grep -E -q "Performance counter stats for 'pipe':" 60 then 61 echo "stat record and report test [Failed]" 62 err=1 63 return 64 fi 65 echo "stat record and report test [Success]" 66} 67 68test_stat_record_script() { 69 echo "stat record and script test" 70 if ! perf stat record -e task-clock -o - true | perf script -i - 2>&1 | \ 71 grep -E -q "CPU[[:space:]]+THREAD[[:space:]]+VAL[[:space:]]+ENA[[:space:]]+RUN[[:space:]]+TIME[[:space:]]+EVENT" 72 then 73 echo "stat record and script test [Failed]" 74 err=1 75 return 76 fi 77 echo "stat record and script test [Success]" 78} 79 80test_stat_repeat_weak_groups() { 81 echo "stat repeat weak groups test" 82 if ! perf stat -e '{cycles,cycles,cycles,cycles,cycles,cycles,cycles,cycles,cycles,cycles}' \ 83 true 2>&1 | grep -q 'seconds time elapsed' 84 then 85 echo "stat repeat weak groups test [Skipped event parsing failed]" 86 return 87 fi 88 if ! perf stat -r2 -e '{cycles,cycles,cycles,cycles,cycles,cycles,cycles,cycles,cycles,cycles}:W' \ 89 true > /dev/null 2>&1 90 then 91 echo "stat repeat weak groups test [Failed]" 92 err=1 93 return 94 fi 95 echo "stat repeat weak groups test [Success]" 96} 97 98test_topdown_groups() { 99 # Topdown events must be grouped with the slots event first. Test that 100 # parse-events reorders this. 101 echo "Topdown event group test" 102 if ! perf stat -e '{slots,topdown-retiring}' true > /dev/null 2>&1 103 then 104 echo "Topdown event group test [Skipped event parsing failed]" 105 return 106 fi 107 td_err=0 108 do_topdown_group_test() { 109 events=$1 110 failure=$2 111 if perf stat -e "$events" true 2>&1 | grep -E -q "<not supported>" 112 then 113 echo "Topdown event group test [Failed $failure for '$events']" 114 td_err=1 115 return 116 fi 117 } 118 do_topdown_group_test "{slots,topdown-retiring}" "events not supported" 119 do_topdown_group_test "{instructions,r400,r8000}" "raw format slots not reordered first" 120 filler_events=("instructions" "cycles" 121 "context-switches" "faults") 122 for ((i = 0; i < ${#filler_events[@]}; i+=2)) 123 do 124 filler1=${filler_events[i]} 125 filler2=${filler_events[i+1]} 126 do_topdown_group_test "$filler1,topdown-retiring,slots" \ 127 "slots not reordered first in no-group case" 128 do_topdown_group_test "slots,$filler1,topdown-retiring" \ 129 "topdown metrics event not reordered in no-group case" 130 do_topdown_group_test "{$filler1,topdown-retiring,slots}" \ 131 "slots not reordered first in single group case" 132 do_topdown_group_test "{$filler1,slots},topdown-retiring" \ 133 "topdown metrics event not move into slots group" 134 do_topdown_group_test "topdown-retiring,{$filler1,slots}" \ 135 "topdown metrics event not move into slots group last" 136 do_topdown_group_test "{$filler1,slots},{topdown-retiring}" \ 137 "topdown metrics group not merge into slots group" 138 do_topdown_group_test "{topdown-retiring},{$filler1,slots}" \ 139 "topdown metrics group not merge into slots group last" 140 do_topdown_group_test "{$filler1,slots},$filler2,topdown-retiring" \ 141 "non-adjacent topdown metrics group not move into slots group" 142 do_topdown_group_test "$filler2,topdown-retiring,{$filler1,slots}" \ 143 "non-adjacent topdown metrics group not move into slots group last" 144 do_topdown_group_test "{$filler1,slots},{$filler2,topdown-retiring}" \ 145 "metrics group not merge into slots group" 146 do_topdown_group_test "{$filler1,topdown-retiring},{$filler2,slots}" \ 147 "metrics group not merge into slots group last" 148 done 149 if test "$td_err" -eq 0 150 then 151 echo "Topdown event group test [Success]" 152 else 153 err="$td_err" 154 fi 155} 156 157test_topdown_weak_groups() { 158 # Weak groups break if the perf_event_open of multiple grouped events 159 # fails. Breaking a topdown group causes the events to fail. Test a very large 160 # grouping to see that the topdown events aren't broken out. 161 echo "Topdown weak groups test" 162 ok_grouping="{slots,topdown-bad-spec,topdown-be-bound,topdown-fe-bound,topdown-retiring},branch-instructions,branch-misses,bus-cycles,cache-misses,cache-references,cpu-cycles,instructions,mem-loads,mem-stores,ref-cycles,cache-misses,cache-references" 163 if ! perf stat --no-merge -e "$ok_grouping" true > /dev/null 2>&1 164 then 165 echo "Topdown weak groups test [Skipped event parsing failed]" 166 return 167 fi 168 group_needs_break="{slots,topdown-bad-spec,topdown-be-bound,topdown-fe-bound,topdown-retiring,branch-instructions,branch-misses,bus-cycles,cache-misses,cache-references,cpu-cycles,instructions,mem-loads,mem-stores,ref-cycles,cache-misses,cache-references}:W" 169 if perf stat --no-merge -e "$group_needs_break" true 2>&1 | grep -E -q "<not supported>" 170 then 171 echo "Topdown weak groups test [Failed events not supported]" 172 err=1 173 return 174 fi 175 echo "Topdown weak groups test [Success]" 176} 177 178test_cputype() { 179 # Test --cputype argument. 180 echo "cputype test" 181 182 # Bogus PMU should fail. 183 if perf stat --cputype="123" -e instructions true > /dev/null 2>&1 184 then 185 echo "cputype test [Bogus PMU didn't fail]" 186 err=1 187 return 188 fi 189 190 # Find a known PMU for cputype. 191 pmu="" 192 devs="/sys/bus/event_source/devices" 193 for i in $devs/cpu $devs/cpu_atom $devs/armv8_pmuv3_0 $devs/armv8_cortex_* 194 do 195 i_base=$(basename "$i") 196 if test -d "$i" 197 then 198 pmu="$i_base" 199 break 200 fi 201 if perf stat -e "$i_base/instructions/" true > /dev/null 2>&1 202 then 203 pmu="$i_base" 204 break 205 fi 206 done 207 if test "x$pmu" = "x" 208 then 209 echo "cputype test [Skipped known PMU not found]" 210 return 211 fi 212 213 # Test running with cputype produces output. 214 if ! perf stat --cputype="$pmu" -e instructions true 2>&1 | grep -E -q "instructions" 215 then 216 echo "cputype test [Failed count missed with given filter]" 217 err=1 218 return 219 fi 220 echo "cputype test [Success]" 221} 222 223test_hybrid() { 224 # Test the default stat command on hybrid devices opens one cycles event for 225 # each CPU type. 226 echo "hybrid test" 227 228 # Count the number of core PMUs, assume minimum of 1 229 pmus=$(ls /sys/bus/event_source/devices/*/cpus 2>/dev/null | wc -l) 230 if [ "$pmus" -lt 1 ] 231 then 232 pmus=1 233 fi 234 235 # Run default Perf stat 236 cycles_events=$(perf stat -a -- sleep 0.1 2>&1 | grep -E "/cpu-cycles/[uH]*| cpu-cycles[:uH]* " -c) 237 238 # The expectation is that default output will have a cycles events on each 239 # hybrid PMU. In situations with no cycles PMU events, like virtualized, this 240 # can fall back to task-clock and so the end count may be 0. Fail if neither 241 # condition holds. 242 if [ "$pmus" -ne "$cycles_events" ] && [ "0" -ne "$cycles_events" ] 243 then 244 echo "hybrid test [Found $pmus PMUs but $cycles_events cycles events. Failed]" 245 err=1 246 return 247 fi 248 echo "hybrid test [Success]" 249} 250 251test_default_stat 252test_null_stat 253test_offline_cpu_stat 254test_stat_record_report 255test_stat_record_script 256test_stat_repeat_weak_groups 257test_topdown_groups 258test_topdown_weak_groups 259test_cputype 260test_hybrid 261exit $err 262