从 Zircon 的角度来看,有不同类型的“暂停”:系统暂停、任务调度暂停(每个 CPU)、平台专用暂停(每个 CPU)和 CPU 空闲。
系统挂起状态
这是一个系统级状态,当用户程序调用 zx_system_suspend_enter() 时,系统会进入此状态。此状态的显著特征是,当设备处于此状态时,所有 CPU 的任务执行都会暂停。也就是说,在此状态下,不会执行任何用户线程。不过,Zircon 的中断处理程序以及每个 CPU 的特殊“空闲电源线程”(Zircon 的一部分)可能会根据需要继续执行。下文将对此进行详细介绍。
进入此状态时,Zircon 会识别哪些中断被指定为唤醒向量 (ZX_INTERRUPT_WAKE_VECTOR),并确保只有这些中断才能使系统退出此状态。
此状态基于任务调度暂停状态(见下文)。为了使系统进入此状态,每个 CPU 都必须进入任务调度暂停状态。
任务调度暂停状态
这是每个 CPU 的状态。当 CPU 处于此状态时,只有其特殊的“空闲电源线程”可以执行。此任务负责管理状态转换、在必要时唤醒系统,以及将 CPU 置于平台特定的挂起状态(如果无可用状态,则置于 CPU 空闲状态)。
特定于平台的暂停状态
这是由平台层(例如“PC”或“通用 ARM”)定义的每个 CPU 的状态。目前,此状态仅在 arm64 架构上受支持,并且仅适用于 QEMU 和 Sorrel。
在 Sorrel 上,此状态通过 PSCI CPU_SUSPEND(见下文)实现。
当进入平台特定的挂起状态时,Zircon 不会尝试屏蔽或以其他方式停用硬件中断(例如 SPI)。如果某个特定设备在进入此状态之前已配置为在某个事件发生时生成中断,并且该事件在此状态下发生,则会生成中断,并且 CPU 将离开此状态。
然后,CPU 的处理程序将执行并确定中断是否为唤醒向量。如果中断是唤醒向量,则 CPU 的空闲电源线程将开始使所有 CPU 从其任务调度挂起状态转换出来,并使系统从系统挂起状态转换出来。如果中断不是唤醒向量,则空闲电源线程将立即重新进入平台专用挂起状态。
PSCI CPU_SUSPEND
这是 CPU 通过发出 CPU_SUSPEND PSCI 调用进入的状态。在 Sorrel 上,此调用有两种版本。一种风格是将调用 CPU 置于挂起状态。另一种变体是将最后一个非挂起 CPU 置于挂起状态并关闭 AP 复合体。也就是说,进入 AP 电源崩溃状态。
在此状态下,中断 CPU 将导致 CPU 恢复执行(即离开此状态)。
CPU 空闲
这实际上并不是挂起状态。当 CPU 没有更好的事情可做时,就会进入此状态。CPU 将暂停执行,进入低功耗状态,并等待中断发生或另一个 CPU 要求其恢复执行。在 arm64 和 riscv64 上,这是通过 WFI 指令完成的。在 x64 上,我们使用 MWAIT 或 HLT。虽然 CPU 可以在上述任何挂起状态期间进入此状态,但此状态并非与系统挂起或任务调度挂起固有相关。