Atom D510: FreeBSD cpu scaling, temperature and the non-existing C-states

A D510MO board was lying in the shelves and I decided to give a try for some FreeBSD testing. One topic I wanted to check out was power saving and getting to know. Most CPUs nowadays (even the now dated D510 Atom) support frequency scaling and most often C-States. Without digging into the details of FreeBSD’s ‘powerd’ enabling basic frequency scaling works as simple as adding the following line to /etc/rc.conf

powerd_enable=”YES”

sysctl can tell us what frequencies the CPU can work at ans the current freqency:

# sysctl dev.cpu | grep freq
dev.cpu.0.freq: 208
dev.cpu.0.freq_levels: 1666/-1 1457/-1 1249/-1 1041/-1 833/-1 624/-1 416/-1 208/-1

Now to check if the frequency scaling was working, hitting the CPU with some load was required, but where to take? On Windows a pretty simple tip taken from old journals was to fire up the system calculator app in scientific mode and let it calculcate very large factorials (german: Fakultät) like 999999999999! which will load the CPU and cause some heating in order to verify how loud a system can become – or in this case: Cause the CPU frequency to go up under load and scale down when back idle. It turns out FreeBSD base ships a with console-based calculator  called bc (on most Linuxes it’s GNU bc) which according to this yet old but still working article in Linux journal allows exactly this with a factorial function:

# bc
define f(x) {
 if (x <= 1) return (1);
 return (x*f(x-1));
}

f(999999999)

In parallel on a second terminal execute “powerd -v” to see how the frequency goes up and down:

# powerd -v
powerd: unable to determine AC line status
[... system is idle, starting bc in the meantime ...]
load   0%, current freq  208 MHz ( 7), wanted freq  208 MHz
load   0%, current freq  208 MHz ( 7), wanted freq  208 MHz
load   4%, current freq  208 MHz ( 7), wanted freq  208 MHz
[...]
load  38%, current freq  416 MHz ( 6), wanted freq  261 MHz
load 141%, current freq  416 MHz ( 6), wanted freq 1044 MHz
changing clock speed from 416 MHz to 1249 MHz
load 100%, current freq 1457 MHz ( 1), wanted freq 3332 MHz
changing clock speed from 1457 MHz to 1666 MHz
load  93%, current freq 1666 MHz ( 0), wanted freq 3332 MHz
load 100%, current freq 1666 MHz ( 0), wanted freq 3332 MHz
load 100%, current freq 1666 MHz ( 0), wanted freq 3332 MHz
load 101%, current freq 1666 MHz ( 0), wanted freq 3332 MHz
load 100%, current freq 1666 MHz ( 0), wanted freq 3332 MHz
[ ... bc is running and now gets stopped ...]
load 100%, current freq 1666 MHz ( 0), wanted freq 3332 MHz
load  68%, current freq 1666 MHz ( 0), wanted freq 3332 MHz
load   0%, current freq 1666 MHz ( 0), wanted freq 3227 MHz
load   0%, current freq 1666 MHz ( 0), wanted freq 3126 MHz
load   0%, current freq 1666 MHz ( 0), wanted freq 3028 MHz
[...]
load   0%, current freq 1666 MHz ( 0), wanted freq 1453 MHz
changing clock speed from 1666 MHz to 1457 MHz
load   0%, current freq 1457 MHz ( 1), wanted freq 1407 MHz
[...]
load   0%, current freq 1457 MHz ( 1), wanted freq 1238 MHz
changing clock speed from 1457 MHz to 1249 MHz
load   0%, current freq 1249 MHz ( 2), wanted freq 1199 MHz
[... we see all supported clock speeds freq_levels passing by]
load   0%, current freq  416 MHz ( 6), wanted freq  208 MHz
changing clock speed from 416 MHz to 208 MHz
load   6%, current freq  208 MHz ( 7), wanted freq  208 MHz

This little experiment show that powerd is not that agressive when slowing the frequency back down as quickly as it rushes up, maybe tha its something to tune more aggressively on laptops.

Temperature readings

For CPU temperatures it happens to be as simple as loading the ‘coretemp’ module via kldload coretemp. Adding coretemp_load=”YES” to /boot/loader.conf enables the module ad system start. Afterwards CPU temperatures were readable via sysctl too:

# sysctl dev.cpu | grep temperature
dev.cpu.0.temperature: 44.0C
dev.cpu.1.temperature: 44.0C
dev.cpu.2.temperature: 41.0C
dev.cpu.3.temperature: 42.0C

C-States

Now most CPUs also support C-States to send to sleep when possible which would be actually quite good for power saving. In FreeBSD it seems sysctl can be used to query what C-states the CPU cores support via dev.cpu.<id>.cx_supported i.e.

# sysctl dev.cpu.1
[...]
dev.cpu.1.cx_supported: C1/1/3
dev.cpu.1.cx_lowest: C1
dev.cpu.1.cx_usage: 100.00% last 58973us
[...]

Technically this would suggest that the CPU has the capability to use C3 but the current lowest C-State would be C1? I tried sysctl dev.cpu.1.cx_lowest=C3 as well as the global hw.acpi.cpu.cx_lowest=C3 (for boot this would be put in /etc/syctl.conf) but allas it remained always using 1 C-State.

It seems the Atom D510 is one of those low-end CPUs that do not support C-States anyway as per ark.intel.com. I’ve come across this thanks to FreeBSD PR 160561 where a very similar D525 was reported.
Possibly the CPU isn’t telling correctly about its supported C-states allas.

This was done on FreeBSD 10-BETA3 btw.

November 7, 2013

Posted In: Uncategorized

Tags: , ,

Leave a Comment