序言

IOMMU 的作用

让虚拟机可以直接控制主机的 PCI 设备。

在使用时也会有一定优势,例如更低的延迟、更高的性能或更多功能。

但当设备传递到虚拟机后该设备不再被主机使用。

环境要求

主板 / 硬件需要支持 IOMMU,并在主板设置中开启 IOMMU


开启 IOMMU [1]

TIP

  • AMD 的 CPU IOMMU 貌似是自动的,可以不设置
  • pcie_acs_override=downstream,multifunction 可以配置 PCIe 设备的 ACS 策略,细分 IOMMU 分组,在最新版内核中可以解决 j3455 的 IOMMU 分组问题
  • iommu=pt 只会影响内核驱动,少一层地址转换可以让内核驱动设备性能更高

Intel CPU 请按此步骤操作

编辑 /etc/default/grub

shell
# /etc/default/grub
GRUB_CMDLINE_LINUX_DEFAULT="quiet"
GRUB_CMDLINE_LINUX="" // [!code --]
GRUB_CMDLINE_LINUX="intel_iommu=on iommu=pt pcie_acs_override=downstream,multifunction" // [!code ++]

更新 GRUB

bash
update-grub

编辑 /etc/kernel/cmdline

shell
# /etc/kernel/cmdline
# 在末尾空格追加
intel_iommu=on iommu=pt pcie_acs_override=downstream,multifunction // [!code ++]

更新 systemd-boot 引导

bash
proxmox-boot-tool refresh

AMD CPU 请按此步骤操作

编辑 /etc/default/grub

shell
# /etc/default/grub
GRUB_CMDLINE_LINUX_DEFAULT="quiet"
GRUB_CMDLINE_LINUX="" // [!code --]
GRUB_CMDLINE_LINUX="amd_iommu=on iommu=pt pcie_acs_override=downstream,multifunction" // [!code ++]

更新 GRUB

bash
update-grub

编辑 /etc/kernel/cmdline

shell
# /etc/kernel/cmdline
# 在末尾空格追加
amd_iommu=on iommu=pt pcie_acs_override=downstream,multifunction // [!code ++]

更新 systemd-boot 引导

bash
proxmox-boot-tool refresh

重启后验证是否配置成功

bash
cat /proc/cmdline

增加所需模块

编辑 /etc/modules

shell
# /etc/modules
vfio  // [!code ++]
vfio_iommu_type1 // [!code ++]
vfio_pci // [!code ++]
vfio_virqfd // [!code ++]

验证 IOMMU

如果输出 DMAR: IOMMU enabled 则说明开启成功

bash
dmesg | grep -e DMAR -e IOMMU -e AMD-Vi

查询 IOMMU 分组情况

bash
#!/bin/bash
shopt -s nullglob
for g in $(find /sys/kernel/iommu_groups/* -maxdepth 0 -type d | sort -V); do
    echo "IOMMU Group ${g##*/}:"
    for d in $g/devices/*; do
        echo -e "\t$(lspci -nns ${d##*/})"
    done;
done;

IOMMU 中断重新映射 [2]

TIP

现代计算机主板几乎都支持,可以跳过此步骤

验证是否支持

bash
dmesg | grep 'remapping'

如果输出类似如下结果说明支持

shell
AMD-Vi: Interrupt remapping enabled
DMAR-IR: Enabled IRQ remapping in x2apic mode

如果您的系统不支持,您可以通过以下方式允许不安全的中断

bash
echo "options vfio_iommu_type1 allow_unsafe_interrupts=1" > /etc/modprobe.d/iommu_unsafe_interrupts.conf

  1. 内核参数说明 ↩︎

  2. PCI_Passthrough ↩︎