| RFC-0250:电源拓扑 | |
|---|---|
| 状态 | 已接受 |
| 区域 |
|
| 说明 | 描述了系统电源管理将使用的相互依赖的状态管理模型。 |
| 问题 | |
| Gerrit 更改 | |
| 作者 | |
| 审核人 | |
| 提交日期(年-月-日) | 2024-03-09 |
| 审核日期(年-月-日) | 2024-06-03 |
摘要
系统电源管理的一个关键问题是支持各种系统元素(我们使用以下术语来简单地指代具有状态的硬件和软件)转换到不同状态,同时正确管理这些状态之间的相互依赖关系。此提案指定了一种名为 Fuchsia 电源拓扑的模型,该模型可用于解决此问题,同时还可为归因和可观测性方面的相关问题提供解决方案。这项工作侧重于建立一个具有严格定义术语的概念框架;未来的 RFC 将更密切地关注与实现相关的设计。
设计初衷
状态管理问题
此提案源于需要在 Fuchsia 中支持系统挂起/恢复操作(如 RFC 230 中所述)。
系统挂起的一项主要任务是确保在 CPU 停止执行指令之前,所有硬件元素都已置于相应的低功耗状态。从表面上看,这似乎是一个深层依赖关系管理问题:硬件元素的“活动”状态取决于 CPU 的活动状态,因此必须先将硬件元素置于暂停状态,然后才能暂停 CPU。
不过,硬件元素可能相互依赖;例如,必须先暂停设备,然后才能断开总线电源。与此同时,设备可能具有多种状态,在系统挂起期间,在不同条件下使用这些状态是可取的,例如,如果设备要充当唤醒源,则应使用低功耗状态;如果设备不充当唤醒源,则应使用完全关闭状态。与此同时,关联的状态管理问题并不局限于系统挂起。在 CPU 处于活动状态时,硬件元素可能会进入低功耗状态,例如当手机处于飞行模式时,需要关闭某些无线装置。
这些因素使得创建支持相关联状态转换的框架变得很有价值。由于电源管理是此类转换的必要原因,因此此责任由 Fuchsia 的电源框架承担。我们引入了“电源拓扑”一词,以较为灵活地指代此框架的核心依赖关系图和框架本身。
在开发电源拓扑时,我们发现,管理硬件元素之间状态依赖关系所需的概念自然会扩展到软件元素,从而在硬件之上提供更高级别的抽象,或者自然地描述面向用户的已启用/已停用功能的状态。具体来说,通过明确捕获支持面向用户的功能所需的依赖项,我们建立了一种自然的方式来强制执行按需利用,以便仅在需要时才利用依赖项,并为需要这些依赖项的功能提供所利用资源的归因。组件级归因也很重要,但功能与功耗利用原因的关联更紧密,因此需要在子组件级进行归因。
我们建立的用于强制执行基于需求的电源状态更改的概念将允许电源拓扑不仅对整个系统中的元素支持的状态进行编码,还对驱动状态更改的规则进行编码。这将为产品开发者和系统工程师打造一款强大的工具,他们将能够通过拓扑本身(而非源代码)来查看系统范围内的行为并提出功能变更建议。
为什么要采用新拓扑?
Fuchsia 已经有两类重要的拓扑结构,用于描述驱动程序和组件。不过,这两种方法都无法轻松解决状态管理问题。因此,我们自行开发电源拓扑,并期望定期重新审视组件和驱动程序图,以明确电源拓扑与它们之间的关系。
为便于参考,我们简要回顾一下现有的拓扑。
组件拓扑描述了两件事:组件实例之间的父级/子级关系和功能路由图。它是一棵描述组件实例层次结构的树,功能映射到该树顶部的 DAG 中。如果某个组件需要访问另一个子树中的功能,则该功能会通过其父级进行路由。
驱动程序管理器还会将自己的节点拓扑作为 DAG 进行跟踪。在驱动程序框架中,节点是设备的抽象表示,驱动程序会绑定到节点以使用其关联的资源,例如访问 MMIO 寄存器。驱动程序是组件拓扑中的组件,但它们会扁平化为集合。之所以采用这种结构,是因为组件拓扑无法表示没有绑定驱动程序的节点,并且节点可能具有多个父节点(这些节点称为复合节点),而组件拓扑的树结构不允许这样做。
利益相关方
辅导员:
Adam Barth abarth@google.com
审核者:
- Power:Kyle Gong kgong@google.com
- Power:Michael Brunson mbrunson@google.com
- 驱动程序框架:Justin Mattson jmatt@google.com
- 驱动程序框架:Harsha Priya NV harshanv@google.com
- Zircon 内核:Nick Maniscalco maniscalco@google.com
- 平台驱动程序:Andres Oportus andresoportus@google.com
- 组件框架:Gary Bressler geb@google.com
已咨询:
- David Gilhooley dgilhooley@google.com
- Corey Tabaka eieio@google.com
- Filip Filmar fmil@google.com
- Guocheng Wei guochengwei@google.com
- HanBin Yoon hanbinyoon@google.com
- Eric Holland hollande@google.com
- Mukesh Agrawal quiche@google.com
- John Wittrock wittrock@google.com
共同化:
此设计最初是通过 Google 内部设计文档进行社交化的,审核人员来自 Power Framework、Component Framework、Driver Framework、Drivers 和 Zircon 团队。在 Power Broker 和 System Activity Governor 的类似设计过程中,该模型得到了进一步完善,这两者都将成为即将发布的 RFC 的主题。
要求
有序的依赖项管理
如前文所述,系统电源管理的关键问题之一是以尊重不同系统元素之间状态依赖关系的方式管理这些元素的状态变化。此类依赖项的影响示例如下:
- 只有在总线供电后,USB 设备才能开启。
- 只有在为时钟供电的电压轨达到足够高的电压时,时钟才能以给定的频率运行。
- 视频流应用只有在有有效的网络连接时才能开始播放视频。
一般来说,给定的系统元素 E 可能具有一组状态 S0、S1、S2 等,它可以处于这些状态。为了使 E 正确占据给定的状态 Si,必须满足 Si 的所有依赖项。
如果某项操作始终保留所有系统元素状态的依赖关系,则称该操作为有序操作。具体而言,对于具有候选状态 Si 的每个元素 E:
- 仅当状态的所有依赖项都得到满足时,E 才会进入 Si。
- 如果 Si 的某个依赖项要被破坏,E 必须先退出 Si。
电源框架必须支持参与的系统元素的有序状态转换。
当无法按顺序执行状态转换时,电源框架应确保将元素置于明确定义的状态,并尽可能减少执行无序更改的元素数量。
归因
系统元素可能处于多种状态,其中一些状态的功耗高于其他状态。当元素处于高功率状态时,电源框架必须能够确定出现这种情况的原因。
效率
应将系统元素驱动到 Power Framework 可以归因于操作原因的最低功耗状态。框架用户必须能够以简单明了的方式根据需要将元素驱动到更高功率状态,但他们可能需要引入新的归因原因才能实现此目的。
可观测性
电源框架必须能够观察框架用户认为与功耗相关的系统元素的状态。
性能
如果系统元素能够以满足一组产品要求的方式执行状态转换,则电源框架必须充分支持它们这样做。这大致可以分为两个方面:
- 不要抑制本地效果。电源框架不得为各个系统元素的状态转换引入过多的延迟。
支持优化非本地效果。电源框架应支持跨多个元素的状态转换优化。
- 例如,假设在系统挂起操作期间,图形和音频子系统并行进入低功耗状态。电源框架应指示它们并行运行,并提供有关哪个操作耗时更长的深入分析,以便系统挂起操作的延迟时间优化可以适当地侧重于其中一个。
适用范围
电源拓扑结构需要考虑非常大的问题空间。本提案明确不涉及以下主题:
- Power Broker 的详细规范。此 RFC 必须确定 Power Broker 的一些基本方面,以开发拓扑模型。不过,它会尽力将有关 Power Broker 规范的内容留给即将发布的 Power Broker RFC。Power Broker 将实现本文档中详细介绍的模型之外的行为,我们希望为其提供所需的全部灵活性。
- 一流的错误处理机制。本文档中开发的拓扑模型未提供用于处理状态转换错误的明确方法。此排除项是前一项的扩展;它对 Power Broker 的错误处理没有任何影响,主要目的是不施加任何限制。
- 作恶方。Power Broker 和元素所有者之间的职责划分最终需要考虑行为不当且以意外方式运行的元素所有者。
- 有截止期限的状态转换。为了强制执行及时的系统级操作,自然会考虑为各个状态转换设置应用时间限制。
随着用例提供具体要求,我们将进一步考虑这些问题。
设计
此处介绍的设计确立了电源拓扑的底层模型,与任何特定接口或实现无关。出于实际目的,以下几项即将发布的 RFC 对于打算将其子系统与电源拓扑集成的开发者来说也很重要:
- 电源代理 RFC 将介绍与管理电源拓扑相关的接口以及实现这些接口的组件。
- 系统活动调控器 RFC 将介绍电源拓扑与系统挂起/恢复流程的集成点。
- 启用电源的驱动程序 RFC 将解决集成过程中与驱动程序相关的特定方面。
不过,拓扑模型本身足够复杂,需要专门撰写一篇文档。此 RFC 旨在批准一个连贯的概念框架中的概念,为其他 RFC 的构建奠定基础,并在此基础上开发稳定的文档,以帮助 Power Framework 用户进行集成。
电源拓扑和核心概念
推动此设计的主要功能需求是上述有序性要求。首先,我们需要确定哪些类型的系统元素可以参与到我们的模型中,它们可以处于哪些类型的状态,以及这些状态可以通过电源拓扑表达哪些依赖关系。只有这样,我们才能有序地指定如何控制这些状态。
电源元素
电源元素是此设计中的基本有状态实体。电源元素可以处于有限数量的状态,并且在任何给定时间都只能处于其中一种状态。有时,将电源元素视为广义的设备模型会很有用,但也可以简单地将其视为状态容器。
给定的硬件设备可以直接对应于单个电源元素,但也可以使用描述不同设备状态的多个电源元素来建模。例如,可以单独配置触摸传感器的采样率和位置跟踪容量;传感器的驱动程序可能会因此公开独立的“采样率”和“位置跟踪”元素。
电源元素还可用于对更抽象的概念进行建模,例如跨多个硬件的子系统的总体状态,或面向用户的软件功能的启用/停用状态。
功率等级
能耗级别是指能耗元素可处于的状态。功率电平架构由给定功率元素可能占据的功率电平集合以及稍后将介绍的元数据组成。
电源框架假定,架构中的级别遵循以下几项限制。框架用户负责确保在为电源元素指定架构时,这些约束条件能够准确反映所建模实体的属性。这些限制如下:
- 它们可以按耗电量递增的顺序排列。(有很多方法可以测量功率;就当前意图和目的而言,特定于上下文的“典型”功耗定义就足够了。)其余限制均以这种顺序表示。
- 依赖关系是累积的:对于给定的元素,在级别 L 正确运行所需的任何资源也需要任何级别 M > L。
功能是累积的:对于给定的元素,级别 L 提供的任何功能也由任何级别 M > L 提供。
- 此要求消除了电源元素的依赖项之间发生冲突的可能性。例如,如果一个依赖项需要第 N 级的功能,而另一个依赖项需要第 (N+1) 级的功能,那么该元素可以通过在第 (N+1) 级运行来满足这两个依赖项的需求。
功率级架构包含以下内容:
- 架构中每个功率级别的标签。
- 按能耗递增顺序排列的级别。
示例
为便于说明,我们将使用字符串标签,并使用从下到上排序的竖向列表来表示排序顺序。(有关如何实际表示功率级别的详细信息将在 Power Broker RFC 中介绍。)
以下展示了三种可能的功率级方案:
|
|
|
特别值得注意的是,电源级别的排序方式与 ACPI 电源状态的排序方式相反。此选择消除了随意措辞中令人遗憾的歧义。根据 ACPI 惯例,“较低的电源状态”等表达式有两种直接冲突的解释,具体取决于“较低”是指功耗(对应于排序顺序中较高的索引)还是排序顺序中的索引(对应于较高的功耗)。“低功率”等表达方式不会出现这种歧义。
并非所有功率元素都能使用与其他元素共享的通用功率级别架构。例如,可以定义一个电源元素,用于指定 CPU 将运行的最低频率,在这种情况下,电源级别对应于相关 CPU 支持的频率。
用途和限制
功率电平架构是表示元素状态的实用起点,原因有多种:
- 它们清晰地表达了常见模式,例如上文所示的模式。
- 它们提供了一种捕获大量状态之间依赖关系的方法,这种方法可以进行聚合,而无需繁琐的重复。
- 它们可以以无冲突的方式使用,虽然并非在所有情况下都能实现,但应尽可能加以利用。
单个电源元素和电源级别架构不足以描述 Power Framework 用户感兴趣的所有场景。例如,单个设备的不同运行模式(简单但脱离上下文的示例:考虑可加热或冷却房间的热泵)无法准确地建模为单个电源元素。
不过,功率等级架构可用作构建块来描述更复杂的系统。相关最佳实践超出了本 RFC 的范围;我们将在即将发布的文档中介绍该主题。 框架用户还可以通过 Fuchsia > Power 组件向 Power 框架团队提交 bug。
可操作性和依赖项
在任何给定时间点,根据当前系统条件,电源元件将能够在部分功率级别下正常运行。这些是其可操作的级别。此子集始终包含小于或等于最大可操作级别(对于元素 E,表示为 max_operable_level(E))的所有级别。
功率级相关性是一种条件,用于指示一个功率元素的可用级别与另一个元素的当前功率级之间的关系。功率等级依赖关系表示,子元素 C 要以等级 L 或更高级别运行,需要父元素 P 以所需等级 RL 运行。更确切地说,(C, L) 对 (P, RL) 的依赖关系意味着:
- 如果 current_level(P) < RL,则 max_operable_level(C) < L。
等效地,此条件可以表述为:
- 仅当 current_level(P) ≥ RL 时,max_operable_level(C) ≥ L。
(C, L) 的每个依赖项都为 L 的可操作性建立了一个必要条件。根据关联条件的状态,依赖项可描述为“已满足”“已实现”等。
另请注意,对于任何级别 K < L,(C, K) 的每个依赖项都会为 L 的可操作性创建一个必要条件。特别是,(C, L) 的可操作性可能会对父元素提出要求,即使 (C, L) 本身并不直接依赖于该元素。我们将满足此类要求的所有元素的集合称为 (C, L) 的必需元素。对于此集中的任何元素 P,(C, L) 可操作的最低必需级别;我们将其表示为 min_required_level(P; C, L)。
汇总所有必需元素,L 必须满足以下必要条件才能正常运行:
- 对于所有 P ∈ required_elements(C, L),current_level(P) ≥ min_required_level(P; C, L)。
如果满足这些条件,我们就说 L 是名义上可操作的。即使 L 在名义上可操作,也可能无法操作;本地条件(例如可能未观察到的硬件错误)可能会阻止 C 在 L 运行,即使所有相关的功率级依赖项都已满足。名义可操作性应视为电源拓扑试图模拟真实可操作性的方式。虽然这两个概念之间不可避免地存在差异,但当元素设计人员尽可能减少此类差异时,电源拓扑将能够发挥最佳功能。
一个电源元素可能对另一个元素有多个功率级依赖关系。 对于固定的父级和子级,所有此类级别依赖关系构成一个幂元素依赖关系。如果 C 的至少一个级别依赖于 P 的某个级别,我们就说 C 依赖于 P。
电源拓扑
作为一种正式的实体,功率拓扑是以功率元素为节点、功率级依赖关系为有向边的多边图。此外,我们还对该图施加了以下限制:
无环性:电源拓扑是无环的。
- 特别是,父级/子级关系的行为符合预期;如果元素 C 依赖于元素 P,则 P 不得依赖于 C。
最低级别可操作性:任何电源元素的最低功率级别必须始终可操作,无论其他元素的当前级别如何。此外,它可能没有功率级依赖项。
此条件是指可操作性,而非名义上的可操作性,它可确保每个元素始终至少有一个可操作级别。必须由元素所有者强制执行。
允许一个元素的最低级别取决于另一个元素的最低级别,不会对可操作性产生影响。但此类依赖关系在功能上无关紧要,允许此类依赖关系还需要考虑仅通过最低级别相互依赖的元素。
电源拓扑可能包含冗余的电源电平依赖关系。例如,(C, L) 可能同时依赖于 (P, RL1) 和 (P, RL2),其中 RL1 < RL2,即使对 (P, RL2) 的依赖所施加的条件严格强于对 (P, RL1) 的依赖所施加的条件。在此提案的模型中,此类冗余被认为是无害的,但在实现时可能会受到特殊考虑。
示例和上下文
注意:这些示例仅用于说明。此 RFC 对必须使用电源元素建模的内容没有影响。
最基本的功率级别依赖关系与开/关状态有关。在一个非常简化的示例中,我们可能会将 USB 总线必须处于开启状态才能使 USB 设备处于开启状态表示为:

为了有序地处理上述依赖关系,必须在设备开机之前开启总线,并且必须在总线关闭之前关闭设备。
更广泛的功率电平依赖关系定义可适应更复杂的关系,例如 DVFS 期间时钟和电压之间的耦合。(DVFS 对时间非常敏感,因此可能不适合进行电源拓扑集成,但它是一个有用的示例。)假设我们有一个时钟,其 DVFS 表如下所示,列出了支持的频率及其所需的电压:
| 时钟频率 | 电压 |
|---|---|
| 1.6 GHz | 900 mV |
| 1.5 GHz | 800 mV |
| 1.4 GHz | 700 毫伏 |
此表转换为电源元素、级别和依赖项,如下所示:

(请注意,从技术上讲,(Clock Frequency, 1.4 GHz) 对 (Voltage, 700 mV) 的依赖关系不会包含在拓扑中,但为了便于与表格进行比较,此处进行了图示。)
表示软件功能或设备用户级运行模式等电源元素的电源元素可能具有许多依赖项,用于描述它们正常运行所需的所有资源。在另一个简化示例中,视频通话客户端的“活跃”级别可能取决于进行视频通话所需的各种硬件子系统:

最后,多个子元素可能依赖于同一元素。在此示例中,我们展示了一款以延迟时间来描述其功率等级的设备。客户端 A 的“活跃”级别需要低延迟,而客户端 B 的“活跃”级别需要中等延迟。设备可以通过低延迟运行来满足儿童的两个活跃度级别。

此示例展示了功率级别的一个重要属性:它们经过精心定义,可确保不同客户端的需求不会相互冲突。
边方向惯例
从目前的图表中可以看出,我们采用的惯例是,电源拓扑中的边从子节点指向父节点,表示依赖关系的方向。对于某些讨论和直观的术语,可能不可避免地要基于从父级到子级的功率流方向。目前,我们打算在所有正式开发中使用依赖项的方向,只是建议读者注意此问题。
功率级管理
为了指定如何在实际系统上利用电源拓扑,接下来我们需要定义参与管理拓扑和各个电源元素的各方。
Power Broker
电源拓扑将由一个名为 Power Broker 的电源框架组件进行管理。电源代理将维护整个电源拓扑的表示形式,包括所有电源元素、电源等级架构、电源等级依赖关系和当前电源等级。它将为每个元素所有者提供接口,以便在适当的时间更新其元素的功率级别,从而尽可能以有序的方式进行级别更改。
Power Broker 的存在反映了此设计的一项关键断言:电源拓扑将由中央管理。我们认为这很有必要,因为:
- 尝试在本地管理拓扑会大大增加依赖项管理中出现实现错误的机会。
- 中央管理员具有必要的全系统可见性,可将提升的功率水平与用电需求相关联,以满足能效要求。
- 中央管理员有权根据提供方信息要求执行提供方信息操作。
- 即使某个子系统未提供检测功能,中央管理员也可以维护和报告详细的遥测数据,以满足可观测性要求。
- 集中管理可让您明确移除不应拥有代理权的元素所有者的代理权。例如,通常情况下,最好不要让驱动程序决定其底层硬件的当前功率级别;这种偏好可以通过驱动程序放弃租用其拥有的功率元素的能力来明确编码。
集中式管理确实会以本地化性能成本为代价,因为管理员引入了一个必须了解功率元素及其级别的实体。因此,在整个 Power Broker 的设计和实现过程中,必须密切关注性能。不过,Power Broker 将支持的全局视角可能会通过提供系统级性能优化机会来抵消其本地成本。
元素所有者
每个电源元素都与一个元素所有者(负责管理该元素的组件的实例,可能是 DFv2 驱动程序)相关联。所有者向 Power Broker 注册元素,声明其能耗级别架构,定义其依赖项,并在适当的时间更新其能耗级别。
如有必要,可以在元素生命周期内委托元素的所有权。这很可能涉及一个组件实例作为注册和配置任务的所有者,而另一个组件实例接收运行时管理的所有权。
电源元素的生命周期时长及其关联的依赖项将在 Power Broker RFC 中进行说明。
电源元素的类型
大多数电源元素都将是受管理的,这意味着其所有者会将电源等级的选择和更改时间推迟到 Power Broker。为了将必要的级别更改通知给元素的所有者,Power Broker 会向所有者发送必需级别。所有者进行更改,然后将元素的新当前级别通知给 Power Broker。
在当前模型中,我们做了一个简化假设。在收到元素 E 的所需级别 RL 的通知后,E 的所有者将始终:
- 如果 RL 可操作,则将 current_level(E) 更新为 RL。
- 如果 RL 不可操作(例如,在尝试更新 E 的当前级别时发现硬件错误),请采取使 (E, RL) 不再名义上可操作的措施。(例如,错误状态元素可用于指定 (E, RL) 的不可操作性。
这绝不是对可能出现的错误情况的详尽处理。相反,它将错误处理的开发工作委托给 Power Broker(如排除项中所述),同时指出了在此模型范围内可实现的主动错误处理方法。
未受管理的元素称为非受管元素。它不能有依赖项,并且其所有者会在其级别发生变化时,简单地向 Power Broker 报告其当前级别。其当前级别会影响依赖于它的任何元素的可操作性。
此类元素对于描述不受软件控制且只能观察到的状态(例如硬件开关的状态或硬件的错误状态)是必需的。
功率级控制
通过受管理的元素,Power Broker 将负责推动整个拓扑中的大多数功率级变化。为了限制此 RFC 中涉及的设计面,我们将重点关注稳态行为。
电源代理的控制方案旨在平衡用电需求与限制用电的约束条件。
从概念上讲,对功耗的需求源于设备的功能要求。这些要求通常会根据对用户当前设备期望的了解而动态变化。用户可能会打开应用来完成特定任务,这表明与该应用关联的某些电源元素需要以较高的功率水平运行。或者,设备可能会感应到表明用户就在附近且可能很快会与设备互动的活动,从而建议设备进入低延迟响应模式。即使应用处理器处于非活跃状态,也会存在需求,因为用户期望某些互动(例如说出启动热词、点击鼠标、点按屏幕等)会唤醒设备。为了向电源拓扑表达需求进入,我们将引入一个名为“租约”的对象。
与此同时,限制可以通过两种不同的方式产生。在一种情况下,不受软件控制的状态可能会直接抑制功耗;这可以通过非受管元素来建模。在另一种情况下,系统可能需要一种方法来表达何时应提高或不应提高功率级别以满足租约所表达的需求;这种需求通过依赖项实现政策来捕获。
总而言之,这些概念将使我们能够指定 Power Broker 将系统引导至的稳定状态,同时将时间相关方面所需的细微差别留给 Power Broker RFC。
稳定状态
在任何给定的时间点,一组特定的因素决定了受管元素的稳态,即只要决定因素保持不变,电源代理就会将受管元素引导至的功率水平。在此 RFC 的范围内,我们从稳态的角度描述了 Power Broker 的控制方案。这样做可以让我们在限制所需细节量的同时,介绍所涉及的关键概念。
稳态决定因素
稳态的决定因素包括:
- 拓扑结构,即电源元素和依赖项。
租赁。
非托管元素的当前级别。
如果这些决定因素发生任何变化,系统都会重新评估稳态。
稳态评估
确定稳态的关键因素是评估哪些租约将得到履行,这意味着租用元素级的所有依赖项都已得到满足。
电源代理将以全有或全无的方式处理租约。如果 (C, L) 上存在租约,但 Power Broker 无法或不会满足 (C, L) 的所有依赖项,则除非满足 (C, L) 的依赖项有助于满足其他可实现的租约,否则 Power Broker 将不会满足 (C, L) 的任何依赖项。
为了确定是否履行租约,Power Broker 需要确定它能否履行租约以及是否应该履行租约。“能否”的问题属于功能要求,可通过非受管元素的级别来解决。回答“应该”这个问题需要引入一个新概念,以指定 Power Broker 是否会主动尝试满足对受管元素的依赖关系。
为此,我们针对功率级依赖项引入了两种可能的实现政策:强实现和弱实现。只有当依赖项的必需元素受管理时,才能强实现依赖项;而受管理元素和不受管理元素的依赖项都可以弱实现。
履单政策也会汇总到依赖项路径中。如果依赖项路径中的每个依赖项都得到强实现,则该路径得到强实现;否则,该路径得到弱实现。
现在,给定一组固定的稳态决定因素,我们就可以指定租赁何时完成。当且仅当对于通过弱实现路径依赖于 (C, L) 的每个元素级 (P, RL),(C, L) 在稳态下得到满足时,(C, L) 的租约才会在稳态下得到满足:
- 如果 P 是非受管的,则 current_level(P) ≥ RL。
- 如果 P 是受管理的,则 (P, RL) 是另一个在稳定状态下得到满足的租约所必需的,并且通过强满足路径依赖于该租约。
确定已实现租约的稳态履约后,任何受管理元素 C 的稳态功率级别就是已实现租约所需的最大级别,或者如果没有任何已实现租约需要 C 的某个级别,则为 min_level(C)。
有序性
电源代理会尽可能按依赖顺序执行操作,引导系统进入稳定状态。尤其值得注意的是,如果所有稳态功率级别都大于或等于当前功率级别,则保证向稳态的进展是有序的。
在某些情况下,当功率水平降低时,可能会出现无序变化。为了描述这种情况,我们针对功率级依赖项引入了两项终止政策:orderly-on-termination 和 disorderly-on-termination。对受管元素的任何依赖项都是有序终止,而对非受管元素的任何依赖项都是无序终止。
与履单政策一样,终止政策会汇总到依赖项路径。如果路径中的所有依赖项在终止时都处于有序状态,则该路径在终止时处于有序状态。否则,为“无序终止”。
如果 (E, L) 通过有序终止路径依赖于 (M, RL),则 Power Broker 将尽可能确保在 current_level(M) 降至 RL 以下之前,current_level(E) 降至 L 以下。相反,如果 (E, L) 通过一条在终止时无序的路径依赖于 (U, RL),则如果 current_level(U) 降低到 RL 以下,本文档的模型不会保证该路径上级别变化的顺序。
为了更具体地描述无序情况(从非受管元素角度来看),请考虑 (E, L) 对 (U, RL) 的终止时无序依赖关系,其中 U 必然是非受管的。如果 current_level(U) 降至低于 RL,则此事件不在 Power Broker 的控制范围内。没有机会提前将 current_level(E) 降至低于 L;Power Broker 必须被动地将其降至较低水平。由于 (U, RL) 上的传递依赖关系也会随着 U 的当前级别的降低而立即中断,因此在系统被驱动到新的稳定状态时,无法明确规定级别变化的顺序。
依赖项类型
上述正式说明产生了三种不同的依赖关系,我们为其分配了以下名称:
| 依赖关系类型 | 配送政策 | 终止政策 |
|---|---|---|
| 基本 | 弱 | 无序 |
| 随机 | 弱 | 有序 |
| Assertive | 极佳 | 有序 |
基本依赖项始终是受管元素对非受管元素的依赖项,而断言性依赖项或机会性依赖项始终是一个受管元素对另一个受管元素的依赖项。
示例
不受管理的元素
此示例演示了在具有硬件静音开关的系统上使用非受管元素。这些元素如下:
静音开关:当静音开关处于分离状态时,系统麦克风正常运行。当麦克风处于“已接合”状态时,其时钟会被固定,因此其提供的信号毫无用处。
输入流:表示音频子系统从麦克风接收并传递给应用的传入数据流。其有效电源电平对(静音开关,未接合)具有基本依赖性。
音频处理器:此元素属于一个应用,该应用处理传入的麦克风数据,但用途未指定。
系统 activity:此元素抽象地表示系统将允许的任务处理范围。当此元素为“高”时,系统将处理各种各样的任务;当此元素为“低”时,系统将更有选择性地处理任务。
步骤:
最初,(Audio Processor, Active) 的租约将所有受管理的元素保持在较高的功率水平。
静音开关切换,静音开关的功率级别立即更改为断开。现在,(输入源,有效)和(音频处理器,有效)的依赖项均已损坏。
电源代理会立即将输入源和音频处理器驱动到其非活动电源级别。由于两个元素的有效功率级别都存在未满足的依赖关系,因此未指定排序。
由于音频处理器的依赖项不再保持其活动状态,系统 activity 会转换为非活动状态。
对受管元素的机会性依赖
在此示例中,有两项功能需要将“系统活动”元素设置为“高”级别才能运行。高优先级功能的依赖关系是断言性的,因此如果(高优先级功能,有效)的租约需要,系统活动将提升到高优先级。但低优先级功能的依赖关系是机会性的,因此只有在高优先级功能的租约将系统活动提升到高优先级时,低优先级功能才能提升到活动状态。
步骤:
(低优先级功能,有效)存在租约,但 Power Broker 不会满足该租约,因为对(系统活动,高)的依赖是机会性的。
已获取(高优先级功能,有效)的租约。这会改变稳态。
系统活动已提升至“高”。
两个功能级别都提升为“有效”,满足了两个租约(顺序不限)。
(高优先级功能,有效)的租约已失效。在新稳态下,(Low Priority Feature, Active) 的租约将不再得到满足。
高优先级功能降为“不活跃”。(注意:此 RFC 不保证此状态更改发生在低优先级功能的级别降低之前。)
为保持有序性,系统活动将保持“高”状态,直到低优先级功能降为“不活跃”。 此步骤重点介绍了机会性依赖项的一个令人惊讶的属性。机会性依赖项与断言性依赖项在实现方式上有所不同,但在确保关机序列的有序性方面,Power Broker 会同等对待这两种依赖项类型。
系统活动终于降至“低”。
错误状态元素
元素所有者可以使用不受管理的元素来模拟错误状态,该元素会抑制某些功率级别的可操作性。下图展示了具有级别 L0、L1、L2、L3 的元素 E 的两种可能的误差元素。

在上面的方案中,错误元素的级别直接反映了 E 的级别。如果 current_level(Error State)=="Li OK",则 Li 是 E 可运行的最大级别。在底部场景中,如果 current_level(Error State)==Error,更简洁的错误元素会阻止 E 在 L2 或 L3 处的运行。
此机制仅用于停用元素架构顶部的一个连续级别块。可以使用其他机制来停用高于某个级别的级别,但至少要保留一个可操作的级别,不过我们希望在出现相关用例时仔细检查。
归因
电源代理将支持将当前电源级别归因于其满足的租约。如果证明这样做有用,Power Broker 将支持区分明确需要给定级别的租约和机会性需要给定级别的租约。
可观测性
电源代理将通过 Fuchsia 的既有诊断设施公开有关电源元素的信息,包括其功率级架构及其依赖项。此外,它还会记录在某个合适的(可能可配置的)回溯期内的租约和功率级过渡情况。总而言之,这些信息将有助于检查查询时的拓扑状态,同时还可让未来的工具重放拓扑的近期历史记录。
配置
电源拓扑的许多方面都可以通过静态配置直接捕获。例如,之前通过图表展示的 USB 示例可以改为通过以下方式描述:
[
{
name: "USB Bus",
levels: ["Off", "On"],
},
{
name: "USB Device",
levels: ["Off", "On"],
dependencies: {
"On": ("USB Bus", "On")
},
}
]
如果必须跨组件边界识别元素,则会增加复杂性。我们将与组件框架团队合作,研究使静态配置变得简单明了的技术。
未来主题
过渡延迟时间支持
从长远来看,电源拓扑旨在提供一个框架,用于了解和优化系统状态转换的延迟。电源元素定义将建立一个规范位置,用于对本地过渡延迟时间(即在满足所有依赖项后更改元素级别所需的时间)进行编码。本地元素延迟时间将不是必需的,但随着系统的成熟,可以添加这些延迟时间。
本地延迟时间的应用包括:
- 对跨越多个元素的复合操作的延迟进行半静态分析(例如,通过捕获运行时拓扑配置)。
- 对观测到的延迟进行运行时跟踪,并报告与预期值的偏差。
- 向客户端报告延迟时间估计值,以支持对时间要求非常严格的操作。
其他类型的状态和依赖项
我们引入的功率级别和依赖关系类型是表示元素状态的有用起点,原因有很多。它们提供了一种捕获大量状态之间依赖关系的方法,这种方法可以进行聚合,而无需繁琐的重复。此外,它们还可以以无冲突的方式使用,虽然并非在所有情况下都能实现,但应尽可能加以利用。
随着电源拓扑的演变,支持其他类型的状态和依赖关系可能有用且/或必要。例如:
- 传感器的固件可能实现为支持一组不相交的运行模式,每种模式都经过优化以满足不同的要求,但这些模式并不遵循功能和功耗严格递增的比例。虽然此类传感器可能针对每种模式使用一个二进制电源元素进行描述,但我们可能会改为引入一种新的状态架构,该架构可以同时描述所有模式,同时包含用于解决竞争客户端之间冲突的规则。
- 某些类型的硬件(例如 GPU)可能会根据多个客户端的同步负载要求来选择其功率级别。电源拓扑可能能够支持以通用方式捕获此类负载要求并累积这些要求的依赖项。
此类开发目前尚处于推测阶段;在将子系统与电源拓扑进行初始集成时,应根据需要重新审视这些开发。
实现
实现电源拓扑本身并在整个 Fuchsia 中使用它是一项艰巨的任务。有几项集中式工作将被广泛使用,因此需要在初始实现的基础上进行重大改进。与此同时,Fuchsia 子系统迄今为止对电源管理的支持有限,在许多情况下,其开发者需要制定适当的电源管理策略,同时将这些策略映射到电源拓扑。
将开发策略分为不同的阶段(其中一些是历史阶段)会很有帮助。在第 1 阶段,核心功能相对独立地开发完成;在第 2 阶段,进行了少量集成,以演示关键使用情形并实现系统挂起/恢复的端到端测试。在第 1 阶段和第 2 阶段积累了经验后,我们现在正在第 3 阶段奠定基础,以便实现更多集成,并如第 4 阶段及后续阶段所述,实现稳定的开发周期。
- 电源代理负责管理电源拓扑。
- 系统活动管理器定义并管理支持系统挂起/恢复操作的元素。
- 驱动程序框架支持将驱动程序与电源框架集成。(电源框架功能将通过标准方式路由到非驱动程序组件,无需特殊支持。)
- 与将硬件置于低功耗和高功耗状态的驱动程序的初始集成。
- 首次与支持唤醒源的驱动程序集成。
- 首次用于端到端挂起/恢复工作流。
- 批准此 RFC;为 Power Broker、系统活动调节器和电源感知驱动程序提出并批准 RFC。
- 表征现有实现所施加的设计限制,例如延迟开销所施加的有效速率限制。
- 确定下一组与 Power Framework 的子系统集成的范围和设计。
- 制定并记录最佳实践和设计模式。
- 确定并实施小规模改进,以协助进行集成(例如 API 改进、简单直接的优化)。
- 建立测试程序和支持库,其中纳入了电源框架的特定领域问题。
确定大规模添加和改进功能方面的最高优先级。可能包括:
- 支持跟踪过渡延迟时间。
- 需要对界面进行重大更改和/或后端实现工作才能实现的性能改进。
- 简化了组件框架集成。
第 4 阶段及后续阶段:进一步集成和大规模改进
- 集成更多子系统。
- 在适当情况下优化现有集成。
- 根据新出现的需求继续进行小规模改进。
- 解决优先级最高的大规模改进问题。
- 确定下一阶段要解决的任何大规模改进。
性能
许多性能方面的问题最适合在第 3 阶段 RFC 中解决,而 Power Broker 与本提案的概念构建最为密切相关。不过,在当前范围内,我们可以制定一些关于考虑性能影响的一般准则。
本地效果与非本地效果对比
本地和非本地性能要求之间存在冲突,因为与电源代理协商状态更改通常会产生至少一些纯本地化解决方案可以避免的成本。不过,纯粹的本地化解决方案无法充分支持执行有效的非本地优化所需的系统级分析。
识别延迟时间开销
Power Broker 对电源拓扑的管理会产生一定的延迟开销,尤其是由于元素所有者与代理之间的 IPC。不过,请务必认真考虑哪些费用才是真正的间接费用。特别值得注意的是,某些子系统本身就需要其进程之间进行通信才能实现任何形式的电源管理,而与电源拓扑的集成可以通过 Power Broker 间接实现该通信。
由大小决定的延迟时间开销
由于系统级暂停和恢复等相对不频繁的操作而产生的延迟开销主要受其影响的子图大小影响。了解子图的广度、深度和节点数量对此类开销的影响非常重要。
由 QPS 驱动的延迟时间开销
目前,预计 Power Broker 的 QPS 主要受暂停阻塞租约的影响;相关电源元素将在系统活动调控器 RFC 中详细说明。
目前尚未明确规定 Power Broker 必须支持的 QPS。 相反,某些子系统集成可能会发现自己需要阻止挂起,因为事件的到达速率足够高,以至于每个事件的租用都会产生过多的开销。在这种情况下,必须采用替代设计模式,以在单个暂停阻塞租约下整合多个事件的处理。
为了帮助进行此类评估,估计每个租约的延迟时间开销将非常重要。
安全注意事项
应在 Phase 3 RFC 中详细考虑安全性,其中更接近具体实现的提案将提供范围更广的讨论。下面我们概述了任何使用电源拓扑的固有安全问题。
电源依赖项和功能
由于电源拓扑使用依赖项将电源元素提升到更高的功率级别,因此声明对特定电源元素的依赖项本身就是一项特权操作。因此,为了符合 Fuchsia 的安全模型,依赖项声明应在相当精细的级别(至少是元素级别)明确受到功能保护。
到目前为止,Power Broker 采用的是集中式权限管理方法,可根据当前支持的功能类型严格处理权限。之所以选择这种方法,是因为它能比组件框架的同步演进更快地让开发者全面了解电源拓扑的含义。从长远来看,组件框架或许能够更自然地表示与电源拓扑关联的功能,从而减轻 Power Broker 的一些安全相关责任,并支持更顺畅的开发者体验。
集中管理的风险
将 Power Broker 用作中央管理员会使其面临 DDoS 攻击等风险,这可能会导致它无法管理系统关键状态转换,并可能导致攻击者绕过其权限逻辑,从而恶意操纵硬件状态。
隐私注意事项
由于设备上会跟踪详细的子系统状态,因此在利用这些数据生成机群指标时,务必要确定如何兼顾隐私保护问题。在第 4 阶段或之后,当我们能够具体展示 Power Broker 可能会为大量子系统导出的数据时,再考虑此问题会更有效。
测试
第 1 阶段已纳入对所有已开发功能的单元测试,以及对 Power Broker 与虚假客户端的集成测试,以及将 Power Broker 与系统 activity 管理器耦合的集成测试。
第 2 阶段新增了端到端暂停/恢复测试,并支持针对系统 activity 管理器的非封闭式驱动程序测试。
第 3 阶段将通过库和文档,为测试与 Power Framework 的集成建立正式支持,以应对实践中遇到的各种使用情形,同时扩大端到端测试的覆盖范围。
文档
此 RFC 是电源拓扑中概念定义的可靠来源。
我们将添加文档来解决以下问题(但不限于):
- 此处定义的概念的易读性优化说明。
- 集成指南。
- 实际功率拓扑集成示例。
- 电源元素的建议使用模式。
缺点、替代方案和未知因素
缺点
与此提案相关的两项主要费用是:
- Power Broker 的实现。在撰写本文时,Power Broker 的实现方案运行正常,仅与本文介绍的概念略有偏差,因此这种成本很小。
- 分摊客户端集成费用。我们将通过文档、客户端库(注意 FIDL 评分标准的注意事项)和测试支持来研究如何降低这些费用。
替代方案
分散式电源控制
作为电源拓扑的一种极端替代方案,可以考虑不采用集中式电源管理的系统。在此类系统上,子系统将提供自定义接口,通过这些接口可将子系统驱动到不同的电源状态。
对于需要子系统处于特定电源状态的任何系统级模式,都需要某个“模式控制器”实体负责确保每个子系统都处于适合该模式的电源状态。该实体需要利用每个子系统特定的接口。
负责控制给定模式的电源状态的实体实际上针对该模式执行集中式电源管理,因此这种方法并非真正分散式。与此同时,要求模式控制器使用其自行选择的接口来控制每个子系统会带来明显的扩展问题。综合考虑这些因素,我们认为 Fuchsia 必须支持某种形式的集中式电源管理,并具有一定程度的接口标准化。
值得注意的是,此提案并未就子系统应在多大程度上利用电源拓扑结构采取强硬立场。一些子系统开发者可能会发现,最适合的做法是执行轻量级集成,仅向电源拓扑公开一两个总体子系统状态,以便与系统模式转换集成。而另一些人可能会发现,利用更深入的集成来全面模拟整个平台和驱动程序中的子系统是值得的。
操作顺序
我们提出的基于状态和依赖关系的方法的替代方案是标准化特定操作的顺序,从本质上讲,就是根据需要概括驱动程序具有“挂起回调”和“恢复回调”的概念,以创建可正常运行的系统。在 Linux 挂起/恢复中,这以四种可能的驱动程序回调形式实现,其中四种用于挂起(prepare、suspend、suspend_late、suspend_noirq),四种用于恢复(resume_noirq、resume_early、resume、complete)。
我们之所以不采用这种方法,有以下几个原因:
它可能会隐藏设备在系统处于暂停状态或恢复状态时的状态;公开此类状态的过程在很大程度上转化为创建此处提出的拓扑。此外,此类状态可能取决于设备在暂停时应有的行为。
这会让人混淆“暂停”和“恢复”是指在任何给定设备上执行的操作,还是在整个系统上执行的操作。
它很容易受到意外要求的影响,如上面的
_late/_early和_noirq回调变体所示。有序依赖关系管理问题适用于任何形式的电源状态控制,而不仅仅是系统范围内的暂停和恢复操作。
采用操作序列化方法时,状态间依赖关系图在抽象层面上仍然存在,但它在源代码中是隐式的。
强制关机
除了按需利用之外,电源框架还可以利用命令式关机模型,其中电源元素默认处于高功率状态,必须明确命令才能降低功率。这种方法可在短期内简化某些功能的实现,但更容易受到未跟踪依赖项引入的影响。此外,它本身并不支持归因。
与此同时,按需利用模型可以在某些范围内根据需要实现强制关机。在电源拓扑的具体细节方面,只需要一个消耗元素,其目的是将资源拉至所需的默认电源级别,并且消耗元素的所有者提供一个接口来根据需要更改级别。然后,可以使用 consumer 元素在系统级视图中明确表示强制关机的使用情况。
推迟的主题
以下问题和疑问将在 Power Broker RFC 中得到解答:
- 元素和依赖项的生命周期时长。
- 租约生命周期。
- 根据兼容性提案中的指南,与功率级别定义相关的 API 版本控制问题,待更新(因 2024-04-22 的讨论而产生)。
- Power Broker 是否会向待处理租约的持有者提供任何反馈?
- 与拓扑集成的子系统的测试指南,特别是关于使用伪 Power Broker 与使用带有伪电源元件的真实 Power Broker 的指南。
- 用于以原子方式添加/移除依赖项的 API。
- 处理冗余依赖项。
- Power Broker 崩溃时的行为。
- 元素所有者崩溃时的行为,包括与正常关机/启动的比较。
- 错误处理。
在先技术和参考资料
Linux
Mac OS
Windows