HOOOS

PVE网卡直通绑定失效?一文看懂IOMMU分组拆分与ACS补丁实操

0 14 玩转Homelab Proxmox VEIOMMU硬件直通
Apple

在玩转 Proxmox VE(PVE)做软路由、NAS 或 AIO(All-in-One)系统时,PCIe 硬件直通几乎是必经之路。但很多人在直通网卡(尤其是多口网卡或板载网卡)时,经常会遇到一个诡异的现象:

一旦把网卡分配给虚拟机,PVE 宿主机上的其他设备(比如某个 NVMe 固态、USB 控制器甚至显卡)突然就动不了了,甚至导致 PVE 直接死机或网络彻底断开。

这背后的根本原因,就是 IOMMU 分组不独立。本文将从底层原理出发,带你一步步解决这个直通领域的最大痛点。


为什么直通网卡会连累其他设备?

简单来说,IOMMU(Intel VT-d 或 AMD-Vi)是负责将物理硬件隔离并分配给虚拟机的技术。为了保证安全,IOMMU 划分了多个 IOMMU Group(分组)

  • 安全规则:同一个 IOMMU 分组内的所有设备,必须打包在一起。要么全部留给宿主机,要么全部直通给同一个虚拟机。
  • 罪魁祸首:许多消费级主板(尤其是 B 系列、H 系列芯片组)为了省电或缩减成本,硬件上不支持 ACS(Access Control Services,访问控制服务)。这导致主板芯片组引出的多个 PCIe 插槽、板载网卡、SATA 控制器被强行划分在同一个 IOMMU 分组里。

当你强行直通其中一个网卡时,PVE 会试图把整个分组的控制权都抢过来。结果就是,同组的其他设备被硬生生切断了与宿主机的联系,瞬间失效。


彻底解决 IOMMU 分组冲突的三个步骤

解决这个问题需要由易到难,从物理层面逐步过渡到软件层面。

第一步:排查 BIOS 设置(最基础但最易遗漏)

有些主板默认关闭了关键的分离协议,先去 BIOS 里确认以下选项已开启:

  1. VT-d / AMD-Vi:必须为 Enabled(开启直通的基础)。
  2. SR-IOV Support:如果主板和网卡支持,务必开启。
  3. PCIe ACS / ARI Support:部分中高端主板在高级 PCI 设置里有 ACS 选项,将其设为 Enabled
  4. IOMMU:设置为 Enabled,不要选 Auto

保存重启后,进入 PVE 终端,运行以下脚本查看当前的 IOMMU 分组情况:

find /sys/kernel/iommu_groups/ -type l

如果发现你的网卡依然和一堆关键设备(如 SATA 控制器)挤在同一个 group 里,说明主板硬件本身确实无法物理拆分,需要进入下一步。


第二步:物理规避——调整 PCIe 插槽

主板上的 PCIe 插槽并非地位平等:

  • 直连 CPU 的插槽(通常是靠近 CPU 的第一条 PCIe x16 插槽,用来插显卡的):通常拥有独立的 IOMMU 分组,拆分非常完美。
  • 芯片组(PCH)引出的插槽:通常共享带宽,极易合用一个 IOMMU 分组。

实操建议
如果你直通的是一张多口网卡(如 Intel i350-T4、i226-V),尝试将它拔下来,插到最靠近 CPU 的主 PCIe 插槽上。把不需要直通的设备(如显卡或 HBA 卡)移到下方的副插槽。这种“物理位移”往往能奇迹般地让网卡获得独立的 IOMMU 分组。


第三步:终极大招——开启 PVE ACS 补丁(软解拆分)

如果物理调整不可行(比如用的是 ITX 主板,或者直通的是板载网卡),我们就必须借助内核参数,强行让内核“假装”设备之间是相互隔离的。这就是经典的 ACS Override 补丁

请根据你的 PVE 引导方式(GRUB 或 systemd-boot)进行配置。如果不确定是哪种,可以通过以下命令判断:

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

情况 A:使用 GRUB 引导(多数 Legacy 模式及部分 UEFI 安装)

  1. 编辑 GRUB 配置文件:

    nano /etc/default/grub
    
  2. 找到 GRUB_CMDLINE_LINUX_DEFAULT 这一行。默认可能长这样:

    GRUB_CMDLINE_LINUX_DEFAULT="quiet intel_iommu=on"
    
  3. 在后面追加 pcie_acs_override=downstream,multifunction

    • Intel CPU 示例
    GRUB_CMDLINE_LINUX_DEFAULT="quiet intel_iommu=on iommu=pt pcie_acs_override=downstream,multifunction"
    
    • AMD CPU 示例
    GRUB_CMDLINE_LINUX_DEFAULT="quiet amd_iommu=on iommu=pt pcie_acs_override=downstream,multifunction"
    
  4. 保存并退出(在 nano 中按 Ctrl+O,回车,再按 Ctrl+X)。

  5. 更新 grub 配置:

    update-grub
    

情况 B:使用 systemd-boot 引导(新版 PVE 默认且使用 ZFS 文件系统)

  1. 编辑内核参数配置文件:

    nano /etc/kernel/cmdline
    
  2. 这一行内容较短,直接在末尾空格后添加参数。

    • 添加后的完整示例
    root=ZFS=rpool/ROOT/pve-1 boot=zfs quiet intel_iommu=on iommu=pt pcie_acs_override=downstream,multifunction
    
  3. 保存并退出。

  4. 更新 PVE 引导工具(此步至关重要,否则重启不生效):

    proxmox-boot-tool refresh
    

关键参数解析:我该用哪个参数?

在上面的配置中,我们使用了 pcie_acs_override=downstream,multifunction。这两个参数的作用不尽相同,你可以根据拆分效果进行微调:

  • pcie_acs_override=downstream:拆分所有从 PCIe 桥(PCIe Bridge)引出的下游设备。通常解决不同插槽之间的设备混淆。
  • pcie_acs_override=multifunction:拆分多功能设备。例如单张网卡上有 4 个网口(通常识别为 01:00.0, 01:00.1 等),如果不加此参数,4 个网口会死死绑定在同一个组里,无法做到“网口 1 直通给 OpenWrt,网口 2 留给 PVE”。
  • pcie_acs_override=id:xxxx:xxxx(进阶):如果你只想针对某一个特定的物理设备进行拆分,避免全局拆分带来安全风险,可以使用设备的 VID/PID 进行精准拆分。

验证拆分结果

完成上述修改后,重启 PVE 宿主机

重启完成后,再次登录 Shell,运行以下脚本来查看分组:

# 这个脚本能清晰地展示每个 IOMMU 组里有哪些设备
for d in /sys/kernel/iommu_groups/*/devices/*; do
    n=${d#*/iommu_groups/*}; n=${n%%/*}
    printf 'IOMMU Group %s ' "$n"
    lspci -nns "${d##*/}"
done

此时你应该会发现,原本挤成一坨的设备已经被整齐地划分到了不同的 IOMMU Group 中。那个你想直通的网口,现在应该独自占有一个 Group。

接下来,你就可以放心地在虚拟机硬件设置里,添加“PCI 设备”,并勾选对应的网卡进行直通,而完全不用担心影响到宿主机的其他设备了。


⚠️ 避坑安全警告

使用 pcie_acs_override 属于“欺骗”内核的黑科技。在享受独立直通的便利时,必须知晓潜在的安全隐患:

  1. 数据安全风险:硬件上它们依然共享某些底层总线。如果直通的虚拟机被黑客攻破,理论上黑客可以利用 DMA(直接内存访问)越界读取或写入同组内其他设备(比如你的系统盘、显卡)的内存数据。
  2. 稳定性隐患:如果某些廉价硬件本身存在设计缺陷,强行拆分可能会导致数据校验出错,极少数情况下会导致 PVE 宿主机无故重启。

因此,在 Homelab 娱乐或个人测试环境中,该补丁可以放心使用;但如果在商用生产环境或多租户的云服务器中,强烈建议通过更换支持 ACS 的企业级主板来彻底解决问题。

点评评价

captcha
健康