RFC-0112:x86 上的 ACPI 支持 | |
---|---|
状态 | 已接受 |
领域 |
|
说明 | 改进了 x86 上的 ACPI 支持。 |
问题 | |
Gerrit 更改 | |
作者 | |
审核人 | |
提交日期(年-月-日) | 2021-06-11 |
审核日期(年-月-日) | 2021-07-21 |
摘要
大多数 x86 设备都使用高级配置与电源接口 (ACPI) 提供有关设备拓扑、配置和 为操作系统提供电源管理功能。Fuchsia 的 ACPI 支持 目前非常有限:不支持 其他总线驱动程序(如 PCI),且不支持访问 x86 之外的设备专属配置或电源管理方法 板驱动程序。
此 RFC 引入了发布复合设备的机制,其中包括: ACPI 设备和总线(即 I2C、SPI、PCI)设备。它还增加了对 以便使用更广泛的 ACPI 功能(接收事件、访问 配置和调用方法)。
设计初衷
目前,所有仅支持 ACPI 的设备(即不在 PCI 总线上)都是 在单个 if/else 语句中枚举。有以下要求的设备: 对其他 ACPI 数据(例如,来自 _DSD 的数据)的访问是 x86 的一部分 开发板驱动程序、对数据进行硬编码,或使用设备专属数据 黑客行为,为设备提供配置所需的数据 。
请注意,x86 板级驱动程序是不恰当的名称:并非所有 x86 平台都一定是 请使用 ACPI。更好的说法是“PC 板驱动程序”,这是适用于 IBM 的板级驱动程序 PC 平台。为简单起见,我们仍然将驱动程序称为 x86 板级驱动程序。虽然此 RFC 尝试概述了一个比较笼统的 适用于 x86 和 ARM 的 ACPI 方法, RFC 的主要关注点是对 x86 板驱动程序的更改,以及未来的 ARM ACPI 可能需要单独的板级驱动程序。
这种处理方式不可扩缩。我们希望支持更多设备 我们会遇到硬编码值相互冲突的情况, x86 板级驱动程序中的驱动程序数量将会变得巨大。此 RFC 将 允许我们添加更多的 x86 平台和电源管理支持,而无需在 技术债务的增加。
设计
x86 上的每部现有设备都将获得一个对应的 ACPI 设备(因此 只要设备在 ACPI 表中有条目即可)。每台 ACPI 设备 由 x86 板级驱动程序发布,并且将提供对设备的 ACPI 的访问权限 配置和方法x86 板级驱动程序还将发布复合 这些设备是“真实”的设备和 ACPI 设备更确切地说 与直接绑定到“真正的”驾驶员需要使用 然后将这些设备绑定到复合设备。板驱动程序还会 发现静态枚举总线(即 I2C、SPI)上的设备,并发布 元数据,告知总线驱动程序其子设备的数量。
部分设备还将获得更危险的 ACPI 使用权限 例如获取 ACPI 全局锁。实际上,没有太多设备 需要使用该功能,因此它只会向 已列入 x86 板级驱动程序许可名单的设备。
设备树的单个分支可能如下所示: 适用于通过 SPI 总线连接的 TPM 设备。
实现
发现设备关系并在系统上发布 ACPI 设备。
在发现 ACPI 设备时,我们需要确定给定设备是否为总线 如果是司机,还要说明是哪款公交车。这些信息很重要 因为它让我们能够确定 应与 ACPI 和真实的同类产品绑定。ACPI 并没有简单的 通过设备确定这两个属性的方法, 总线上的设备将是总线的子项因此需要进行拆分 将设备发现和发布流程分为三个阶段:
- 在树中发现设备,设置设备的 ACPI 映射 其内部表示法的句柄,其中包括所需的信息 当我们最终发布设备时,比如其父设备、句柄以及 总线类型。
- 对于每部设备,请检查其 _CRS(“当前资源”)是否具有 I2C/SPI/等资源如果是,请获取总线设备的句柄 (在资源中指定),请在第 1 步的映射中查找该句柄, 并告知其新的子设备和总线类型。
- 按照在第 1 步中发现设备的顺序发布所有设备,包括 与设备总线相关的信息(如 PCI) bus:device.function),还会为每个总线设备创建总线 ID。这是 因为我们需要区分不同的查询,例如两台 I2C 设备 在不同公交车上使用相同的地址。
发布复合“ACPI + 实际”设备。
为了访问设备所在的总线提供的资源, 配置方法,我们需要创建复合设备 由“真实的”组成设备,以及 ACPI 设备 由 x86 板级驱动程序发布。
利用在上一实施阶段收集的信息, 板驱动程序将执行以下两种操作之一,具体取决于设备使用的总线:
- 对于在运行时枚举的总线(例如 PCI、USB):提供
ACPI 通过特定协议指定的设备的相关信息
机制(例如,对于 PCI,这将是 bus:device.functions 列表
作为 Pciroot 的
GetPciPlatformInfo()
调用的一部分返回)。公交车司机 然后,将负责发布绑定到 ACPI 设备和“实际”由总线驱动程序发布的 - 对于运行时未枚举的总线(例如 I2C、SPI):ACPI 驱动程序将发布复合设备,并使用现有机制(例如 DEVICE_METADATA_I2C_CHANNELS)将子女的信息告知总线驱动程序。在 在这种情况下,总线驱动程序只会发布 复合 fragment。x86 板级驱动程序发布复合设备。
这种职责分离的原因是 在运行时枚举的总线(如 PCI)中,设备驱动程序会使用 进行绑定(例如供应商和设备 ID)。发布 x86 板级驱动程序中的这些复合元数据将涉及到设计一种机制 用于从公交车司机处收集这些信息。
同样,I2C 和 SPI 等其他总线也不会包含 所需的资源他们通常只知道 对设备进行寻址(例如 I2C 地址、SPI 芯片选择编号),但不是 设备类型此信息则显示在 ACPI 表中的硬件或兼容 ID。从以下位置发布这些复合元数据: 因此,要以一种有效的方式告知公交车司机,就需要告知公交车司机 并非真正需要的信息(HID 和 CID)。
绑定程序示例
对于第一种情况,x86 板级驱动程序将告知总线哪些设备需要 因此,总线驱动程序将发布一款具有两个 fragment。例如,PCI 总线驱动程序可能会发布复合设备 两个 fragment。第一个请求将绑定到 PCI 总线上的设备,采用 绑定程序运行如下命令:
BIND_PROTOCOL == PCI
BIND_PCI_TOPO == 0x5a
第二个函数将绑定到由 ACPI 总线发布的等效设备:
BIND_PROTOCOL == ACPI
BIND_ACPI_BUS_TYPE == PCI
BIND_PCI_TOPO == 0x5a
对于第二种情况,x86 板级驱动程序将使用其知道的信息 创建两个 fragment,与上述代码类似。例如,I2C 复合设备会通过类似于以下内容的绑定程序绑定到其 I2C 父项:
BIND_PROTOCOL == I2C
BIND_I2C_ADDRESS == 0xaa
BIND_I2C_BUS_ID == 0
而相应的 ACPI 绑定程序将如下所示:
BIND_PROTOCOL == ACPI
BIND_ACPI_BUS_TYPE == I2C
BIND_I2C_ADDRESS == 0xaa
BIND_I2C_BUS_ID == 0
通过 FIDL 公开 ACPI 事件、配置和方法
x86 板级驱动程序使用 ACPICA 库与 ACPI 交互。我们将 将 ACPICA 库的子集作为 FIDL 接口公开给每种设备(我们可以 我们希望未来会公开更多内容,但这涵盖了所有 树内驱动程序):
AcpiEvaluateObject
- 允许设备任意访问来评估 方法(用于控制设备状态或获取配置) 信息。我们将限制设备本身评估方法, 子项。- 事件处理脚本 - ACPI 支持三种事件类型:固定事件、常规事件 用途事件和设备对象通知。这三个选项 类似:设备可以启用/停用事件和安装事件处理脚本 当收到事件时调用该方法我们将介绍启用、停用和 通过 FIDL 调用 install 方法 - remove 将通过 关闭传递至安装的渠道的设备端。
- 地址空间处理程序 - 与事件处理程序非常相似,将由其进行处理 采用类似的方式
还有一种危险机制,我们要将限制
单独的 FIDL 协议,仅供列入许可名单的设备使用;
AcpiAcquireGlobalLock
。目前仅由 acpi-ec
驱动程序使用,
在增强型转化之外,它似乎并没有得到广泛使用。我们会将它列入许可名单
基于 HID,仅从 ACPI EC HID 开始。
迁移驱动程序
在这一阶段,我们可以开始将驱动程序迁移到使用 ACPI。对于 当前包含在 x86 开发板驱动程序中的驱动程序,这将需要重写以使用 新的 ACPI-over-FIDL 协议。对于 x86 板级驱动程序之外的驱动程序, 例如 Intel I2C 驱动程序或 I2C HID 驱动程序,这会相对简单 - 将现有硬编码配置值替换为确定的新值 。
性能
性能影响预计微乎其微。新增的大部分开销 来自当前在 x86 板驱动程序中的驱动程序将迁移到自己的 驱动程序,并被迫进行 IPC 来与 ACPI 交互。
安全注意事项
- ACPI 方法可以做任何事情,即使设置了范围,最终也能做到 如上文所述,ACPI 方法可以执行所需的任何操作(例如关机) 在不恰当的时机使用硬件),而任何有权呼叫硬件的驱动程序 因此该方法可以执行它所需的任何操作。因此,我们需要 信任使用 ACPI(以及 ACPI 表本身)的所有驱动程序。这不是 改变现状,即所有 ACPI 驱动程序都位于板驱动程序中。 另请注意,所有板级驱动程序的权限均等, 驱动程序可能由外部提供(即未编写或内置) fuchsia.git).更好的可审核性和控制 。
隐私注意事项
无。
测试
我们将严重依赖单元测试来测试板级驱动程序的实现, 因为 ACPI 假定访问整个系统。这些单元测试将验证 功能按预期运行(例如总线类型推断、设备发现、 等)。我们还将纳入测试,以确保所有 FIDL 方法 是否正确实现。
设备驱动程序将能够公平地模拟新的 ACPI FIDL 协议 这样,我们就能为设备编写单元测试和集成测试 以前无法测试(或难以测试)的驱动程序。
文档
FIDL ACPI 协议将包含有关如何使用它及其 限制。您需要撰写一些文档来解释 “ACPI+real”复合模型,以及驱动程序应如何 处理绑定。
缺点、替代方案和未知问题
不支持任意总线类型
要在通过 ACPI 公开的 x86 系统上支持新总线类型,将需要 对 x86 开发板驱动程序进行了修改。遗憾的是,这是 ACPI 实施方式:不支持“generic”或“未知”公交车。 我们预计这项服务的维护负担相对较小且容易 抵消了访问主板外部的 ACPI 表所带来的好处