RFC-0112:对 x86 设备提供 ACPI 支持

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 设备。

SPI 设备树分支

实现

发现设备关系并在系统上发布 ACPI 设备。

在发现 ACPI 设备时,我们需要确定给定设备是否为总线 如果是司机,还要说明是哪款公交车。这些信息很重要 因为它让我们能够确定 应与 ACPI 和真实的同类产品绑定。ACPI 并没有简单的 通过设备确定这两个属性的方法, 总线上的设备将是总线的子项因此需要进行拆分 将设备发现和发布流程分为三个阶段:

  1. 在树中发现设备,设置设备的 ACPI 映射 其内部表示法的句柄,其中包括所需的信息 当我们最终发布设备时,比如其父设备、句柄以及 总线类型。
  2. 对于每部设备,请检查其 _CRS(“当前资源”)是否具有 I2C/SPI/等资源如果是,请获取总线设备的句柄 (在资源中指定),请在第 1 步的映射中查找该句柄, 并告知其新的子设备和总线类型。
  3. 按照在第 1 步中发现设备的顺序发布所有设备,包括 与设备总线相关的信息(如 PCI) bus:device.function),还会为每个总线设备创建总线 ID。这是 因为我们需要区分不同的查询,例如两台 I2C 设备 在不同公交车上使用相同的地址。

发布复合“ACPI + 实际”设备。

为了访问设备所在的总线提供的资源, 配置方法,我们需要创建复合设备 由“真实的”组成设备,以及 ACPI 设备 由 x86 板级驱动程序发布。

利用在上一实施阶段收集的信息, 板驱动程序将执行以下两种操作之一,具体取决于设备使用的总线:

  1. 对于在运行时枚举的总线(例如 PCI、USB):提供 ACPI 通过特定协议指定的设备的相关信息 机制(例如,对于 PCI,这将是 bus:device.functions 列表 作为 Pciroot 的 GetPciPlatformInfo() 调用的一部分返回)。公交车司机 然后,将负责发布绑定到 ACPI 设备和“实际”由总线驱动程序发布的
  2. 对于运行时未枚举的总线(例如 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 表所带来的好处

先验技术和参考资料