4. 设备直通核心概念
在 Jailhouse 的分区模型中,设备直通并不是把物理设备“复制”给某个 inmate,而是把设备原本由 Linux 掌控的访问路径整体移交给目标分区。要理解这一过程,需要同时看清四条主线:PCI 设备如何被识别与归属、MMIO 如何映射到分区地址空间、DMA 如何被重映射到安全的内存区域,以及隔离与资源所有权如何保证分区之间互不干扰。这四者共同构成设备直通的最小完整闭环。
一、PCI 设备直通:从枚举到归属转移
PCI 设备直通的第一步是“识别与解绑”。在 Jailhouse 场景中,Linux 作为 root cell 先完成 PCI 枚举,获得设备的 BDF(Bus:Device.Function)、BAR 基址、中断号等信息。随后,Jailhouse 通过配置单元(cell config)声明该设备归属某个 inmate,Linux 侧需要把对应驱动解绑,避免两个分区同时操作同一设备。
设备直通的关键不是“让 inmate 看见设备”,而是“让 inmate 独占设备”。因此,配置中必须明确设备的 BDF、BAR 范围、中断类型(MSI/MSI-X 或 INTx)以及所属分区。Jailhouse 在启动 inmate 时,会把这些资源从 root cell 的视野中移除,并注入到 inmate 的虚拟 PCI 配置空间中。
/* jailhouse cell config 片段:声明 PCI 设备归属 */
.pci_devices = {
{
.type = JAILHOUSE_PCI_TYPE_DEVICE,
.domain = 0x0000,
.bdf = 0x0000, /* 00:00.0 */
.bar_mask = {
0xfffffff0, 0x00000000,
0x00000000, 0x00000000,
0x00000000, 0x00000000,
},
.irq = 0x00000010, /* 中断号 */
},
},
这段配置表达了三个核心信息:设备身份(BDF)、可访问的 MMIO 窗口(BAR mask)、中断资源(IRQ)。只有三者同时被正确声明,inmate 才能在不触碰其他分区的前提下完成设备初始化。
二、MMIO 映射:把寄存器窗口交给分区
PCI 设备的 BAR 空间本质上是 MMIO 区域。设备直通时,Jailhouse 需要把这段物理地址映射到 inmate 的地址空间,并确保 root cell 不再映射或访问同一区域。MMIO 映射的核心是“地址窗口 + 权限 + 归属”三要素:窗口决定 inmate 能访问哪些寄存器,权限决定读写属性,归属决定谁拥有这段地址。
如果 MMIO 映射不完整,inmate 在读写设备寄存器时会出现异常或静默失败;如果映射重叠,则可能造成两个分区同时写同一寄存器,导致设备状态错乱。因此,Jailhouse 在建立 inmate 地址空间时,会以页为单位检查 MMIO 区域是否与 root cell 或其他 inmate 冲突。
三、DMA 重映射:设备访问内存的安全闸门
设备直通中最危险的部分是 DMA。PCI 设备可以绕过 CPU 直接读写物理内存,如果不对 DMA 地址进行限制,设备可能写入 root cell 的内核内存,造成崩溃或安全漏洞。Jailhouse 依赖 IOMMU(如 Intel VT-d、ARM SMMU)进行 DMA 重映射,把设备发出的 DMA 地址翻译到 inmate 拥有的内存区域。
DMA 重映射的关键在于“地址空间隔离”:每个设备被分配一个独立的 IOMMU 域,域内只允许访问该 inmate 的物理页。设备发出的 DMA 请求先经过 IOMMU 查表,若目标地址不在允许范围内,则被拦截并产生错误。这样,即使设备固件或驱动存在缺陷,也无法越界访问其他分区的内存。
/* 查看 IOMMU 分组与设备归属(Linux root cell 侧) */
$ ls /sys/kernel/iommu_groups/
$ find /sys/kernel/iommu_groups/ -name "*00:00.0*"
/sys/kernel/iommu_groups/12/devices/0000:00:00.0
/* Jailhouse 启动后,该设备应出现在 inmate 的 IOMMU 域中 */
$ jailhouse cell list
$ jailhouse cell stat inmate1
IOMMU 分组信息可以帮助判断设备是否具备独立直通条件。如果多个设备共享同一 IOMMU 组,单独直通其中一个可能影响同组其他设备,需要谨慎评估。
四、设备隔离与资源所有权
设备隔离的目标是让每个分区只看到并只操作属于自己的设备。Jailhouse 通过“资源所有权表”实现这一点:PCI 设备、MMIO 窗口、中断线、DMA 域、IOMMU 域都被登记为某个分区的资源。当分区启动时,Jailhouse 检查资源是否冲突;当分区运行时,硬件隔离机制(IOMMU、中断重映射、MMIO 权限)持续生效。
资源所有权不仅包括“谁拥有”,还包括“谁不能访问”。例如,root cell 在设备直通后不应再访问该设备的 BAR 和中断,否则会破坏 inmate 的设备状态。Jailhouse 通过配置和运行时检查,确保资源所有权在分区之间清晰划分。
| 资源类型 | 直通前归属 | 直通后归属 | 隔离机制 |
|---|---|---|---|
| PCI 设备(BDF) | root cell | inmate | 配置声明 + 驱动解绑 |
| MMIO BAR 窗口 | root cell 地址空间 | inmate 地址空间 | 页表映射 + 权限检查 |
| DMA 地址空间 | root cell 物理内存 | inmate 物理内存 | IOMMU 重映射 |
| 中断线 / MSI-X | root cell 中断控制器 | inmate 中断注入 | 中断重映射 + 注入 |
| IOMMU 域 | root cell 默认域 | inmate 独立域 | 域隔离 + 页表校验 |
五、典型场景与常见误区
假设一块网卡需要直通给实时分区 inmate1。操作流程如下:首先在 Linux 中确认网卡 BDF 与 IOMMU 分组;然后在 Jailhouse 配置中声明该 PCI 设备归属 inmate1,并填写 BAR mask 与 IRQ;接着解绑 Linux 驱动,停止 root cell 对该设备的访问;最后启动 inmate1,由 inmate 内的驱动完成设备初始化。启动后,inmate1 通过 MMIO 读写网卡寄存器,通过 DMA 收发数据包,中断由 Jailhouse 注入。
常见误区有三个。第一,只声明 PCI 设备却忘记配置 MMIO 窗口,导致 inmate 访问 BAR 时失败。第二,忽略 IOMMU 分组,直通后同组其他设备异常。第三,root cell 未解绑驱动,两个分区同时操作设备,出现随机崩溃或数据损坏。复盘时应优先检查资源所有权表是否完整、IOMMU 域是否独立、中断路径是否只注入目标分区。
总结来看,PCI 设备直通解决“设备归属”,MMIO 映射解决“寄存器访问”,DMA 重映射解决“内存安全”,设备隔离与资源所有权解决“互不干扰”。四者缺一不可,共同构成 Jailhouse 设备直通的核心概念体系。理解这四条主线,才能在后续配置与排障中快速定位问题所在。