| RFC-0255:系统活动调节器 | |
|---|---|
| 状态 | 已接受 |
| 区域 |
|
| 说明 | 定义了一个组件,该组件利用电源拓扑概念来管理平台的挂起状态。 |
| 问题 | |
| Gerrit 更改 | |
| 作者 | |
| 审核人 | |
| 提交日期(年-月-日) | 2024-05-07 |
| 审核日期(年-月-日) | 2024-08-02 |
摘要
此 RFC 建议添加一个名为“系统活动调控器”(SAG) 的核心组件来管理系统的功率级别。本文档介绍了 SAG 的要求、政策以及在实现中使用的流程,以实现对系统电源级别的管理。此 RFC 可视为 RFC-0230:Fuchsia 中的 Suspend-To-Idle 的实现部分。
目标
- 启用对进入“挂起到空闲”状态的时间的管理。
- 提供有关暂停的统计信息,以进一步改进未来的电源并实现对整个车队的功耗监控。
非目标
- 实现特定硬件系统到不同电源状态的转换,包括但不限于 CPU、GPU、内存、网络接口等。
- 实现用于触发任务暂停的逻辑,例如
zx_system_suspend_enter。
设计初衷
Fuchsia 是一种通用操作系统,旨在为各种硬件和软件生态系统提供支持。为了满足对功耗敏感的硬件和软件的需求,Fuchsia 必须能够管理其运行的硬件平台的功耗。这包括能够将 CPU 转换为低功耗模式、触发系统级任务暂停、激活内存自刷新以及任意数量的其他省电硬件功能。旨在降低能耗的一组硬件配置或状态被归类为一个称为挂起状态的概念。
许多系统都支持多种挂起状态。每个挂起状态都有一组硬件状态、能耗和恢复延迟时间(退出挂起状态的时间延迟)。每个系统在概念上可能定义了相同的挂起状态(挂起到空闲),但该状态会映射到完全不同的硬件配置。
例如,Fuchsia 可能在两个具有不同 CPU 的系统上运行。一个 CPU 可能支持比另一个 CPU 功耗更低的电源状态;不过,这两个系统都可能会将转换到最低功耗状态视为进入 Suspend-to-Idle 状态的操作之一。
在考虑此主题时,平台的状态如下:
- RFC-0230:Fuchsia 中的挂起到空闲状态定义了挂起到空闲状态的高级要求和设计。目前,这是 Fuchsia 平台支持的唯一一种暂停状态。
- RFC-0250:电源拓扑定义了电源拓扑,该拓扑是 Fuchsia 中未来电源管理系统的基础。
- 另一份 RFC 定义了在运行时管理电源拓扑的组件:电源代理。
- 必须解读来自各种子系统的各种信号,才能协调转换到挂起到空闲状态。
为了使用 RFC-0250:电源拓扑实现 RFC-0230:Fuchsia 中的挂起到空闲,需要创建一个实现政策以管理向挂起到空闲的过渡的组件:系统活动调控器。
利益相关方
辅导员:
Adam Barth abarth@google.com
审核者:
- Aidan Wolter awolter@google.com(软件组装)
- Andres Oportus andresoportus@google.com(平台驱动程序)
- Gary Bressler geb@google.com(组件框架)
- Gurjant Kalsi gkalsi@google.com(平台驱动程序)
- Harsha Priya N V harshanv@google.com(驱动程序框架)
- Justin Mattson jmatt@google.com(驱动程序框架)
- Kyle Gong kgong@google.com(电源)
- Mukesh Agrawal quiche@google.com (界面)
- Nick Maniscalco maniscalco@google.com(Zircon 内核)
- Onath Dillinger claridge@google.com(电源)
已咨询:
- Alice Neels neelsa@google.com(界面)
- David Gilhooley dgilhooley@google.com(组件框架)
- Didi She didis@google.com(Power)
- Eric Holland hollande@google.com(权力)
- Filip Filmar fmil@google.com(界面)
- Guocheng Wei guochengwei@google.com (Starnix)
- HanBin Yoon hanbinyoon@google.com(平台驱动程序)
- John Wittrock wittrock@google.com(软件交付)
- Novin Changizi novinc@google.com(驱动程序框架)
- Suraj Malhotra surajmalhotra@google.com(驱动程序框架)
共同化:
此设计已与负责管理内核、驱动程序、驱动程序框架、组件框架、产品政策和电源框架的电源团队和子系统所有者讨论过。
要求
支持转换到挂起状态的系统必须支持 Fuchsia 产品的用例以及挂起状态的硬件要求。为了在支持产品用例的同时正确促进向挂起的过渡,SAG 必须满足以下要求:
- Fuchsia 组件(包括驱动程序)必须能够在关键操作正在进行时阻止转换到挂起状态。例如,假设用户正在观看视频。设备不应在播放视频时尝试暂停系统;否则,用户体验会很差。
- 如需启用由产品驱动的暂停政策,必须收集并公开有关暂停的统计信息。例如,假设某个产品中,只有在上次恢复至少 1 秒后,才能触发向挂起状态的转换。为了使产品组件支持此功能,它必须能够计算自上次恢复转换以来的时间。
SAG 将仅负责确定何时进行转换。向每种挂起状态的过渡的定义和实现将由实现 SAG 使用的
fuchsia.hardware.power.suspend.Suspender协议的组件处理。此 RFC 推迟了对完整协议的定义,但Suspender必须提供以下功能:- 列出硬件支持的挂起状态。
- 将硬件转换为挂起状态。
在此设计中,SAG 充当系统执行代码能力的调控器(或限制器),通过 Fuchsia Suspend HAL(实现上述 Suspender 协议)将系统转换为挂起状态。为了适应这一概念,我们做出了以下假设:
- 硬件平台是指一组硬件和软件系统,可让计算设备执行此 RFC 中的代码。这通常包括 CPU、内存、操作系统以及这些组件正常运行所需的其他控制项(时钟树、电源域等)。这明确不包括传统的外围组件,例如微控制器单元、无线电、显示控制器、辅助存储空间(固态硬盘、eMMC)等。
- 希望支持硬件平台挂起的全部产品中必须存在电源代理组件。
- 在暂停期间,Fuchsia 组件(包括 SAG 本身)不会在 CPU 上执行。在微控制器或其他外围硬件上运行的固件可能会继续处理数据。当硬件平台进入挂起状态时,CPU 可能会离线,调度程序可能会更新其政策,而外围设备可能会更改配置。
- Fuchsia 组件必须(直接或间接)与电源拓扑集成,以允许和/或阻止转换到挂起状态。这种集中式会计机制使 SAG 能够了解系统的其余部分需要什么,而无需了解这些组件的状态。
- 不与电源拓扑集成的 Fuchsia 组件不得期望不间断执行。这要求任何需要不间断执行才能执行关键任务(例如从网络或外围设备接收数据)的组件通过直接或间接与电源框架交互(采用防止挂起中所述的方法之一)来考虑硬件平台挂起。
- 在唤醒中断挂起时,硬件平台不得挂起。这对所有驱动程序都很重要,因为无论驱动程序与电源框架的交互如何,它都能让驱动程序有机会处理中断。如果驱动程序需要在确认中断后执行更多处理,则必须与电源框架交互,以防止硬件平台挂起。
- SAG 必须可供驱动程序和急切组件使用,这些驱动程序和组件具有电源感知能力,并且存在于内核读取的第一个文件系统中(例如来自 RFC-0167:早期用户空间引导中的软件包的 bootfs)。如果没有此功能,电源感知型组件将无法设置电源配置来防止系统在 SAG 可用之前挂起。此外,在挂起转换期间,可以配置更高级别的文件系统,使其比存在于较低级别文件系统中的驱动程序更早断电。这会造成电源元件依赖性问题。
- SAG 将尽可能使用电源拓扑概念将硬件平台驱动到最低功耗水平。最终,设备进入/保持此最低功耗级别的时间长短取决于产品行为和政策、环境条件以及用户行为。
设计
系统活动调节器包含以下部分:
- 电源元件
- 用于初始化、状态管理和处理功率电平变化的业务逻辑。
- 一种 FIDL 服务,用于提供对有关暂停/恢复的统计信息的访问权限。
- FIDL 服务,以允许客户端保持硬件平台唤醒状态,并接收有关挂起/恢复转换的通知。
FIDL 服务的确切定义将推迟到 API 审核/校准会话中确定。
电源拓扑
如需了解电源拓扑图的惯例,请参阅 RFC-0250:电源拓扑。
SAG 会创建和管理一个电源元素 Execution State,该元素表示硬件平台执行代码的能力。此电源元素会汇总来自其他组件的信号,以确定何时应尝试挂起转换。
通过创建电源元素,SAG 可让其他组件:
- 只要硬件平台的执行状态保持断言声明,就提高其功率水平
- 说明硬件平台应继续通过电源元素及其依赖链执行代码的原因
- 通过保留机会性声明来响应执行状态的变化。
这还允许 SAG 实现针对
Execution State的每个依赖项的功率级变化产生副作用。 - 最重要的是,RFC-0250:电源拓扑要求电源元素趋向于其最低功率水平。当没有依赖的电源元素处于活动状态时,这自然会导致对硬件平台的执行状态采取控制操作。
执行状态
此电源元素尽可能贴近硬件平台执行代码的能力。它支持 3 个效力级别:
- 有效
- 暂停
- 无效
当硬件平台正常运行时,此元素应处于 Active 电源级别。当硬件平台处于 Inactive 电源级别时,应处于挂起状态或正尝试过渡到挂起状态。此时,只有不感知电源或与电源无关的设备部件应处于运行状态。如需详细了解此设计模式,请参阅按执行状态限制设备。如需详细了解何时以及如何触发挂起,请参阅挂起/恢复。
Suspending 功率等级介于 Inactive 和 Active 功率等级之间。此电源级别用于区分以下两种电源依赖项:仅允许在硬件平台运行时运行的电源依赖项,以及可能需要在硬件平台在挂起状态和运行状态之间转换时(无论哪个方向)运行的电源依赖项。如需了解此区别的实用场景,请参阅下方的存储空间示例。
设计模式
防止挂起
为防止硬件平台进入暂停状态,组件可以构建一个对 Execution State 具有肯定依赖关系的电源元素。
假设某产品具有媒体播放器功能。产品所有者希望媒体播放功能阻止硬件平台进入暂停状态,以便支持连续播放音乐。为了支持此功能,管理播放状态的组件可以创建对 Execution
State 的断言依赖项,以防止 SAG 触发暂停转换。
在上图中,媒体播放器组件有一个名为“播放”的电源元素。播放电源元素对 Execution State 的 Active 电源级别具有断言依赖性。当媒体播放需要开始时,媒体播放器组件将请求 Playback 的 Active 功率级租赁,以防止硬件平台暂停。满足租约后,媒体播放器组件可以运行媒体播放逻辑,而无需担心硬件平台意外暂停。
按执行状态限制设备
产品可以采用的一种强大模式是根据硬件平台的执行状态来限制设备的功率级别。这可用于将外围设备的功耗与硬件平台的挂起状态相关联。当硬件平台过渡到挂起状态时,驱动程序可以关闭其设备的电源或更改其配置。当硬件平台挂起时,此设置可能有助于产品关闭特定功能或子系统,从而降低功耗。
音频示例
考虑使用具有高耗电音频硬件的产品。产品所有者只希望在硬件平台处于唤醒状态时激活音频硬件。产品所有者可以使用对 Execution State 具有机会性依赖关系的电源拓扑来表示此配置。
在上图中,音频驱动程序(在图中称为“音频”)具有一个名为“电源”的电源元素。音频驱动程序对 Execution State 的 Active 电源级别具有机会性依赖关系。音频驱动程序可以通过从 Power Broker 请求租用来监视其依赖项是否已得到满足。当 Execution State 转换为 Active 时,音频驱动程序对电源的租用将得到满足。届时,音频驱动程序可以运行所需的任何逻辑来激活音频硬件。相反,当 Execution State 想要将其功率级别从 Active 降下来时,音频驱动程序对功率的租用变得不满足。届时,音频驱动程序可以运行逻辑来停用音频硬件,然后再通知 Power Broker 其电源元素的电源级别已降低。
处理唤醒中断
当硬件平台处于暂停状态时,可能会因外部刺激而恢复。这种外部刺激通常以由某个外围组件引发的 CPU 中断的形式出现。为了正确处理唤醒中断,需要发生以下情况:
- 驱动程序的唤醒向量是在挂起之前的某个时间点进行编程的。
- 处理中断时:
- 如果驱动程序正在等待端口上的中断,则其中断处理程序线程 (IHT) 由内核调度。
- IHT 或由其通知的其他组件可以创建租约来阻止硬件平台暂停。
- 驱动程序会根据需要与硬件和/或其他组件通信,以处理中断。在此期间,其他组件可能会请求租约。
- 驱动程序会在中断处理完成后调用
zx_interrupt_ack。
在处理中断时,SAG 可以随时运行,因为当硬件平台转换为挂起状态时,内核会恢复挂起的任务。
存储示例
请参阅按执行状态限制设备 中的音频示例。虽然存储硬件可能遵循与音频类似的模式,即在硬件平台暂停时通常处于关闭状态,但在硬件平台转换到暂停状态或恢复以处理唤醒中断时,存储硬件也会处于关闭状态。如果当前已分页调出的组件需要在挂起之前关闭电源并执行清理操作,则可能会导致问题。由于关机操作的顺序不确定,因此这种简化的设计是不够的。
解决此缺点的一种方法是允许存储驱动程序在转换发生时运行。
在上图中,名为“存储”的存储驱动程序具有两个电源元素:
- 电源对(执行状态,暂停)具有机会性依赖关系。当其他电源元素将
Execution State的电源级别提升到相应级别时,此依赖项将得到满足。只要存储驱动程序在执行状态上电到Suspending后保持对电源的租约,执行状态就无法降低其电源级别。这是必需的,可让存储驱动程序监控何时应关闭电源。 - 唤醒请求对(执行状态,挂起)具有断言依赖关系。此依赖项会强制
Execution State提升其功率级别。存储驱动程序会在收到存储请求时租用此电源元素。这是必需的,可让存储硬件即使在系统其他部分断电时也能启动。
处理系统级过渡
启动
当 SAG 首次启动时,在系统完成启动过程之前,它不会触发暂停。在此启动状态下,Execution State 电源元素应处于 Active 电源级别,以反映硬件平台正在积极运行且未尝试挂起的实际情况。
在此期间,其他组件可以创建影响 Execution State 的依赖项和租约;不过,在启动完成之前,Execution State 将始终处于 Active 电源级别。为了退出启动状态,必须通知由 SAG 托管的 FIDL 服务启动已完成。当系统的更高级别可以表达其电源需求时,例如在用户可以互动的会话期间,预计会使用此服务。
暂停/恢复
当 Execution State 电源级别为 Inactive(最低电源级别)时,将请求挂起转换。在开始挂起转换之前,SAG 会通知已注册的监听器即将发生挂起。为了正确处理自身、电源代理和中断处理驱动程序之间可能存在的竞态条件,SAG 需要满足以下条件:
- 如果唤醒中断未得到确认,Fuchsia Suspend HAL 必须返回错误。这可防止出现以下竞态条件:在中断处理程序有机会请求租约并确认中断之前,SAG 就已运行。
- 当挂起请求正在进行时,SAG 不得更改
Execution State的功率级别。当 SAG 从挂起状态恢复时,Execution State的功率级别应始终为Inactive。依赖于Execution State的设备将在转换到挂起状态之前和转换期间立即转换到并保持在适当的电源级别。SAG 会“锁定”Execution State的功率级别,方法是延迟处理 Power Broker 请求的功率级别更改,从而确保这一点。 - 如果驱动程序需要在确认中断后执行工作,则驱动程序或中断处理程序必须先获取租约,然后再确认中断。
当硬件平台恢复执行时,SAG 将收到来自 Suspender 设备的响应,其中指明了挂起请求的结果。然后,SAG 会将暂停请求的结果通知给注册的监听器。届时,监听器可以请求阻止硬件平台暂停的租约。如需了解详情,请参阅防止暂停。
暂停请求也可能会在发生转换之前失败。 这可能是由以下原因造成的:挂起的中断会立即唤醒硬件平台,或者 Fuchsia Suspend HAL 或内核中存在其他错误。当挂起请求失败时,SAG 会将失败情况通知给监听器,并等待所有监听器确认该通知。此设置允许产品级组件请求租约并更改系统配置,以防止重复发送最终会失败的暂停请求。
如果没有任何监听器在恢复过渡期间将功率级别提升到 Execution State,SAG 会记录此失败情况。如果监听器崩溃,或者产品没有有效(或不完整/正在开发中)的产品体验,则可能会出现此情形。
关闭
当系统中运行的组件请求关停或重新启动时,组件管理器会根据功能图开始终止组件。这会造成一个问题,即阻止硬件平台进入挂起状态的组件会在 SAG 之前终止。这会导致 SAG 在关停正在进行时错误地触发中止。
为解决此问题,负责协调关机(shutdown-shim 和/或 power-manager)的组件必须持有将 Execution
State 保持在 Suspending 电源级别的租约。由于 shutdown-shim 和 power-manager 是在重新启动之前最后几个仍在运行的组件,因此这可以防止出现错误的暂停。
实现
添加此功能需要进行许多单独的更改,并且需要关键子系统的支持,然后才能完成全面实现。此过程可分为以下步骤:
- 基本暂停支持
- 当
Execution State变为Inactive时,触发挂起 - 在恢复时发送监听器通知。
- 连接侦听器以接收恢复通知,从而使系统保持唤醒状态。
- 当
- 将所有关键子系统连接到 SAG 接口,使其能够感知电源状态。
- 优化了挂起时间。
- 公开来自内核和/或 Fuchsia Suspend HAL 的中断和/或其他唤醒条件的存在。
- 使用内核/Fuchsia Suspend HAL 信号来延迟触发预期会失败的暂停请求。
- 持续集成其他支持挂起的子系统。
性能
对系统性能的总体影响在很大程度上取决于 Power Broker 的性能。大多数 SAG 客户端会在初始化期间执行一次性调用来设置依赖项,后续互动将通过 Power Broker 间接进行。监听 SAG 事件的客户端会对系统性能产生直接影响,因为它们必须确认对恢复和暂停失败通知的处理。我们应密切监控这些事件处理程序的延迟时间指标,以确保及时处理各个产品中的恢复和暂停失败问题。最后,触发挂起的延迟由 Fuchsia Suspend HAL 报告。我们应监控此延迟时间,以确保在各种产品中及时完成挂起操作。这包括在发生暂停失败时,监控反转暂停请求的延迟时间和性能影响。
安全注意事项
RFC-0250:电源拓扑建立的电源框架定义了电源拓扑的安全模型。SAG 通过协议功能公开对电源元素的访问权限。通过访问此协议,其他电源元素可以依赖于 SAG 的电源元素。最终,SAG 安全性依赖于组件框架为路由协议功能提供的保证。
SAG 在协议功能方面依赖于 Fuchsia Suspend HAL 和 Power Broker。这些组件中任何偏离预期行为的情况都可能导致 SAG 实现出现异常行为。SAG 需要考虑缺失和行为异常的依赖项,以减轻潜在的级联负面影响。
注册监听器的客户端可能会滥用该功能。恶意组件可能会因未及时确认事件而阻止正常挂起或恢复。或许可以通过为响应设置超时时间来避免此类问题。
隐私注意事项
我们预计 SAG 不会收集任何个人身份信息;不过,SAG 会通过 FIDL 协议和 Inspect 收集并公开从暂停/恢复行为中派生的数据。此数据将在设备外系统中汇总,以供产品所有者和 Fuchsia 工程师进行分析。这需要对实现进行隐私权审核。
测试
SAG 将通过一系列集成测试和端到端测试进行测试。集成测试将确保 SAG 在内部状态之间正确转换并正确发送挂起请求。
客户端可以使用一组测试支持库(使用 Power Broker 和 SAG,但移除了 Fuchsia Suspend HAL)来测试其实现。此测试支持库将允许客户端调用 SAG 中的特定状态,以确保客户端组件能够正确响应这些更改。这包括确保由功率级转换触发的所有副作用都得到妥善处理。对于依赖于 SAG 电源元素的组件,完整的测试套件应包含以下场景:
- 无电源框架
- 初始启动状态下具有锁定功率等级的 SAG
Execution State,功率等级为ActiveExecution State,功率等级为SuspendingExecution State,功率等级为Inactive- (如适用)在关键操作期间不暂停
文档
需要提供详尽的文档来解释 SAG 在系统中的角色、配置(包括产品负责人的预期)、API 模式和测试支持库。文档应包含有关操作 SAG 电源元素和正确使用其 API 的示例和最佳实践。示例应包含上述设计模式部分中列出的场景的分步指南。
此文档应是电源框架及其概念的更大型文档集的一部分。
缺点、替代方案和未知因素
实现此提案的缺点是基于电源框架的总体缺点。
触发中止的信号是分散的。除非产品所有者组织组件来强制执行此模式,否则没有任何单个组件可以保证使用此 API 时会发生暂停。从 API 使用的角度来看,这会使系统的行为变得模糊不清。例如,当对 Execution State 具有租约的组件放弃租约时,如果其他组件具有租约,SAG 可能不会暂停。组件只有通过向 SAG 注册监听器才能知道挂起已触发,这会增加复杂性。
如果用户空间提供恢复延迟时间要求,Fuchsia 应遵守该要求。如果未提供恢复延迟时间,Fuchsia 应以尽可能低的恢复延迟时间进入挂起到空闲状态。
由于平台目前仅支持一种挂起状态,因此此 RFC 未考虑此要求。
我们尚未确定现场驱动程序和硬件的所有可能存在的电源控制模式,因此随着这些模式的发现,此设计可能需要不断改进。这包括但不限于恢复延迟时间考虑因素、对更多暂停状态的支持等。这些设计变更将根据需要在后续 RFC 中进行编纂。