xref: /linux/tools/testing/selftests/amd-pstate/run.sh (revision ba2d788aa873da9c65ff067ca94665853eab95f0)
1#!/bin/bash
2# SPDX-License-Identifier: GPL-2.0
3
4# protect against multiple inclusion
5if [ $FILE_MAIN ]; then
6	return 0
7else
8	FILE_MAIN=DONE
9fi
10
11source basic.sh
12source tbench.sh
13
14# amd-pstate-ut only run on x86/x86_64 AMD systems.
15ARCH=$(uname -m 2>/dev/null | sed -e 's/i.86/x86/' -e 's/x86_64/x86/')
16VENDOR=$(cat /proc/cpuinfo | grep -m 1 'vendor_id' | awk '{print $NF}')
17
18msg="Skip all tests:"
19FUNC=all
20OUTFILE=selftest
21OUTFILE_TBENCH="$OUTFILE.tbench"
22
23SYSFS=
24CPUROOT=
25CPUFREQROOT=
26MAKE_CPUS=
27
28TIME_LIMIT=100
29PROCESS_NUM=128
30LOOP_TIMES=3
31TRACER_INTERVAL=10
32CURRENT_TEST=amd-pstate
33COMPARATIVE_TEST=
34
35# Kselftest framework requirement - SKIP code is 4.
36ksft_skip=4
37all_scaling_names=("acpi-cpufreq" "amd-pstate")
38
39# Get current cpufreq scaling driver name
40scaling_name()
41{
42	if [ "$COMPARATIVE_TEST" = "" ]; then
43		echo "$CURRENT_TEST"
44	else
45		echo "$COMPARATIVE_TEST"
46	fi
47}
48
49# Counts CPUs with cpufreq directories
50count_cpus()
51{
52	count=0;
53
54	for cpu in `ls $CPUROOT | grep "cpu[0-9].*"`; do
55		if [ -d $CPUROOT/$cpu/cpufreq ]; then
56			let count=count+1;
57		fi
58	done
59
60	echo $count;
61}
62
63# $1: policy
64find_current_governor()
65{
66	cat $CPUFREQROOT/$1/scaling_governor
67}
68
69backup_governor()
70{
71	policies=$(ls $CPUFREQROOT| grep "policy[0-9].*")
72	for policy in $policies; do
73		cur_gov=$(find_current_governor $policy)
74		echo "$policy $cur_gov" >> $OUTFILE.backup_governor.log
75	done
76
77	printf "Governor $cur_gov backup done.\n"
78}
79
80restore_governor()
81{
82	i=0;
83
84	policies=$(awk '{print $1}' $OUTFILE.backup_governor.log)
85	for policy in $policies; do
86		let i++;
87		governor=$(sed -n ''$i'p' $OUTFILE.backup_governor.log | awk '{print $2}')
88
89		# switch governor
90		echo $governor > $CPUFREQROOT/$policy/scaling_governor
91	done
92
93	printf "Governor restored to $governor.\n"
94}
95
96# $1: governor
97switch_governor()
98{
99	policies=$(ls $CPUFREQROOT| grep "policy[0-9].*")
100	for policy in $policies; do
101		filepath=$CPUFREQROOT/$policy/scaling_available_governors
102
103		# Exit if cpu isn't managed by cpufreq core
104		if [ ! -f $filepath ]; then
105			return;
106		fi
107
108		echo $1 > $CPUFREQROOT/$policy/scaling_governor
109	done
110
111	printf "Switched governor to $1.\n"
112}
113
114# All amd-pstate tests
115amd_pstate_all()
116{
117	printf "\n=============================================\n"
118	printf "***** Running AMD P-state Sanity Tests  *****\n"
119	printf "=============================================\n\n"
120
121	count=$(count_cpus)
122	if [ $count = 0 ]; then
123		printf "No cpu is managed by cpufreq core, exiting\n"
124		exit;
125	else
126		printf "AMD P-state manages: $count CPUs\n"
127	fi
128
129	# unit test for amd-pstate kernel driver
130	amd_pstate_basic
131
132	# tbench
133	amd_pstate_tbench
134}
135
136help()
137{
138	printf "Usage: $0 [OPTION...]
139	[-h <help>]
140	[-o <output-file-for-dump>]
141	[-c <all: All testing,
142	     basic: Basic testing,
143	     tbench: Tbench testing.>]
144	[-t <tbench time limit>]
145	[-p <tbench process number>]
146	[-l <loop times for tbench>]
147	[-i <amd tracer interval>]
148	[-m <comparative test: acpi-cpufreq>]
149	\n"
150	exit 2
151}
152
153parse_arguments()
154{
155	while getopts ho:c:t:p:l:i:m: arg
156	do
157		case $arg in
158			h) # --help
159				help
160				;;
161
162			c) # --func_type (Function to perform: basic, tbench (default: all))
163				FUNC=$OPTARG
164				;;
165
166			o) # --output-file (Output file to store dumps)
167				OUTFILE=$OPTARG
168				;;
169
170			t) # --tbench-time-limit
171				TIME_LIMIT=$OPTARG
172				;;
173
174			p) # --tbench-process-number
175				PROCESS_NUM=$OPTARG
176				;;
177
178			l) # --tbench-loop-times
179				LOOP_TIMES=$OPTARG
180				;;
181
182			i) # --amd-tracer-interval
183				TRACER_INTERVAL=$OPTARG
184				;;
185
186			m) # --comparative-test
187				COMPARATIVE_TEST=$OPTARG
188				;;
189
190			*)
191				help
192				;;
193		esac
194	done
195}
196
197command_perf()
198{
199	if ! command -v perf > /dev/null; then
200		echo $msg please install perf. >&2
201		exit $ksft_skip
202	fi
203}
204
205command_tbench()
206{
207	if ! command -v tbench > /dev/null; then
208		if apt policy dbench > /dev/null 2>&1; then
209			echo $msg apt install dbench >&2
210			exit $ksft_skip
211		elif yum list available | grep dbench > /dev/null 2>&1; then
212			echo $msg yum install dbench >&2
213			exit $ksft_skip
214		fi
215	fi
216
217	if ! command -v tbench > /dev/null; then
218		echo $msg please install tbench. >&2
219		exit $ksft_skip
220	fi
221}
222
223prerequisite()
224{
225	if ! echo "$ARCH" | grep -q x86; then
226		echo "$0 # Skipped: Test can only run on x86 architectures."
227		exit $ksft_skip
228	fi
229
230	if ! echo "$VENDOR" | grep -iq amd; then
231		echo "$0 # Skipped: Test can only run on AMD CPU."
232		echo "$0 # Current cpu vendor is $VENDOR."
233		exit $ksft_skip
234	fi
235
236	scaling_driver=$(cat /sys/devices/system/cpu/cpufreq/policy0/scaling_driver)
237	if [ "$COMPARATIVE_TEST" = "" ]; then
238		if [ "$scaling_driver" != "$CURRENT_TEST" ]; then
239			echo "$0 # Skipped: Test can only run on $CURRENT_TEST driver or run comparative test."
240			echo "$0 # Please set X86_AMD_PSTATE enabled or run comparative test."
241			echo "$0 # Current cpufreq scaling drvier is $scaling_driver."
242			exit $ksft_skip
243		fi
244	else
245		case "$FUNC" in
246			"tbench")
247				if [ "$scaling_driver" != "$COMPARATIVE_TEST" ]; then
248					echo "$0 # Skipped: Comparison test can only run on $COMPARATIVE_TEST driver."
249					echo "$0 # Current cpufreq scaling drvier is $scaling_driver."
250					exit $ksft_skip
251				fi
252				;;
253
254			*)
255				echo "$0 # Skipped: Comparison test are only for tbench."
256				echo "$0 # Current comparative test is for $FUNC."
257				exit $ksft_skip
258				;;
259		esac
260	fi
261
262	if [ ! -w /dev ]; then
263		echo $msg please run this as root >&2
264		exit $ksft_skip
265	fi
266
267	case "$FUNC" in
268		"all")
269			command_perf
270			command_tbench
271			;;
272
273		"tbench")
274			command_perf
275			command_tbench
276			;;
277	esac
278
279	SYSFS=`mount -t sysfs | head -1 | awk '{ print $3 }'`
280
281	if [ ! -d "$SYSFS" ]; then
282		echo $msg sysfs is not mounted >&2
283		exit 2
284	fi
285
286	CPUROOT=$SYSFS/devices/system/cpu
287	CPUFREQROOT="$CPUROOT/cpufreq"
288
289	if ! ls $CPUROOT/cpu* > /dev/null 2>&1; then
290		echo $msg cpus not available in sysfs >&2
291		exit 2
292	fi
293
294	if ! ls $CPUROOT/cpufreq > /dev/null 2>&1; then
295		echo $msg cpufreq directory not available in sysfs >&2
296		exit 2
297	fi
298}
299
300do_test()
301{
302	# Check if CPUs are managed by cpufreq or not
303	count=$(count_cpus)
304	MAKE_CPUS=$((count*2))
305
306	if [ $count = 0 ]; then
307		echo "No cpu is managed by cpufreq core, exiting"
308		exit 2;
309	fi
310
311	case "$FUNC" in
312		"all")
313			amd_pstate_all
314			;;
315
316		"basic")
317			amd_pstate_basic
318			;;
319
320		"tbench")
321			amd_pstate_tbench
322			;;
323
324		*)
325			echo "Invalid [-f] function type"
326			help
327			;;
328	esac
329}
330
331# clear dumps
332pre_clear_dumps()
333{
334	case "$FUNC" in
335		"all")
336			rm -rf $OUTFILE.log
337			rm -rf $OUTFILE.backup_governor.log
338			rm -rf *.png
339			;;
340
341		"tbench")
342			rm -rf $OUTFILE.log
343			rm -rf $OUTFILE.backup_governor.log
344			rm -rf tbench_*.png
345			;;
346
347		*)
348			;;
349	esac
350}
351
352post_clear_dumps()
353{
354	rm -rf $OUTFILE.log
355	rm -rf $OUTFILE.backup_governor.log
356}
357
358# Parse arguments
359parse_arguments $@
360
361# Make sure all requirements are met
362prerequisite
363
364# Run requested functions
365pre_clear_dumps
366do_test | tee -a $OUTFILE.log
367post_clear_dumps
368