Table of Contents

Undervolting


Undervolting is an old technic that consist in lowering the CPU voltage. Few explanations : Current CPU can use speedstep technology to adjust their frequency to the need. For each frequency step, there is a corresponding voltage. The first thing to do if you want to reduce consumption is to reduce frequency, but you lose performances. However, there is a trick to reduce power consumption without impacting performances: undervolting. You will manually change the voltage for each frequency step. In fact, the CPU are natively overvolted, and depending of the quality of your CPU, you can lower these voltage with a good margin.

Introduction

Example

I have a laptop with a Core 2 T9550.

The native voltage are 1.050V-1.212V for 35W energy consumption at full load. Using undervolting, I can use a new range : 0.9V-1.0V. Because dissipation is function of the square of voltage, you can assume that at full power, the 35W will be reduced to: 1.0*1.0*35/(1.212*1.212) = 24W. My CPU goes from 85c to 60c, which is not perfect but much better. I also gain battery life and noise level.

Undervolting

How to achieve this ?

Two ways :

More information here : Intel 64 and IA-32 Architectures Software Developer s Manual Volume (3A, 3B & 3C) System Programming Guide In the June 2013 version, the MSRs are defined in chapter 35, see table 35-2, IA32_PERF_STATUS (MSR 0x198) and IA32_PERF_CTL (MSR 0x199).

Why undervolting ?

To increase your CPU energetic efficiency. By reducing the voltage, you do not impact performances, but of course you reduce the power consumed by the CPU. This means less electricity consumption, less heat dissipated (less noise and more battery for laptop), and higher life durability for the CPU.

Why does manufacturer do not undervolt the CPU ?

Good question. I have no direct answers. If you respect a good margin reducing the Vcore but not too much, the CPU is perfectly stable, but it depends on each CPU in each category. Too much fluctuations to bother with, maybe this is why the Vcore is so high by default.

I will only expose here the ways to undervolt using software approach (if you prefer the BIOS way, see the motherboard manual), which means it is only useful for Core 2 and previous CPU generations. Be extremely careful, do this only if you have knowledge. Im am not responsible for any damage you may encounter.

Few Core 2 notions

Vcore is the CPU voltage Frequency is the CPU frequency VID is an integer number in the MSR table. Intel do not give information on this, but the assumed relation is :

Vcore = 800 mV + VID*12.5 mV

FID is the same has VID, but for frequency. It is the multiplicator for the reference clock.

On Microsoft Windows

Best way is to use rmClock (RightMark CPU Clock Utility). This well know tool can be used on Windows XP x86 (do not know for x64), Windows Vista x86/x64, Windows 7 x86/x64, Windows 8 x86/x64. It can be used to force CPU du underclock or/and to undervolt.

Note that to use it on x64 systems, you need a signed x64 driver. I provide it here : MMIIISSSIIINNGGG

Note : before going any further, never ask RMclock to start automatically at Windows start up before you find all the stable voltage. If you choose a wrong voltage, you will be glad to be able to change it before RMClock activate.

Now, it is simple. In Advanced CPU settings, Choose CPY type, Desktop or Mobile. Then relaunch RMClock, and go in Profiles. Here, you can choose all Profiles, and choose which FID and VID (here, it's Vcore, bad name) to choose. I suggest you start with the more powerful step, and reduce by iterations the voltage by 50mV at each step. After reducing the voltage, test the stability using a stress tool (intelBurnTest for example). If you get a BSOD, then you went too low, choose more. If it works, try to lower more. When you reach the limit, add 50mv for stability and stay there. Then work on the other frequency step. When all steps are done, you can activate RMClock at Windows startup.

Last thing : when watching a film, or playing some games, you can force the CPU to stay at a designed level, to reduce noise or temperature (for example, when playing Age Of Empire 2 on my Core 2, I block the CPU to 1.6Ghz, which is much more than needed, and the laptop do not heat too much. Same with a film, 800mhz for non HD films is sufficient).

On linux 2.6

It's a little trickier if you do it yourself, so I recommend using c2ctl, which is a perfect open source tool. It allows you to change FID and VID from the MSR table.

The c2ctl home page is http://www.ztex.de/misc/c2ctl.e.html. In case the tool is no more available, you can find here a copy : c2ctl.tar.bz2. I suppose you are using an ubuntu (debian based) system, but this tool can be used on all system if you have the msr kernel module.

First, install the tools. Go root:

sudo su

Then, install the msr kernel module and its tools:

apt-get install msr-tools
modprobe msr

Now you can use c2ctl. Use the static binary, or build it yourself. For reference, my test system was :

cat /proc/cpuinfo
[...]
model name : Intel(R) Core(TM)2 Duo CPU E8500 @ 3.16GHz
stepping : 10
microcode : 0xa07
cpu MHz : 2000.000
cache size : 6144 KB
[...]
uname -a
Linux Volt 3.8.0-19-generic #30-Ubuntu SMP Wed May 1 16:35:23 UTC 2013 x86_64 x86_64 x86_64 GNU/Linux

To display current FID/VID couple and the min/max values by default, use (0-1 for dual core CPU, 0-3 for quad core, etc) :

./c2ctl 0-1
CPU0
Current Target Min. Max.
FID: 6 6 6 73
VID: 22 22 22 38
ESIT_ENABLE = TRUE ESIT_LOCK = TRUE

CPU1
Current Target Min. Max.
FID: 6 6 6 73
VID: 22 22 22 38
ESIT_ENABLE = TRUE ESIT_LOCK = TRUE

You can also use msr tools to display such information : rdmsr to read, wrmsr to write.

rdmsr 0x199; rdmsr 0x198
616
616492606000616

Or you can use this script (not from me) :

for MSR in 198 199 1A0; do for CPU in `sed -rn 's@^processor[\t]: ([0-9]+)$@\1@p' /proc/cpuinfo`; do echo -n "CPU${CPU} ${MSR}: "; sudo rdmsr -0 -X -p ${CPU} 0x${MSR}; done; done

Has you can see, the max performance couple is 73/38. Using the previous formula, we have: UCpu = 800 mV + VID*12.5 mV = 1275 mV. Let's do a performance check:

sysbench --num-threads=2 --test=cpu --cpu-max-prime=40000 run

Total time of the test: 26.44s Power consumption of computer at power socket on the wall: 75W-77W-79W-78W

OK, now lets reduce VID for the same FID, I choose 73/30, but I could go bellow 30, this is just for the test. UCpu = 800 mV + VID*12.5 mV = 1175 mV.

sysbench --num-threads=2 --test=cpu --cpu-max-prime=40000 run

Total time of the test: 26.42s Power consumption of computer at power socket on the wall: 68W-69W-70W-69W

Let's check the formula: 78W * 1.175 * 1.175 / (1.275 * 1.275) = 66W. Not that far from our resulting measures, considering there is we measure here all the computer components.

We gained 10W, i.e. 12.5% of power consumption for all the computer, without impacting performances. And the 73/30 couple was not the ideal one, you can go below (I was lazy to test the best value. If you test 73/20, kernel panic, so this is between 73/30 and 73/20).

Note that the system will automatically overwrite your settings few milliseconds after you wrote yours on the MSR table; you have to refresh your values. A simple way to achieve this is to use a bash loop. (This effect also occur with RmClock, the Microsoft Windows tool, you will see that sometime the system set full VID for few milliseconds. Some kind of competition between you and the onboard speedstep.)

Create a file :

vim resetmsr.sh
#!/bin/bash
for(( ; ; ))
do
   ./c2ctl 0-1 73 30
   sleep 0.1s
chmod +x resetmsr.sh

The good way is: try to find minimal VID for each VID. You often do not need to look too far, check for the maximum FID and for the minimum, then do 2 scripts, and use one to force lowest FID and VID when needed (Video watching, web browsing, office, etc), and another one for full power with maximum FID with its associated lowest VID (when compiling, calculating, rendering, etc).