162306a36Sopenharmony_ci#!/bin/bash
262306a36Sopenharmony_ci# perf stat JSON output linter
362306a36Sopenharmony_ci# SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause)
462306a36Sopenharmony_ci# Checks various perf stat JSON output commands for the
562306a36Sopenharmony_ci# correct number of fields.
662306a36Sopenharmony_ci
762306a36Sopenharmony_ciset -e
862306a36Sopenharmony_ci
962306a36Sopenharmony_ciskip_test=0
1062306a36Sopenharmony_ci
1162306a36Sopenharmony_cipythonchecker=$(dirname $0)/lib/perf_json_output_lint.py
1262306a36Sopenharmony_ciif [ "x$PYTHON" == "x" ]
1362306a36Sopenharmony_cithen
1462306a36Sopenharmony_ci	if which python3 > /dev/null
1562306a36Sopenharmony_ci	then
1662306a36Sopenharmony_ci		PYTHON=python3
1762306a36Sopenharmony_ci	elif which python > /dev/null
1862306a36Sopenharmony_ci	then
1962306a36Sopenharmony_ci		PYTHON=python
2062306a36Sopenharmony_ci	else
2162306a36Sopenharmony_ci		echo Skipping test, python not detected please set environment variable PYTHON.
2262306a36Sopenharmony_ci		exit 2
2362306a36Sopenharmony_ci	fi
2462306a36Sopenharmony_cifi
2562306a36Sopenharmony_ci
2662306a36Sopenharmony_cistat_output=$(mktemp /tmp/__perf_test.stat_output.json.XXXXX)
2762306a36Sopenharmony_ci
2862306a36Sopenharmony_cicleanup() {
2962306a36Sopenharmony_ci  rm -f "${stat_output}"
3062306a36Sopenharmony_ci
3162306a36Sopenharmony_ci  trap - EXIT TERM INT
3262306a36Sopenharmony_ci}
3362306a36Sopenharmony_ci
3462306a36Sopenharmony_citrap_cleanup() {
3562306a36Sopenharmony_ci  cleanup
3662306a36Sopenharmony_ci  exit 1
3762306a36Sopenharmony_ci}
3862306a36Sopenharmony_citrap trap_cleanup EXIT TERM INT
3962306a36Sopenharmony_ci
4062306a36Sopenharmony_ci# Return true if perf_event_paranoid is > $1 and not running as root.
4162306a36Sopenharmony_cifunction ParanoidAndNotRoot()
4262306a36Sopenharmony_ci{
4362306a36Sopenharmony_ci	 [ "$(id -u)" != 0 ] && [ "$(cat /proc/sys/kernel/perf_event_paranoid)" -gt $1 ]
4462306a36Sopenharmony_ci}
4562306a36Sopenharmony_ci
4662306a36Sopenharmony_cicheck_no_args()
4762306a36Sopenharmony_ci{
4862306a36Sopenharmony_ci	echo -n "Checking json output: no args "
4962306a36Sopenharmony_ci	perf stat -j -o "${stat_output}" true
5062306a36Sopenharmony_ci	$PYTHON $pythonchecker --no-args --file "${stat_output}"
5162306a36Sopenharmony_ci	echo "[Success]"
5262306a36Sopenharmony_ci}
5362306a36Sopenharmony_ci
5462306a36Sopenharmony_cicheck_system_wide()
5562306a36Sopenharmony_ci{
5662306a36Sopenharmony_ci	echo -n "Checking json output: system wide "
5762306a36Sopenharmony_ci	if ParanoidAndNotRoot 0
5862306a36Sopenharmony_ci	then
5962306a36Sopenharmony_ci		echo "[Skip] paranoia and not root"
6062306a36Sopenharmony_ci		return
6162306a36Sopenharmony_ci	fi
6262306a36Sopenharmony_ci	perf stat -j -a -o "${stat_output}" true
6362306a36Sopenharmony_ci	$PYTHON $pythonchecker --system-wide --file "${stat_output}"
6462306a36Sopenharmony_ci	echo "[Success]"
6562306a36Sopenharmony_ci}
6662306a36Sopenharmony_ci
6762306a36Sopenharmony_cicheck_system_wide_no_aggr()
6862306a36Sopenharmony_ci{
6962306a36Sopenharmony_ci	echo -n "Checking json output: system wide no aggregation "
7062306a36Sopenharmony_ci	if ParanoidAndNotRoot 0
7162306a36Sopenharmony_ci	then
7262306a36Sopenharmony_ci		echo "[Skip] paranoia and not root"
7362306a36Sopenharmony_ci		return
7462306a36Sopenharmony_ci	fi
7562306a36Sopenharmony_ci	perf stat -j -A -a --no-merge -o "${stat_output}" true
7662306a36Sopenharmony_ci	$PYTHON $pythonchecker --system-wide-no-aggr --file "${stat_output}"
7762306a36Sopenharmony_ci	echo "[Success]"
7862306a36Sopenharmony_ci}
7962306a36Sopenharmony_ci
8062306a36Sopenharmony_cicheck_interval()
8162306a36Sopenharmony_ci{
8262306a36Sopenharmony_ci	echo -n "Checking json output: interval "
8362306a36Sopenharmony_ci	perf stat -j -I 1000 -o "${stat_output}" true
8462306a36Sopenharmony_ci	$PYTHON $pythonchecker --interval --file "${stat_output}"
8562306a36Sopenharmony_ci	echo "[Success]"
8662306a36Sopenharmony_ci}
8762306a36Sopenharmony_ci
8862306a36Sopenharmony_ci
8962306a36Sopenharmony_cicheck_event()
9062306a36Sopenharmony_ci{
9162306a36Sopenharmony_ci	echo -n "Checking json output: event "
9262306a36Sopenharmony_ci	perf stat -j -e cpu-clock -o "${stat_output}" true
9362306a36Sopenharmony_ci	$PYTHON $pythonchecker --event --file "${stat_output}"
9462306a36Sopenharmony_ci	echo "[Success]"
9562306a36Sopenharmony_ci}
9662306a36Sopenharmony_ci
9762306a36Sopenharmony_cicheck_per_core()
9862306a36Sopenharmony_ci{
9962306a36Sopenharmony_ci	echo -n "Checking json output: per core "
10062306a36Sopenharmony_ci	if ParanoidAndNotRoot 0
10162306a36Sopenharmony_ci	then
10262306a36Sopenharmony_ci		echo "[Skip] paranoia and not root"
10362306a36Sopenharmony_ci		return
10462306a36Sopenharmony_ci	fi
10562306a36Sopenharmony_ci	perf stat -j --per-core -a -o "${stat_output}" true
10662306a36Sopenharmony_ci	$PYTHON $pythonchecker --per-core --file "${stat_output}"
10762306a36Sopenharmony_ci	echo "[Success]"
10862306a36Sopenharmony_ci}
10962306a36Sopenharmony_ci
11062306a36Sopenharmony_cicheck_per_thread()
11162306a36Sopenharmony_ci{
11262306a36Sopenharmony_ci	echo -n "Checking json output: per thread "
11362306a36Sopenharmony_ci	if ParanoidAndNotRoot 0
11462306a36Sopenharmony_ci	then
11562306a36Sopenharmony_ci		echo "[Skip] paranoia and not root"
11662306a36Sopenharmony_ci		return
11762306a36Sopenharmony_ci	fi
11862306a36Sopenharmony_ci	perf stat -j --per-thread -a -o "${stat_output}" true
11962306a36Sopenharmony_ci	$PYTHON $pythonchecker --per-thread --file "${stat_output}"
12062306a36Sopenharmony_ci	echo "[Success]"
12162306a36Sopenharmony_ci}
12262306a36Sopenharmony_ci
12362306a36Sopenharmony_cicheck_per_cache_instance()
12462306a36Sopenharmony_ci{
12562306a36Sopenharmony_ci	echo -n "Checking json output: per cache_instance "
12662306a36Sopenharmony_ci	if ParanoidAndNotRoot 0
12762306a36Sopenharmony_ci	then
12862306a36Sopenharmony_ci		echo "[Skip] paranoia and not root"
12962306a36Sopenharmony_ci		return
13062306a36Sopenharmony_ci	fi
13162306a36Sopenharmony_ci	perf stat -j --per-cache -a true 2>&1 | $PYTHON $pythonchecker --per-cache
13262306a36Sopenharmony_ci	echo "[Success]"
13362306a36Sopenharmony_ci}
13462306a36Sopenharmony_ci
13562306a36Sopenharmony_cicheck_per_die()
13662306a36Sopenharmony_ci{
13762306a36Sopenharmony_ci	echo -n "Checking json output: per die "
13862306a36Sopenharmony_ci	if ParanoidAndNotRoot 0
13962306a36Sopenharmony_ci	then
14062306a36Sopenharmony_ci		echo "[Skip] paranoia and not root"
14162306a36Sopenharmony_ci		return
14262306a36Sopenharmony_ci	fi
14362306a36Sopenharmony_ci	perf stat -j --per-die -a -o "${stat_output}" true
14462306a36Sopenharmony_ci	$PYTHON $pythonchecker --per-die --file "${stat_output}"
14562306a36Sopenharmony_ci	echo "[Success]"
14662306a36Sopenharmony_ci}
14762306a36Sopenharmony_ci
14862306a36Sopenharmony_cicheck_per_node()
14962306a36Sopenharmony_ci{
15062306a36Sopenharmony_ci	echo -n "Checking json output: per node "
15162306a36Sopenharmony_ci	if ParanoidAndNotRoot 0
15262306a36Sopenharmony_ci	then
15362306a36Sopenharmony_ci		echo "[Skip] paranoia and not root"
15462306a36Sopenharmony_ci		return
15562306a36Sopenharmony_ci	fi
15662306a36Sopenharmony_ci	perf stat -j --per-node -a -o "${stat_output}" true
15762306a36Sopenharmony_ci	$PYTHON $pythonchecker --per-node --file "${stat_output}"
15862306a36Sopenharmony_ci	echo "[Success]"
15962306a36Sopenharmony_ci}
16062306a36Sopenharmony_ci
16162306a36Sopenharmony_cicheck_per_socket()
16262306a36Sopenharmony_ci{
16362306a36Sopenharmony_ci	echo -n "Checking json output: per socket "
16462306a36Sopenharmony_ci	if ParanoidAndNotRoot 0
16562306a36Sopenharmony_ci	then
16662306a36Sopenharmony_ci		echo "[Skip] paranoia and not root"
16762306a36Sopenharmony_ci		return
16862306a36Sopenharmony_ci	fi
16962306a36Sopenharmony_ci	perf stat -j --per-socket -a -o "${stat_output}" true
17062306a36Sopenharmony_ci	$PYTHON $pythonchecker --per-socket --file "${stat_output}"
17162306a36Sopenharmony_ci	echo "[Success]"
17262306a36Sopenharmony_ci}
17362306a36Sopenharmony_ci
17462306a36Sopenharmony_ci# The perf stat options for per-socket, per-core, per-die
17562306a36Sopenharmony_ci# and -A ( no_aggr mode ) uses the info fetched from this
17662306a36Sopenharmony_ci# directory: "/sys/devices/system/cpu/cpu*/topology". For
17762306a36Sopenharmony_ci# example, socket value is fetched from "physical_package_id"
17862306a36Sopenharmony_ci# file in topology directory.
17962306a36Sopenharmony_ci# Reference: cpu__get_topology_int in util/cpumap.c
18062306a36Sopenharmony_ci# If the platform doesn't expose topology information, values
18162306a36Sopenharmony_ci# will be set to -1. For example, incase of pSeries platform
18262306a36Sopenharmony_ci# of powerpc, value for  "physical_package_id" is restricted
18362306a36Sopenharmony_ci# and set to -1. Check here validates the socket-id read from
18462306a36Sopenharmony_ci# topology file before proceeding further
18562306a36Sopenharmony_ci
18662306a36Sopenharmony_ciFILE_LOC="/sys/devices/system/cpu/cpu*/topology/"
18762306a36Sopenharmony_ciFILE_NAME="physical_package_id"
18862306a36Sopenharmony_ci
18962306a36Sopenharmony_cicheck_for_topology()
19062306a36Sopenharmony_ci{
19162306a36Sopenharmony_ci	if ! ParanoidAndNotRoot 0
19262306a36Sopenharmony_ci	then
19362306a36Sopenharmony_ci		socket_file=`ls $FILE_LOC/$FILE_NAME | head -n 1`
19462306a36Sopenharmony_ci		[ -z $socket_file ] && return 0
19562306a36Sopenharmony_ci		socket_id=`cat $socket_file`
19662306a36Sopenharmony_ci		[ $socket_id == -1 ] && skip_test=1
19762306a36Sopenharmony_ci		return 0
19862306a36Sopenharmony_ci	fi
19962306a36Sopenharmony_ci}
20062306a36Sopenharmony_ci
20162306a36Sopenharmony_cicheck_for_topology
20262306a36Sopenharmony_cicheck_no_args
20362306a36Sopenharmony_cicheck_system_wide
20462306a36Sopenharmony_cicheck_interval
20562306a36Sopenharmony_cicheck_event
20662306a36Sopenharmony_cicheck_per_thread
20762306a36Sopenharmony_cicheck_per_node
20862306a36Sopenharmony_ciif [ $skip_test -ne 1 ]
20962306a36Sopenharmony_cithen
21062306a36Sopenharmony_ci	check_system_wide_no_aggr
21162306a36Sopenharmony_ci	check_per_core
21262306a36Sopenharmony_ci	check_per_cache_instance
21362306a36Sopenharmony_ci	check_per_die
21462306a36Sopenharmony_ci	check_per_socket
21562306a36Sopenharmony_cielse
21662306a36Sopenharmony_ci	echo "[Skip] Skipping tests for system_wide_no_aggr, per_core, per_die and per_socket since socket id exposed via topology is invalid"
21762306a36Sopenharmony_cifi
21862306a36Sopenharmony_cicleanup
21962306a36Sopenharmony_ciexit 0
220