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