blob: 48136c86797c8102070cfe26171618e2ff75dd8b [file] [log] [blame] [view]
# Suspend States (from Zircon's perspective)
From Zircon's perspective, there are different kinds of "suspend": system
suspend, task scheduling suspend (per-CPU), and platform-specific suspend
(per-CPU), and CPU Idle.
## System Suspend State
This is a system-wide state that is entered when a user program calls
[`zx_system_suspend_enter()`]. The defining characteristic is that while in
this state, task execution is suspended for all CPUs. That is, while in this
state, no user thread will execute. However, Zircon's interrupt handlers as
well each CPU's special "idle power thread" (part of Zircon) *may* continue to
execute as necessary. More on this below.
When entering this state Zircon identifies which interrupts are designated as
wake vectors (`ZX_INTERRUPT_WAKE_VECTOR`) and ensures that only those interrupts
will bring the system out of this state.
This state builds on Task Scheduling Suspend State (see below). In order for
the system to enter this state, every CPU must enter the Task Scheduling Suspend
State.
## Task Scheduling Suspend State
This is a per-CPU state. When a CPU is in this state, its special "idle power
thread" is the only task that may execute. This task is responsible for
managing state transitions, waking the system when necessary, and putting the
CPU into a Platform-Specific Suspend State or none is available, a CPU Idle
State.
## Platform-Specific Suspend State
This is a per-CPU state that's defined by the platform layer (think "PC" or
"generic ARM"). Currently, this state is only supported on the arm64
architecture and only for QEMU and Sorrel.
On Sorrel, this state is implemented via PSCI CPU_SUSPEND (see below).
When entering a Platform-Specific Suspend State, Zircon makes no effort to mask
off or otherwise disable hardware interrupts (think SPIs). If, prior to
entering this state, a particular device had been configured to generate an
interrupt on some event *and* that event occurs while in this state, the
interrupt will be generated and the CPU will leave this state.
The CPU's handler will then execute and determine whether the interrupt is a
wake vector or not. If the interrupt *is* a wake vector, then the CPU's idle
power thread will begin to transition all CPUs out of their Task Scheduling
Suspend State and the system out of System Suspend. If the interrupt is *not* a
wake vector, then the idle power thread will immediately re-enter the
Platform-Specific Suspend State.
### PSCI CPU_SUSPEND
This is a state that a CPU enters by issuing a `CPU_SUSPEND` PSCI call. On
Sorrel, this call comes in two flavors. One flavor is for putting just the
calling CPU into a suspend state. The other flavor is for putting the last
non-suspended CPU into suspend and powering down the AP complex. That is,
entering AP Power Collapse.
When in this state, interrupting the CPU will cause the CPU to resume execution
(i.e. leave this state).
## CPU Idle
This isn't really a suspend state. A CPU enters this state whenever it has
nothing better to do. The CPU will pause execution, enter a lower power state
and wait until an interrupt occurs or another CPU has asked it to resume
execution. On arm64 and riscv64, this is done using a `WFI` instruction. On
x64, we use either `MWAIT` or `HLT`. While a CPU may enter this state during
any of the above suspend states, this state is not inherently tied to System
Suspend, or Task Scheduling Suspend.
[`zx_system_suspend_enter()`]: /reference/syscalls/system_suspend_enter.md