3. 设备直通概述

设备直通(Device Passthrough)是指把宿主机上一块真实的物理设备,例如网卡、GPU、NVMe SSD 或 FPGA 加速卡,直接分配给某个虚拟机独占使用,使虚拟机内的驱动能够像访问本地硬件一样访问它。与虚拟磁盘、虚拟网卡这类由 VMM 模拟出来的设备不同,直通设备在虚拟机看来就是一块真实的 PCIe 设备,拥有自己的配置空间、BAR 空间、中断和 DMA 能力。

理解设备直通的关键在于 DMA 与中断。设备发起 DMA 时使用的是物理地址,如果虚拟机直接操作设备,就必须保证设备只能访问该虚拟机被授权的内存区域,这正是 IOMMU 存在的意义。IOMMU 通过 DMA 重映射把设备发出的地址翻译并限制在指定域内,同时配合中断重映射把设备中断安全地投递到目标虚拟机。因此,设备直通可以概括为:把物理设备的所有权交给虚拟机,由 IOMMU 负责地址翻译与隔离,由 VFIO 负责设备的安全暴露与生命周期管理。

全虚拟化与半虚拟化对比

在设备虚拟化层面,常见路线有全虚拟化、半虚拟化和直通三类。全虚拟化由 VMM 完全模拟设备寄存器行为,客户机无需修改驱动,但每次寄存器访问都会触发陷入与模拟,性能开销大;半虚拟化则要求客户机安装特定前端驱动,通过共享内存与后端驱动通信,减少陷入次数,典型代表是 virtio;直通则把真实设备交给虚拟机,性能接近原生,但牺牲了设备的共享性与可迁移性。

对比维度 全虚拟化 半虚拟化(virtio) 设备直通(VFIO)
客户机驱动 原生驱动即可 需安装前端驱动 使用设备原生驱动
性能 较低,陷入频繁 较高,批量提交 接近原生
设备共享 可多虚拟机共享 可多虚拟机共享 通常单虚拟机独占
依赖硬件 无特殊要求 无特殊要求 需 IOMMU/VT-d 或 SMMU
典型场景 兼容性优先 通用 I/O 虚拟化 高性能网卡、GPU、NVMe

VFIO 与 VFIO-pci

VFIO(Virtual Function I/O)是 Linux 内核提供的用户态设备访问框架,它把设备的安全暴露抽象为容器(container)、IOMMU 组(group)和设备(device)三层结构。容器代表一个 IOMMU 地址空间,组是 IOMMU 隔离的最小单位,设备则挂载在组内。只有当一个组内的所有设备都被绑定到 VFIO 时,该组才能被安全地交给虚拟机,否则会出现 DMA 隔离漏洞。

VFIO-pci 是 VFIO 框架下针对 PCI 设备的驱动实现。它并不真正驱动硬件,而是接管设备的配置空间、BAR 映射和中断,把设备以文件描述符的形式暴露给用户态,由 QEMU 等 VMM 通过 ioctl 完成访问。使用前通常需要开启内核参数并绑定设备:

# 开启 IOMMU
# Intel: intel_iommu=on iommu=pt
# AMD:   amd_iommu=on iommu=pt

# 查看设备所属 IOMMU 组
for d in /sys/kernel/iommu_groups/*/devices/*; do
  echo "Group $(basename $(dirname $(dirname $d))): $(basename $d)"
done

# 将设备绑定到 vfio-pci
echo 0000:01:00.0 > /sys/bus/pci/devices/0000:01:00.0/driver/unbind
echo vfio-pci > /sys/bus/pci/devices/0000:01:00.0/driver_override
echo 0000:01:00.0 > /sys/bus/pci/drivers/vfio-pci/bind

在 QEMU 命令行中,直通设备通过 -device vfio-pci 挂载,并可用 host= 指定 BDF、用 rombar=0 控制 ROM 映射。若设备支持 SR-IOV,还可以把虚拟功能(VF)单独直通给不同虚拟机,从而在保持隔离的同时实现一定程度的共享。

设备直通:从物理设备到虚拟机的数据通路 物理 PCIe 设备 网卡 / GPU / NVMe BDF: 0000:01:00.0 BAR / MSI-X / DMA IOMMU DMA 重映射 中断重映射 IOMMU 组隔离 VFIO / VFIO-pci container / group 设备文件描述符 ioctl 访问控制 虚拟机(Guest) 原生驱动直接操作设备 GPA → HPA 由 IOMMU 翻译 MSI-X 中断直达 vCPU QEMU -device vfio-pci 宿主机内核 vfio-pci 驱动 IOMMU 页表管理 设备解绑 / 绑定 关键约束:同一 IOMMU 组内所有设备必须一起绑定到 VFIO,否则组内其他设备可绕过隔离发起 DMA。 典型收益:接近原生的吞吐与延迟;典型代价:设备独占、热迁移受限、依赖 ACS 与 IOMMU 拓扑。

PCIe 设备直通典型场景

直通最典型的场景是高性能网络。把物理网卡直通给虚拟机后,虚拟机内的 DPDK 或内核协议栈可以直接操作网卡队列,绕过虚拟交换层,获得接近裸机的包处理能力,常用于 NFV、防火墙和负载均衡。第二个场景是 GPU 直通,用于 AI 推理、图形工作站和云游戏,虚拟机独占 GPU 显存与计算单元,避免虚拟 GPU 的兼容性与性能损耗。第三个场景是 NVMe SSD 直通,为数据库或高性能存储节点提供低延迟、高 IOPS 的本地盘访问。此外,FPGA 加速卡、采集卡和专用加密卡也常通过直通方式交付给租户。

实践提示:直通前先用 lspci -nnk 确认设备驱动与 IOMMU 组,用 dmesg | grep -i iommu 确认 IOMMU 已启用。若设备与宿主机关键设备同组,可考虑开启 ACS 重定向或调整 PCIe 插槽位置。

常见误区与复盘

  • 误区一:只要绑定 vfio-pci 就能直通。实际上 IOMMU 未开启、设备与宿主机驱动冲突、组内存在其他设备,都会导致直通失败或隔离失效。
  • 误区二:直通设备可以随意热插拔。多数平台对直通设备的热拔支持有限,强行操作可能造成虚拟机崩溃或宿主机 IOMMU 域异常。
  • 误区三:直通一定比 virtio 快。对于小包、低频或共享型负载,virtio 的批量与共享优势可能更合适,直通更适合高吞吐、低延迟、独占型负载。
  • 误区四:忽略中断亲和与 NUMA。设备所在 NUMA 节点与 vCPU 不匹配时,跨节点 DMA 与中断会显著拉高延迟。

排障顺序建议:先确认 IOMMU 已启用并识别到设备,再确认设备已绑定 vfio-pci 且组内无其他设备,然后检查 QEMU 命令行与虚拟机 XML 中的 host 地址是否正确,最后观察 dmesg 与虚拟机内 lspci 是否识别到设备。多数直通失败都集中在 IOMMU 未开启、组隔离不完整和驱动抢占这三类原因上。

综上,设备直通是虚拟化中性能与隔离之间的一种权衡方案。它以 IOMMU 为安全底座,以 VFIO 为暴露框架,以 VFIO-pci 为 PCI 设备的具体实现,把物理设备的所有权安全地转移给虚拟机。理解容器、组、设备三层结构,理解 DMA 重映射与中断重映射的作用,是后续配置直通、排查故障和评估性能的前提。