These are the ramblings of Matthijs Kooijman, concerning the software he hacks on, hobbies he has and occasionally his personal life.
Most content on this site is licensed under the WTFPL, version 2 (details).
Questions? Praise? Blame? Feel free to contact me.
My old blog (pre-2006) is also still available.
See also my Mastodon page.
Sun | Mon | Tue | Wed | Thu | Fri | Sat |
---|---|---|---|---|---|---|
1 | 2 | 3 | ||||
4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | 15 | 16 | 17 |
18 | 19 | 20 | 21 | 22 | 23 | 24 |
25 | 26 | 27 | 28 | 29 | 30 |
(...), Arduino, AVR, BaRef, Blosxom, Book, Busy, C++, Charity, Debian, Electronics, Examination, Firefox, Flash, Framework, FreeBSD, Gnome, Hardware, Inter-Actief, IRC, JTAG, LARP, Layout, Linux, Madness, Mail, Math, MS-1013, Mutt, Nerd, Notebook, Optimization, Personal, Plugins, Protocol, QEMU, Random, Rant, Repair, S270, Sailing, Samba, Sanquin, Script, Sleep, Software, SSH, Study, Supermicro, Symbols, Tika, Travel, Trivia, USB, Windows, Work, X201, Xanthe, XBee
This afternoon on IRC people were discussing the assignments of the NIO, a programming contest for high school students I've participated in a few times. One particularly nice one was the "happy" assignment.
In short, the assignment says there are happy numbers and non happy numbers. To see if a number is happy, you take the square of every digit and add these squares together. You do this squaring and summing until you get either the number "1" of the number "4". If you get "1", the number is happy, if you get "4", the number is not. This is a fairly simple assignment to write a program for, but the program could not have more than 1000 characters, which makes it kinda interesting.
As soon as somebody posed that he could to it in four hundred something characters, without leaving out stuff (like whitespace and indentation), people started trying too. Before long, a couple of people were trying to make their programs as short as possible. Later we merged our tries to get even shorter versions. The end result was a very short solution for this problem (chopped into two lines for readability):
m[666],o,x;h(i){for(x=0;i;i/=10)x+=i%10*(i%10);m[x]=m[x]?:h(x);}
main(i){for(m[m[4]=scanf("%d",&i)]=2;i;o+=h(i--)-1);printf("%d\n",o);}
I've previously mentioned that I've undervolted my MSI Megabook S270 notebook. I got a request about how exactly I did this, so I'll elaborate here.
Undervolting is modifying your hardware parameters in such a way, that the system CPU runs on a lower voltage that it is supposed to. Running on a lower voltage means the CPU uses less power and produces less heat, which are both wanted on a mobile system. Different laptops have different methods of undervolting. What I describe here should applies to AMD Turion64 processors (Which I have), but should also work for all other AMD processors with PowerNow support.
AMD PowerNow is AMD's technology for scaling CPU frequencies and voltages. How
exactly the scaling itself is performed is not all that interesting, how to
control it is. Linux has a special cpufreq driver for PowerNow processors,
which exports its interface through /sys/devices/system/cpu/cpu0/cpufreq
.
Here you can select a governor which decides at what speed your CPU should
run.
Hidden from the cpufreq interface (which only concerns CPU speed changes), the PowerNow driver also changes the CPU voltage when the speed changes. So, your CPU voltage is already automatically decreased whenever the CPU speed is lowered. Yet, we want to decrease it even further.
Since we cannot set the CPU voltage when scaling, only the frequency, how does PowerNow know what voltage to set? You might think that the CPU itself handles this, but fortunately this is not so. The PowerNow driver gets the information about the possible states and corresponding voltages from the system itself, through one of two means: ACPI and legacy BIOS.
The preferred way of retrieving this information is through ACPI and this
might or might not work. For me, this didn't work (There were errors in my
kernel logs with CONFIG_CPU_FREQ_DEBUG
enabled). When ACPI does not work,
the PowerNow driver uses some legacy BIOS call I don't fully understand to get
its values.
So, we want to modify the voltage values the PowerNow driver finds. Since I didn't fully know how the BIOS thing worked, that wasn't the way to go. So I had two options:
I settled for the last one, since that is nicer and a lot better when upgrading kernels.
Some poking around with the kernel and its debug output, I found that the ACPI object (CPU1._PSS) holding the PowerNow information was not properly loaded by the kernel. Doing the decompile-and-recompile-with-Intel's-compiler trick, showed that the Intel ACPI compiler didn't like that _PSS ACPI object either. See my older post about how I fixed these compilation errors. After fixing these, the PowerNow driver properly gets its settings from ACPI.
With CONFIG_CPU_FREQ_DEBUG
enabled, PowerNow properly reports the found
settings (don't know if this was any different before fixing ACPI, I don't
want to break my ACPI and reboot to find out).
powernow-k8: Found 1 AMD Athlon 64 / Opteron processors (version 1.50.4)
powernow-k8: 0 : fid 0x8, vid 0xa
powernow-k8: 1 : fid 0x0, vid 0x1c
powernow-k8: 0 : fid 0x8 (1600 MHz), vid 0xa (1300 mV)
powernow-k8: 1 : fid 0x0 (800 MHz), vid 0x16 (1000 mV)
powernow-k8: cpu0, init lo 0x808, hi 0x1
powernow-k8: policy current frequency 1600000 kHz
cpu_init done, current fid 0x8, vid 0x8
Part of fixing the ACPI table, is recompiling a fixed version and inserting it into the kernel source. Now, instead of getting the ACPI table from the system on startup, Linux uses your modified table. This means we can modify any value in the table as if the actual ACPI table was changed.
Time to turn to find out how to read the ACPI table and find out which value to actually change. After searching a lot I found the "BIOS and kernel developers guide for Athlon 64 and Opteron". At page 278 they describe where PowerNow gets its information. From there I find that the CPU1._PSS ACPI Package contains a number of (unnamed) packages, one for every CPU State (Two in my case). Each packets contains 6 32bits numbers, which represent various settings. This is my original _PSS Package:
Name (_PSS, Package (0x02)
{
Package (0x06)
{
0x00000640,
0x000055F0,
0x00000064,
0x00000007,
0xE0202A88,
0x00000288
},
Package (0x06)
{
0x00000320,
0x00001EDC,
0x00000064,
0x00000007,
0xE0202D80,
0x00000580
}
})
From the PowerNow specs we learn that every CPU state has a fid and vid, for Frequency ID and Voltage ID respectively. The frequency is calculated as 800 + fid * 100 (in MHz). The voltage is calculated as 1550 - vid * 25 (in mV). This means the frequency cannot go below 800MHz, and since the maximum vid value is 0x1e the minimum voltage is 800mV. I seem to vaguely remember that either the fid or vid can only be set to multiples of 2, yet I can't seem to find any hint of that in the specs now. I did find that the maximum supported frequency change in one go is 200MHz, but the kernel takes care of that, so we don't need to worry about this.
The actual vid is coded into the fifth value in the package, at bits 6-10
(Powernow specs page 280). This means you can increment the fifth value
by 0x80 to decrease the voltage by 50mV. Below is the package from the ACPI
table I use now, along with a few other examples of different voltages (//
denotes a comment).
Package (0x06)
{
0x00000320,
0x00001EDC,
0x00000064,
0x00000007,
//0xE0202D80, // 1000mV
//0xE0202E80, // 900 mV
0xE0202F00, // 850 mV
//0xE0202F80, // 800 mV
0x00000580
}
I've tried running as low as 800mV, but then my system seems to boot okay, but as soon as I login (type my password correctly), it powers off. This seems so predictable that you would suspect the voltage change to have this effect, but increasing the voltage back to 850 mV gives me a stable system that is slightly cooler and uses less power. I'll repeat the (very rough) benchmarks I made back then here (current values are for the entire system).
As you can see, the power savings are very little when the CPU is idle, but quite significant when the CPU gets busy (100% load, though still at 800MHz). I have so for only undervolted my 800MHz state, since I barely ever need all my 1600MHz. But since my CPU gets especially power hungry when it's really fully loaded at 1600MHz (up to 2500mA), I suspect that a lot of power can be saved here. If you try this and get it to work, do tell! And don't forget to mention the actual voltage you get it to run on.
Update: Youri Matthys has been experimenting with undervolting too, and has managed to make his Turion at 1600Mhz run on 1000mV instead of the default 1300mV. The power savings are even better then I'd have hoped for: Under full load the battery usage drops from around 2500mA to 1700mA.
Did you know that the sound of a nearly empty tube of toothpaste is almost identical to the sound of a paintbal gun, only less loud?
While I was editing some wiki pages just now, I kept being annoyed by the stupid little poor-excuse-for-an-editor text-area in Firefox. But using my favourite editor, vim, would mean copypasting all the text into vim and back again, which is rather clumsy since vim runs in an xterm.
At these moments, you suddenly realise that you cannot be the only one that is being annoyed by something like this. A quick search for "vim" at the Firefox extensions page gives no useful results, though. Searching a little further, I come across Mozex, an extension that supports not only editing textareas in an external program, but also intersepts mailto links, ssh links, news links, etc.
So, whenever I wanna edit something in vim now, I just press Meta+V and get my trusty editor in an xterm :-D
Just a little heads up for anyone owning an Asus access point. I spent the day at Brenda's today and their access needed a firmware upgrade. After a first failed attempt (upgrading the access point over the wireless connection is a bad idea and crashed the web management interface, requiring a reboot) I managed to succesfully upgrade the access point.
Yet, even though the upgrade page claimed that "all settings will be preserved", after upgrading we had a brand new (unencrypted) wireless network in town, with an SSID of "Broadcom" (wasn't this an Asus device?). So much for saving our settings... But, not only did it throw away our wireless settings, also the administrator password went out the window. Better yet, apparently it was not replaced with the default "admin/admin" password, since that didn't work.
So, your effectively locked out of your own acces point. That's bad points for Asus there... But if you should find yourself in this same situation, don't panic! Just press the reset button on the back of your AP to restore it to factory default settings. Tada, it works again, and since it trashed your settings anyway, you don't lose anything :-)