因为仅仅使用PCIE_ACS_OVERRIDE依旧无法成功达成所需的IOMMU分组,故而选择直接编译PVE的内核,暂时解决IOMMU的分组问题。

WARNING

注意本文提到的方法只供实验学习使用。方法本身是存在安全隐患的。生产环境中切勿使用。

背景 | Context

手上有一个闲置的ASUS B460M Prime主板,另外手上有两个NVME,还有空闲的GPU以及SATA Expansion card。于是想着组一个新的家用服务器,开始了新一轮的折腾。

硬件 | Hardware

ASUS B460M Prime是一个低端MATX主板,4内存插槽,1 PCIEx16,2 PCIEx1,两个M.2接口,单1GbE Realtek网卡,没有无线网卡(WIFI对于拿来做服务器反而不是任何缺点,有也基本上是浪费,没有的话,network接口还稍微简单清晰一点),6个板载SATA。

SATA Expansion card主要是当初图方便,没有从Ebay上面淘HBA卡,况且也算是契合PCIEx1的接口。PCIEx1的接口除了干这个,目前估计也没有什么更合适的用处了,前提是SATA Expansion card只接HDD。

麻烦就处在这两个SATA Expansion card所在的PCIEx1上面。

软件|Software

PVE 8.0,Linux内核版本6.2,这个内核实际上是有PVE自己的补丁的。本来是寄希望于新版本的Linux也许可以对PCIE_ACS_OVERRIDE有更好的支持,可惜没有如愿。

问题|Problem

在使用了 PCIE_ACS_OVERRIDE argument的情况下,IOMMU分组里面,SATA Expansion card所在的两个PCIEx1接口,和板载的Ethernet接口在同一个分组。

现在大多数Promox启动应该都是用的systemd了,所以argument是加在 /etc/kernel/cmdline里面:

root=ZFS=rpool/ROOT/pve-1 boot=zfs quiet intel_iommu=on iommu=pt pcie_acs_override=downstream,multifunction initcall_blacklist=sysfb_init

注意以上内容必须是一行。 pcie_acs_override=downstream,multifunction 这里应该会把能拆开的设备都拆开。而且理论上multifunction可能也是不需要的,这个flag其实会把GPU里面的声卡拆分出来。

对于之前的Gigabyte Z270P D3主板,单独加这个 downstream,multifunction 已经足够了。板上的所有PCIE插槽都会分配到各自的IOMMU Group里面。

  • 通常来讲这样就足够了,而且对于CPU直连的设备,基本上可以确保能满足分组的要求了。对于GPU passthrough的情况,应该只需要这两个 flags。

对于GPU Passthrough,可以详见这篇:[proxmox-74-gpu-passthrough]

但是对于ASUS B460M,使用如下script查看分组:

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

Example output:

IOMMU Group 0 00:02.0 VGA compatible controller [0300]: Intel Corporation CometLake-S GT2 [UHD Graphics 630] [8086:9bc8] (rev 03)
IOMMU Group 1 00:00.0 Host bridge [0600]: Intel Corporation 10th Gen Core Processor Host Bridge/DRAM Registers [8086:9b63] (rev 03)
IOMMU Group 2 00:01.0 PCI bridge [0604]: Intel Corporation 6th-10th Gen Core Processor PCIe Controller (x16) [8086:1901] (rev 03)
IOMMU Group 3 00:14.0 USB controller [0c03]: Intel Corporation Comet Lake PCH-V USB Controller [8086:a3af]
IOMMU Group 4 00:16.0 Communication controller [0780]: Intel Corporation Comet Lake PCH-V HECI Controller [8086:a3ba]
IOMMU Group 5 00:17.0 SATA controller [0106]: Intel Corporation 400 Series Chipset Family SATA AHCI Controller [8086:a382]
IOMMU Group 6 00:1b.0 PCI bridge [0604]: Intel Corporation Device [8086:a3e9] (rev f0)
IOMMU Group 7 00:1b.4 PCI bridge [0604]: Intel Corporation Comet Lake PCI Express Root Port #21 [8086:a3eb] (rev f0)
IOMMU Group 8 00:1c.0 PCI bridge [0604]: Intel Corporation Device [8086:a392] (rev f0)
IOMMU Group 9 00:1c.3 PCI bridge [0604]: Intel Corporation Device [8086:a393] (rev f0)
IOMMU Group 10 00:1c.4 PCI bridge [0604]: Intel Corporation Comet Lake PCI Express Root Port #05 [8086:a394] (rev f0)
IOMMU Group 11 00:1c.5 PCI bridge [0604]: Intel Corporation Device [8086:a395] (rev f0)
IOMMU Group 12 00:1d.0 PCI bridge [0604]: Intel Corporation Comet Lake PCI Express Root Port 9 [8086:a398] (rev f0)
IOMMU Group 13 00:1f.0 ISA bridge [0601]: Intel Corporation B460 Chipset LPC/eSPI Controller [8086:a3c8]
IOMMU Group 13 00:1f.2 Memory controller [0580]: Intel Corporation Cannon Lake PCH Power Management Controller [8086:a3a1]
IOMMU Group 13 00:1f.3 Audio device [0403]: Intel Corporation Comet Lake PCH-V cAVS [8086:a3f0]
IOMMU Group 13 00:1f.4 SMBus [0c05]: Intel Corporation Comet Lake PCH-V SMBus Host Controller [8086:a3a3]
IOMMU Group 14 01:00.0 VGA compatible controller [0300]: NVIDIA Corporation GA104 [GeForce RTX 3070] [10de:2484] (rev a1)
IOMMU Group 15 01:00.1 Audio device [0403]: NVIDIA Corporation GA104 High Definition Audio Controller [10de:228b] (rev a1)
IOMMU Group 16 03:00.0 Non-Volatile memory controller [0108]
IOMMU Group 17 05:00.0 Ethernet controller [0200]: Realtek Semiconductor Co., Ltd. RTL8111/8168/8411 PCI Express Gigabit Ethernet Controller [10ec:8168] (rev 15)
IOMMU Group 18 06:00.0 SATA controller [0106]: Marvell Technology Group Ltd. 88SE9128 PCIe SATA 6 Gb/s RAID controller [1b4b:9128] (rev 20)
IOMMU Group 19 07:00.0 SATA controller [0106]: ASMedia Technology Inc. Device [1b21:1064] (rev 02)
IOMMU Group 20 08:00.0 Non-Volatile memory controller [0108]

可以看到 Ethernet controller 和两个 SATA Controller 已经属于不同的 IOMMU Group了。(之前,三个设备都在Group 9)

后记|Appendix

这个目前只能说是暂时的解决方案。终归用 Consumer grade 的主板做虚拟机平台总还是有点不方便。这个ACS Override的方法(哪怕不重新编译 kernel ),实际上也是有安全隐患的。

Why is pcie_acs_override=downstream,multifunction discouraged

参考|References

Tutorial Building the PVE Kernel on Proxmox VE 6.x