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