Don't Panic

Undervolting your CPU on Debian

Posted in Debian, Linux by o0arthur0o on June 17, 2010

Revised (2011-01-14)

This post will show you how to undervolt your cpu(s) on Debian for fun and profit. Some benefits include longer battery life on laptops and quieter operation since the fans won’t need to kick in as often.

What you need…

  • Debian, or sys-v-init comptible OS like LMDE.
  • A compatible CPU # The linux-phc wiki has some useful information.
  • Kernel headers and build tools # On Debian you can install ‘build-essentials’ and then appropriate headers ‘aptitude search headers | grep $(uname -r)’
  • The acpi-cpufreq module (or amd equivilant) compiled as a module. # Debian stock kernels have this already.
  • The appropriate linux-phc package # Check the downloads page for one that corresponds to your kernel.

Alternatively…

  • Install the liquorix kernel, which comes pre-patched for undervolting.

Setting up Linux-PHC with Stock or Custom Kernel

If you’re running the liquorix kernel you can skip to the next section.

Extract the downloaded linux-phc package and in a terminal, from the extracted directory, run ‘make prepare’ and then ‘make’. Assuming there are no errors you’ll have something called ‘intel-phc.ko’ or the amd equivilant. Locate your current acpi-cpufreq.ko file by using something like ‘find’ or ‘locate’. Unload the current acpi-cpufreq module, and then move it out of the way. The following few lines of code should work well, or at least point you in the right direction:

$ cd /lib/modules/$(uname -r)/kernel/arch/x86/kernel/cpu/cpufreq
$ rmmod acpi-cpufreq
$ mv acpi-cpufreq.ko orig.acpi-cpufreq.ko.disabled

Now we need to move the intel-phc.ko file to your current location, but rename it to acpi-cpufreq.ko. If you happened to have built the module in /home/your_username/phc/, then it would be something like this:

$ mv /home/your_username/phc/intel-phc.ko /lib/modules/$(uname -r)/kernel/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.ko

Now it’s time to see if it all worked. Reload the acpi-cpufreq module, and if it works you should see some new and interesting files under ‘/sys/devices/system/cpu/cpu0/cpufreq/’, like phc_vids and other various phc related files.

$ modprobe acpi-cpufreq
$/etc/init.d/cpufrequtils reload

Choosing some custom VIDs

First, check out what your defaults are. Also, notice that the current VID’s are the same as the default VID’s. The files in question are under ‘/sys/devices/system/cpu/cpu[N]/cpufreq/

$ cat phc_vids
     45 37 23 15

$ cat phc_default_vids
     45 37 23 15

Each of those numbers corresponds to one of the available frequency steps of my CPU. At the highest frequency, 1600Mhz a VID value of 45 is applied by default. At the lowest frequency, 800Mhz, a VID value of 15 is provided. Undervolting means we’re going to replace those numbers with lower values of our own choosing. The question is, which values to apply?

Depending on your CPU, you might be somewhat restricted in terms of what you can choose. For example, atom processors are hard-wired to draw a fixed amount. The VIDs are simply ignored. On my Intel Core 2 Duo an absolute minimum is hard-wired in, and any attempts to go below it will be interpreted as some kind of hardware failure, causing the CPU to ignore the VID’s I try to apply. So if you try and apply values which are below some pre-defined hard-wired minimum, they’ll be ignored and it’ll be difficult to detect, but ultimately harmless. On the other hand, if you choose valid VID’s but that are too low for the demand then you’ll experience more significant problems: Lockups, freezes, data corruption, etc. So again, which values to choose?

You can try searching the phc forums, or forums on your distribution. It’s possible someone with the same CPU has already found some sane values. Or you can simply experiment. I never go below the deault minimum, which in my case is 15. Beyond that, I know the minimum won’t work for the highest frequency so I usually go about five higher to start. So, in my case I’ll be trying ’21 17 15 15′.

Applying the chosen VIDs

Ultimately we want our custom VIDs applied at every boot, and after resuming from suspend or hibernation, but first let’s just apply them manually until we’re sure we have some sane values.

echo "21 17 15 15" > /sys/devices/system/cpu/cpu0/cpufreq/phc_vids
echo "21 17 15 15" > /sys/devices/system/cpu/cpu1/cpufreq/phc_vids

The first thing to note is that yes, we have to do this for every CPU on the system. Intel CPUs at least have some protection built-in whereby if one is drawing lower VIDs than another it assumes some kind of hardware error has occurred and will just draw the default on all CPUs. Again, this is a difficult error to detect, so be sure you’ve applied the correct values to all CPUs/Cores.

At this point I’d recommend you stress the system and monitor for errors. cpuburn is one option for this. Alternatively, you can decode a DVD and compile a kernel and see if the system locks up. Or just use the system normally and if you have problems, think about raising your VIDs.

Applying chosen VIDs at boot time

So now you’ve got the module being loaded at boot time correctly, and you’ve found some sane values that you’re happy with and want to have them automatically applied at every boot. How to do so? Apply them via an initscript. This script is very simple, and perhaps it will be improved over time, but it works just fine and is very easy to understand.


#! /bin/sh 
### BEGIN INIT INFO 
# Provides:          phc
# Required-Start:    $acpi 
# Required-Stop: 
# Default-Start:     2 3 4 5 
# Default-Stop: 
# Short-Description: linux-phc 
# Description:       linux-phc patched acpi-cpufreq module to allow 
#                    custom vids (processor hardware control) 
### END INIT INFO 
NAME=phc 

case $1 in start) 
## Edit these next two lines ##
echo "21 17 15 15" > /sys/devices/system/cpu/cpu0/cpufreq/phc_vids
echo "21 17 15 15" > /sys/devices/system/cpu/cpu1/cpufreq/phc_vids

;; stop) 
# No-op 

;; restart)
# No-op

;; force-reload)
rmmod acpi-cpufreq
modprobe acpi-cpufreq 
## Edit these next two lines ##
echo "21 17 15 15" > /sys/devices/system/cpu/cpu0/cpufreq/phc_vids
echo "21 17 15 15" > /sys/devices/system/cpu/cpu1/cpufreq/phc_vids

;; status)
## This doesn't give real status. For that use the read_msr utility.
## Edit these next two lines ## 
cat /sys/devices/system/cpu/cpu0/cpufreq/phc_vids 
cat/sys/devices/system/cpu/cpu1/cpufreq/phc_vids 

;; *) echo "Usage: $NAME {start|stop|restart|force-reload} >&2 exit 3 
;; esac 
:

Edit the lines where it calls for it according to your needs. Create a new file called /etc/init.d/phc and paste the contents of the above into it, save and exit, then make the file executable.

chmod +x /etc/init.d/phc

Now we need to edit /etc/insserv.conf, because if we don’t explicitly tell the system not to apply custom vids until the acpi-cpufreq module is loaded the phc script may try to execute before the phc_vid file is created, resulting in errors. So we edit /etc/insserv.conf and add the following line:

# $acpi        cpufrequtils loadcpufreq

You can see that ‘cpufrequtils’ and ‘loadcpufreq’ are both names of scripts under /etc/init.d, and which provide the services and directories we need in order to apply custom vids. We gave these two scripts an alias called ‘$acpi’, and you may recall in the /etc/intit.d/phc script the line that says ‘# Required-Start:    $acpi’

Now we ask insserv to update the system and make arrangments to start the phc script at the appropriate time. To do that we just call ‘insserv’ from the command line as root.

Make sure values are applied after Suspend / Resume cycle

I found that after resuming from suspend and checking the status using ‘/etc/init.d/phc status’, often times only one cpu still had the correct (aka. my custom) vids applied. Which of course means neither of my CPUs have the correct value (see earlier for explanation). We need a little sleed hook to ensure the correct values are applied after resuming. With our init script this is quite simple

Create a new file under /usr/lib/pm-utils/sleep.d and call it something like ’93phc’. The name itself doesn’t matter so much, only the number. List the contents of the directory and make the number 1 less than any cpu type operations. For instance, I have a file called ’94cpufreq’, so I want my vids applied after that script has done its work upon waking up, thus 94-1 is 93phc. When going to sleed the scripts in this dir are executed from lowest number to highest, when resuming it’s the reverse. Copy and paste the following into that file:


#!/bin/sh
# Ensure any custom vids in /etc/init.d/phc are being applied
# after suspend / resume cycle .
"${PM_FUNCTIONS}"
[ -d /sys/devices/system/cpu/ ] || exit

$NA hibernate_cpuphc() 
    { /etc/init.d/phc stop }
thaw_cpuphc()
    { /etc/init.d/phc start }

case "$1" in suspend|hibernate) 
    hibernate_cpuphc ;; 
resume|thaw) 
    thaw_cpuphc ;; 
*) 
    exit $NA ;; 
esac

Make it executable as before

Getting Help

Hopefully everything above has worked for you, but if not there’s a few places you can go to get help with undervolting. The first is obviously the linux-phc forums. The developers maintain an active presence on the board, though you should be patient as it can take up to a week sometimes before getting your question answered. You can also try getting help on their IRC channel, which is #linux-phc on freenode.net. Any questions or comments that you have about this post should be directed to the corresponding support thread on the Debian Forums.

Tagged with: , ,

Comments Off on Undervolting your CPU on Debian

Follow

Get every new post delivered to your Inbox.