Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add 3 CPU turbo frequency cases when other CPUs are in active idle #323

Merged
merged 1 commit into from
Jul 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
151 changes: 151 additions & 0 deletions BM/cstate/powermgr_cstate_tests.sh
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,24 @@ else
block_test "msr-tools is required to run CSTATE cases."
fi

# stress tool is required to run cstate cases
if which stress 1>/dev/null 2>&1; then
stress --help 1>/dev/null || block_test "Failed to run stress tool,
please check stress tool error message."
else
block_test "stress tool is required to run cstate cases,
please get it from latest upstream kernel-tools."
fi

# This function is used to kill stress process if it is still running.
# We do this to release cpu resource.
do_kill_pid() {
[[ $# -ne 1 ]] && die "You must supply 1 parameter"
local upid="$1"
upid=$(ps -e | awk '{if($1~/'"$upid"'/) print $1}')
[[ -n "$upid" ]] && do_cmd "kill -9 $upid"
}

# Function to verify if Intel_idle driver refer to BIOS _CST table
test_cstate_table_name() {
local cstate_name=""
Expand Down Expand Up @@ -697,6 +715,130 @@ ccstate_res_offline_online() {
fi
}

# Function to check one CPU turbo freqency when other CPUs are in active idle state
verify_single_cpu_freq() {
local stress_pid=""
local cpu_stat=""
local max_freq=""
local current_freq=""
local delta=0
local turbo_on=""
local cpu_no_turbo_mode="/sys/devices/system/cpu/intel_pstate/no_turbo"

# Get the CPUs num and the deepest idle cstate number
cpus_num=$(lscpu | grep "On-line CPU(s) list" | awk '{print $NF}' | awk -F "-" '{print $2}')
states=($(grep . /sys/devices/system/cpu/cpu0/cpuidle/state*/name | awk -F "/" '{print $(NF-1)}'))

length=${#states[@]}

turbo_on=$(cat "$cpu_no_turbo_mode")

test_print_trc "Executing stress -c 1 -t 90 & in background"
taskset -c 1 stress -c 1 -t 90 &
stress_pid=$!

cpu_stat_debug=$(turbostat -i 1 sleep 1 2>&1)
test_print_trc "Turbostat debug output is:"
test_print_trc "$cpu_stat_debug"
cpu_stat=$(turbostat -q -i 1 sleep 1 2>&1)
test_print_trc "Turbostat output is:"
test_print_trc "$cpu_stat"

if [[ "$turbo_on" -eq 0 ]]; then
max_freq=$(echo "$cpu_stat_debug" |
grep "MHz max turbo" | tail -n 1 | awk '{print $5}')
test_print_trc "Max_freq_turbo_On: $max_freq"
else
max_freq=$(echo "$cpu_stat_debug" |
grep "base frequency" |
awk '{print $5}')
test_print_trc "Max_freq_turbo_off: $max_freq"
fi

current_freq=$(echo "$cpu_stat" |
awk '{for(k=0;++k<=NF;)a[k]=a[k]?a[k] FS $k:$k} END{for(k=0;k++<NF;)print a[k]}' |
grep "Bzy_MHz" | awk -F " " '{print $2}')
do_cmd "do_kill_pid $stress_pid"
test_print_trc "current freq: $current_freq"
test_print_trc "max freq: $max_freq"

[[ -n "$max_freq" ]] || {
echo "$cpu_stat"
die "Cannot get the max freq"
}
[[ -n "$current_freq" ]] || {
echo "$cpu_stat"
die "Cannot get current freq"
}
delta=$(awk -v x="$max_freq" -v y="$current_freq" \
'BEGIN{printf "%.1f\n", x-y}')
test_print_trc "Delta freq between max_freq and current_freq is:$delta MHz"

# Enable all the CPUs idle cstate
for ((i = 0; i < length; i++)); do
for ((j = 0; j < cpus_num; j++)); do
do_cmd "echo 0 > grep . /sys/devices/system/cpu/cpu$j/cpuidle/state$i/disable"
done
done

if [[ $(echo "$delta > 100" | bc) -eq 1 ]]; then
if power_limit_check; then
test_print_trc "The package and core power limitation is asserted."
test_print_trc "$current_freq is lower than $max_freq with power limitation assert"
else
test_print_trc "The package and core power limitation is NOT assert."
die "$current_freq is lower than $max_freq without power limitation assert"
fi
else
test_print_trc "checking single cpu freq when other CPUs are in idle: PASS"
fi
}

# Function to verify the turbo frequency of a single CPU
# when all CPUs are in P0, L1, C1, or C1E states
turbo_freq_when_idle() {
local cpu_num=""
local idle_state=$1

# Get the CPUs num and the deepest idle cstate number
cpus_num=$(lscpu | grep "On-line CPU(s) list" | awk '{print $NF}' | awk -F "-" '{print $2}')
states=($(grep . /sys/devices/system/cpu/cpu0/cpuidle/state*/name | awk -F "/" '{print $(NF-1)}'))

length=${#states[@]}
test_print_trc "The deepest core cstate num is: $length"

# Enable the idle state for all the CPUs
# If test idle state is POLL/C1/C1E, then disable all the other deeper idle cstate
if [[ "$idle_state" == POLL ]]; then
for ((i = 1; i < length; i++)); do
for ((j = 0; j < cpus_num; j++)); do
do_cmd "echo 1 > grep . /sys/devices/system/cpu/cpu$j/cpuidle/state$i/disable"
done
done
elif [[ "$idle_state" == C1 ]]; then
for ((i = 2; i < length; i++)); do
for ((j = 0; j < cpus_num; j++)); do
do_cmd "echo 1 > grep . /sys/devices/system/cpu/cpu$j/cpuidle/state$i/disable"
done
done
elif [[ "$idle_state" == C1E ]]; then
if grep -q 'C1E' /sys/devices/system/cpu/cpu0/cpuidle/state*/name; then
for ((i = 3; i < length; i++)); do
for ((j = 0; j < cpus_num; j++)); do
do_cmd "echo 1 > grep . /sys/devices/system/cpu/cpu$j/cpuidle/state$i/disable"
done
done
else
block_test "The C1E state is not present"
fi
fi

# Run a 100% stress workload exclusively on CPU0 and verify the turbo frequency
# If the turbo frequency does not meet the expected value
# Then determine whether a thermal limitation has been reached
verify_single_cpu_freq
}

# Function to do CPU offline and online short stress
cpu_off_on_stress() {
local cycle=$1
Expand Down Expand Up @@ -808,6 +950,15 @@ core_cstate_test() {
verify_ccstate_res_offline_online)
ccstate_res_offline_online 0x10 0x660 0x3fd
;;
verify_turbo_freq_in_poll)
turbo_freq_when_idle POLL
;;
verify_turbo_freq_in_c1)
turbo_freq_when_idle C1
;;
verify_turbo_freq_in_c1e)
turbo_freq_when_idle C1E
;;
verify_cpu_offline_online_stress)
cpu_off_on_stress 5
;;
Expand Down
10 changes: 10 additions & 0 deletions BM/cstate/tests-server
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
# @other_dep:
# @other_warn: which turbostat 2>/dev/null @ turbostat tool is required
# @other_warn: which perf 2>/dev/null @ perf tool is required, please install perf.x86_64 package
# @other_warn: which rdmsr 2>/dev/null @ rdmsr tool is required, please install msr-tools
# @other_warn: which stress 2>/dev/null @ stress tool is required, please install stress.x86_64 or stress-ng.x86_64

powermgr_cstate_tests.sh -t verify_cstate_name
powermgr_cstate_tests.sh -t verify_server_all_cores_cstate6
Expand All @@ -17,6 +19,14 @@ powermgr_cstate_tests.sh -t verify_server_perf_module_cstat_update
powermgr_cstate_tests.sh -t verify_server_pc2_entry
powermgr_cstate_tests.sh -t verify_server_pc6_entry
powermgr_cstate_tests.sh -t verify_server_pc6_residency
# Below case is to verify the PC6 entry or not after CPUs offline
powermgr_cstate_tests.sh -t verify_offline_cpu_deepest_pc
# Below case is to verify the CC1 and CC6 residency after CPUs offline and online
powermgr_cstate_tests.sh -t verify_ccstate_res_offline_online
# Below case are to verify whether a single CPU can reach the turbo frequecy
# When other CPUs are all in POLL or C1 or C1E
powermgr_cstate_tests.sh -t verify_turbo_freq_in_poll
powermgr_cstate_tests.sh -t verify_turbo_freq_in_c1
powermgr_cstate_tests.sh -t verify_turbo_freq_in_c1e
# Below case is verify the CPUs offline and online stress
powermgr_cstate_tests.sh -t verify_cpu_offline_online_stress
Loading