1#!/bin/bash 2# perf stat CSV output linter 3# SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) 4# Tests various perf stat CSV output commands for the 5# correct number of fields and the CSV separator set to ','. 6 7set -e 8 9skip_test=0 10csv_sep=@ 11 12function commachecker() 13{ 14 local -i cnt=0 15 local exp=0 16 17 case "$1" 18 in "--no-args") exp=6 19 ;; "--system-wide") exp=6 20 ;; "--event") exp=6 21 ;; "--interval") exp=7 22 ;; "--per-thread") exp=7 23 ;; "--system-wide-no-aggr") exp=7 24 [ $(uname -m) = "s390x" ] && exp='^[6-7]$' 25 ;; "--per-core") exp=8 26 ;; "--per-socket") exp=8 27 ;; "--per-node") exp=8 28 ;; "--per-die") exp=8 29 esac 30 31 while read line 32 do 33 # Check for lines beginning with Failed 34 x=${line:0:6} 35 [ "$x" = "Failed" ] && continue 36 37 # Count the number of commas 38 x=$(echo $line | tr -d -c $csv_sep) 39 cnt="${#x}" 40 # echo $line $cnt 41 [[ ! "$cnt" =~ $exp ]] && { 42 echo "wrong number of fields. expected $exp in $line" 1>&2 43 exit 1; 44 } 45 done 46 return 0 47} 48 49# Return true if perf_event_paranoid is > $1 and not running as root. 50function ParanoidAndNotRoot() 51{ 52 [ $(id -u) != 0 ] && [ $(cat /proc/sys/kernel/perf_event_paranoid) -gt $1 ] 53} 54 55check_no_args() 56{ 57 echo -n "Checking CSV output: no args " 58 perf stat -x$csv_sep true 2>&1 | commachecker --no-args 59 echo "[Success]" 60} 61 62check_system_wide() 63{ 64 echo -n "Checking CSV output: system wide " 65 if ParanoidAndNotRoot 0 66 then 67 echo "[Skip] paranoid and not root" 68 return 69 fi 70 perf stat -x$csv_sep -a true 2>&1 | commachecker --system-wide 71 echo "[Success]" 72} 73 74check_system_wide_no_aggr() 75{ 76 echo -n "Checking CSV output: system wide " 77 if ParanoidAndNotRoot 0 78 then 79 echo "[Skip] paranoid and not root" 80 return 81 fi 82 echo -n "Checking CSV output: system wide no aggregation " 83 perf stat -x$csv_sep -A -a --no-merge true 2>&1 | commachecker --system-wide-no-aggr 84 echo "[Success]" 85} 86 87check_interval() 88{ 89 echo -n "Checking CSV output: interval " 90 perf stat -x$csv_sep -I 1000 true 2>&1 | commachecker --interval 91 echo "[Success]" 92} 93 94 95check_event() 96{ 97 echo -n "Checking CSV output: event " 98 perf stat -x$csv_sep -e cpu-clock true 2>&1 | commachecker --event 99 echo "[Success]" 100} 101 102check_per_core() 103{ 104 echo -n "Checking CSV output: per core " 105 if ParanoidAndNotRoot 0 106 then 107 echo "[Skip] paranoid and not root" 108 return 109 fi 110 perf stat -x$csv_sep --per-core -a true 2>&1 | commachecker --per-core 111 echo "[Success]" 112} 113 114check_per_thread() 115{ 116 echo -n "Checking CSV output: per thread " 117 if ParanoidAndNotRoot 0 118 then 119 echo "[Skip] paranoid and not root" 120 return 121 fi 122 perf stat -x$csv_sep --per-thread -a true 2>&1 | commachecker --per-thread 123 echo "[Success]" 124} 125 126check_per_die() 127{ 128 echo -n "Checking CSV output: per die " 129 if ParanoidAndNotRoot 0 130 then 131 echo "[Skip] paranoid and not root" 132 return 133 fi 134 perf stat -x$csv_sep --per-die -a true 2>&1 | commachecker --per-die 135 echo "[Success]" 136} 137 138check_per_node() 139{ 140 echo -n "Checking CSV output: per node " 141 if ParanoidAndNotRoot 0 142 then 143 echo "[Skip] paranoid and not root" 144 return 145 fi 146 perf stat -x$csv_sep --per-node -a true 2>&1 | commachecker --per-node 147 echo "[Success]" 148} 149 150check_per_socket() 151{ 152 echo -n "Checking CSV output: per socket " 153 if ParanoidAndNotRoot 0 154 then 155 echo "[Skip] paranoid and not root" 156 return 157 fi 158 perf stat -x$csv_sep --per-socket -a true 2>&1 | commachecker --per-socket 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 205exit 0 206