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