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 -a -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_die() 126{ 127 echo -n "Checking json output: per die " 128 if ParanoidAndNotRoot 0 129 then 130 echo "[Skip] paranoia and not root" 131 return 132 fi 133 perf stat -j --per-die -a -o "${stat_output}" true 134 $PYTHON $pythonchecker --per-die --file "${stat_output}" 135 echo "[Success]" 136} 137 138check_per_node() 139{ 140 echo -n "Checking json output: per node " 141 if ParanoidAndNotRoot 0 142 then 143 echo "[Skip] paranoia and not root" 144 return 145 fi 146 perf stat -j --per-node -a -o "${stat_output}" true 147 $PYTHON $pythonchecker --per-node --file "${stat_output}" 148 echo "[Success]" 149} 150 151check_per_socket() 152{ 153 echo -n "Checking json output: per socket " 154 if ParanoidAndNotRoot 0 155 then 156 echo "[Skip] paranoia and not root" 157 return 158 fi 159 perf stat -j --per-socket -a -o "${stat_output}" true 160 $PYTHON $pythonchecker --per-socket --file "${stat_output}" 161 echo "[Success]" 162} 163 164# The perf stat options for per-socket, per-core, per-die 165# and -A ( no_aggr mode ) uses the info fetched from this 166# directory: "/sys/devices/system/cpu/cpu*/topology". For 167# example, socket value is fetched from "physical_package_id" 168# file in topology directory. 169# Reference: cpu__get_topology_int in util/cpumap.c 170# If the platform doesn't expose topology information, values 171# will be set to -1. For example, incase of pSeries platform 172# of powerpc, value for "physical_package_id" is restricted 173# and set to -1. Check here validates the socket-id read from 174# topology file before proceeding further 175 176FILE_LOC="/sys/devices/system/cpu/cpu*/topology/" 177FILE_NAME="physical_package_id" 178 179check_for_topology() 180{ 181 if ! ParanoidAndNotRoot 0 182 then 183 socket_file=`ls $FILE_LOC/$FILE_NAME | head -n 1` 184 [ -z $socket_file ] && return 0 185 socket_id=`cat $socket_file` 186 [ $socket_id == -1 ] && skip_test=1 187 return 0 188 fi 189} 190 191check_for_topology 192check_no_args 193check_system_wide 194check_interval 195check_event 196check_per_thread 197check_per_node 198if [ $skip_test -ne 1 ] 199then 200 check_system_wide_no_aggr 201 check_per_core 202 check_per_cache_instance 203 check_per_die 204 check_per_socket 205else 206 echo "[Skip] Skipping tests for system_wide_no_aggr, per_core, per_die and per_socket since socket id exposed via topology is invalid" 207fi 208cleanup 209exit 0 210