356 lines
14 KiB
Bash
356 lines
14 KiB
Bash
#!/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 |