VFIO(Virtual Function I/O)是一个现代化的、安全的内核框架,用于在用户空间实现设备直通,例如在 QEMU/KVM 虚拟化环境中。vfio-pci 是该框架下的 PCI 设备驱动。
1. 核心概念:设备直通
设备直通允许虚拟机独占并直接访问宿主机上的一个物理硬件设备。对于虚拟机来说,这个设备就像直接插在它自己的主板上一样,从而可以获得近乎原生的性能。
-
传统模拟:QEMU 完全通过软件模拟一个设备(如 e1000 网卡),性能较差。
-
半虚拟化:使用
virtio等驱动,在宿主机和虚拟机之间使用高效的通信机制,性能很好,但仍然是虚拟设备。 -
设备直通:虚拟机直接使用物理设备,绕过 VMM 的大部分干预,性能最高。
vfio-pci就是实现 PCI/PCIe 设备直通的关键。
2. 配置 VFIO-PCI 直通
配置步骤如下,下面我们来详细讲解每个步骤。

2.1 确认硬件和 BIOS 支持
-
IOMMU 支持
-
对于 Intel CPU:需要支持
VT-d(Virtualization Technology for Directed I/O)。 -
对于 AMD CPU:需要支持
AMD-Vi。 -
如何确认:在 BIOS/UEFI 中确保这些功能已开启。然后在 Linux 中执行:
dmesg | grep -e DMAR -e IOMMU如果看到 DMAR 表或 IOMMU 被初始化的相关信息,则表示支持。
-
-
OMMU 分组检查
执行以下命令检查 IOMMU 分组情况:shopt -s nullglob for g in /sys/kernel/iommu_groups/*; do echo "IOMMU Group ${g##*/}:" for d in $g/devices/*; do echo -e "\t$(lspci -nns ${d##*/})" done done
2.2 配置 Linux 内核以使用 VFIO
-
启用内核模块:
确保vfio_pci、vfio、vfio_iommu_type1和vfio_virqfd模块已加载。通常需要修改 initramfs 来在早期启动时加载它们。 -
配置内核参数:
在 GRUB 引导器中,修改/etc/default/grub文件中的GRUB_CMDLINE_LINUX行。-
对于 Intel:
GRUB_CMDLINE_LINUX="intel_iommu=on iommu=pt" -
对于 AMD:
GRUB_CMDLINE_LINUX="amd_iommu=on iommu=pt" -
iommu=pt表示只为需要直通的设备启用 IOMMU,有助于提升性能。
-
-
让 VFIO 提前接管设备(推荐):
为了防止宿主机系统抢先占用你想要直通的设备,可以在内核参数中指定vfio-pci来绑定它们。首先,获取设备的 Vendor ID 和 Device ID:lspci -n -s <设备PCI地址,如 01:00.0> # 输出示例:01:00.0 0300: 10de:1b80 (rev a1)然后,同样在
/etc/default/grub的内核参数中添加:GRUB_CMDLINE_LINUX="... vfio-pci.ids=10de:1b80,8086:100e"多个设备 ID 用逗号分隔。
-
更新配置:
修改后,更新 GRUB 并重建 initramfs,然后重启。sudo update-grub sudo update-initramfs -u sudo reboot
2.3 验证并手动绑定设备(可选)
重启后,验证设备是否已被 vfio-pci 驱动绑定:
lspci -kn -s <设备PCI地址>
在输出中,你应该看到 Kernel driver in use: vfio-pci。
如果未能自动绑定,你可以手动操作:
# 1. 解绑原有驱动
echo <设备PCI地址> | sudo tee /sys/bus/pci/devices/<设备PCI地址>/driver/unbind
# 2. 绑定到 vfio-pci
echo <vendor id> <device id> | sudo tee /sys/bus/pci/drivers/vfio-pci/new_id
# 或者直接使用 PCI ID
echo <设备PCI地址> | sudo tee /sys/bus/pci/drivers/vfio-pci/bind
2.4 在 QEMU 命令行中添加设备
最后,在启动 QEMU 虚拟机时,使用 -device vfio-pci 来将设备传递给虚拟机。
-device vfio-pci,host=<BB:DD.F>[,...其他选项]
3. 典型示例
-
直通一个 GPU
qemu-system-x86_64 \ ... # 其他参数(内存、CPU等) -device vfio-pci,host=01:00.0,multifunction=on \ -device vfio-pci,host=01:00.1 \ ...-
host=01:00.0:指定要直通的设备在宿主机上的 PCI 地址。 -
multifunction=on:如果设备是多功能设备(如 GPU 通常带一个音频控制器01:00.1),需要此参数,并且必须同时传递所有功能设备。
-
-
直通一个网卡
qemu-system-x86_64 \ ... # 其他参数 -net none \ # 确保不为此设备创建默认网络 -device vfio-pci,host=06:00.0 \ ...
4. 重要注意事项
-
安全性:VFIO 设计上是安全的,它利用 IOMMU 进行 DMA 隔离,防止设备直接访问任意内存。
-
GPU 直通:这是最常见的用途(也称为 "VGA Passthrough" 或 "GPU Passthrough")。通常还需要在 QEMU 参数中隐藏虚拟化状态、使用特定的 BIOS 设置(如
vgabios转储)等,过程更为复杂。 -
驱动程序冲突:最大的挑战是确保宿主机没有占用设备。使用内核参数提前绑定是最可靠的方法。
-
IOMMU 分组:如果设备所在的 IOMMU 组中有其他不想直通的设备,你将无法单独直通该设备。解决此问题可能需要使用支持 ACS override 的内核参数(
pci=acs_override=on)或特定的 PCIe 插槽,但这可能会降低系统安全性。IOMMU Group 10: 01:00.0 VGA compatible controller [0300]: NVIDIA Corporation GP106 [GeForce GTX 1060 6GB] [10de:1c03] (rev a1) 01:00.1 Audio device [0403]: NVIDIA Corporation GP106 High Definition Audio Controller [10de:10f1] (rev a1)-
独立分组:理想的直通设备应该位于独立的 IOMMU 组中。
-
多功能设备:如上面的 Group 10,包含 GPU (
01:00.0) 和其音频控制器 (01:00.1),它们必须一起直通。 -
问题分组:如果一个组包含不相关的设备(如 GPU + 网卡),则无法单独直通其中一个。
-
VFIO-PCI 驱动是实现高性能 PCI/PCIe 设备直通的工业标准方法。虽然配置过程稍显复杂,但它能让你在虚拟机中获得最佳的硬件性能,尤其适用于图形工作站、游戏虚拟机和需要低延迟网络的应用场景。
技术交流,欢迎加入社区:GPUers。
&spm=1001.2101.3001.5002&articleId=154060519&d=1&t=3&u=59af38f273e74dc08be8343b82400cb1)
352

被折叠的 条评论
为什么被折叠?



