Axvisor 模拟设备框架
Axvisor 的模拟设备由 Hypervisor 在软件中实现,客户机通过 MMIO、x86 Port I/O 或架构系统寄存器访问这些设备。用户配置只描述稳定 ID、model 名和设备语义参数,地址、中断、MSI、host IRQ 与固件 identity 均由 machine profile、host snapshot 和设备图统一规划。
这套框架主要分布在 virtualization/axdevice_base、virtualization/axdevice、virtualization/axvmconfig 和 virtualization/axvm 中。本文以现有代码为准,说明配置解析、model 注册、设备图构建、资源规划、运行时注册、访问分派、DMA 授权、中断连接、固件生成以及各架构现有设备实现。
1. 代码组成
模拟设备没有集中在单一目录。公共访问接口与运行时保持架构无关;GIC、PLIC、IOAPIC、PCH-PIC、fw_cfg、串口和 host replacement 等设备由 AxVM 的架构 prepare 阶段加入同一张设备图。
1.1 核心 crate
核心依赖方向可以概括为 axvm -> axdevice -> axdevice_base;axvmconfig 位于配置边界,负责把 TOML 解析为不含数字硬件资源的请求。
| 位置 | 主要内容 | 运行阶段 |
|---|---|---|
virtualization/axdevice_base/src/lib.rs | Device、DeviceAccess、DeviceContext、GuestMemoryAccess、Resource、grant、IRQ 与 MSI 基础接口 | 注册与访问热路径 |
virtualization/axdevice/src/model.rs | DeviceModel、DeviceFirmwareSpec | 设备声明与构建 |
virtualization/axdevice/src/graph/* | DeviceNodeSpec、DeviceGraphBuilder、ResolvedDeviceGraph | VM prepare |
virtualization/axdevice/src/resources/* | DeviceRequirements、ResourcePools、VmResourcePlanner、claim/lease | 资源规划与构建校验 |
virtualization/axdevice/src/device.rs | DeviceRuntime、资源索引、总线分派、grant 校验 | VM prepare 与 VM-exit |
virtualization/axdevice/src/registration.rs | DeviceBundle、pollable、DMA pollable、lifecycle、interrupt-controller 能力 | 设备构建与 VM 生命周期 |
virtualization/axdevice/src/fw_cfg/*、serial/*、x86/* | 通用和 x86 设备实现 | 设备构建与访问 |
virtualization/axvmconfig/src/lib.rs | GuestDevices、VirtualDeviceRequest 配置入口 | TOML 解析 |
virtualization/axvm/src/configured* | ConfiguredDeviceCatalog、默认串口、IVC model 构造 | 配置请求转设备图节点 |
virtualization/axvm/src/vm/prepare/device_plan/* | 设备图合成、guest RAM 保留、host passthrough 节点、资源池接入 | VM prepare |
virtualization/axvm/src/arch/* | 架构默认节点、资源池、固件 plan、VM-exit 接入 | VM prepare 与 vCPU 运行期 |
下图按 VM 边界划分各层职责。箭头表示构建期注入或运行时调用,不表示完整 Rust 依赖图。
设备实现仍只依赖公共契约。VM 内存、定时器、vCPU 唤醒、VM 停止请求和中断控制器等能力通过窄接口注入,而不是把 AxVM 对象交给设备。
1.2 配置入口与内置 model
GuestConfig 使用 [devices] 下的三类设备选择:passthrough、disabled 和 virtual。普通虚拟设备通过 [[devices.virtual]] 声明,配置项由稳定 ID、model 名和 model 自己解释的 options 组成。
[[devices.virtual]]
id = "console0"
model = "pl011-mmio"
clock_hz = 48000000
backend = { type = "host-console" }
[[devices.virtual]]
id = "ivc0"
model = "ivc-channel"
普通虚拟设备配置不得填写 base_gpa、mmio_base、pio_base、irq_id、msi_device_id、msi_event_id、lpi_id 等框架资源字段。这些值如果来自用户,会在 VirtualDeviceRequest::validate() 中被拒绝;如果确实需要固定资源,必须由 machine profile、host firmware snapshot 或架构内部节点产生 FixedDeviceBindings 或 fixed DeviceRequirement。
默认 catalog 注册的用户可选 model 如下。
| model | 设备语义 | 资源声明 |
|---|---|---|
pl011-mmio | PL011 串口 | MMIO registers + wired IRQ irq |
uart16550-mmio | MMIO 16550 串口 | MMIO registers + wired IRQ irq |
uart16550-pio | x86 PIO 16550 串口 | PIO registers + wired IRQ irq |
ivc-channel | Axvisor IVC 共享窗口与通知端点 | MMIO registers + wired IRQ notify |
ConfiguredDeviceCatalog 是开放边界,外部可以通过 ConfiguredModelRegistration 注册更多 model。未注册 model 返回 UnknownVirtualDeviceModel,prepare 阶段会明确失败。
1.3 总体流程
从 TOML 到一次设备访问,主路径分为 prepare 和 VM-exit 两段。prepare 生成静态设备图和资源计划;VM-exit 热路径只构造包含 source vCPU 的不可变请求、查找索引、创建能力上下文,并调用 Device::read() 或 Device::write()。
host MMIO passthrough 不是模拟设备访问路径。passthrough 和 passthrough_addresses 会被规范化成 HostPassthroughMapping 节点,参与资源冲突规划,然后在地址空间准备阶段映射。x86 的 passthrough_ports 是例外:端口访问不能用 stage-2 映射表达,因此会创建 HostPortPassthroughDeviceModel,最终仍由 DeviceRuntime 分派到宿主 in/out 适配器。
2. 配置与 model 注册
设备框架把“用户想要什么设备”和“这个设备落在哪个地址/中断”分成两个阶段。用户只提交 VirtualDeviceRequest;catalog 把 request 变成持有 Arc<dyn DeviceModel> 的 DeviceNodeSpec;资源规划器再根据 model 的 slot 声明分配资源。