1*4882a593Smuzhiyun#!/bin/bash 2*4882a593Smuzhiyun# SPDX-License-Identifier: GPL-2.0 3*4882a593Smuzhiyun# 4*4882a593Smuzhiyun# This test runs on Intel x86 based hardware which support the intel_pstate 5*4882a593Smuzhiyun# driver. The test checks the frequency settings from the maximum turbo 6*4882a593Smuzhiyun# state to the minimum supported frequency, in decrements of 100MHz. The 7*4882a593Smuzhiyun# test runs the aperf.c program to put load on each processor. 8*4882a593Smuzhiyun# 9*4882a593Smuzhiyun# The results are displayed in a table which indicate the "Target" state, 10*4882a593Smuzhiyun# or the requested frequency in MHz, the Actual frequency, as read from 11*4882a593Smuzhiyun# /proc/cpuinfo, the difference between the Target and Actual frequencies, 12*4882a593Smuzhiyun# and the value of MSR 0x199 (MSR_IA32_PERF_CTL) which indicates what 13*4882a593Smuzhiyun# pstate the cpu is in, and the value of 14*4882a593Smuzhiyun# /sys/devices/system/cpu/intel_pstate/max_perf_pct X maximum turbo state 15*4882a593Smuzhiyun# 16*4882a593Smuzhiyun# Notes: In some cases several frequency values may be placed in the 17*4882a593Smuzhiyun# /tmp/result.X files. This is done on purpose in order to catch cases 18*4882a593Smuzhiyun# where the pstate driver may not be working at all. There is the case 19*4882a593Smuzhiyun# where, for example, several "similar" frequencies are in the file: 20*4882a593Smuzhiyun# 21*4882a593Smuzhiyun# 22*4882a593Smuzhiyun#/tmp/result.3100:1:cpu MHz : 2899.980 23*4882a593Smuzhiyun#/tmp/result.3100:2:cpu MHz : 2900.000 24*4882a593Smuzhiyun#/tmp/result.3100:3:msr 0x199: 0x1e00 25*4882a593Smuzhiyun#/tmp/result.3100:4:max_perf_pct 94 26*4882a593Smuzhiyun# 27*4882a593Smuzhiyun# and the test will error out in those cases. The result.X file can be checked 28*4882a593Smuzhiyun# for consistency and modified to remove the extra MHz values. The result.X 29*4882a593Smuzhiyun# files can be re-evaluated by setting EVALUATE_ONLY to 1 below. 30*4882a593Smuzhiyun 31*4882a593SmuzhiyunEVALUATE_ONLY=0 32*4882a593Smuzhiyun 33*4882a593Smuzhiyun# Kselftest framework requirement - SKIP code is 4. 34*4882a593Smuzhiyunksft_skip=4 35*4882a593Smuzhiyun 36*4882a593Smuzhiyunif ! uname -m | sed -e s/i.86/x86/ -e s/x86_64/x86/ | grep -q x86; then 37*4882a593Smuzhiyun echo "$0 # Skipped: Test can only run on x86 architectures." 38*4882a593Smuzhiyun exit $ksft_skip 39*4882a593Smuzhiyunfi 40*4882a593Smuzhiyun 41*4882a593Smuzhiyunmsg="skip all tests:" 42*4882a593Smuzhiyunif [ $UID != 0 ] && [ $EVALUATE_ONLY == 0 ]; then 43*4882a593Smuzhiyun echo $msg please run this as root >&2 44*4882a593Smuzhiyun exit $ksft_skip 45*4882a593Smuzhiyunfi 46*4882a593Smuzhiyun 47*4882a593Smuzhiyunmax_cpus=$(($(nproc)-1)) 48*4882a593Smuzhiyun 49*4882a593Smuzhiyunfunction run_test () { 50*4882a593Smuzhiyun 51*4882a593Smuzhiyun file_ext=$1 52*4882a593Smuzhiyun for cpu in `seq 0 $max_cpus` 53*4882a593Smuzhiyun do 54*4882a593Smuzhiyun echo "launching aperf load on $cpu" 55*4882a593Smuzhiyun ./aperf $cpu & 56*4882a593Smuzhiyun done 57*4882a593Smuzhiyun 58*4882a593Smuzhiyun echo "sleeping for 5 seconds" 59*4882a593Smuzhiyun sleep 5 60*4882a593Smuzhiyun grep MHz /proc/cpuinfo | sort -u > /tmp/result.freqs 61*4882a593Smuzhiyun num_freqs=$(wc -l /tmp/result.freqs | awk ' { print $1 } ') 62*4882a593Smuzhiyun if [ $num_freqs -ge 2 ]; then 63*4882a593Smuzhiyun tail -n 1 /tmp/result.freqs > /tmp/result.$1 64*4882a593Smuzhiyun else 65*4882a593Smuzhiyun cp /tmp/result.freqs /tmp/result.$1 66*4882a593Smuzhiyun fi 67*4882a593Smuzhiyun ./msr 0 >> /tmp/result.$1 68*4882a593Smuzhiyun 69*4882a593Smuzhiyun max_perf_pct=$(cat /sys/devices/system/cpu/intel_pstate/max_perf_pct) 70*4882a593Smuzhiyun echo "max_perf_pct $max_perf_pct" >> /tmp/result.$1 71*4882a593Smuzhiyun 72*4882a593Smuzhiyun for job in `jobs -p` 73*4882a593Smuzhiyun do 74*4882a593Smuzhiyun echo "waiting for job id $job" 75*4882a593Smuzhiyun wait $job 76*4882a593Smuzhiyun done 77*4882a593Smuzhiyun} 78*4882a593Smuzhiyun 79*4882a593Smuzhiyun# 80*4882a593Smuzhiyun# MAIN (ALL UNITS IN MHZ) 81*4882a593Smuzhiyun# 82*4882a593Smuzhiyun 83*4882a593Smuzhiyun# Get the marketing frequency 84*4882a593Smuzhiyun_mkt_freq=$(cat /proc/cpuinfo | grep -m 1 "model name" | awk '{print $NF}') 85*4882a593Smuzhiyun_mkt_freq=$(echo $_mkt_freq | tr -d [:alpha:][:punct:]) 86*4882a593Smuzhiyunmkt_freq=${_mkt_freq}0 87*4882a593Smuzhiyun 88*4882a593Smuzhiyun# Get the ranges from cpupower 89*4882a593Smuzhiyun_min_freq=$(cpupower frequency-info -l | tail -1 | awk ' { print $1 } ') 90*4882a593Smuzhiyunmin_freq=$(($_min_freq / 1000)) 91*4882a593Smuzhiyun_max_freq=$(cpupower frequency-info -l | tail -1 | awk ' { print $2 } ') 92*4882a593Smuzhiyunmax_freq=$(($_max_freq / 1000)) 93*4882a593Smuzhiyun 94*4882a593Smuzhiyun 95*4882a593Smuzhiyun[ $EVALUATE_ONLY -eq 0 ] && for freq in `seq $max_freq -100 $min_freq` 96*4882a593Smuzhiyundo 97*4882a593Smuzhiyun echo "Setting maximum frequency to $freq" 98*4882a593Smuzhiyun cpupower frequency-set -g powersave --max=${freq}MHz >& /dev/null 99*4882a593Smuzhiyun run_test $freq 100*4882a593Smuzhiyundone 101*4882a593Smuzhiyun 102*4882a593Smuzhiyun[ $EVALUATE_ONLY -eq 0 ] && cpupower frequency-set -g powersave --max=${max_freq}MHz >& /dev/null 103*4882a593Smuzhiyun 104*4882a593Smuzhiyunecho "========================================================================" 105*4882a593Smuzhiyunecho "The marketing frequency of the cpu is $mkt_freq MHz" 106*4882a593Smuzhiyunecho "The maximum frequency of the cpu is $max_freq MHz" 107*4882a593Smuzhiyunecho "The minimum frequency of the cpu is $min_freq MHz" 108*4882a593Smuzhiyun 109*4882a593Smuzhiyun# make a pretty table 110*4882a593Smuzhiyunecho "Target Actual Difference MSR(0x199) max_perf_pct" | tr " " "\n" > /tmp/result.tab 111*4882a593Smuzhiyunfor freq in `seq $max_freq -100 $min_freq` 112*4882a593Smuzhiyundo 113*4882a593Smuzhiyun result_freq=$(cat /tmp/result.${freq} | grep "cpu MHz" | awk ' { print $4 } ' | awk -F "." ' { print $1 } ') 114*4882a593Smuzhiyun msr=$(cat /tmp/result.${freq} | grep "msr" | awk ' { print $3 } ') 115*4882a593Smuzhiyun max_perf_pct=$(cat /tmp/result.${freq} | grep "max_perf_pct" | awk ' { print $2 } ' ) 116*4882a593Smuzhiyun cat >> /tmp/result.tab << EOF 117*4882a593Smuzhiyun$freq 118*4882a593Smuzhiyun$result_freq 119*4882a593Smuzhiyun$((result_freq - freq)) 120*4882a593Smuzhiyun$msr 121*4882a593Smuzhiyun$((max_perf_pct * max_freq)) 122*4882a593SmuzhiyunEOF 123*4882a593Smuzhiyundone 124*4882a593Smuzhiyun 125*4882a593Smuzhiyun# print the table 126*4882a593Smuzhiyunpr -aTt -5 < /tmp/result.tab 127*4882a593Smuzhiyun 128*4882a593Smuzhiyunexit 0 129