Add CPU power management tools and dynamic frequency scaling
- Add cpu-power-control.sh: Script for managing CPU power limits and presets - Add monitor-cpu-freq.sh: Real-time CPU frequency monitoring tool - Add test-single-core-boost.sh: Tool for testing single-core boost frequencies - Add BIOS-FIX.md: Documentation for BIOS configuration fix - Update tlp.conf: Configure dynamic CPU frequency scaling (400MHz-4.2GHz on AC, 400MHz-2.2GHz on battery) - Add Intel RAPL power limit controls for CPU power capping - Enable dynamic frequency scaling with proper platform profiles - Fix CPU frequency stuck at 1.6GHz issue (required BIOS SpeedStep disable) - Configure balanced battery mode with 2.2GHz max for responsiveness
This commit is contained in:
356
scripts/cpu-power-control.sh
Executable file
356
scripts/cpu-power-control.sh
Executable file
@@ -0,0 +1,356 @@
|
||||
#!/bin/bash
|
||||
|
||||
# CPU Power Control Script
|
||||
# Provides slider-like functionality for setting CPU power limits
|
||||
# Replaces the missing GUI power slider functionality
|
||||
|
||||
RAPL_PATH="/sys/class/powercap/intel-rapl:0"
|
||||
CONSTRAINT_LONG="${RAPL_PATH}/constraint_0_power_limit_uw"
|
||||
CONSTRAINT_SHORT="${RAPL_PATH}/constraint_1_power_limit_uw"
|
||||
|
||||
# Color codes for output
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
BLUE='\033[0;34m'
|
||||
NC='\033[0m' # No Color
|
||||
|
||||
print_usage() {
|
||||
echo "CPU Power Control - Equivalent to GUI Power Slider"
|
||||
echo ""
|
||||
echo "Usage: $0 [COMMAND] [VALUE]"
|
||||
echo ""
|
||||
echo "Commands:"
|
||||
echo " status Show current CPU power limits"
|
||||
echo " set <watts> Set both long and short term limits"
|
||||
echo " set-long <watts> Set long term limit only"
|
||||
echo " set-short <watts> Set short term limit only"
|
||||
echo " preset <name> Apply predefined power profile"
|
||||
echo ""
|
||||
echo "Presets:"
|
||||
echo " dynamic 400MHz-4.2GHz dynamic (recommended)"
|
||||
echo " max-performance 1.6GHz-4.2GHz (high performance)"
|
||||
echo " balanced 400MHz-2.2GHz (battery friendly, responsive)"
|
||||
echo " power-save 400MHz-2.0GHz (battery optimized)"
|
||||
echo " ultra-save 400MHz-1.6GHz (extreme battery)"
|
||||
echo ""
|
||||
echo "Examples:"
|
||||
echo " $0 status Show current settings"
|
||||
echo " $0 set 10 Set both limits to 10W"
|
||||
echo " $0 preset dynamic Dynamic scaling (800MHz-4.2GHz)"
|
||||
echo ""
|
||||
}
|
||||
|
||||
check_permissions() {
|
||||
if [ "$EUID" -ne 0 ]; then
|
||||
echo -e "${RED}Error: This script requires root privileges${NC}"
|
||||
echo "Please run with sudo: sudo $0 $*"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
check_rapl_support() {
|
||||
if [ ! -d "$RAPL_PATH" ]; then
|
||||
echo -e "${RED}Error: Intel RAPL not supported on this system${NC}"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
watts_to_microwatts() {
|
||||
echo $(($1 * 1000000))
|
||||
}
|
||||
|
||||
microwatts_to_watts() {
|
||||
echo "scale=1; $1 / 1000000" | bc -l
|
||||
}
|
||||
|
||||
get_current_limits() {
|
||||
if [ -r "$CONSTRAINT_LONG" ] && [ -r "$CONSTRAINT_SHORT" ]; then
|
||||
LONG_UW=$(cat "$CONSTRAINT_LONG")
|
||||
SHORT_UW=$(cat "$CONSTRAINT_SHORT")
|
||||
LONG_W=$(microwatts_to_watts $LONG_UW)
|
||||
SHORT_W=$(microwatts_to_watts $SHORT_UW)
|
||||
else
|
||||
echo -e "${RED}Error: Cannot read power limit files${NC}"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
get_max_limits() {
|
||||
MAX_LONG_UW=$(cat "${RAPL_PATH}/constraint_0_max_power_uw")
|
||||
MAX_SHORT_UW=$(cat "${RAPL_PATH}/constraint_1_max_power_uw")
|
||||
MAX_LONG_W=$(microwatts_to_watts $MAX_LONG_UW)
|
||||
MAX_SHORT_W=$(microwatts_to_watts $MAX_SHORT_UW)
|
||||
}
|
||||
|
||||
show_status() {
|
||||
echo -e "${BLUE}=== CPU Power Limits Status ===${NC}"
|
||||
echo ""
|
||||
|
||||
get_current_limits
|
||||
get_max_limits
|
||||
|
||||
echo -e "Current Limits:"
|
||||
echo -e " Long term (PL1): ${GREEN}${LONG_W}W${NC}"
|
||||
echo -e " Short term (PL2): ${GREEN}${SHORT_W}W${NC}"
|
||||
echo ""
|
||||
echo -e "Maximum Limits:"
|
||||
echo -e " Long term max: ${YELLOW}${MAX_LONG_W}W${NC}"
|
||||
echo -e " Short term max: ${YELLOW}${MAX_SHORT_W}W${NC}"
|
||||
echo ""
|
||||
|
||||
# Show platform profile
|
||||
if [ -r "/sys/firmware/acpi/platform_profile" ]; then
|
||||
PLATFORM_PROFILE=$(cat /sys/firmware/acpi/platform_profile)
|
||||
echo -e "Platform Profile: ${GREEN}${PLATFORM_PROFILE}${NC}"
|
||||
fi
|
||||
|
||||
# Show CPU performance percentage
|
||||
if [ -r "/sys/devices/system/cpu/intel_pstate/min_perf_pct" ]; then
|
||||
MIN_PERF=$(cat /sys/devices/system/cpu/intel_pstate/min_perf_pct)
|
||||
MAX_PERF=$(cat /sys/devices/system/cpu/intel_pstate/max_perf_pct)
|
||||
echo -e "CPU Performance: ${GREEN}${MIN_PERF}% - ${MAX_PERF}%${NC}"
|
||||
fi
|
||||
|
||||
# Show current CPU frequency
|
||||
if [ -r "/sys/devices/system/cpu/cpu0/cpufreq/scaling_cur_freq" ]; then
|
||||
CUR_FREQ=$(cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_cur_freq)
|
||||
CUR_FREQ_MHZ=$((CUR_FREQ / 1000))
|
||||
MAX_FREQ=$(cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_max_freq)
|
||||
MAX_FREQ_MHZ=$((MAX_FREQ / 1000))
|
||||
echo -e "Current CPU frequency: ${GREEN}${CUR_FREQ_MHZ} MHz${NC} (max: ${MAX_FREQ_MHZ} MHz)"
|
||||
fi
|
||||
|
||||
# Show governor
|
||||
if [ -r "/sys/devices/system/cpu/cpu0/cpufreq/scaling_governor" ]; then
|
||||
GOVERNOR=$(cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor)
|
||||
echo -e "CPU Governor: ${GREEN}${GOVERNOR}${NC}"
|
||||
fi
|
||||
|
||||
# Show power usage if available
|
||||
if command -v powertop >/dev/null 2>&1; then
|
||||
echo ""
|
||||
echo -e "${BLUE}Tip: Run 'sudo powertop' to monitor real-time power consumption${NC}"
|
||||
fi
|
||||
}
|
||||
|
||||
set_power_limit() {
|
||||
local watts=$1
|
||||
local type=$2
|
||||
|
||||
if [ -z "$watts" ]; then
|
||||
echo -e "${RED}Error: Power value required${NC}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Validate input is a number
|
||||
if ! [[ "$watts" =~ ^[0-9]+\.?[0-9]*$ ]]; then
|
||||
echo -e "${RED}Error: Invalid power value '$watts'. Must be a number.${NC}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
local microwatts=$(watts_to_microwatts $watts)
|
||||
get_max_limits
|
||||
|
||||
# Check against maximum limits
|
||||
case $type in
|
||||
"long")
|
||||
if [ $microwatts -gt $MAX_LONG_UW ]; then
|
||||
echo -e "${YELLOW}Warning: ${watts}W exceeds maximum long term limit of ${MAX_LONG_W}W${NC}"
|
||||
echo -e "Setting to maximum: ${MAX_LONG_W}W"
|
||||
microwatts=$MAX_LONG_UW
|
||||
fi
|
||||
echo $microwatts > "$CONSTRAINT_LONG"
|
||||
echo -e "${GREEN}Long term power limit set to $(microwatts_to_watts $microwatts)W${NC}"
|
||||
;;
|
||||
"short")
|
||||
if [ $microwatts -gt $MAX_SHORT_UW ]; then
|
||||
echo -e "${YELLOW}Warning: ${watts}W exceeds maximum short term limit of ${MAX_SHORT_W}W${NC}"
|
||||
echo -e "Setting to maximum: ${MAX_SHORT_W}W"
|
||||
microwatts=$MAX_SHORT_UW
|
||||
fi
|
||||
echo $microwatts > "$CONSTRAINT_SHORT"
|
||||
echo -e "${GREEN}Short term power limit set to $(microwatts_to_watts $microwatts)W${NC}"
|
||||
;;
|
||||
"both")
|
||||
# For setting both, use appropriate limits
|
||||
echo $microwatts > "$CONSTRAINT_LONG"
|
||||
|
||||
# Short term should be higher, but not exceed max
|
||||
local short_microwatts=$((microwatts * 3 / 2)) # 1.5x long term
|
||||
if [ $short_microwatts -gt $MAX_SHORT_UW ]; then
|
||||
short_microwatts=$MAX_SHORT_UW
|
||||
fi
|
||||
echo $short_microwatts > "$CONSTRAINT_SHORT"
|
||||
|
||||
echo -e "${GREEN}Power limits set:${NC}"
|
||||
echo -e " Long term: $(microwatts_to_watts $microwatts)W"
|
||||
echo -e " Short term: $(microwatts_to_watts $short_microwatts)W"
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
apply_preset() {
|
||||
local preset=$1
|
||||
|
||||
case $preset in
|
||||
"dynamic")
|
||||
# Full dynamic range: 400MHz to 4.2GHz
|
||||
set_power_limit 15 long
|
||||
set_power_limit 25 short
|
||||
# Set platform profile to balanced for dynamic scaling
|
||||
if [ -w "/sys/firmware/acpi/platform_profile" ]; then
|
||||
echo "balanced" > /sys/firmware/acpi/platform_profile 2>/dev/null
|
||||
echo -e "${BLUE}Platform profile: balanced${NC}"
|
||||
fi
|
||||
# Allow full range 0-100%
|
||||
if [ -w "/sys/devices/system/cpu/intel_pstate/min_perf_pct" ]; then
|
||||
echo 0 > /sys/devices/system/cpu/intel_pstate/min_perf_pct
|
||||
echo -e "${BLUE}CPU Performance: 0% - 100% (400MHz - 4.2GHz)${NC}"
|
||||
fi
|
||||
# Set governor to powersave for dynamic scaling
|
||||
for gov in /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor; do
|
||||
echo "powersave" > $gov 2>/dev/null
|
||||
done
|
||||
# Set energy preference to balance_performance
|
||||
for epp in /sys/devices/system/cpu/cpu*/cpufreq/energy_performance_preference; do
|
||||
echo "balance_performance" > $epp 2>/dev/null
|
||||
done
|
||||
echo -e "${GREEN}Applied dynamic scaling preset (recommended)${NC}"
|
||||
;;
|
||||
"max-performance")
|
||||
# Higher base but still allows boost: 1.6GHz to 4.2GHz
|
||||
set_power_limit 15 long
|
||||
set_power_limit 25 short
|
||||
# Set platform profile to performance
|
||||
if [ -w "/sys/firmware/acpi/platform_profile" ]; then
|
||||
echo "performance" > /sys/firmware/acpi/platform_profile 2>/dev/null
|
||||
echo -e "${BLUE}Platform profile: performance${NC}"
|
||||
fi
|
||||
# Set minimum to base frequency (38% = 1.6GHz)
|
||||
if [ -w "/sys/devices/system/cpu/intel_pstate/min_perf_pct" ]; then
|
||||
echo 38 > /sys/devices/system/cpu/intel_pstate/min_perf_pct
|
||||
echo -e "${BLUE}CPU Performance: 38% - 100% (1.6GHz - 4.2GHz)${NC}"
|
||||
fi
|
||||
# Set governor to powersave (still allows turbo with intel_pstate)
|
||||
for gov in /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor; do
|
||||
echo "powersave" > $gov 2>/dev/null
|
||||
done
|
||||
# Set energy preference to performance
|
||||
for epp in /sys/devices/system/cpu/cpu*/cpufreq/energy_performance_preference; do
|
||||
echo "performance" > $epp 2>/dev/null
|
||||
done
|
||||
echo -e "${GREEN}Applied maximum performance preset${NC}"
|
||||
;;
|
||||
"balanced")
|
||||
set_power_limit 10 long
|
||||
set_power_limit 15 short
|
||||
# Set platform profile to balanced
|
||||
if [ -w "/sys/firmware/acpi/platform_profile" ]; then
|
||||
echo "balanced" > /sys/firmware/acpi/platform_profile 2>/dev/null
|
||||
echo -e "${BLUE}Platform profile: balanced${NC}"
|
||||
fi
|
||||
# Allow dynamic scaling 0-52% (400MHz - 2.2GHz)
|
||||
if [ -w "/sys/devices/system/cpu/intel_pstate/min_perf_pct" ]; then
|
||||
echo 0 > /sys/devices/system/cpu/intel_pstate/min_perf_pct
|
||||
echo -e "${BLUE}CPU Performance: 0% - 52% (400MHz - 2.2GHz)${NC}"
|
||||
fi
|
||||
if [ -w "/sys/devices/system/cpu/intel_pstate/max_perf_pct" ]; then
|
||||
echo 52 > /sys/devices/system/cpu/intel_pstate/max_perf_pct
|
||||
fi
|
||||
# Set max frequency to 2.2 GHz
|
||||
for freq in /sys/devices/system/cpu/cpu*/cpufreq/scaling_max_freq; do
|
||||
echo 2200000 > $freq 2>/dev/null
|
||||
done
|
||||
# Set governor to powersave
|
||||
for gov in /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor; do
|
||||
echo "powersave" > $gov 2>/dev/null
|
||||
done
|
||||
# Set energy preference to balance_power
|
||||
for epp in /sys/devices/system/cpu/cpu*/cpufreq/energy_performance_preference; do
|
||||
echo "balance_power" > $epp 2>/dev/null
|
||||
done
|
||||
echo -e "${GREEN}Applied balanced preset (battery friendly)${NC}"
|
||||
;;
|
||||
"power-save")
|
||||
set_power_limit 8 long
|
||||
set_power_limit 12 short
|
||||
# Set platform profile to low-power
|
||||
if [ -w "/sys/firmware/acpi/platform_profile" ]; then
|
||||
echo "low-power" > /sys/firmware/acpi/platform_profile 2>/dev/null
|
||||
echo -e "${BLUE}Platform profile: low-power${NC}"
|
||||
fi
|
||||
# Limit to 50% max performance
|
||||
if [ -w "/sys/devices/system/cpu/intel_pstate/min_perf_pct" ]; then
|
||||
echo 0 > /sys/devices/system/cpu/intel_pstate/min_perf_pct
|
||||
echo -e "${BLUE}CPU Performance: 0% - 50% (800MHz - 2.0GHz)${NC}"
|
||||
fi
|
||||
if [ -w "/sys/devices/system/cpu/intel_pstate/max_perf_pct" ]; then
|
||||
echo 50 > /sys/devices/system/cpu/intel_pstate/max_perf_pct
|
||||
fi
|
||||
# Set energy preference to power
|
||||
for epp in /sys/devices/system/cpu/cpu*/cpufreq/energy_performance_preference; do
|
||||
echo "power" > $epp 2>/dev/null
|
||||
done
|
||||
echo -e "${GREEN}Applied power-saving preset${NC}"
|
||||
;;
|
||||
"ultra-save")
|
||||
set_power_limit 6 long
|
||||
set_power_limit 8 short
|
||||
# Set platform profile to low-power
|
||||
if [ -w "/sys/firmware/acpi/platform_profile" ]; then
|
||||
echo "low-power" > /sys/firmware/acpi/platform_profile 2>/dev/null
|
||||
echo -e "${BLUE}Platform profile: low-power${NC}"
|
||||
fi
|
||||
# Limit to base frequency (38% = 1.6GHz max)
|
||||
if [ -w "/sys/devices/system/cpu/intel_pstate/min_perf_pct" ]; then
|
||||
echo 0 > /sys/devices/system/cpu/intel_pstate/min_perf_pct
|
||||
echo -e "${BLUE}CPU Performance: 0% - 38% (800MHz - 1.6GHz)${NC}"
|
||||
fi
|
||||
if [ -w "/sys/devices/system/cpu/intel_pstate/max_perf_pct" ]; then
|
||||
echo 38 > /sys/devices/system/cpu/intel_pstate/max_perf_pct
|
||||
fi
|
||||
# Set energy preference to power
|
||||
for epp in /sys/devices/system/cpu/cpu*/cpufreq/energy_performance_preference; do
|
||||
echo "power" > $epp 2>/dev/null
|
||||
done
|
||||
echo -e "${GREEN}Applied ultra power-saving preset${NC}"
|
||||
;;
|
||||
*)
|
||||
echo -e "${RED}Error: Unknown preset '$preset'${NC}"
|
||||
echo "Available presets: dynamic, max-performance, balanced, power-save, ultra-save"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
# Main script logic
|
||||
case "$1" in
|
||||
"status")
|
||||
check_rapl_support
|
||||
show_status
|
||||
;;
|
||||
"set")
|
||||
check_permissions
|
||||
check_rapl_support
|
||||
set_power_limit "$2" "both"
|
||||
;;
|
||||
"set-long")
|
||||
check_permissions
|
||||
check_rapl_support
|
||||
set_power_limit "$2" "long"
|
||||
;;
|
||||
"set-short")
|
||||
check_permissions
|
||||
check_rapl_support
|
||||
set_power_limit "$2" "short"
|
||||
;;
|
||||
"preset")
|
||||
check_permissions
|
||||
check_rapl_support
|
||||
apply_preset "$2"
|
||||
;;
|
||||
*)
|
||||
print_usage
|
||||
;;
|
||||
esac
|
||||
61
scripts/monitor-cpu-freq.sh
Executable file
61
scripts/monitor-cpu-freq.sh
Executable file
@@ -0,0 +1,61 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Real-time CPU Frequency Monitor
|
||||
# Shows actual CPU frequencies and helps identify boost behavior
|
||||
|
||||
echo "=== Real-time CPU Frequency Monitor ==="
|
||||
echo "Press Ctrl+C to stop"
|
||||
echo ""
|
||||
echo "Note: Modern Intel CPUs dynamically adjust frequency based on:"
|
||||
echo " - Workload type (single vs multi-core)"
|
||||
echo " - Power limits (TDP)"
|
||||
echo " - Temperature"
|
||||
echo " - Energy efficiency preferences"
|
||||
echo ""
|
||||
|
||||
# Check if turbostat is available
|
||||
if command -v turbostat >/dev/null 2>&1; then
|
||||
echo "Using turbostat for accurate frequency monitoring..."
|
||||
echo ""
|
||||
sudo turbostat --quiet --show Core,CPU,Busy%,Bzy_MHz,PkgWatt --interval 2
|
||||
else
|
||||
echo "turbostat not available, using basic monitoring..."
|
||||
echo ""
|
||||
echo "Timestamp | CPU0 CPU1 CPU2 CPU3 | Avg MHz | Governor | Temp"
|
||||
echo "----------------+---------------------------------+---------+-----------+------"
|
||||
|
||||
while true; do
|
||||
TIMESTAMP=$(date +"%H:%M:%S")
|
||||
|
||||
# Get frequencies
|
||||
FREQ0=$(cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_cur_freq)
|
||||
FREQ1=$(cat /sys/devices/system/cpu/cpu1/cpufreq/scaling_cur_freq)
|
||||
FREQ2=$(cat /sys/devices/system/cpu/cpu2/cpufreq/scaling_cur_freq)
|
||||
FREQ3=$(cat /sys/devices/system/cpu/cpu3/cpufreq/scaling_cur_freq)
|
||||
|
||||
# Convert to MHz
|
||||
F0=$((FREQ0 / 1000))
|
||||
F1=$((FREQ1 / 1000))
|
||||
F2=$((FREQ2 / 1000))
|
||||
F3=$((FREQ3 / 1000))
|
||||
|
||||
# Calculate average
|
||||
AVG=$(( (F0 + F1 + F2 + F3) / 4 ))
|
||||
|
||||
# Get governor
|
||||
GOV=$(cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor)
|
||||
|
||||
# Get temperature if available
|
||||
if [ -r "/sys/class/thermal/thermal_zone0/temp" ]; then
|
||||
TEMP_RAW=$(cat /sys/class/thermal/thermal_zone0/temp)
|
||||
TEMP=$((TEMP_RAW / 1000))
|
||||
else
|
||||
TEMP="N/A"
|
||||
fi
|
||||
|
||||
printf "%s | %4d %4d %4d %4d | %4d MHz | %-9s | %s°C\n" \
|
||||
"$TIMESTAMP" "$F0" "$F1" "$F2" "$F3" "$AVG" "$GOV" "$TEMP"
|
||||
|
||||
sleep 2
|
||||
done
|
||||
fi
|
||||
29
scripts/test-single-core-boost.sh
Executable file
29
scripts/test-single-core-boost.sh
Executable file
@@ -0,0 +1,29 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Single Core Boost Test Script
|
||||
# Forces maximum single-core performance to reach peak boost frequencies
|
||||
|
||||
echo "Testing single-core boost capability..."
|
||||
echo "Current base frequency: $(cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_cur_freq | awk '{print $1/1000}') MHz"
|
||||
|
||||
# Disable cores 1-7 temporarily to force single-core boost
|
||||
for cpu in {1..7}; do
|
||||
echo 0 | sudo tee /sys/devices/system/cpu/cpu${cpu}/online > /dev/null 2>&1
|
||||
done
|
||||
|
||||
echo "Cores 1-7 disabled, testing single-core boost..."
|
||||
|
||||
# Run intensive single-core workload
|
||||
timeout 5s bash -c 'while true; do echo "scale=5000; 4*a(1)" | bc -l > /dev/null 2>&1; done' &
|
||||
|
||||
sleep 2
|
||||
echo "Peak frequency during single-core load: $(cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_cur_freq | awk '{print $1/1000}') MHz"
|
||||
|
||||
# Re-enable all cores
|
||||
for cpu in {1..7}; do
|
||||
echo 1 | sudo tee /sys/devices/system/cpu/cpu${cpu}/online > /dev/null 2>&1
|
||||
done
|
||||
|
||||
wait
|
||||
echo "All cores re-enabled"
|
||||
echo "Final frequency: $(cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_cur_freq | awk '{print $1/1000}') MHz"
|
||||
Reference in New Issue
Block a user