linux QEMU 的PCI设备直通(pass through)

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 支持

  1. 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 被初始化的相关信息,则表示支持。

  2. 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

  1. 启用内核模块
    确保 vfio_pcivfiovfio_iommu_type1 和 vfio_virqfd 模块已加载。通常需要修改 initramfs 来在早期启动时加载它们。

  2. 配置内核参数
    在 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,有助于提升性能。

  3. 让 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 用逗号分隔。

  4. 更新配置
    修改后,更新 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. 典型示例

  1. 直通一个 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),需要此参数,并且必须同时传递所有功能设备。

  2. 直通一个网卡

    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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

DeeplyMind

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值