Cpu frequency scaling using the kernel or powernowd 

AUTHOR: Ken Moffat <ken@kenmoffat.uklinux.net> DATE: 2005-06-15 LICENSE: MIT License

http://www.linuxfromscratch.org/hints/downloads/files/cpufreq.txt

DESCRIPTION: With processors that support it (e.g. recent athlon64, many laptop processors), you can reduce the processor frequency, to reduce wasted energy or conserve battery power.

PREREQUISITES: 2.6.9 or later kernel, the bootscripts target LFS-6.1

Overview 

Frequency scaling is an important part of increasing the battery life of notebooks, but it also has a place in reducing power consumption, and thus waste heat, on desktops and servers. Most CPUs that support it will have at least two valid frequency/voltage settings, e.g. my athlon64 Winchester 3200 (2.0 GHz) can run at approx 1.0 GHz, 1.8 GHz, and 2.0 GHz. Give the ondemand governor a heavy load and the speed quickly ramps up. After the load has fallen back, the speed will first fall to 1.8 GHz and then some seconds later to 1.0 GHz.

The kernel began by offering 'powersave' (slow) and 'performance' (fast) drivers, with a 'userspace' alternative to allow a daemon to dynamically change the frequency. As of 2.6.9, an 'ondemand' driver was made available. Other demand-based governors, such as 'conservative', have been introduced in later kernels.

Meanwhile, the powernowd daemon was developed, see http://www.deater.net/john/powernowd.html - this will dynamically change the frequency as the load goes up and down.

It would seem that the 'ondemand' driver makes powernowd redundant, but some CPUs (like the ppc 7447) apparently have a very high transition latency which causes the ondemand governor to decline to manage them - on my 7447A the powersave and performance drivers ('governors') work, but trying to install 'ondemand' fails. Equally, on a laptop powernowd will probably be a little quicker at dropping the speed, and can therefore give a little more battery life.

On x86 and x86_64 it appears that your bios has to support frequency scaling (typically labelled Cool'n'Quiet on boards with AMD CPUs) - after upgrading to a new mobo/cpu, I lost the ability to use both the 'ondemand' governor and powernowd until I configured the bios properly.

Kernel Configuration 

On the Processor menu, select CPU Frequency scaling

Set the Default CPUFreq governor to userspace (the default is often 'performance')

Select the governors you wish to use, typically 'performance', 'powersave', and try 'ondemand'. Feel free to select any other available governors. I assume most people will want to build these governors in, rather than compiling them as modules.

Select the correct cpu-freq hardware driver (on a mac there is nothing further to select, on x86, choose from POWERNOW_K7, POWERNOW_K8, SPEEDSTEP_CENTRINO, and similar options).

Testing 

After you've booted the new kernel, you can test which of the kernel governors work. As root, echo the governor name to /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor - presumably, people with SMP boxes need to try this for each CPU. Then test the status of the command, e.g. with 'echo $?' - if the governor loaded, the status will be 0 and you can use that governor, otherwise the status will be 1.

You can view the current CPU frequency in /proc/cpuinfo. To test the ondemand or other variable-speed governors, run something "expensive" (e.g. untar the gcc .bz2, or do a big compile) and repeatedly check the spead in the cpuinfo file. You should find that it ramps up shortly after the load starts, and falls back a few seconds after the load drops. [ BUT, if you are in an xterm on a kernel > 2.6.12-rc5, see the ignore_nice line in my bootscript below. ]

Bootscript for kernel cpufreq 

If one or more of the demand-based governors works for you, you're almost done, you just need to ensure the appropriate governor is loaded after you boot. For my desktop box (athlon64) I use the following :

cat >>/etc/rc.d/init.d/cpufreq << EOF
#!/bin/sh

. /etc/sysconfig/rc
. ${rc_functions}

case "${1}" in
        start|demand)
                boot_mesg "Enabling ondemand cpu frequency"
                echo ondemand \
                >/sys/devices/system/cpu/cpu0/cpufreq/scaling_governor
                boot_mesg "ignoring niceness for ondemand"
                echo 1 \
                >/sys/boot/devices/system/cpu0/cpufreq/ondemand/ignore_nice
                ;;
        powersave)
                boot_mesg "Enabling powersave cpu frequency"
                echo powersave \
                >/sys/devices/system/cpu/cpu0/cpufreq/scaling_governor
                ;;
        performance)
                boot_mesg "Enabling performance cpu frequency"
                echo performance \
                >/sys/devices/system/cpu/cpu0/cpufreq/scaling_governor
                ;;
        *)
                echo "Usage: ${0} {start|demand|powersave|performance}"
                exit 1
                ;;
esac
EOF

chmod 754 /etc/rc.d/init.d/cpufreq

ln -s ../init.d/cpufreq /etc/rc.d/rcsysinit.d/S45cpufreq

Note that this allows me to set powersave or performance if I ever wish to, and that I just install this in rcsysinit.d so there is no 'stop' option.

The 'ignore_nice' ensures the old behaviour of ondemand for kernels newer than 2.6.12-rc5 : without this, anything I start in an xterm has a niceness of 10 and the kernel doesn't allow it to influence the cpu frequency.

Powernowd 

This is based on 0.96. Untar it, you'll notice the Makefile is described as -very- simple. Unfortunately, it installs into /usr/sbin - on a laptop, you probably want to bring it up as part of the boot process, so I think it belongs in /sbin. The easy way to do that is

make && install -m 755 powernowd /sbin

There is an example powernowd.init in the package, which could be adapted for the bootscript, using variations of "dyn" (dynamic), "low", "high" - I go with something a little simple - dynamic frequency control at all times:

Bootscript for powernowd 

cat >>/etc/rc.d/init.d/powernowd << EOF
#!/bin/sh

. /etc/sysconfig/rc
. ${rc_functions}

case "${1}" in
        start)
                boot_mesg "Starting powernowd"
                loadproc /sbin/powernowd
                ;;
        status)
                boot_mesg "Starting powernowd"
                statusproc /sbin/powernowd
                ;;
        stop)
                boot_mesg "Starting powernowd"
                killproc /sbin/powernowd
                ;;
        *)
                echo "Usage: ${0} {start|status|stop}"
                exit 1
                ;;
esac
EOF

chmod 754 /etc/rc.d/init.d/powernowd

ln -s ../init.d/powernowd /etc/rc.d/rcsysinit.d/S45powernowd
ln -s ../init.d/powernowd /etc/rc.d/rc0.d/K45powernowd
ln -s ../init.d/powernowd /etc/rc.d/rc6.d/K45powernowd

ACKNOWLEDGEMENTS: 

Barry Shilliday for bringing the scaling_governors to my attention in an article in PC Plus magazine.

Eric Piel for explaining how to restore the old behaviour for the ondemand governor.

CHANGELOG: 

2005-07-12 First version.

Updated versions of this hint may be found at http://www.kenmoffat.uklinux.net/hints/

documented on: 2005.09.12