2. Contents & References
ļ¬ Scope of the Document
ļ¬ Section 1
ā ACPI Specification
ā States defined by ACPI Specification
ā System Power Management States
ā Sysfs Interface
ā Tasks: Freeze, Thaw
ā Device Power Management
ā Notifiers
ā Memory Snapshot
ļ¬ Section 2
ā Hibernate Algorithm
ā Resume Algorithm
ļ¬ Section 3
ā Android Wakelocks
ļ¬ Section 4
ā Appendix: Code Flow in Linux 2.6.29
Ā Ā
3. Scope of the Document
This Document is divided into following 4 sections:
ā Section 1 covers, in brief, the concepts required to understand
hibernate/resume implementation in Linux-2.6.29
ā Section 2 explains the hibernate/resume algorithm that is implemented in
Linux-2.6.29. Understanding of the concepts explained in the first section is a
prerequisite to understand the algorithm
ā Section 3 explains the Android Wakelock feature, which breaks the
/sys/power/state interface
ā The Appendix explains the hibernate/resume code flow in Linux 2.6.29
Ā Ā
4. ACPI Specification
The Advanced Configuration and Power Interface (ACPI) specification was
developed to establish industry common interfaces enabling robust operating
system (OS)-directed motherboard device configuration and power
management of both devices and entire systems. ACPI is the key element in
Operating System-directed configuration and Power Management (OSPM)
The interfaces and OSPM concepts defined within this specification are
suitable to all classes of computers including (but not limited to) desktop,
mobile, workstation, and server machines. From a power management
perspective, OSPM/ACPI promotes the concept that systems should conserve
energy by transitioning unused devices into lower power states including
placing the entire system in a low-power state (sleeping state) when possible.
Ā Ā
5. States defined by ACPI Specification
Global Power States:
Global power states apply to the entire system and are visible to the user
ļ¬ G0 Working: A state where the system dispatches user mode threads and
they execute. In this state peripheral devices are having their power state
changed dynamically
ļ¬G1 Sleeping: A state where the system consumes a small amount of power,
user mode threads are not being executed, and the system appears to be off.
Work can be resumed without rebooting the OS because large elements of
system context are saved by the h/w and rest by the system s/w
ļ¬ G2/S5 Soft Off: A state where the system consumes a minimal amount of
power. No user mode or system code is run. The system's context will not be
preserved by the h/w. The system must be restarted to return to the working
state
ļ¬ G3 Mechanical Off: A state that is entered and left by mechanical means
(turning off the system). The OS must be restarted to return to working state.
No h/w context is retained. Except for RTC, power consumption is zero
Ā Ā
6. States defined by ACPI Specification
Sleeping State Definitions:
Sleeping states are types of sleeping states within the global sleeping state
G1
ļ¬ S1: In this state no system context is lost (CPU or chip set) and h/w
maintains all system context
ļ¬ S2: This state is similar to S1 except that the CPU and system cache context
is lost (the OS is responsible for maintaining the caches and CPU context).
Control starts from the processorās reset vector after the wake event
ļ¬ S3: CPU, cache, and chip set context are lost in this state. Hardware
maintains memory context and restores some CPU and L2 configuration
context. Control starts from the processorās reset vector after the wake event
ļ¬ S4: The S4 sleeping state is the lowest power state. In order to reduce
power to a minimum, it is assumed that the hardware platform has powered
off all devices. Platform context is maintained
ļ¬S5 Soft Off: The S5 state is similar to the S4 state except that the OS does
not save any context. The system is in āsoftā off state and requires a complete
boot when it wakes Ā
Ā Ā
7. States defined by ACPI Specification
Device Power States:
Device power states are states of particular devices; as such they are
generally not visible to he user
ļ¬ D0: State in which device is on and running. It is receiving full power from
the system and is delivering full functionality to the user
ļ¬D1: Class-specific low-power state in which the device context may or may
not be lost. Buses in D1 cannot do anything to the bus that would force the
devices on that bus to lose context (Many Device classes may not define D1)
ļ¬ D2: Class-specific low-power state in which the device context may or may
not be lost. Attains greater power savings than D1. Buses in D2 can cause
devices on that bus to lose some context (e.g. the bus reduces power supplied
to the bus, thus forcing the device to turn off some of its functions). Devices in
D2 must be prepared for the bus to be in D2 or higher (Many Device classes
may not define D2)
ļ¬ D3: State in which device is off and not running. Device context is lost.
Power can be removed from the device
Ā Ā
8. System Power Management States
Standby/Power-On Suspend:
This state offers minimal, though real, power savings, while providing a very
low latency transition back to a working system. No operating state is lost (the
CPU retains power)
ACPI states mapping:
Sleeping state: S1
Device state: Devices which support D1 are put into D1. The ones which don't,
are left on
Ā Ā
9. System Power Management States
Suspend-to-RAM
This state offers significant power savings as everything in the system is put
into a low-power state, except for memory, which is placed in self-refresh
mode to retain its contents
System and device state is saved and kept in memory
ACPI states mapping:
Sleeping state: S3
Device state: All devices are suspended and put into D3
Ā Ā
10. System Power Management States
Suspend-to-Disk (Hibernation)
This state offers the greatest power savings. This state operates similarly to
Suspend-to-RAM, but includes a final step of writing memory contents to non-
volatile storage. On resume, this is read and memory is restored to its pre-
suspend state
For suspend-to-disk, a mechanism called swsusp called 'swsusp' (Swap
Suspend) is used to write memory contents to free swap space. Once memory
state is written to disk, the system may either enter a low-power state (like
ACPI S4), or it may simply power down. Powering down offers greater savings,
and allows this mechanism to work on any system. However, entering a real
low-power state allows the user to trigger wake up events (e.g. pressing a key
or opening a laptop lid)
ACPI states mapping:
Sleeping state: S4
Device state: All devices are suspended and put into D3
Ā Ā
12. Sysfs Interface
The interface exists in /sys/power/ directory
/sys/power/state:
This controls the system power state
Reading from this file returns what states are supported:
ļ¬ 'standby': Power-on Suspend
ļ¬ 'mem': Suspend-to-RAM
ļ¬ 'disk': Suspend-to-Disk
Writing to this file one of these strings causes the system to transition into
that state
Ā Ā
13. Sysfs Interface
/sys/power/disk:
This controls the operating mode of the Suspend-to-Disk mechanism
Operating modes:
ļ¬ 'platform': put the system to sleep using platform driver (ACPI)
ļ¬ 'shutdown': power off the system
ļ¬ 'reboot': reboot the system (for testing)
ļ¬ 'testproc': will cause the kernel to disable nonboot CPUs and freeze tasks,
wait for 5 seconds, unfreeze tasks and enable nonboot CPUs
ļ¬ 'test': will cause the kernel to disable nonboot CPUs and freeze tasks, shrink
memory, suspend devices, wait for 5 seconds, resume devices, unfreeze tasks
and enable nonboot CPUs
Reading from this file will display all supported modes and the currently
selected one in brackets
Writing one of the strings to this file will select the corresponding mode
When 'disk' is written to /sys/power/state the Suspend-to-Disk mechanism will
work according to the selected mode
Ā Ā
14. Sysfs Interface
/sys/power/image_size:
This controls the size of the image created by the Suspend-to-Disk mechanism
It can be written a string representing a non-negative integer that will be used
as an upper limit of the image size, in bytes. The suspend-to-disk mechanism
will do its best to ensure the image size will not exceed that number.
However, if this turns out to be impossible, it will try to suspend anyway using
the smallest image possible. In particular, if "0" is written to this file, the
suspend image will be as small as possible
Reading from this file will display the current image size limit, which is set to
500 MB by default
/sys/power/resume:
Reading from this file will display the major:minor numbers of the swap
partition to be used for Suspend-to-Disk
Writing major:minor numbers to this file will cause the system to resume from
the mentioned partition
Ā Ā
15. Tasks: Freeze, Thaw
The freezing of tasks is a mechanism by which user space processes and
some kernel threads are controlled during hibernation or system-wide
suspend. The tasks are frozen before the hibernation image is created and are
thawed after the system memory state has been restored from a hibernation
image and devices have been reinitialized
Relevant flags:
include/linux/shed.h:
ļ¬ PF_NOFREEZE: this thread should not be frozen
ļ¬ PF_FROZEN: frozen for system suspend
ļ¬ PF_FREEZER_SKIP: Freezer should not count it as freezable
arch/arm/include/asm/thread_info.h
ļ¬ TIF_FREEZE
The tasks that have PF_NOFREEZE unset (all user space processes and some
kernel threads) are regarded as 'freezable' and treated in a special way before
the system enters a suspend state as well as before a hibernation image is
created
Ā Ā
16. Tasks: Freeze, Thaw
kernel/power/process.c, include/linux/freeze.h
Freeze:
freeze_processes():
It executes try_to_freeze_tasks() that sets TIF_FREEZE for all the freezable
tasks and either wakes them up, if they are kernel threads, or sends fake
signals to them if they are user space processes
A task that has TIF_FREEZE set should react to it by calling the function
refrigerator(), which sets the task's PF_FROZEN flag, changes its state to
TASK_UNINTERRUPTIBLE and makes it loop until PF_FROZEN is cleared for it.
Then, we say that the task is 'frozen'
For user space processes try_to_freeze() is called automatically from the
signal-handling code, but the freezable kernel threads need to call it explicitly
in suitable places or use the wait_event_freezable() or
wait_event_freezable_timeout()
Ā Ā
17. Tasks: Freeze, Thaw
Thaw:
thaw_processes():
It clears the PF_FROZEN flag for each frozen task. Then the tasks that have
been frozen leave the refrigerator() and continue running
Ā Ā
18. Tasks: Freeze, Thaw
Why is freezing of tasks required:
ļ¬ To prevent filesystems from being damaged after hibernation. The
hibernation image contains some filesystem-related information that must be
consistent with the state of the on-disk data and metadata after the system
memory state has been restored from the image (otherwise the filesystems
will be damaged in a nasty way). This is accomplished by freezing the tasks
that might cause the on-disk filesystems' data and metadata to be modified
after the hibernation image has been created and before the system is finally
powered off. The majority of these are user space processes, but if any of the
kernel threads may cause something like this to happen, they have to be
freezable
ļ¬ To create the hibernation image a sufficient amount of memory
(approximately 50% of available RAM) needs to be freed before the devices
are deactivated. Then, after the memory for the image has been freed, we
don't want tasks to allocate additional memory and that is prevented by
freezing them earlier
ļ¬To prevent user space processes and some kernel threads from interfering
with the suspending and resuming of devices
Ā Ā
19. Device Power Management
System Sleep Model:
Drivers can enter low power states as part of entering system-wide low-power
states like Suspend-to-Ram, Suspend-to-Disk (hibernation)
This is something that device, bus, and class drivers collaborate on by
implementing various role-specific suspend and resume methods to
cleanly power down hardware and software subsystems, then reactivate them
without loss of data
Ā Ā
20. Device Power Management
include/linux/device.h:
Bus Driver Methods:
The core methods to suspend and resume devices reside in struct bus_type.
Bus drivers implement those methods as appropriate for the hardware and the
drivers using it
struct bus_type {
...
int (*suspend)(struct device *dev, pm_message_t state);
int (*suspend_late)(struct device *dev, pm_message_t state);
int (*resume_early)(struct device *dev);
int (*resume)(struct device *dev);
struct dev_pm_ops *pm;
};
Ā Ā
21. Device Power Management
Upper layers of driver stacks:
Device drivers generally have at least two interfaces, and the but_type
methods are the ones which apply to the lower level (bus hardware). The
network and block layers are examples of upper level interfaces, as is a
character device talking to userspace.
Power management requests normally need to flow through those upper
levels, which often use domain-oriented requests. In some cases those upper
levels will have power management intelligence that relates to end-user
activity, or other devices that work in cooperation.
For the upper level interfaces that are structured using class interfaces, there
is a standard way to have the upper layer stop issuing requests to a given
class device (and restart later)
struct class {
...
int (*suspend)(struct device *dev, pm_message_t state);
int (*resume)(struct device *dev);
struct dev_pm_ops *pm;
};
Ā Ā
22. Device Power Management
Device:
struct device {
...
struct device_type *type;
struct bus_type *bus;
struct class *class;
...
};
struct device_type {
...
int (*suspend)(struct device *dev, pm_message_t state);
int (*resume)(struct device *dev);
struct dev_pm_ops *pm;
};
Ā Ā
23. Device Power Management
include/linux/sysdev.h:
Sysdev:
struct sysdev_class {
ā¦
struct list_head drivers;
int (*shutdown)(struct sys_device *);
int (*suspend)(struct sys_device *, pm_message_t state);
int (*resume)(struct sys_device *);
};
struct sysdev_driver {
...
int (*shutdown)(struct sys_device *);
int (*suspend)(struct sys_device *, pm_message_t state);
int (*resume)(struct sys_device *);
};
struct sys_device {
...
struct sysdev_class *cls;
};
Ā Ā
24. Device Power Management
include/linux/pm.h:
struct dev_pm_ops {
int (*prepare)(struct device *dev);
void (*complete)(struct device *dev);
int (*suspend)(struct device *dev);
int (*resume)(struct device *dev);
int (*freeze)(struct device *dev);
int (*thaw)(struct device *dev);
int (*poweroff)(struct device *dev);
int (*restore)(struct device *dev);
int (*suspend_noirq)(struct device *dev);
int (*resume_noirq)(struct device *dev);
int (*freeze_noirq)(struct device *dev);
int (*thaw_noirq)(struct device *dev);
int (*poweroff_noirq)(struct device *dev);
int (*restore_noirq)(struct device *dev);
};
Ā Ā
25. Device Power Management
ļ¬ prepare(): Prepare the device for the upcoming transition, but do NOT
change its hardware state. Prevent new children of the device from being
registered after prepare() returns (the driver's subsystem and generally the
rest of the kernel is supposed to prevent new calls to the probe method from
being made too once prepare() has succeeded)
ļ¬ freeze(): Hibernation-specific, executed before creating a hibernation
image. Quiesce operations so that a consistent image can be created, but do
NOT otherwise put the device into a low power device state and do NOT emit
system wakeup events. Save in main memory the device settings to be used
by restore() during the subsequent resume from hibernation or by the
subsequent thaw(), if the creation of the image or the restoration of main
memory contents from it fails
ļ¬ thaw(): Hibernation-specific, executed after creating a hibernation image
OR if the creation of the image fails. Also executed after a failing attempt to
restore the contents of main memory from such an image. Undo the changes
made by the preceding freeze(), so the device can be operated in the same
way as immediately before the call to freeze()
Ā Ā
26. Device Power Management
ļ¬ poweroff(): Hibernation-specific, executed after saving a hibernation
image. Quiesce the device, put it into a low power state appropriate for the
upcoming system state, and enable wakeup events as appropriate
ļ¬ restore(): Hibernation-specific, executed after restoring the contents of
main memory from a hibernation image. Driver starts working again,
responding to hardware events and software requests
ļ¬ complete(): Undo the changes made by prepare(). This method is
executed for all kinds of resume transitions, following one of the resume
callbacks: resume(), thaw(), restore(). Also called if the state transition fails
before the driver's suspend callback (suspend(), freeze(), poweroff()) can be
executed. The PM core executes complete() after it has executed the
appropriate resume callback for all devices
ļ¬ freeze_noirq(), thaw_noirq(), poweroff_noirq(), restore_noirq():
Complete the operations of the corresponding function (freeze(), thaw(),
poweroff(), restore()) by carrying out any actions required for freezing the
device that need interrupts to be disabled
Ā Ā
27. Device Power Management
Relevant P_EVENT_ messages:
ļ¬ P_EVENT_FREEZE: System is going to hibernate, call prepare() and freeze()
for all devices
ļ¬ P_EVENT_THAW: Hibernation image has been created, call thaw() and
complete() for all devices
ļ¬P_EVENT_HIBERNATE: Hibernation image has been saved, call prepare() and
poweroff() for all devices
ļ¬ P_EVENT_QUIESCE: Contents of main memory are going to be restored from
a (loaded) hibernation image, call prepare() and freeze() for all devices
ļ¬ P_EVENT_RESTORE: Contents of main memory have been restored from a
hibernation image, call restore() and complete() for all devices
Ā Ā
28. Notifiers
There are some operations that device drivers may want to carry out in their
suspend()/prepare() routines, but shouldn't, because they can cause the
hibernation or suspend to fail. For example, a driver may want to allocate a
substantial amount of memory (like 50 MB) in suspend()/prepare(), but that
shouldn't be done after the swsusp's memory shrinker has run. Also, there
may be some operations, that subsystems want to carry out before a
hibernation/suspend or after a restore/resume, requiring the system to be
fully functional
A Hibernation notifier may be used for this purpose. The subsystems that
have such needs can register suspend notifiers that will be called upon the
following events by the suspend core:
ļ¬ PM_HIBERNATION_PREPARE: The system is going to hibernate or suspend,
tasks will be frozen immediately
ļ¬ PM_POST_HIBERNATION: The system memory state has been restored from a
hibernation image or an error occurred during the hibernation. Device drivers'
resume()/restore() callbacks have been executed and tasks have been thawed
Ā Ā
29. Notifiers
ļ¬ PM_RESTORE_PREPARE: The system is going to restore a hibernation image.
If all goes well the restored kernel will issue a PM_POST_HIBERNATION
notification
ļ¬PM_POST_RESTORE: An error occurred during the hibernation restore. Device
drivers' resume() callbacks have been executed and tasks have been thawed
ļ¬ PM_SUSPEND_PREPARE: The system is preparing for a suspend
ļ¬ PM_POST_SUSPEND: The system has just resumed or an error occurred
during the suspend. Device drivers' resume() callbacks have been executed
and tasks have been thawed
Ā Ā
30. Memory Snapshot
The hibernation core 'snapshots' system memory by indexing and copying
every active page in the system. Once a snapshot is complete, the saved
image and index is stored persistently
The snapshot sequence is a three-step process. First, all of the active pages
are indexed, enough new pages are allocated to clone these pages, then each
page is copied into its clone
The snapshot process has one critical requirement: that at least half of the
memory be free. For this the memory needs to be freed before the snapshot
is taken. This is done using the memory shrinker
Ā Ā
32. Hibernate
ļ¬ The power management notifiers registered for the event PM_HIBERNATION_PREPARE are
executed
ļ¬All the filesystems are synced (Flush file system buffers, force changed blocks to disk, update the
superblock)
ļ¬ Tasks are frozen
ļ¬ The platform driver is informed that hibernation is being started
ļ¬ The requisite memory to save the snapshot is freed using the memory shrinker
ļ¬ The devices are suspended for the event P_EVENT_FREEZE. For each dev in dpm_list the following
are executed (in sequence): (dev->bus->pm, dev->type->pm, dev->class->pm)->prepare(), dev-
>class->pm->freeze() or dev->class->suspend(), dev->type->pm->freeze() or dev->type-
>suspend(), dev->bus->pm->freeze() or dev->bus->suspend()
ļ¬ Machine is prepared for hibernation using the platform driver
ļ¬ Non-boot CPUs are taken offline
ļ¬ Interrupts are disabled on the main CPU
ļ¬Late suspend of the devices (that require interrupts to be disabled) is carried out for the event
PM_EVENT_FREEZE. For each dev in dpm_list the following is executed: dev->bus->pm-
>freeze_noirq() or dev->bus->suspend_late()
ļ¬ System devices are suspended for the event PM_EVENT_FREEZE. For each cls in system_kset->list
Ā following is executed (in sequence): (For each drv in cls->drivers) ->suspend(), cls->suspend()
the Ā
33. Hibernate
ļ¬ Co-processor and the processor state is saved
ļ¬ Atomic copy of the system memory (hibernation image) is created
ļ¬ The co-processor state is restored
ļ¬ System devices are resumed. For each cls in system_kset->list the following is executed (in
sequence): cls->resume(), (For each drv in cls->drivers) ->resume()
ļ¬ Early resume of the devices is carried out for the event PM_EVENT_THAW. For each dev in dpm_list
the following is executed: dev->bus->pm->thaw_noirq() or dev->bus->resume_early()
ļ¬ Interrupts are enabled on the main CPU
ļ¬ Non-boot CPUs are enabled
ļ¬ Machine is switched to normal mode mode of operation using platform driver
ļ¬ The devices are resumed for the event P_EVENT_THAW. For each dev in dpm_list the following is
executed (in sequence): dev->bus->pm->thaw() or dev->bus->resume(), dev->type->pm->thaw()
or dev->type->resume(), dev->class->pm->thaw() or dev->class->resume(), (dev->class->pm,
dev->type->pm, dev->bus->pm)->complete()
ļ¬ The platform driver is informed that the system has entered the working state
ļ¬ Hibernation image is saved in the allocated swap partition
ļ¬ Machine is shutdown
Ā Ā
35. Resume
ļ¬ Probing of the known devices is allowed to be finished before proceeding
ļ¬ The swsusp signature is checked for in the resume device
ļ¬ The power management notifiers registered for the event PM_RESTORE_PREPARE are executed
ļ¬ Tasks are frozen
ļ¬ Hibernation image is loaded into RAM
ļ¬ The devices are suspended for the event P_EVENT_QUIESCE. For each dev in dpm_list the following
is executed (in sequence): (dev->bus->pm, dev->type->pm, dev->class->pm)->prepare(), dev-
>class->pm->freeze() or dev->class->suspend(), dev->type->pm->freeze() or dev->type-
>suspend(), dev->bus->pm->freeze() or dev->bus->suspend()
ļ¬ The platform is prepared for restoration from a hibernation image
ļ¬ Non-boot CPUs are taken offline
ļ¬ Interrupts are disabled on the main CPU
ļ¬Late suspend of the devices (that require interrupts to be disabled) is carried out for the event
PM_EVENT_QUIESCE. For each dev in dpm_list the following is executed: dev->bus->pm-
>freeze_noirq() or dev->bus->suspend_late()
ļ¬ System devices are suspended for the event PM_EVENT_QUIESCE. For each cls in system_kset-
>list the following is executed (in sequence): (For each drv in cls->drivers)->suspend(), cls-
>suspend()
Ā Ā
36. Resume
ļ¬ Control is passed to the target kernel. This also restores the processor state
ļ¬ Co-processor state is restored
ļ¬ Machine is prepared for switching to normal mode of operation using the platform driver
ļ¬ System devices are resumed. For each cls in system_kset->list the following is executed (in
sequence): cls->resume(), (For each drv in cls->drivers)->resume()
ļ¬ Early resume of the devices is carried out for the event PM_EVENT_RESTORE. For each dev in
dpm_list the following is executed: dev->bus->pm->restore_noirq() or dev->bus->resume_early()
ļ¬ Interrupts are enabled on the the main CPU
ļ¬ Non-boot CPUs are enabled
ļ¬ Machine is switched to normal mode of operation using the platform driver
ļ¬The devices are resumed for the event P_EVENT_RESTORE. For each dev in dpm_list the following is
executed (in sequence): dev->bus->pm->restore() or dev->bus->resume(), dev->type->pm-
>restore() or dev->type->resume(), dev->class->pm->restore() or dev->class->resume(), (dev-
>class->pm, dev->type->pm, dev->bus->pm)->complete()
ļ¬ The platform driver is informed that the system has entered the working state
ļ¬ Tasks are thawed
ļ¬ Power management notifiers are executed for PM_POST_HIBERNATION
Ā Ā
37. Android Wakelocks
Android supports its own Power Management (on top of the standard Linux
Power Management) designed with the premise that the CPU shouldn't
consume power if no applications or services require power
Android requires that applications and services request CPU resources with
"wake locks" through the Android application framework and native Linux
libraries. If there are no active wake locks, Android will shut down the
CPU
The default behavior for the system is to suspend, even if a process is
running; keeping a system awake may involve a chain of wakelocks obtained
by various software components. Therefore Wakelocks don't go well with
the existing /sys/power/state interface
If a wakelock is being held, and if we trigger hibernation through
/sys/power/state, it will fail
Ā Ā
38. Appendix: Code Flow in Linux 2.6.29
kernel/power/disk.c: hibernate()
ļ¬ kernel/power/console.c::pm_prepare_console()
ļ¬kernel/power/main.c::pm_notifier_call_chain(): Call the notifier functions registered for the event
PM_HIBERNATION_PREPARE
ļ¬ fs/sync.c::sys_sync(): Sync all the file systems. Flush file system buffers, force changed blocks to disk, update the
super block
ļ¬ kernel/power/disk.c::prepare_processes():
ā kernel/power/process.c::freeze_processes(): Freeze the tasks
ļ¬ kernel/power/disk.c::hibernation_snapshot(): Quiesce devices and create the hibernation snapshot image
ā kernel/power/disk.c::platform_begin()
ā kernel/power/swsusp.c::swsusp_shrink_memory():
ā¢ mm/vmscan.c::shrink_all_memory(): Free pages from memory (LRU)
ā kernel/printk.c::suspend_console(): Suspend the console subsystem, this disables printk
ā drivers/base/power/main.c::device_suspend(event: P_EVENT_FREEZE): For each dev in dpm_list invoke the
sequence: (dev->bus->pm, dev->type->pm, dev->class->pm)->prepare(), dev->class->pm->freeze() or
dev->class->suspend(), dev->type->pm->freeze() or dev->type->suspend(), dev->bus->pm->freeze() or
dev->bus->suspend()
ā kernel/power/disk.c::platform_pre_snapshot()
ā kernel/cpu.c::disable_nonboot_cpus(): Take down all the non-boot CPUs
ā kernel/power/disk.c::create_image():
ā¢ arch/arm/include/asm/suspend.h::arch_prepare_suspend()
Ā Ā
39. Appendix: Code Flow in Linux 2.6.29
ā¢ drivers/base/power/main.c::device_pm_lock(): Lock the list of active devices used by the PM core
ā¢ include/linux/irqflags.h::local_irq_disable()
ā¢ drivers/base/power/main.c::device_power_down(event: P_EVENT_FREEZE): For each dev in dpm_list
invoke: dev->bus->pm->freeze_noirq() or dev->bus->suspend_late()
ā¢ drivers/base/sys.c::sysdev_suspend(event: P_EVENT_FREEZE): For each cls in system_kset->list invoke
the sequence: (For each drv in cls->drivers)->suspend(), cls->suspend()
ā¢ arch/arm/power/cpu.c::save_processor_state(): KESSLER: Save the co-processor registers
ā¢ arch/arm/power/swsusp.S::swsusp_arch_suspend(): KESSLER:
ā Save processor registers for different modes
ā kernel/power/snapshot.c::swsusp_save(): Create and copy hibernation image
Ā» Spill the per-cpu pages from the cpu back to buddy allocator
Ā» kernel/power/snapshot.c::count_data_pages(): Compute the total number of savable non-
highmem pages
Ā» kernel/power/snapshot.c::count_highmem_pages(): Compute the total number of savable
highmempages
Ā» kernel/power/snapshot.c::enough_free_mem(): Make sure enough free memory for
snapshot image is available
Ā» kernel/power/snapshot.c::swsusp_alloc(): Allocate memory for suspend image
Ā» mm/page-alloc.c:drain_local_pages(): Kill the new cold pages created during allocation
Ā» kernel/power/snapshot.c::copy_data_pages()
THE RESTORE CONTROL FLOW RETURNS HERE WHEN THIS HIBERNATION
IMAGE IS RESTORED
ā¢ arch/arm/power/cpu.c::restore_processor_state(): KESSLER: Restore the co-processor registers
ā¢ drivers/base/sys.c::sysdev_resume(): For each cls in system_kset->list invoke the sequence: cls-
Ā Ā
>resume(), (For each drv in cls->drivers) ->resume()
40. Appendix: Code Flow in Linux 2.6.29
ā¢ drivers/base/power/main.c::device_power_up(event: P_EVENT_THAW): For each dev in dpm_list invoke:
dev->bus->pm->thaw_noirq() or dev->bus->resume_early()
ā¢ Include/linux/irqflags.h::local_irq_enable()
ā¢ drivers/base/power/main.c::device_pm_unlock(): Unlock the list of active PM devices used by the PM
core
ā kernel/cpu.c:enable_nonboot_cpus(): Enable the non-boot CPUs
ā kernel/power/disk.c::platform_finish()
ā drivers/base/power/main.c::device_resume(event: P_EVENT_THAW)
ā kernel/printk.c::resume_console(): Resume the console subsystem. This enables printk
ā kernel/power/disk.c::platform_end()
ļ¬ kernel/power/swap.c::swsusp_write(): Write entire image and metadata
ā kernel/power/swap.c::swsusp_swap_check(): Check if the resume device is a swap device and get its index
ā kernel/power/snapshot.c::snapshot_read_next(): Read the system memory snapshot
ā kernel/power/swap.c::enough_swap(): To make sure enough swap is available to save the image
ā kernel/power/swap.c::save_image(): Save the suspend image data
ā kernel/power/swap.c::swsusp_close(): Close the swap device
ļ¬ kernel/power/snapshot.c::swsusp_free(): Free pages allocated for suspend
kernel/power/process.c:thaw_processes(): Thaw the tasks
Ā Ā
ļ¬
41. Appendix: Code Flow in Linux 2.6.29
ļ¬ kernel/power/disk.c::power_down(): Shut the machine down for hibernation
ā [HIBERNATION_SHUTDOWN mode]: kernel/sys.c::kernel_poweroff(): Shutdown everything and perform a
clean system power off
ā¢ kernel/sys.c::kernel_shutdown_prepare():
ā Call notifiers for SYS_POWER_OFF
ā drivers/base/core.c::device_shutdown(): For each dev in devices_kset->list invoke : (dev->bus or
dev->driver)->shutdown()
ā¢ kernel/cpu.c::disable_nonboot_cpus()
ā¢ drivers/base/sys.c::sysdev_shutdown: For each cls in system_kset->list invoke the sequence: cls-
>shutdown(), (For each drv in cls->drivers) ->shutdown()
ā¢ arch/arm/kernel/process.c::machine_power_off()
Ā Ā
42. Appendix: Code Flow in Linux 2.6.29
kernel/power/disk.c: software_resume()
ļ¬ drivers/base/dd.c::wait_for_device-probe(): Wait for known devices to complete their probing
ļ¬ init/do_mounts.c::name_to_dev_t(): Get the major and minor numbers for the swap partition
ļ¬ kernel/power/swap.c::swsusp_check(): Check for swap signature in resume device
ļ¬ kernel/power/console.c::pm_prepare_console()
ļ¬ kernel/power/main.c::pm_notifier_call_chain(): Call the notifier functions registered for the event
PM_RESTORE_PREPARE
ļ¬ kernel/power/disk.c::prepare_processes():
ā kernel/power/process.c::freeze_processes(): Freeze the tasks
ļ¬ kernel/power/swap.c::swsusp_read(): Read the hibernation image
ā kernel/power/swap.c::load_image(): Load the image
ļ¬ kernel/power/disk.c::hibernation_restore(): Quiesce devices and restore hibernation snapshot image
ā kernel/power/console.c::pm_prepare_console()
ā kernel/printk.c::suspend_console(): Suspend the console subsystem, this disables printk
ā drivers/base/power/main.c::device_suspend(event: P_EVENT_QUIESCE): For each dev in dpm_list invoke the
sequence: (dev->bus->pm, dev->type->pm, dev->class->pm)->prepare(), dev->class->pm->freeze() or
dev->class->suspend(), dev->type->pm->freeze() or dev->type->suspend(), dev->bus->pm->freeze() or
dev->bus->suspend()
ā kernel/power/disk.c::platform_pre_restore()
ā kernel/cpu.c::disable_nonboot_cpus(): Take down all the non-boot CPUs
Ā Ā
43. Appendix: Code Flow in Linux 2.6.29
ā kernel/power/disk.c::resume_target_kernel(): prepare devices that need to be suspended with interrupts off,
restore the contents of highmem that have not been restored yet from the image and run the low level code
that will restore the remaining contents of memory and switch to the just restored target kernel
ā¢ drivers/base/power/main.c::device_pm_lock(): Lock the list of active devices used by the PM core
ā¢ include/linux/irqflags.h::local_irq_disable()
ā¢ drivers/base/power/main.c::device_power_down(event: P_EVENT_QUIESCE): For each dev in dpm_list
invoke: dev->bus->pm->freeze_noirq() or dev->bus->suspend_late()
ā¢ drivers/base/sys.c::sysdev_suspend(event: P_EVENT_QUIESCE): For each cls in system_kset->list
invoke the sequence: (For each drv in cls->drivers)->suspend(), cls->suspend()
ā¢ arch/arm/power/cpu.c::save_processor_state(): KESSLER: Save the co-processor registers
ā¢ kernel/power/snapshot.c::restore_highmem(): for each highmem page that was allocated before the
suspend and included in the suspend image, and also has been allocated by the "resume" kernel swap
its current (ie. "before resume") contents with the previous (ie. "before suspend") one
ā¢ arch/arm/power/swsusp.S::swsusp_arch_resume(): KESSLER: Restore "nr_copy_pages" pages which are
saved and specified at "pagedir_nosave". Restore the processor registers in different modes.
THIS FUNCTION TRANSFERS THE CONTROL TO THE TARGET KERNEL. THE
TARGET KERNEL RESUMES FROM THE RETURN OF
arch/arm/power/swsusp.S::swsusp_arch_suspend() IN
kernel/power/disk.c::create_image()
ā kernel/power/disk.c::create_image():
ā¢ arch/arm/power/swsusp.S::swsusp_arch_suspend(): returns
ā¢ arch/arm/power/cpu.c::restore_processor_state(): KESSLER: Restore the co-processor registers
ā¢ kernel/power/disk.c::platform_leave()
Ā Ā
44. Appendix: Code Flow in Linux 2.6.29
ā¢ drivers/base/sys.c::sysdev_resume(): For each cls in system_kset->list invoke the sequence: cls-
>resume(), (For each drv in cls->drivers) ->resume()
ā¢ drivers/base/power/main.c::device_power_up(event: P_EVENT_RESTORE): For each dev in dpm_list
invoke: dev->bus->pm->thaw_noirq() or dev->bus->resume_early()
ā¢ Include/linux/irqflags.h::local_irq_enable()
ā¢ drivers/base/power/main.c::device_pm_unlock(): Unlock the list of active PM devices used by PM core
RETURN TO kernel/power/disk.c::hibernation_snapshot()
ļ¬ kernel/power/disk.c::hibernation_snapshot():
ā kernel/cpu.c:enable_nonboot_cpus(): Enable the non-boot CPUs
ā kernel/power/dosk.c::platform_finish()
ā drivers/base/power/main.c::device_resume(event: P_EVENT_RESTORE)
ā kernel/printk.c::resume_console(): Resume the console subsystem. This enables printk
ā kernel/power/disk.c::platform_end()
RETURN TO kernel/power/disk.c::hibernate()
kernel/power/disk.c: hibernate()
ļ¬ kernel/power/snapshot.c::swsusp_free(): Free pages allocated for suspend
ļ¬ kernel/power/process.c:thaw_processes(): Thaw the tasks
ļ¬ kernel/power/main.c::pm_notifier_call_chain(): Call the notifier functions registered for the event
PM_POST_HIBERNATION
Ā kernel/power/console.c::pm_restore_console()
ļ¬
Ā