1#!/bin/bash 2# perf stat JSON output linter 3# SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) 4# Checks various perf stat JSON output commands for the 5# correct number of fields. 6 7set -e 8 9skip_test=0 10 11shelldir=$(dirname "$0") 12# shellcheck source=lib/setup_python.sh 13. "${shelldir}"/lib/setup_python.sh 14pythonchecker=$(dirname $0)/lib/perf_json_output_lint.py 15 16stat_output=$(mktemp /tmp/__perf_test.stat_output.json.XXXXX) 17 18cleanup() { 19 rm -f "${stat_output}" 20 21 trap - EXIT TERM INT 22} 23 24trap_cleanup() { 25 cleanup 26 exit 1 27} 28trap trap_cleanup EXIT TERM INT 29 30# Return true if perf_event_paranoid is > $1 and not running as root. 31function ParanoidAndNotRoot() 32{ 33 [ "$(id -u)" != 0 ] && [ "$(cat /proc/sys/kernel/perf_event_paranoid)" -gt $1 ] 34} 35 36check_no_args() 37{ 38 echo -n "Checking json output: no args " 39 perf stat -j -o "${stat_output}" true 40 $PYTHON $pythonchecker --no-args --file "${stat_output}" 41 echo "[Success]" 42} 43 44check_system_wide() 45{ 46 echo -n "Checking json output: system wide " 47 if ParanoidAndNotRoot 0 48 then 49 echo "[Skip] paranoia and not root" 50 return 51 fi 52 perf stat -j -a -o "${stat_output}" true 53 $PYTHON $pythonchecker --system-wide --file "${stat_output}" 54 echo "[Success]" 55} 56 57check_system_wide_no_aggr() 58{ 59 echo -n "Checking json output: system wide no aggregation " 60 if ParanoidAndNotRoot 0 61 then 62 echo "[Skip] paranoia and not root" 63 return 64 fi 65 perf stat -j -A -a --no-merge -o "${stat_output}" true 66 $PYTHON $pythonchecker --system-wide-no-aggr --file "${stat_output}" 67 echo "[Success]" 68} 69 70check_interval() 71{ 72 echo -n "Checking json output: interval " 73 perf stat -j -I 1000 -o "${stat_output}" true 74 $PYTHON $pythonchecker --interval --file "${stat_output}" 75 echo "[Success]" 76} 77 78 79check_event() 80{ 81 echo -n "Checking json output: event " 82 perf stat -j -e cpu-clock -o "${stat_output}" true 83 $PYTHON $pythonchecker --event --file "${stat_output}" 84 echo "[Success]" 85} 86 87check_per_core() 88{ 89 echo -n "Checking json output: per core " 90 if ParanoidAndNotRoot 0 91 then 92 echo "[Skip] paranoia and not root" 93 return 94 fi 95 perf stat -j --per-core -a -o "${stat_output}" true 96 $PYTHON $pythonchecker --per-core --file "${stat_output}" 97 echo "[Success]" 98} 99 100check_per_thread() 101{ 102 echo -n "Checking json output: per thread " 103 if ParanoidAndNotRoot 0 104 then 105 echo "[Skip] paranoia and not root" 106 return 107 fi 108 perf stat -j --per-thread -p $$ -o "${stat_output}" true 109 $PYTHON $pythonchecker --per-thread --file "${stat_output}" 110 echo "[Success]" 111} 112 113check_per_cache_instance() 114{ 115 echo -n "Checking json output: per cache_instance " 116 if ParanoidAndNotRoot 0 117 then 118 echo "[Skip] paranoia and not root" 119 return 120 fi 121 perf stat -j --per-cache -a true 2>&1 | $PYTHON $pythonchecker --per-cache 122 echo "[Success]" 123} 124 125check_per_cluster() 126{ 127 echo -n "Checking json output: per cluster " 128 if ParanoidAndNotRoot 0 129 then 130 echo "[Skip] paranoia and not root" 131 return 132 fi 133 perf stat -j --per-cluster -a true 2>&1 | $PYTHON $pythonchecker --per-cluster 134 echo "[Success]" 135} 136 137check_per_die() 138{ 139 echo -n "Checking json output: per die " 140 if ParanoidAndNotRoot 0 141 then 142 echo "[Skip] paranoia and not root" 143 return 144 fi 145 perf stat -j --per-die -a -o "${stat_output}" true 146 $PYTHON $pythonchecker --per-die --file "${stat_output}" 147 echo "[Success]" 148} 149 150check_per_node() 151{ 152 echo -n "Checking json output: per node " 153 if ParanoidAndNotRoot 0 154 then 155 echo "[Skip] paranoia and not root" 156 return 157 fi 158 perf stat -j --per-node -a -o "${stat_output}" true 159 $PYTHON $pythonchecker --per-node --file "${stat_output}" 160 echo "[Success]" 161} 162 163check_per_socket() 164{ 165 echo -n "Checking json output: per socket " 166 if ParanoidAndNotRoot 0 167 then 168 echo "[Skip] paranoia and not root" 169 return 170 fi 171 perf stat -j --per-socket -a -o "${stat_output}" true 172 $PYTHON $pythonchecker --per-socket --file "${stat_output}" 173 echo "[Success]" 174} 175 176# The perf stat options for per-socket, per-core, per-die 177# and -A ( no_aggr mode ) uses the info fetched from this 178# directory: "/sys/devices/system/cpu/cpu*/topology". For 179# example, socket value is fetched from "physical_package_id" 180# file in topology directory. 181# Reference: cpu__get_topology_int in util/cpumap.c 182# If the platform doesn't expose topology information, values 183# will be set to -1. For example, incase of pSeries platform 184# of powerpc, value for "physical_package_id" is restricted 185# and set to -1. Check here validates the socket-id read from 186# topology file before proceeding further 187 188FILE_LOC="/sys/devices/system/cpu/cpu*/topology/" 189FILE_NAME="physical_package_id" 190 191check_for_topology() 192{ 193 if ! ParanoidAndNotRoot 0 194 then 195 socket_file=`ls $FILE_LOC/$FILE_NAME | head -n 1` 196 [ -z $socket_file ] && return 0 197 socket_id=`cat $socket_file` 198 [ $socket_id == -1 ] && skip_test=1 199 return 0 200 fi 201} 202 203check_for_topology 204check_no_args 205check_system_wide 206check_interval 207check_event 208check_per_thread 209check_per_node 210if [ $skip_test -ne 1 ] 211then 212 check_system_wide_no_aggr 213 check_per_core 214 check_per_cache_instance 215 check_per_cluster 216 check_per_die 217 check_per_socket 218else 219 echo "[Skip] Skipping tests for system_wide_no_aggr, per_core, per_die and per_socket since socket id exposed via topology is invalid" 220fi 221cleanup 222exit 0 223