HOOOS

PVE 硬件直通避坑指南:打破 IOMMU 分组限制,实现 PCIe 设备完美独立直通

0 9 极客探路者 PVEIOMMUPCIe直通
Apple

在玩 Proxmox VE (PVE) 虚拟机直通(比如直通显卡做 HTPC/AI 绘图,或者直通多口网卡做软路由)时,很多人都会遇到一个极其恶心的“连坐”问题:

想把网卡 A 直通给 OpenWrt,网卡 B 直通给 TrueNAS,结果在 PVE 添加 PCIe 设备时,发现它们全都被死死地捆在同一个 IOMMU 分组里。只要一启动虚拟机,PVE 就会报错,或者直接把另一个虚拟机的设备也强行抢过来。

这是因为民用级主板(尤其是 B 系列、Z 系列芯片组)在 PCIe 拓扑设计上阉割了 ACS(Access Control Services,访问控制服务),导致 CPU 无法从硬件层面安全地隔离这些通道。

不用换服务器主板,本文教你如何用底层内核“黑科技”强行拆分 IOMMU 分组,实现 PCIe 设备的自由直通。


第一步:排查现状,看看你的 IOMMU 分组到底有多乱

在动手修改配置之前,先看清“敌人”的长相。

登录 PVE 的 SSH 终端,运行以下一键脚本,查看当前物理机上所有 PCIe 设备的 IOMMU 分组情况:

#!/bin/bash
for d in $(find /sys/kernel/iommu_groups/ -type l | sort -n -t$'/') ; do
    pcipath=$(echo $d | awk -F/ '{print $(NF-2)"/"$(NF-1)"/"$NF}')
    printf 'IOMMU Group %s ' "$pcipath"
    lspci -nns "${d##*/}"
done

如果输出结果中,你想要的网卡、显卡和一大堆主板桥接芯片、USB 控制器都挤在同一个 IOMMU Group X 里,那就说明你必须进行拆分了。


第二步:开启内核 ACS 覆盖(核心操作)

既然硬件不支持完美的物理隔离,我们就需要通过 Linux 内核参数,强行让系统给每个 PCIe 设备分配独立的 IOMMU 分组。这就是 ACS Override(ACS 旁路)

1. 确定你的 PVE 引导模式

PVE 的引导方式有两种:GRUBSystemd-boot。引导方式不同,修改内核参数的文件也不同。

在终端运行以下命令判断:

[ -d /sys/firmware/efi ] && echo "EFI 模式" || echo "Legacy 模式"

注:如果是 EFI 模式,PVE 7.x/8.x 默认多采用 systemd-boot,但也可能使用 GRUB,最稳妥的判断方式是检查 /etc/kernel/cmdline 是否存在。

2. 情况 A:修改 GRUB 引导配置(最常见)

如果你的系统使用 GRUB 引导,编辑 /etc/default/grub 文件:

nano /etc/default/grub

找到 GRUB_CMDLINE_LINUX_DEFAULT 这一行,在原有参数(如 quiet)后面追加以下内容:

  • Intel 平台:
    intel_iommu=on iommu=pt pcie_acs_override=downstream,multifunction
    
  • AMD 平台:
    amd_iommu=on iommu=pt pcie_acs_override=downstream,multifunction
    

参数解释:

  • pcie_acs_override=downstream:强制将 PCIe 交换机下游的所有设备拆分成独立的组。
  • multifunction:针对多功能设备(如双口网卡、显卡自带的声卡/USB控制器),将其每个功能子项也拆分为独立组。

保存并退出(Nano 编辑器下按 Ctrl+O 保存,Ctrl+X 退出),然后更新 GRUB 引导:

update-grub

3. 情况 B:修改 Systemd-boot 引导配置

如果 /etc/kernel/cmdline 文件存在,说明是由 systemd-boot 引导。

nano /etc/kernel/cmdline

该文件只有一行内容,直接在末尾(不要换行)空一格,加上:

pcie_acs_override=downstream,multifunction

保存退出后,必须刷新 PVE 引导配置:

proxmox-boot-tool refresh

第三步:加载直通必备的内核模块

确保 PVE 在开机时就准备好 VFIO(Virtual Function I/O)驱动,以便接管这些被拆分的设备。

编辑 /etc/modules 文件:

nano /etc/modules

在文件末尾添加以下四行:

vfio
vfio_iommu_type1
vfio_pci
vfio_virqfd

保存退出。


第四步:重启并验证拆分结果

完成上述步骤后,果断重启 PVE 物理机:

reboot

重启完成后,再次运行第一步中的一键排查脚本。你会发现,原本挤在同一个 Group 里的 PCIe 设备,现在已经被整整齐齐地拆分到了不同的 IOMMU Group 中。

此时,你就可以在 PVE 的 Web GUI 界面中,把网卡 A、网卡 B、显卡分别分配给不同的虚拟机,再也不会报“设备处于同一分组”的错误了。


⚠️ 深度思考:ACS 拆分的潜在风险与最优解

虽然 pcie_acs_override 解决了直通难题,但作为一名合格的 Homelab 玩家,你必须明白这是一个**“欺骗内核”的非官方黑科技**,它伴随着潜在风险:

  1. 安全隐患(DMA 攻击):
    硬件上没有物理隔离,意味着虚拟机 A 的恶意代码理论上可以通过 DMA(直接内存访问)去窥探或篡改虚拟机 B 或者 PVE 宿主机的内存。在多租户、生产环境、高安全性要求的场景下,绝对不要开启此功能。
  2. 数据损坏风险:
    如果两个设备在物理上共享同一个 PCIe 通道且没有硬隔离,高负载下的数据传输可能会产生冲突,极罕见情况下会导致直通的 NVMe 固态硬盘数据损坏或网卡丢包。

💡 更好的不折腾替代方案:

如果你对数据安全和系统稳定性有极高要求,建议在购买硬件和装机时采用以下策略:

  • 利用直连 CPU 的 PCIe 通道:
    通常主板上靠近 CPU 的第一条 PCIe x16 插槽(显卡插槽)是直接走 CPU 管道的,天然支持完善的 ACS 隔离。把最核心的直通设备(如万兆网卡、主力显卡)插在这个槽位上。
  • 走芯片组(PCH)的设备做好归类:
    主板下方的 PCIe 插槽通常走南桥芯片组,这些插槽上的设备容易被归为一组。可以将不需要直通的设备(如 PVE 宿主机的系统盘、副网卡)安置在这些插槽中,把干净的直连通道留给直通虚拟机。
  • 购买原生支持 SRIOV 的网卡:
    如果是为了多虚拟机共享网卡,与其折腾 PCIe 独立直通,不如买一张支持 SR-IOV 的网卡(如 Intel X520/X540/I350)。它能在硬件层面虚拟出几十个虚拟网卡(VF),每个 VF 都可以独立直通,完全不需要开启危险的 ACS Override。

点评评价

captcha
健康