Soekris CPU Scaling and OpenBSD 5.2

OpenBSD 5.2 was released nearly two months ago and I had forgotten to upgrade my Soekris net6501, apart from my driver now being part of the kernel, this release also added support to the SpeedStep frequency scaling driver for the Atom CPU.

The simple benchmark to keep in mind is using the md5(1) command, using its built-in time trial test. Under the previous OpenBSD 5.1 release:

# md5 -ttt
MD5 time trial.  Processing 1000000 10000-byte blocks...
Digest = f0843f04c524250749d014a8152920ec
Time   = 124.227876 seconds
Speed  = 80497230.750367 bytes/second

You can see I’m getting roughly 80 MB/s. Now upgrade to OpenBSD 5.2 and repeat the test, you’ll get pretty much the same speeds, however now we have the CPU frequency scaling to play with. The scaling is very coarse, the only two speeds supported are 600 MHz and whatever maximum the CPU supports, so in my case with a net6501-70, it’s 1.6 GHz. To change the scaling simply manipulate the hw.setperf sysctl(8) variable.

By default the CPU is running at 100%, confirmed by:

# sysctl hw.setperf

Now set the CPU frequency to the slowest speed:

# sysctl hw.setperf=0
hw.setperf: 100 -> 0

Now running the test again I get the following results:

# md5 -ttt
MD5 time trial.  Processing 1000000 10000-byte blocks...
Digest = f0843f04c524250749d014a8152920ec
Time   = 123.948587 seconds
Speed  = 80678612.334645 bytes/second

Almost exactly the same speed, which doesn’t make sense given I’ve knocked 1 GHz off the clock speed! So put the CPU back to 100% and try again:

# sysctl hw.setperf=100
hw.setperf: 0 -> 100
# md5 -ttt
MD5 time trial.  Processing 1000000 10000-byte blocks...
Digest = f0843f04c524250749d014a8152920ec
Time   = 46.424699 seconds
Speed  = 215402581.285449 bytes/second

Ah-ha, about 210 MB/s this time! It transpires there’s a bug in the Soekris BIOS, despite advertising the CPU as 1.6 GHz it wasn’t programmed correctly and was only being clocked at 600 MHz, so all this time I’ve effectively had the base net6501-30 model albeit with the extra RAM. You can work around this by setting hw.setperf to 100 on each boot.

A new BIOS 1.41c has been released which fixes this issue and programs the CPU to run at its advertised maximum speed. However to upgrade to this involves my eternal battle with serial terminal software and uploading over XMODEM which is notoriously fickle, although I think I have it cracked…

I usually use a Mac OS X host with a KeySpan USB/Serial adapter to connect to the net6501 so I already have tools like cu(1) and screen(1). You’ll also need the lrzsz tools installed which if using MacPorts is as easy as:

# sudo port install lrzsz

Using cu(1), connect to the Soekris:

# sudo cu -l /dev/tty.KeySerial1 -s 19200

Power the board on, use Ctrl+P to break into the BIOS monitor and type download to start the Soekris waiting to receive over XMODEM. Now you need to type ~+sz -X /path/to/b6501_141c.bin, possibly as quickly as you can after the previous command. If that works, type flashupdate afterwards to reprogram the BIOS. You’ll get something like the following transcript:

> download
Start sending file using XMODEM/CRC protocol.
~+sz -X /path/to/b6501_141c.bin
Sending /path/to/b6501_141c.bin, 1982 blocks: Give your local XMODEM receive command now.
Bytes Sent: 253696   BPS:1746                            
Transfer complete
File downloaded succesfully, size 253696 Bytes.
> flashupdate
Updating BIOS Flash ,,,,,,,,,,,,, Done.
> reboot

Reboot and boot back into OpenBSD. Now the time trial should return a result of roughly 210 MB/s every time. Because I obviously don’t need 1.6 GHz of CPU all time, I’ve enabled the apmd(8) daemon which manipulates the hw.setperf variable based on the CPU idle time. Add the following to /etc/rc.conf.local:

apmd_flags="-C -f /dev/null"

The -f is only necessary when running i386 otherwise apmd(8) complains. Start with:

# /etc/rc.d/apmd start

Normally hw.setperf will be 0 however when you do something CPU-intensive (such as the MD5 time trial) apmd(8) will automatically adjust hw.setperf back to 100 so you still get the 210 MB/s result, but most of the time you’ll have lower power draw and less heat.

Tags: , , ,

10 Responses to “Soekris CPU Scaling and OpenBSD 5.2”

  1. vlad says:

    I tried to follow the above advice, so upgraded my 6501 to 1.41c and verified that setting the perf sysctl manually works. However, apmd refuses to start with: cannot open device file `/dev/apmctl’: Operation not supported by device

    The /dev/apmctl is present however I cannot see any apm entry in dmesg. I am running the FLASHRD 5.2 kernel from the flashrd distro ( Is there some other pre-requisite I am missing ?

    • Matt says:

      I just checked the dmesg output from GENERIC on my net6501 and I don’t see anything related to APM either. To be honest, it doesn’t need any real APM hardware as it’s not managing batteries or power status.

      I would confirm you’re starting apmd with the -C flag, and double check using the GENERIC kernel. It looks like the FLASHRD kernel is just GENERIC with some ISA devices removed which can’t ever be present on a net6501.


      • vlad says:

        I just checked on my x86 whitebox running 5.2/i386 with GENERIC kernel (and where frequency scaling using apmd works correctly) and it does not report apm in dmesg either and yet apmd -C works. It has bunch of acpi entries in dmesg, though.

        The FLASHRD kernel config is indeed very similar to GENERIC, only bunch of differences, none of these seem to be related to apm. I can do an experiment and create a kernel as close to GENERIC as possible (flashrd needs some stanza for read-only boots).

        As for the -C flag when running on 6501:

        # /usr/sbin/apmd -d -C
        apmd: cannot open device file `/dev/apmctl’: Operation not supported by device
        # echo $?

        • vlad says:

          I noticed 32-bit support BIOS value check in i386/apm.c:apmattach(), perhaps you’re running amd64 and not i386 ?

          • vlad says:

            Anyway, after going through the apmd.c source, I added -f /dev/null as workaround and it works fine now.

          • Matt says:

            Yeah, I’m running amd64. I think amd64 is only theoretically ACPI-based these days so the amd64 version of apm(4) doesn’t interface directly with any APM hardware whereas on i386 it potentially does and therefore has some sort of check when it opens /dev/apmctl.

            Good catch, I’ll update the post.

          • vlad says:

            If my hypothesis is correct and the apmattach() routine fails on i386 (which then makes the apmopen() return ENOTSUP) thanks to the lack of APM_32BIT_SUPPORTED flag in apm_detail which comes from the BIOS, then it’s a question whether the fact the 6501’s BIOS does not set the flag is correct. I have minimal knowledge of this area so this is only very wild guess.

  2. Pedro Caetano says:

    Hi Joel, thank you for your post!
    First time commenting although i’ve followed your blog for a while back.
    This weekend i finally flashed latest bios onto my soekris.
    Turns out cpu scaling is not working on July 26th amd64 -current snapshot.
    I wonder if anyone can confirm this behaviour.

    All the best,
    Pedro Caetano

    P.S.:Sorry for digging this article which is some months old, i guessed i’d be able to draw attention from some soekris owners 🙂

  3. dcat says:

    using -f /dev/null would cause it to not perform anything, -f specifies the device to act on.

    • Matt says:

      If you read the previous comments you’ll see it was needed as a workaround on i386. When using the -C flag, we only wanted apmd to manage the hw.setperf setting so the device that would be specified by -f isn’t used (and there isn’t a valid one on a Soekris board anyway hence specifying /dev/null).

      This was all true back in the 5.2 days when the article was written. Somewhere around 5.7, there’s now kernel-based CPU scaling so running apmd isn’t required (and doesn’t support the -C flag now either).

Leave a Reply