Nehalem CPU Power State

Recently I re-installed Arch Linux after a several year hiatus. One of the hiccups in coming back was that I'm no longer running the latest and greatest hardware. My CPU (Nehalem) is power managed with the acpi_cpufreq module while the latest and greatest processors are using a new p-states based driver. It seems like the defaults for acpi_cpufreq are not what they were several years ago! Previously, acpi_cpufreq loaded several frequency governors; on the latest install only two governors were available, ondemand and performance. For temperature & noise reasons it is also nice to run the powersave governor. Additionally, according to nearly every resource on the web, it should be possible to quickly change governors with cpupower -c all frequency-set -g $governor. Unfortunately, this was not working on my old hardware. This post describes how to get powersave back and get around the inability of cpupower to change the governor.

Loading the powersave module

By default, this installation only provided the ondemand and performance governors. In order to set the governor to powersave, the cpufreq_powersave module needed to load on boot. This was trivial to do by creating /etc/modules-load.d/cpufreq_powersave.conf and adding the single line:

cpufreq_powersave  

lsmod verifies the modules load on boot.

Change file permissions on boot

In order for a non-root user to alter the cpufrequency governor the permissions on /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor need to be changed. Ideally this happens automatically on boot. The following systemd service changes the file permissions on all of the scaling_governor files to 646 which allows the owner (root) and all others (nonroot) to have rw permission.

Save the the unit as /usr/lib/systemd/system/scaling_governor.service and run systemctl enable scaling_governor.service.

[Unit]
Description=Allow non root to set scaling_governor

[Service]
Type=oneshot  
EnvironmentFile=/etc/default/cpupower  
ExecStart=/usr/bin/chmod 646 /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor  
RemainAfterExit=yes

[Install]
WantedBy=multi-user.target  

Toggling script

With the cpufreq_powersave module loaded and rw permissions on all of the scaling_governors, it's possible to quickly change the governor with a bash one-liner

echo $governor | tee /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor > /dev/null  

The cpu* makes the change on all cores of the processor

I would like to change the governor very quickly with a single hotkey so the following script toggles the governor every time it runs from powersave -> ondemand -> performance. I'm running in an i3/dunst environment, so notify-send is used to popup a small notification that the governor has changed.

#!/bin/bash

# Toggle through powersave/ondemand/performance governors
current=`cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor`

case $current in  
    'powersave')
        echo ondemand | tee /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor > /dev/null
        notify-send "CPU FREQUENCY" "ondemand set"
        ;;
    'ondemand')
        echo performance | tee /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor > /dev/null
        notify-send "CPU FREQUENCY" "performance set"
        ;;
    'performance')
        echo powersave | tee /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor > /dev/null
        notify-send "CPU FREQUENCY" "powersave set"
        ;;
esac  
# vim:set ts=2 sw=2 ft=sh et:

In .config/i3/config the script is tied to F8 with the following line:

bindcode 74 exec /path/to/script/toggle_governor  

Verify everything is working

Running cpupower frequency-info will display the active governor. Alternatively, it's possible to watch the frequency in something like i7z; if the governor is set to performance the frequencies should be near the maximum state of the processor.


Was this information useful? Consider using my Amazon Affilliate URL as a way of saying thanks. I'll receive a small portion of your purchases made within the next 24 hours.