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