| #!/bin/bash | |
| # SPDX-License-Identifier: GPL-2.0 | |
| # protect against multiple inclusion | |
| if [ $FILE_MAIN ]; then | |
| return 0 | |
| else | |
| FILE_MAIN=DONE | |
| fi | |
| SCRIPTDIR=`dirname "$0"` | |
| TRACER=$SCRIPTDIR/../../../power/x86/amd_pstate_tracer/amd_pstate_trace.py | |
| source $SCRIPTDIR/basic.sh | |
| source $SCRIPTDIR/tbench.sh | |
| source $SCRIPTDIR/gitsource.sh | |
| # amd-pstate-ut only run on x86/x86_64 AMD systems. | |
| ARCH=$(uname -m 2>/dev/null | sed -e 's/i.86/x86/' -e 's/x86_64/x86/') | |
| VENDOR=$(cat /proc/cpuinfo | grep -m 1 'vendor_id' | awk '{print $NF}') | |
| msg="Skip all tests:" | |
| FUNC=all | |
| OUTFILE=selftest | |
| OUTFILE_TBENCH="$OUTFILE.tbench" | |
| OUTFILE_GIT="$OUTFILE.gitsource" | |
| PERF=/usr/bin/perf | |
| SYSFS= | |
| CPUROOT= | |
| CPUFREQROOT= | |
| MAKE_CPUS= | |
| TIME_LIMIT=100 | |
| PROCESS_NUM=128 | |
| LOOP_TIMES=3 | |
| TRACER_INTERVAL=10 | |
| CURRENT_TEST=amd-pstate | |
| COMPARATIVE_TEST= | |
| # Kselftest framework requirement - SKIP code is 4. | |
| ksft_skip=4 | |
| all_scaling_names=("acpi-cpufreq" "amd-pstate") | |
| # Get current cpufreq scaling driver name | |
| scaling_name() | |
| { | |
| if [ "$COMPARATIVE_TEST" = "" ]; then | |
| echo "$CURRENT_TEST" | |
| else | |
| echo "$COMPARATIVE_TEST" | |
| fi | |
| } | |
| # Counts CPUs with cpufreq directories | |
| count_cpus() | |
| { | |
| count=0; | |
| for cpu in `ls $CPUROOT | grep "cpu[0-9].*"`; do | |
| if [ -d $CPUROOT/$cpu/cpufreq ]; then | |
| let count=count+1; | |
| fi | |
| done | |
| echo $count; | |
| } | |
| # $1: policy | |
| find_current_governor() | |
| { | |
| cat $CPUFREQROOT/$1/scaling_governor | |
| } | |
| backup_governor() | |
| { | |
| policies=$(ls $CPUFREQROOT| grep "policy[0-9].*") | |
| for policy in $policies; do | |
| cur_gov=$(find_current_governor $policy) | |
| echo "$policy $cur_gov" >> $OUTFILE.backup_governor.log | |
| done | |
| printf "Governor $cur_gov backup done.\n" | |
| } | |
| restore_governor() | |
| { | |
| i=0; | |
| policies=$(awk '{print $1}' $OUTFILE.backup_governor.log) | |
| for policy in $policies; do | |
| let i++; | |
| governor=$(sed -n ''$i'p' $OUTFILE.backup_governor.log | awk '{print $2}') | |
| # switch governor | |
| echo $governor > $CPUFREQROOT/$policy/scaling_governor | |
| done | |
| printf "Governor restored to $governor.\n" | |
| } | |
| # $1: governor | |
| switch_governor() | |
| { | |
| policies=$(ls $CPUFREQROOT| grep "policy[0-9].*") | |
| for policy in $policies; do | |
| filepath=$CPUFREQROOT/$policy/scaling_available_governors | |
| # Exit if cpu isn't managed by cpufreq core | |
| if [ ! -f $filepath ]; then | |
| return; | |
| fi | |
| echo $1 > $CPUFREQROOT/$policy/scaling_governor | |
| done | |
| printf "Switched governor to $1.\n" | |
| } | |
| # All amd-pstate tests | |
| amd_pstate_all() | |
| { | |
| printf "\n=============================================\n" | |
| printf "***** Running AMD P-state Sanity Tests *****\n" | |
| printf "=============================================\n\n" | |
| count=$(count_cpus) | |
| if [ $count = 0 ]; then | |
| printf "No cpu is managed by cpufreq core, exiting\n" | |
| exit; | |
| else | |
| printf "AMD P-state manages: $count CPUs\n" | |
| fi | |
| # unit test for amd-pstate kernel driver | |
| amd_pstate_basic | |
| # tbench | |
| amd_pstate_tbench | |
| # gitsource | |
| amd_pstate_gitsource | |
| } | |
| help() | |
| { | |
| printf "Usage: $0 [OPTION...] | |
| [-h <help>] | |
| [-o <output-file-for-dump>] | |
| [-c <all: All testing, | |
| basic: Basic testing, | |
| tbench: Tbench testing, | |
| gitsource: Gitsource testing.>] | |
| [-t <tbench time limit>] | |
| [-p <tbench process number>] | |
| [-l <loop times for tbench>] | |
| [-i <amd tracer interval>] | |
| [-b <perf binary>] | |
| [-m <comparative test: acpi-cpufreq>] | |
| \n" | |
| exit 2 | |
| } | |
| parse_arguments() | |
| { | |
| while getopts ho:c:t:p:l:i:b:m: arg | |
| do | |
| case $arg in | |
| h) # --help | |
| help | |
| ;; | |
| c) # --func_type (Function to perform: basic, tbench, gitsource (default: all)) | |
| FUNC=$OPTARG | |
| ;; | |
| o) # --output-file (Output file to store dumps) | |
| OUTFILE=$OPTARG | |
| ;; | |
| t) # --tbench-time-limit | |
| TIME_LIMIT=$OPTARG | |
| ;; | |
| p) # --tbench-process-number | |
| PROCESS_NUM=$OPTARG | |
| ;; | |
| l) # --tbench/gitsource-loop-times | |
| LOOP_TIMES=$OPTARG | |
| ;; | |
| i) # --amd-tracer-interval | |
| TRACER_INTERVAL=$OPTARG | |
| ;; | |
| b) # --perf-binary | |
| PERF=`realpath $OPTARG` | |
| ;; | |
| m) # --comparative-test | |
| COMPARATIVE_TEST=$OPTARG | |
| ;; | |
| *) | |
| help | |
| ;; | |
| esac | |
| done | |
| } | |
| command_perf() | |
| { | |
| if ! $PERF -v; then | |
| echo $msg please install perf or provide perf binary path as argument >&2 | |
| exit $ksft_skip | |
| fi | |
| } | |
| command_tbench() | |
| { | |
| if ! command -v tbench > /dev/null; then | |
| if apt policy dbench > /dev/null 2>&1; then | |
| echo $msg apt install dbench >&2 | |
| exit $ksft_skip | |
| elif yum list available | grep dbench > /dev/null 2>&1; then | |
| echo $msg yum install dbench >&2 | |
| exit $ksft_skip | |
| fi | |
| fi | |
| if ! command -v tbench > /dev/null; then | |
| echo $msg please install tbench. >&2 | |
| exit $ksft_skip | |
| fi | |
| } | |
| prerequisite() | |
| { | |
| if ! echo "$ARCH" | grep -q x86; then | |
| echo "$0 # Skipped: Test can only run on x86 architectures." | |
| exit $ksft_skip | |
| fi | |
| if ! echo "$VENDOR" | grep -iq amd; then | |
| echo "$0 # Skipped: Test can only run on AMD CPU." | |
| echo "$0 # Current cpu vendor is $VENDOR." | |
| exit $ksft_skip | |
| fi | |
| scaling_driver=$(cat /sys/devices/system/cpu/cpufreq/policy0/scaling_driver) | |
| if [ "$COMPARATIVE_TEST" = "" ]; then | |
| if [ "$scaling_driver" != "$CURRENT_TEST" ]; then | |
| echo "$0 # Skipped: Test can only run on $CURRENT_TEST driver or run comparative test." | |
| echo "$0 # Please set X86_AMD_PSTATE enabled or run comparative test." | |
| echo "$0 # Current cpufreq scaling driver is $scaling_driver." | |
| exit $ksft_skip | |
| fi | |
| else | |
| case "$FUNC" in | |
| "tbench" | "gitsource") | |
| if [ "$scaling_driver" != "$COMPARATIVE_TEST" ]; then | |
| echo "$0 # Skipped: Comparison test can only run on $COMPARISON_TEST driver." | |
| echo "$0 # Current cpufreq scaling driver is $scaling_driver." | |
| exit $ksft_skip | |
| fi | |
| ;; | |
| *) | |
| echo "$0 # Skipped: Comparison test are only for tbench or gitsource." | |
| echo "$0 # Current comparative test is for $FUNC." | |
| exit $ksft_skip | |
| ;; | |
| esac | |
| fi | |
| if [ ! -w /dev ]; then | |
| echo $msg please run this as root >&2 | |
| exit $ksft_skip | |
| fi | |
| case "$FUNC" in | |
| "all") | |
| command_perf | |
| command_tbench | |
| ;; | |
| "tbench") | |
| command_perf | |
| command_tbench | |
| ;; | |
| "gitsource") | |
| command_perf | |
| ;; | |
| esac | |
| SYSFS=`mount -t sysfs | head -1 | awk '{ print $3 }'` | |
| if [ ! -d "$SYSFS" ]; then | |
| echo $msg sysfs is not mounted >&2 | |
| exit 2 | |
| fi | |
| CPUROOT=$SYSFS/devices/system/cpu | |
| CPUFREQROOT="$CPUROOT/cpufreq" | |
| if ! ls $CPUROOT/cpu* > /dev/null 2>&1; then | |
| echo $msg cpus not available in sysfs >&2 | |
| exit 2 | |
| fi | |
| if ! ls $CPUROOT/cpufreq > /dev/null 2>&1; then | |
| echo $msg cpufreq directory not available in sysfs >&2 | |
| exit 2 | |
| fi | |
| } | |
| do_test() | |
| { | |
| # Check if CPUs are managed by cpufreq or not | |
| count=$(count_cpus) | |
| MAKE_CPUS=$((count*2)) | |
| if [ $count = 0 ]; then | |
| echo "No cpu is managed by cpufreq core, exiting" | |
| exit 2; | |
| fi | |
| case "$FUNC" in | |
| "all") | |
| amd_pstate_all | |
| ;; | |
| "basic") | |
| amd_pstate_basic | |
| ;; | |
| "tbench") | |
| amd_pstate_tbench | |
| ;; | |
| "gitsource") | |
| amd_pstate_gitsource | |
| ;; | |
| *) | |
| echo "Invalid [-f] function type" | |
| help | |
| ;; | |
| esac | |
| } | |
| # clear dumps | |
| pre_clear_dumps() | |
| { | |
| case "$FUNC" in | |
| "all") | |
| rm -rf $OUTFILE.log | |
| rm -rf $OUTFILE.backup_governor.log | |
| rm -rf *.png | |
| ;; | |
| "tbench") | |
| rm -rf $OUTFILE.log | |
| rm -rf $OUTFILE.backup_governor.log | |
| rm -rf tbench_*.png | |
| ;; | |
| "gitsource") | |
| rm -rf $OUTFILE.log | |
| rm -rf $OUTFILE.backup_governor.log | |
| rm -rf gitsource_*.png | |
| ;; | |
| *) | |
| ;; | |
| esac | |
| } | |
| post_clear_dumps() | |
| { | |
| rm -rf $OUTFILE.log | |
| rm -rf $OUTFILE.backup_governor.log | |
| } | |
| # Parse arguments | |
| parse_arguments $@ | |
| # Make sure all requirements are met | |
| prerequisite | |
| # Run requested functions | |
| pre_clear_dumps | |
| do_test | tee -a $OUTFILE.log | |
| post_clear_dumps |