Aumentando la duración de la batería en GNU/Linux con PowerTOP

En los últimos años, gracias a las nuevas generaciones de procesadores optimizados para portátiles y a la proliferación de discos de estado sólido, hemos visto cómo aparecían ultrabooks cuya autonomía supera con holgura las 5 horas. Por otra parte, a mayor duración de la batería, mayor impacto en la misma tiene la configuración y el comportamiento del software.

Por fortuna, en GNU/Linux disponemos de PowerTOP, una herramienta desarrollada por ingenieros de Intel, que nos ofrece información detallada sobre la distribución del consumo energético, y una serie de recomendaciones para reducirlo.

Usando PowerTOP: ¿Qué procesos despiertan la CPU?

Desde hace varios años, los procesadores x86 ofrecen al sistema operativo la posibilidad de minimizar el consumo energético reduciendo la frecuencia del reloj (Dynamic frequency scaling), o incluso apagándolos parcialmente (saltando entre C-States). Lógicamente, el S.O. sólo puede hacer uso de estas funcionalidades cuando no hay ningún proceso reclamando ser planificado.


En esta línea, la primera pantalla de PowerTOP nos muestra información sobre los eventos que “despiertan” la CPU y el origen de los mismos. Conviene que revisemos la parte alta de dicha lista, en busca de algún proceso que no debiera estar allí. Puede sonar extraño, pero dependiendo del escritorio y la distribución que estemos empleando, nos podemos encontrar con un gestor de ventanas que no para de lanzar eventos, o con alguna aplicación de sincronización en la nube que está “demasiado activa”.

Usando PowerTOP: Opciones recomendadas

Una funcionalidad especialmente útil de PowerTOP, es la que nos muestra una lista de configuraciones recomendadas para el S.O. que no tenemos activas, y nos indica el comando que debemos ejecutar para reestablecerlas.


Es posible activar dichas opciones pulsando enter sobre ellas, pero dicha configuración no es permanente, y ser perderá tras un reinicio. Una forma sencilla de extraer los comandos para cargarlos en el rc.local (o el equivalente que use nuestra distro), sería algo así:

slp@linux-18od:/tmp> # Generamos un informe en CSV con PowerTOP
slp@linux-18od:/tmp> sudo powertop --csv
Cargado 260 medidas previas
RAPL device for cpu 0
RAPL device for cpu 0
RAPL device for cpu 0
Preparing to take measurements
Taking 1 measurement(s) for a duration of 20 second(s) each.
PowerTOP outputing using base filename powertop.csv
slp@linux-18od:/tmp> # Editamos el fichero powertop.csv, y eliminamos todo menos en la sección "Software Settings in need of Tuning"
slp@linux-18od:/tmp> vi powertop.csv
slp@linux-18od:/tmp> # Preparamos un pequeño script para extraer la parte que nos interesa:
slp@linux-18od:/tmp> cat > << EOF
import re

file = open("powertop.csv", "r")
lines = file.readlines()
for l in lines:
    m = re.match(".*?;(.*)", l)
    if m:
slp@linux-18od:/tmp> # Y hacemos uso de él
slp@linux-18od:/tmp> python > commands
slp@linux-18od:/tmp> # Finalmente, revisamos el fichero y hacemos copypaste a nuestro rc.local
slp@linux-18od:/tmp> vi commands

Tras reiniciar, al volver a la misma pantalla de PowerTOP, deberíamos ver cómo todas las configuraciones parecen como ya establecidas:


Running RISCOS on QEMU

UPDATE (17/09/14): Some time after writing this, I’ve replaced the QEMU repository referenced here with a clean one without the changes needed for running RISCOS. I’ve just created another repository with the proper sources:

Some time ago, while trying to get NetBSD to run on Efika MX Smartbook (I should write about that), I’ve decided that I would never do any serious OS development on a platform without a JTAG interface, or a working emulator. Being able to stop the execution at will, for looking at the CPU registers, or examining an arbitrary memory location, will save you a lot of hours otherwise invested in a painful trial and error cycle.

For this reason, when I’ve decided to try and do some hacking on RISCOS (and I’m not going to lie, I was attracted by their bounty program), the first option I’ve considered was trying to get it to work under QEMU. This serves a double purpose: establishing a comfortable development environment, and getting myself to know RISCOS internals and its build process.

Nowadays, in addition to other platforms, RISCOS is able to run on BeagleBoard (OMAP3) and Raspberry Pi (BCM2835). I have access to a real RPi, so being able to emulate this platform would allow me to do most part of the coding under QEMU, and then verify the results with a physical device.

The bad news is that QEMU, as is, doesn’t emulate the BCM2835 SoC. True, some people are running Raspberry Pi GNU/Linux distributions under QEMU, but this is being done with a trick, replacing the original kernel with one compiled for VersatilePB SoC, which is fully emulated under QEMU. As the userland doesn’t care much about the SoC (it just needs a platform compatible with its ABI, which it’s mostly the case, unless you’re applying some NEON/VFP3 optimizations), this approach works reasonably well. But, for this strategy to work for RISCOS, I would need to do a new port to the VersatilePB platform, and that’s a project far beyond the size of what I initially considered.

Luckily, I’ve came across the amazing work being done by Gregory Estrade to add real BCM2835 emulation on QEMU. Older versions of RISCOS did run on qemu-rpi, but recent ones refused to boot. With a bit of hacking here and there, I’ve managed to get it to boot to the Desktop, but I still needed a working pointer.

As with the real RPi, the emulated one should be able to provide an USB mouse, but with pre-EHCI interfaces, data polling for USB pointer interfaces its just too expensive, and it showed an erratic behavior. I can’t say this came to me as a surprise, as I still remember the days when the first USB mouse got introduced to x86 desktops, and how it jumped around the screen when the CPU was slightly loaded.

Thinking about this problem, I’ve remembered that QEMU also features USB Tablet emulation. A tablet always provides absolute positions for the pointer, which makes it more precise, even when working with a lower interrupt rate. After applying an ugly and crude (but working!) hack to make QEMU provide resolution adjusted values that RISCOS could properly interpret as pointer positions, I’ve finally got a working RISCOS Desktop:


Running it yourself

To be able to run RISCOS on QEMU, follow this steps:

  1. Checkout my fork of qemu-rpi, switch to the rpi branch, and build it (you’ll only need the arm-softmmu target).
  2. Grab a RISCOS for Raspberry Pi SD Card image from here:
  3. Get my patched ROM: riscos.rom. Alternatively, if you have access to a RISCOS machine and the DDE, you can download this patch and build it yourself.
  4. Uncompress both files.
  5. Launch QEMU with something like this:
    qemu-system-arm -kernel riscos.rom -initrd riscos.rom -cpu arm1176 -M raspi -sd riscos-2013-07-10-RC11.img -d guest_errors -serial stdio -device usb-kbd -device usb-tablet -usb

Stuff to be done

  • Support for USB storages. This needs some fixes on the QEMU BCM2835 USB stack.
  • Network support. This needs some of the fixes mentioned above, and extending RISCOS support for USB CDC network devices.
  • Fix some graphic glitches.