Linux kernel undervolting patch for AMD processors

Tagged:

Simple patch for 2.6.27 Linux kernel to provide full control over voltages/frequencies of AMD CPUs supporting Cool’n’Quiet technology.

Update: patches for 2.6.31 and 2.6.32 are available too.

Update 2010/02/10: it was pointed out that Linux-PHC project currently provides patches for AMD (see comments for details), so I’d strongly recommend checking their patches first instead of mine.

Intro

When assembling my home server back in 2007 spring one of the key requirements was to support near-silent operation. The whole setup is beyond the scope of this article, but one of the tasks I had to solve was to lower the power CPU uses, so that I can use passive cooling.

Getting mobile CPU or CPU with reduced TDP was not an option due to their cost and unavailability, so I bought just normal AMD Sempron CPU with standard TDP, and reduced the voltages CPU runs at to decrease CPU power usage. It should be noted that the power CPU dissipates is squarely proportional to the voltage CPU uses, so even slight decrease in voltage might produce quite noticeable difference in power.

As the server was intended only for very modest use (= most of the time it runs idle) the other important requirement was that CPU supports frequency/voltage scaling (which AMD called PowerNow! first and then changed it to Cool’n’Quiet), so that CPU remains on its lowest frequency/voltage most of the time and starts to consume power only when load is sufficiently high.

However, at that time I was not able to find any reasonable solution that would allow me to perform the undervolting on Linux, especially considering I needed Cool’n’Quiet support, so voltages should be reduced not once and for fixed frequency, but the whole voltage table should be changed.

I’ve found Linux PHC project, which supported undervolting for Intel CPUs, but they did not have AMD support - they’ve claimed they have it working, but not ready for release yet.

To keep the story short: I took the patch from Linux PHC project for Intel CPUs and adapted it for powernow-k8 driver in Linux, which at that time was somewhere near 2.6.21 version, if I remember correctly. I expected it to be “temporary hack” only, until Linux PHC releases “proper” patch, so I haven’t published it at that time.

However, 1.5 years later, it seems there’s still no progress in the direction of AMD patch; besides that, for all previous kernel upgrades I’ve just copied the same patched powernow-k8.c/.h files over current kernel implementation (so, in fact downgrading powernow-k8 driver to the patched version of 2.6.21 kernel I had), but recently for 2.6.27 upgrade I’ve ported the patch to the new driver version - and, after doing that, decided that it might be useful to publish it - just in case anyone else has the same problem to solve

Disclaimer

Well, I hope you understand what you’re doing, if not - STOP NOW!

Also note that the patch was meant to be “temporary hack”, with all the consequences it has

Download

powernow-k8.c driver patch for undervolting support for linux-2.6.27 kernel series, 2.20.0 powernow-k8 driver version.

Installation

Just patch your kernel & recompile it.

Usage

Either pass modified voltages & frequencies list on kernel command line at boot or print it to the /sys/devices/system/cpu/cpu0/cpufreq/voltage_table control file on sysfs.

Examples for my setup are below:

  • Command line: powernow-k8.freq_list=1800000,1600000,800000 powernow-k8.vcore_list=1150,1000,900
  • sysfs: echo 1800000:1050,1600000:1000,800000:875 > /sys/devices/system/cpu/cpu0/cpufreq/voltage_table

Note that when you pass these options in kernel command line, you are not forced to use exactly the frequencies your CPU is initially designed for: for example, my AMD Sempron CPU is meant to work with frequencies 1.0 GHz and 1.8 GHz in Cool’n’Quiet mode, but I successfully use frequencies 0.8 GHz, 1.6 GHz and 1.8 GHz, which allows me to run it in idle mode at lower frequency and lower voltage than if I would use default 1.0 GHz frequency.

Note, however, that frequencies choice is not arbitrary: you’re advised to read AMD documentation to understand which frequencies can be specified and which cannot, particularly you should understand “high” and “low” states concept.

I’m not 100% sure (as quite some time passed since then), but if I remember correctly changing frequencies after powernow-k8 driver is initialized is not supported, as cpufreq has already initialized its own structures which depend on frequencies and will screw up if things are changed after initialization.

Tuning voltages

Finding optimal voltages may be quite tedious and long process. While not being expert, I recommend using similar practices as to what overclockers use to find optimal values: i.e. start with default values and then gradually change them in small steps, each time checking thoroughly your system for stability.

All voltages should be multiple of 0.025 V and lie in the range 0.8 V - 1.55 V, but of course you should also use your common sense and not try to apply 1.55 V at 0.8 GHz or 0.8 V at 2.6 GHz

Note that it might be a good idea to find first optimal voltages for every frequency separately by locking one particular frequency using /sys/devices/system/cpu/cpu0/cpufreq/* interface, and after voltages for all frequencies are known - test system in actual mode you’re going to use it, for example with “ondemand” governor or whatever.

One more observation: changing voltages too sharply might sometimes lead to system freezes & other failures. For example, changing voltage from 1.4 V (if I remember correctly, that’s the default voltage for my CPU on 1.8 GHz frequency) to 1.05 V (which is the optimal value found experimentally) causes system freezes in almost half of the cases, so I perform gradual transition instead by setting 1.15 V at kernel command line and later correcting it to 1.05 V during the boot sequence.

Limitations

  • Current implementation is not tested on fully ACPI-compliant motherboards/BIOSes: the only system it was tested on is certainly not, so I have no clue if it works correctly on these systems or not.
  • I haven’t tested it with sysfs or ACPI options turned off in kernel config - so I’m not sure if it compiles at all with these options, and if yes - whether it works or not.

End notes

  • In fact, though I’ve used it for undervolting, nobody forbids you to use it for overclocking also.
  • Instead of patching powernow-k8.c you might also consider changing your ACPI table so that it contains the values you want: Linux kernel allows you to override the needed part of ACPI table at boot with custom values. In my case it was not an option because I needed transition to happen in two steps, and also my original BIOS is not enough ACPI-compliant, so I didn’t want to risk by experimenting with that - but in other situations it might be quite reasonable alternative.

Comment viewing options

ndl@home is currently in maintenance. During this maintenance it is not possible to change site content (like comments, pages and users).
Select your preferred way to display the comments and click "Save settings" to activate your changes.

There has been an AMD K8 patch on Linux-PHC for a while

I just came across this blog. There has been an AMD k8 driver for quite a while on Linux-PHC, I think it was already there (for a few days) at the time you wrote this post, but it was so close you probably missed it. (Also the forum was not functioning for a couple of months before that.)

Anyway, you can check it out at http://linux-phc.org/forum/viewtopic.php?f=13&t=2

And we can still use some help...

Re: There has been an AMD K8 patch on Linux-PHC for a while

NDL's picture

Hello David,

First of all - thanks for Linux-PHC project!!! Its code was very useful as basis for the patch. As for the availability of AMD K8 Linux-PHC patch - to the best of my understanding it was not publicly available when I started to work on my patch, which in fact happened more than a year ago before I wrote this post - it’s just I had no time to put that in writing … So I haven’t checked very carefully current status of Linux-PHC before publishing this post indeed, as I already had the patch available and working, so it’s quite possible I’ve missed something.

However, I’m all for not having multiple incompatible patches floating around: I’d prefer to use your patch instead of mine as mine patch is just quick hack to get things done on one particular PC - not a “full blown” solution tested by multiple people on multiple systems.

I regularly update kernel on my server PC - and for the next update I will try to use Linux-PHC patch version to see how well it works on my system. It’s likely that I will have to apply some changes to PHC patch, though - currently I use somewhat changed transition algorithm compared to default one (slower transitions to lower voltages because default timings cause system to freeze), I will provide feedback with appropriate patches in this case to PHC project.

I’ll also update the post with information on recent Linux-PHC status.

Thanks!

Syndicate content