Skip to content

ACPI 与设备树:固件接口建模

概述

Hypervisor 需要把“虚拟硬件拓扑”准确告诉 guest 内核:

  • 在 x86_64 上,通常通过 ACPI 表
  • 在 aarch64 上,通常通过 Device Tree(DT)

你可以把它理解为“启动时硬件说明书”。说明书不对,guest 就会出现“设备看不见、IRQ 不工作、热插拔失败”等问题。

代码定位

目录/文件角色
vmm/src/acpi.rsACPI 表构建与拼装入口
arch/src/x86_64/x86_64 启动布局、ACPI 相关逻辑
arch/src/aarch64/aarch64 启动参数与 DT 相关逻辑
vmm/src/device_manager.rs设备拓扑变化触发表/树更新

ACPI:x86_64 的主路径

ACPI 关注三类信息:

  1. 资源拓扑:CPU、内存、NUMA
  2. 设备拓扑:PCI 总线、设备地址、热插拔槽位
  3. 中断与电源:IRQ 路由、电源状态模型

构建流程(概念)

热插拔关联

当 CPU/内存/PCI 设备支持热插拔时,ACPI 不仅要描述“当前状态”,还要描述“可变化能力”。

典型要求:

  • 预留插槽信息
  • 正确触发通知事件
  • guest 侧可识别并完成驱动重探测

Device Tree:aarch64 的主路径

在 ARM 场景里,DT(FDT blob)通常描述:

  • CPU 节点与拓扑
  • 内存区间
  • 中断控制器
  • MMIO 设备与 IRQ 号

最小可用节点集合(概念)

节点作用
/cpus描述 vCPU 核心信息
/memory描述可用内存区间
/chosen启动参数与内核入口上下文
/soc/*平台设备、MMIO 与 IRQ 映射

x86_64 与 aarch64 的实现差异

维度x86_64aarch64
固件描述主机制ACPIDevice Tree
中断控制器模型APIC/IOAPICGIC
启动参数注入ACPI 指针与引导参数FDT 地址传递
热插拔信息承载ACPI table/AMLDT 更新机制(受限)

中断建模与设备可见性

无论 ACPI 还是 DT,最终都要回答两个问题:

  1. 这个设备“在哪儿”(MMIO/PCI 地址)
  2. 这个设备“怎么中断”(IRQ 路由)

如果任何一项错误,常见表现是:

  • 设备能枚举但不工作
  • 驱动 probe 失败
  • 中断风暴或完全无中断

设备热插拔时的文档更新策略

建议采用“显式更新 + 事件通知”策略:

  1. 更新内核可见的拓扑描述
  2. 通知 guest 触发重探测
  3. 校验 guest 侧枚举结果

对于不支持动态更新的路径,明确标注“需重启生效”。

常见故障排查

1) guest 识别不到设备

  • 检查 ACPI 表/DT 节点是否生成
  • 检查设备地址与总线号是否冲突
  • 检查驱动是否启用对应 feature

2) 中断异常

  • 检查 IRQ 路由和控制器类型是否匹配
  • 检查中断触发模式(电平/边沿)
  • 检查 guest 内核日志中的 irq init 信息

3) 热插拔失败

  • 检查是否更新了可热插拔描述
  • 检查通知事件是否发出并被 guest 接收
  • 检查 guest udev/驱动重探测链路

阅读顺序建议

  1. vmm/src/acpi.rs(理解描述生成)
  2. arch/src/x86_64/(看 ACPI 接入启动流程)
  3. arch/src/aarch64/(对照 DT 模型)
  4. vmm/src/device_manager.rs(看设备变化如何反映到固件描述)

小结

ACPI/DT 是“虚拟硬件契约”。契约正确,guest 启动与设备管理才能稳定;契约错误,问题往往表现为“看似随机”的设备或中断故障。源码学习时,建议把拓扑描述与设备创建、中断注册三条线一起看。