Gentoo/Userspace software suspend

Page last edited 3,789 days ago
From Alon Bar-Lev's Site
Jump to navigation Jump to search

Userspace software suspend, also known as µswsusp or uswsusp, is a system for hibernating/suspending. It supports suspend-to-RAM, suspend-to-disk, and "suspend-to-both".

Uswsusp is an altenative to TuxOnIce (Suspend2), which is the suspend-to-disk tool recommended by the Gentoo Power Management Guide. It is the successor to swsusp, a suspend-to-disk mechanism built into 2.6 kernels that notably lacked support for LVM.

Comparison with TuxOnIce

TuxOnIce has many more features than uswsusp, like writing to multiple swap devices. An interesting feature that both uswsusp and TuxOnIce have is "suspend-to-both", where the system state is recorded to both RAM and disk so the computer can resume quickly while staying resilient to power loss. On uswsusp, "suspend-to-both" is a explicit method to suspend, ready to use; on TuxOnIce it requires a bit of configuration: user needs to manually set /sys/power/tuxonice/powerdown_method to 3 or do it by a helper, like hibernate-script which can be set with option PowerdownMethod 3.

Uswsusp has, arguably, a better design than TuxOnIce, as most of its code is in userland rather than in the kernel. TuxOnIce requires patches to the mainline kernel, meaning you have to either run sys-kernel/tuxonice-sources or patch your kernel by hand. Running tuxonice-sources may not be an option if you're already running a patched kernel (xen-sources, hardened-sources, etc.) or you need a newer kernel version than the tuxonice-sources ebuilds offer.

Installation

Make sure your kernel has initramfs and suspend support enabled. You can probably leave "Default resume partition" blank if you're using an initramfs.

Linux Kernel Configuration: Suspend kernel config
 General setup  --->
    [*] Initial RAM filesystem and RAM disk (initramfs/initrd) support
  Power management and ACPI options  --->
    [*] Suspend to RAM and standby
    [*] Hibernation (aka 'suspend to disk')
    [*] ACPI (Advanced Configuration and Power Interface) Support  --->
      -*-   Button

Unmask sys-power/suspend, the userspace programs for uswsusp. Emerge suspend and the sys-power/hibernate-script wrapper.

File: /etc/portage/package.accepted_keywords/suspend.conf
sys-power/suspend ~amd64
emerge -av suspend hibernate-script

Configuration

Uswsusp

Uswsusp reads its configuration from /etc/suspend.conf. The key parameter is resume device, which you should set to the path of your swap device.

File: /etc/suspend.conf
snapshot device = /dev/snapshot
resume device = /dev/RESUME_DEVICE
compute checksum = y
compress = y

Hibernate script

The hibernate script, described in the Gentoo Power Management Guide, is a wrapper for various suspend and hibernate implementations. It handles stopping and starting any services and drivers that don't play well with suspend, as well as invoking the actual suspend commands.

Recommended settings:

File: /etc/hibernate/common.conf
SaveClock yes             # this will save current system time into RTC when suspending.
Unmount /boot /mnt/tmp    # in case resume fails, or filesystem is accessed during boot, better to umount it cleanly before suspend.
FullSpeedCPU yes          # perform suspend as fast as we can, even if we chose to save power on batteries for example.
OnSuspend 55 sync         # execute command during suspend
GentooModulesAutoload yes # hack for Gentoo
SwitchToTextMode no       # save if you are using kernel mode switching

That'll get you started, but you may have to do further machine-specific configuration. Check out man hibernate.conf, especially the VBE and force options.

Integration with initramfs

You will need an initramfs that runs resume. If you don't have one, this page can walk you through making one. If you already have one -- either homemade or generated by genkernel -- you will likely have to configure your initramfs to support uswsusp. If you're not sure whether you use an initramfs, check for an initrd line in your bootloader configuration (/boot/grub/grub.conf or /boot/lilo/lilo.conf).

Genkernel

It looks like the current version of genkernel doesn't support uswsusp, but the next version might. bug 156445 explains the current situation and contains a patch to make uswsusp work.

The simple manual method:

cp /usr/share/genkernel/defaults/linuxrc /usr/share/genkernel/defaults/linuxrc.uswsusp

Modify:

File: /usr/share/genkernel/defaults/linuxrc.uswsusp
 #!/bin/sh
 
 . /etc/initrd.defaults
 . /etc/initrd.scripts
+swsusp_resume() {
+    /sbin/resume
+}
 splash() {
mkdir -p /var/lib/genkernel/overlay/etc /var/lib/genkernel/overlay/sbin
cp /etc/suspend.conf /var/lib/genkernel/overlay/etc
cp /usr/lib/suspend/resume /var/lib/genkernel/overlay/sbin
genkernel --linuxrc=/usr/share/genkernel/defaults/linuxrc.uswsusp --initramfs-overlay=/var/lib/genkernel/overlay \ your_standard_parameters

Basically it will use standard genkernel process with the patched linuxrc script and inject the resume utility and suspend.conf into the initramfs.

Custom initramfs

If you use a custom initramfs that mounts your root file system and/or activates your swap, you need to alter your usual init steps slightly to get resume from suspend-to-disk working. Basically, you need to manually invoke uswsusp's userspace resume utility before the root partition is mounted.

The minimal example below shows how to integrate uswsusp with a simple LVM/dm-crypt setup. If used, make sure that sys-apps/busybox and sys-fs/lvm2 were emerged with the static USE flag enabled and sys-fs/cryptsetup was emerged with the dynamic USE flag disabled.

Populating directory tree

Create and populate the directories for your initramfs. The commands below work for amd64; for x86, substitute /usr/lib64 with /usr/lib:

mkdir ~/initramfs cd ~/initramfs mkdir bin dev dev/mapper dev/vc etc etc/lvm newroot proc sys cp /bin/busybox /sbin/cryptsetup /usr/lib64/suspend/resume bin cp /sbin/lvm.static bin/lvm ln -s busybox bin/sh ln -s lvm bin/vgchange cp -a /dev/console /dev/null /dev/sda2 /dev/snapshot /dev/random /dev/urandom dev ln -s ../console dev/vc/0 cp /etc/suspend.conf etc cp /etc/lvm/lvm.conf etc/lvm
Note: Remember to update your initramfs's binaries and suspend.conf whenever you update their counterparts on the root file system. Rebuild the initramfs.img after copying the new files.

Init script example

Write an init script to suit your needs.

The example script here assumes a single dm-crypt/LUKS partition, inside of which is an LVM volume group, inside of which is the root volume and the swap volume. The swap volume is the "resume device" (configured in /etc/suspend.conf) where uswsusp dumps the machine's state, so the resume has to happen after the swap is unlocked, but before the root volume is mounted. If the resume command finds a suspend image, then the command never returns and the rest of the script is not executed; otherwise, init proceeds normally.

Note: This is just an example, not a generic init script. It won't work on your system without modification. Customize it to handle your actual storage layout.
File: ~/initramfs/init
#!/bin/sh

mount -t proc proc /proc
mount -t sysfs sysfs /sys
sleep 2  # wait for kernel msgs to quiet

if cryptsetup luksOpen /dev/sda2 vault; then
  vgchange -ay vault_vg
  resume
  mount -r /dev/mapper/vault_vg-root /newroot

  if [[ -x /newroot/sbin/init ]]; then
    umount /sys /proc
    exec switch_root /newroot /sbin/init
  fi
fi

# Uncomment if you want a rescue shell
# exec sh
chmod a+x init

If you want to add more advanced functionality to your init script, like reading kernel command line parameters or loading a keymap, consult the excellent init script in the DM-Crypt with LUKS article.

Install script

This script builds an initramfs image from your ~/initramfs directory tree and copies the image to /boot. Run this script whenever you change a file in your initramfs.

File: ~/initramfs/install
#!/bin/sh

if ! mount | grep ' on /boot ' > /dev/null; then
  echo 1>&2 "WARNING: /boot doesn't appear to be mounted"
fi

find . | cpio --quiet -o -H newc | gzip -9 > /boot/initramfs.img

chmod a+x install
mount /boot ./install

Configuring the bootloader

Configure your bootloader to use your initramfs image. For Grub, add/edit an initrd line to the appropriate boot entry in grub.conf.

File: /boot/grub/grub.conf
title Linux
root (hd0,0)
kernel /vmlinuz
initrd /initramfs.img

Usage

Uswsusp uses three userspace utilities -- s2ram, s2disk, and s2both -- to execute suspend-to-RAM, suspend-to-disk, and suspend-to-both, respectively. The preferred method for suspending, however, is via the hibernate script, so you shouldn't need to invoke the s2* commands directly unless you're testing your setup.

Suspend-to-disk / Suspend-to-both

To suspend-to-disk (or suspend-to-both, depending on how you configured /etc/hibernate/hibernate.conf), just run hibernate as root:

hibernate

Actually /etc/hibernate/hibernate.conf refers to /etc/hibernate/disk.conf which tries to load ususpend-disk.conf. You may want to change this line to ususpend-both.conf to use suspend-to-both.

Suspend-to-RAM

To suspend-to-RAM, run:

hibernate-ram

Troubleshooting

If something goes wrong, first try suspend/resume without X11 running, most issues are video card related.

Also try s2disk directly from text mode without hibernate script and see if it works.

Suspend to RAM is more problematic than suspend to disk as it requires hardware support and cooperation. In most recent laptops it works correctly.

File: /etc/hibernate/ususpend-ram.conf
USuspendRamForce yes     # if hardware is unrecognized (most probably)
USuspendRamAcpiSleep 3   # if you experiencing problem in waking up, also try 1 or 2

Then try:

hibernate-ram

If suspend fails not resume, look at var/log/messages, you may find modules that broke the suspend cycle, try to unload them during suspend:

File: /etc/hibernate/ram.conf
UnloadModules MODULE_NAME

Try googling for how other people with your particular hardware (e.g., video card) have gotten it to work.

If the screen stays black when you resume, your computer may still be running fine even though the display is borked. Before you reset the machine, try to shut it down cleanly with Ctrl+Alt+Del or by ssh'ing in.

Integrating acpid

The following will suspend to disk when sleep button is pressed, and suspend to RAM if power button is pressed or lid is closed, add:

emerge sys-apps/acpid
rc-update add acpid default
File: /etc/acpid/default.sh
         button)
                 case "$action" in
+                        power)
+                                /usr/sbin/hibernate
+
+                        ;;
+                        lid)
+                                grep -q closed /proc/acpi/button/lid/LID/state && \
+                                        /usr/sbin/hibernate-ram
+                        ;;
+                        sleep)
+                                /usr/sbin/hibernate
+                        ;;

You may need to ajust the lid button location to match your architecture.

Integrating splashutils

uswsusp can show nice splash activity during suspend/resume.

File: /etc/portage/package.use/suspend.conf
sys-power/suspend fbsplash

Add:

File: /etc/suspend.conf
splash = y
File: /etc/hibernate/common.conf
FBSplash on

Recreate the initramfs overlay with the new resume and suspend.conf.

Recreate your initramfs with new suspend.conf and try again.

Links

Userspace software suspend

From the forums : a simple init script to resume from uswsusp in your initramfs