#!/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 Set both long and short term limits" echo " set-long Set long term limit only" echo " set-short Set short term limit only" echo " preset 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