Extending the swsusp Hibernation Framework to ARM – Russell Dill (TI)

Russell has worked mainly on software support for beaglebone. The goal of swsusp is to have zero power consumption sleep. But it also shares infrastructure with Off+DDR self-refresh (which is more complex than suspend-resume because CPU state is not saved) and snapshoting.

[Unfortunately I had a hard time following this talk, so the quality of this report is probably low.]

swsusp history: Mainline hibernation uses swap device to store the image. There is also uswsusp, where the kernel passes the suspend image to a userspace helper.

Generic suspend-resume saves CPU state, then calls an architecture-specific function. On resume, the boot loader jumps to a saved stack pointer and it looks as if you just return from the suspend() function to the kernel.

swsusp uses a similar code path, but it first saves all the pages. During this time, an in_suspend flag tells the world that they have to be careful with what they’re doing. On restore, the kernel reads the saved image and puts them back in the right place and then calls the resume functionality.

A minimum arch implementation has an arch_suspend and arch_resume function to save the CPU state and snapshot the memory, plus some additional functions. You can use cpu_suspend for the first part. Resume is a bit more convoluted because you overwrite the memory that it’s using. Fortunately, the resume kernel has to be identical to the snapshoting kernel so the critical parts are overwritten with identical data (but someone in the audience pointed out that this is a limitation that we want to remove).

It gets complicated with the OMAP PM. The current Linux support assumes that the wakeup power domain is always available. So after hibernation, the state of this domain has to be restored and very quickly. Fortunately there is the generic hwmod interface so you can just go over all IP blocks and call the generic handlers. Pinctrl is another issue: it needs to know which power domain it is in, so it knows which registers need to be saved/restored. This requires heavy rewriting and is probably not upstreamable as it is implemented now. clocksource is assumed to be always running at the moment and is used for delays, so the earliest restore functionality should restore this first.

For many devices, you just have to tell the driver that they’ve been turned off instead of restoring. However, currently  lot of drivers only implement the suspend and not the freeze interface, so it’s assumed they don’t need to do anything on hibernation.

Debugging this work is extremely difficult because the processor is dead when something goes wrong. Since so much is turned off, you can’t use e.g. printk because it’ll just abort. GPIOs are better because some are retained in the wakeup domain and you can easily access them even from assembly. JTAG is nice if it works, especially because you can read the log buffer. while(1) is useful because it’s really predictable. devmem2 is good to match before/after state and see if you missed some state.

Restoring is just copying pages from disk into memory – which is exactly what U-Boot does. So it would be better if U-Boot would do the restore and jump to the right address. Some pages shouldn’t be saved, however, so these are still handled by the kernel when it boots. But now in U-Boot, you cannot overwrite the U-Boot code and stack, so these should also be handled by the kernel itself – but fortunately U-Boot has a very simple and predictable memory map. U-Boot in the end calls the resume function that is stored in the hibernation image.


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s