Undervolting: what and why?
Fan noise is always annoying. Even more so for those of us who use them in audio-related tasks, where it can interfere with the work we are trying to accomplish.
Some CPU families, normally high-end ones, are programmed to operate at what is considered a safe voltage level, but allow to be configured by the end user to work at even lower voltages.
This means the CPU consumes less power and dissipates less heat. Less heat means less need for fans to cool down the CPU so, besides the noise reduction, we get a second source of power saving.
By undervolting our CPU we achieve less power consumption, longer battery life and shorter bursts of fan noise.
We can combine this with other power-saving techniques like CPU frequency management or CPU throttling to achieve silent or near-silent operation under light CPU load conditions, depending on the environment temperature and the thermal features of our laptop.
However, there is a caveat: if we lower down too much the operation voltage the CPU may become unstable, which normally translates into a system freeze needing a hard reset of our computer.
I have been happily undervolting my CPU through different kernels in the same computer for more than 4 years and I haven’t had any problems with it. But, if incorrectly used, undervolting can provoke computer freezes. So, once again:
Undervolting makes your CPU operate outside manufacturer specifications and can make your computer unstable: use at your own risk!
For the Linux world the Linux-PHC project provides a patch to the kernel module acpi-cpufreq that allows the user to adjust the operating voltage of his CPU via a /sys filesystem interface.
Since undervolting may provoke unstability I think it is extremely unlikely that PHC will ever be incorporated to the main kernel source or to any distribution official repositories. Therefore, we will usually have to resort to build and install it on our own.
Assuming our machine is running the kernel we intend to patch, the general procedure to get this nifty piece of software working is:
- Get the latest stable linux-phc version for our CPU architecture and kernel version.
- Get the appropriate acpi-cpufreq.c file for our CPU architecture and kernel version.
- Patch it with the PHC patch.
- Build a patched module for your kernel.
- Install the patched module.
- Unload the original module (if loaded) and load the patched one.
- Find the optimal operating voltage for every frequency of your CPU by trial-and-error.
- Load your voltage table on startup.
For Ubuntu users: recent versions of the Ubuntu kernel don’t build acpi-cpufreq as a module, but integrate it in the monolithic bunch loaded at boot time :-/. Therefore, this procedure won’t work there: you will have to either rebuild a full kernel (perhaps you can skip module building) or download a pre-compiled user-contributed version from this PPA. The good news in the latter case is that you don’t have to mess around with compilations if you just want the PHC addition. The bad news is that it will make it more difficult for you to combine PHC with other features, like the RT patch. You can find more information about this at the PHC website.
I will describe here the steps I follow for my particular audio-oriented setup:
- CPU: Intel Pentium-M 1.6 MHz.
- Distribution: Fedora Core 11.
- Kernel: 22.214.171.124-1.rt23.4.fc11.ccrma.i586.rt, a realtime enhanced kernel created by the fine people at PlanetCCRMA.
- PHC version: phc-intel-0.3.2-9.
The procedure I outline here should not be too different for other kernels or CPUs (AMD, multicore, etc.) Please, check out the PHC page if you need advice on this.
Get the latest stable linux-phc version for our CPU architecture and kernel version
The Linux-PHC patch is distributed as a tarball. At the PHC website we will find a “PHC Downloads” subforum and inside it a “Releases” thread. There are several versions there; we will download the one that best fits our CPU architecture and contains a patch for the kernel version we are using. Since I have an Intel CPU and intend to patch 2.6.29 and 2.6.30 kernels, the appropriate choice for me is phc-intel-0.3.2-9.tar.gz.
After downloading it we will unzip it in a folder of our choice. We will find its contents are:
- A collection of patches for different versions of the vanilla kernel.
- The unpatched version of the vanilla kernel acpi-cpufreq.c file so, if we are lucky and it wasn’t modified for the kernel version we use, we won’t need your full kernel sources, just the headers.
- Some build scripts to streamline the module compilation procedure.
Get the appropriate acpi-cpufreq.c file for our CPU architecture and kernel version
The PHC tarball bundles already the acpi-cpufreq.c file for a number of vanilla kernel versions, big emphasis in the “vanilla” qualifier. Few distributions bundle a pure vanilla kernel, as distributed by www.kernel.org: most of them modify different parts of it with a series of patches. If we are lucky these distribution-specific patches won’t include modifications to acpi-cpufreq.c, so we will be able to use the one provided by the PHC tarball.
To find out if we have been lucky or not, jump below to the following section, titled “Patch acpi-cpufreq.c with the PHC patch”. If you don’t get any error there you will probably be fine and can safely ignore the rest of this section. Otherwise, come back here and learn how to get hold of the proper version you need.
In my case I found out that I can use the bundled file with no problem for Fedora’s stock kernel 126.96.36.199-105.fc11.i586, but not for PlanetCCRMA’s realtime version 188.8.131.52-1.rt23.4.fc11.ccrma.i586.
For the latter, thus, I needed to get hold of the patched acpi-cpufreq.c for that kernel and hope that the corresponding PHC patch can be applied to it. The best way to do this is to install that kernel RPMS, bring it to the preparation stage and get the file from there.
To work with RPMS packages we need a series of tools, bundled within the aptly-named rpmdevtools package. So we will install it and its dependencies, and then execute the command:
This will create the subtree rpmbuild in our home directory.
Then we install the kernel RPMS with the following command:
rpm -i http://ccrma.stanford.edu/planetccrma/mirror/fedora/linux/planetcore/11/SRPMS/kernel-184.108.40.206-1.rt23.4.fc11.ccrma.src.rpm
This will deploy a bunch of files at rpmbuild/SOURCES and a spec file at rpmbuild/SPECS.
Now we launch the kernel RPM build process up to the ‘prepare’ stage, which will unzip the kernel tarball and apply all the patches at rpmbuild/BUILD.
rpmbuild -bp --target i686 ~/rpmbuild/SPECS/kernel.spec
We can now overwrite the vanilla acpi-cpufreq.c file bundled with the PHC tarball with the one found in our kernel sources. We go to the folder where we unzipped PHC and execute:
cp ~/rpmbuild/BUILD/kernel-2.6.29/linux-2.6.29.i686/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c inc/2.6.29/acpi-cpufreq.c
Patch acpi-cpufreq.c with the PHC patch
For this stop to work we need to install the package that provides our kernel headers. Since we want to build a module for the kernel provided by the kernel-rt package we will need to install kernel-rt-devel too. The patching script supplied by PHC is not too sophisticated, so if we forgot to install the headers it will stop at a certain point and we will have to terminate it with Ctrl+C. Other packages that we may need, if they are not already installed, are gcc, patch and make.
We launch the patching procedure from the folder where we unzipped the PHC tarball with the command:
This will locate the acpi-cpufreq.c best suited to our kernel version, rename it to linux-phc.c and patch it.
The patching procedure may succeed, perhaps warning about some “fuzz” (which shouldn’t be too worrying if the compilation goes well later on) or may fail. In the latter case you will have to review carefully the source/patch combination that it is being used and perhaps ask for help at the PHC message board.
Build a patched module for your kernel
This is where the real compilation takes place. We simply run:
If the build isn’t successful again we may not be using the proper acpi-cpufreq.c or the proper patch. Review the previous steps and, if in doubt, seek help at the PHC forum (be sure to search its contents before posting a question, you may not be the first person with that particular problem.)
Install the patched module
If the build was successful we must now install our new module. We need root permissions to do this, so we will have to use our preferred mechanism to acquire superuser powers (sudo, su…) The command to install it is:
This will copy phc-intel.ko to the appropriate place in /lib/modules. It will also copy the file phc-intel.modprobe as /etc/modprobe.d/phc-intel.conf, which will ensure that in future boot-ups the phc-intel module is loaded instead of acpi-cpufreq.
Unload the original module and load the patched one
Next, still as root, we unload the acpi-cpufreq module and load our new phc-intel:
If all has gone as expected, we will now be able to access all PHC-related information at a new set of files that will have appeared at /sys/devices/system/cpu/cpu0/cpufreq. These files start with the prefix “phc_”.
Find the optimal operating voltage for every frequency of your CPU by trial-and-error
To configure properly your CPU voltages you need to understand the concept of VIDs and FIDs. VID means voltage identifier and FID frequency identifier. Those numbers identify the multipliers that are allowed for your CPU voltage and frequency.
For my CPU, the following formulas apply, it may be different for yours:
F = FID * 133.3 MHz
V = 0.700 + VID * 0.016 V
We can see the available FIDs at /sys/devices/system/cpu/cpu0/cpufreq/phc_fids:
12 10 8 6
This means my CPU can run at 1600, 1333, 1066 and 800 MHz.
We can access the manufacturer configured voltages at /sys/devices/system/cpu/cpu0/cpufreq/phc_default_vids:
cat /sys/devices/system/cpu/cpu0/cpufreq/phc_default_vids 38 32 25 18
This means Intel guarantees the operation of my Pentium-M at the following combinations of frequency/voltage:
- 1600 MHz / 1.308 V
- 1333 MHz / 1.212 V
- 1066 MHz / 1.100 V
- 800 MHz / 0.988 V
To lower down our CPU voltages at each frequency we must write a full set of VIDs to the file /sys/devices/system/cpu/cpu0/cpufreq/phc_controls like this:
echo "12:14 10:8 8:3 6:0" > /sys/devices/system/cpu/cpu0/cpufreq/phc_controls
With this I am telling my CPU to operate at these combinations of frequency/voltage:
- 1600 MHz / 0.924 V
- 1333 MHz / 0.828 V
- 1066 MHz / 0.748 V
- 800 MHz / 0.700 V
These are the minimum voltages I found out my CPU can tolerate without becoming unstable. It doesn’t mean they work for any other CPU, even if it is the exact same model. At the PHC site some users have posted the values that work for them for a range of CPUs; we can use them as a guideline, but we must always look for our own.
To find out what voltages work for our particular CPU we must proceed by trial and error. First of all, make sure to set up your CPU to always operate at a fixed frequency. I use the cpufreq-set command from the cpufrequtils package, but there are other possibilities:
cpufreq-set -d 800000 -u 800000
Then gradually lower down the VID for that particular frequency until you find the lowest stable value. The fastest method should be proceeding by binary search, dividing the available voltage range in two, discarding one of the halves as too low or too high, dividing the remaining one in two, and so on.
Test the stability of that voltage with some CPU intensive program, like those which calculate prime numbers or the digits of pi. Let it “burn” your CPU for a couple of minutes. If your system freezes you will have to hard-reset it and try with a higher VID. If it doesn’t, try a lower one until you find the limit.
Repeating these steps for all our available frequencies will give us a list of minimal voltages, one for each frequency.
Load your voltage table on startup
The simplest way of ensuring the voltages we have found are loaded at boot time is to add a line like this to /etc/rc.local:
if [ -f /sys/devices/system/cpu/cpu0/cpufreq/phc_controls ]; then echo "12:14 10:8 8:3 6:0" > /sys/devices/system/cpu/cpu0/cpufreq/phc_controls fi
Learning to undervolt a CPU takes some time, but it is well worth the effort if you appreciate silence, low power consumption and extended battery life. It is both practical an environment-friendly. Give it a try!