序言
PVE 本身是支持 PCI 硬件直通的,可是在一些硬件(例如:华擎 J3455 ITX 主板)却出现 IOMMU 分组问题,从而导致硬件直通不成功。
关于 PCI 的直通请参阅官方的 wiki:
PVE PCI 直通设置
简单来说要实现直通需要通过如下步骤:
第一步:在主机 BIOS 设置中 VT-D 开启和 Video Options (Embedded Video Primary,Optional Video Secondary)
第二步:开启 IOMMU 功能 ,修改/etc/default/grub 文件 (The IOMMU has to be activated on the kernel commandline)
打开:
nano /etc/default/grub
修改:
GRUB_CMDLINE_LINUX_DEFAULT="quiet"
到:
GRUB_CMDLINE_LINUX_DEFAULT="quiet intel_iommu=on" # INTEL CPU
GRUB_CMDLINE_LINUX_DEFAULT="quiet amd_iommu=on" # AMD CPU
然后执行:
update-grub
第三步:添加核心模块 (You have to make sure the following modules are loaded. This can be achieved by adding them to ‘/etc/modules’)
echo "vfio" >> /etc/modules
echo "vfio_iommu_type1" >> /etc/modules
echo "vfio_pci" >> /etc/modules
echo "vfio_virqfd" >> /etc/modules
第四步:更新 initramfs 核心后重启
update-initramfs -u -k all
reboot
直通效果验证
运行:dmesg | grep -e DMAR -e IOMMU
假如没有回显,那么可能哪里出了问题。若是出现 IOMMU, Directed I/O or Interrupt Remapping is enabled 之类的字样那么说明 IOMMU 开启了。
当你在 PVE 主机执行:
find /sys/kernel/iommu_groups/ -type l
回显:
find /sys/kernel/iommu_groups/ -type l
/sys/kernel/iommu_groups/0/devices/0000:00:00.0
/sys/kernel/iommu_groups/1/devices/0000:01:00.1
/sys/kernel/iommu_groups/2/devices/0000:00:02.0
/sys/kernel/iommu_groups/3/devices/0000:00:16.0
/sys/kernel/iommu_groups/4/devices/0000:00:1a.0
/sys/kernel/iommu_groups/5/devices/0000:00:1b.0
/sys/kernel/iommu_groups/6/devices/0000:00:1c.0
/sys/kernel/iommu_groups/7/devices/0000:00:1c.5
/sys/kernel/iommu_groups/8/devices/0000:00:1c.6
/sys/kernel/iommu_groups/9/devices/0000:00:1c.7
但是你也可能看到:
find /sys/kernel/iommu_groups/ -type l
/sys/kernel/iommu_groups/1/devices/0000:00:0f.0
/sys/kernel/iommu_groups/2/devices/0000:00:02.0
/sys/kernel/iommu_groups/3/devices/0000:00:15.0
/sys/kernel/iommu_groups/4/devices/0000:00:12.0
/sys/kernel/iommu_groups/2/devices/0000:00:0e.0
/sys/kernel/iommu_groups/5/devices/0000:03:00.0
/sys/kernel/iommu_groups/5/devices/0000:00:13.2
/sys/kernel/iommu_groups/5/devices/0000:00:13.0
/sys/kernel/iommu_groups/5/devices/0000:04:00.1
/sys/kernel/iommu_groups/5/devices/0000:01:00.0
/sys/kernel/iommu_groups/5/devices/0000:00:13.3
/sys/kernel/iommu_groups/5/devices/0000:00:13.1
/sys/kernel/iommu_groups/5/devices/0000:04:00.0
/sys/kernel/iommu_groups/6/devices/0000:00:00.0
/sys/kernel/iommu_groups/7/devices/0000:00:1f.0
/sys/kernel/iommu_groups/7/devices/0000:00:1f.1
可以在第四列看到许多的 device 被分到了一个相同的组内 (5),那么恭喜你,你中奖了,由于你的 IOMMU 分组没有区分开,那么也就意味着没有完全成功。
官方的 Wiki 对此也有说明,请自行查阅,他给出的一个方法是:
- 首先加入强制非安全分割:
echo "options vfio_iommu_type1 allow_unsafe_interrupts=1" > /etc/modprobe.d/iommu_unsafe_interrupts.conf
- 再修改/etc/default/grub:
GRUB_CMDLINE_LINUX_DEFAULT="quiet intel_iommu=on pcie_acs_override=downstream"
此时假如你的分组问题解决了,那么恭喜你,要是发现分组还是有问题,那么今天我们就要开始大动干戈了。
PVE 内核重编译
- 准备编译主机:推荐 debian,Ubuntu。
- 更新主机源为国内源,为后续下载更新准备。
- 导入 PVE GPG 密钥:
wget -qO - http://download.proxmox.com/debian/proxmox-ve-release-6.x.gpg | sudo apt-key add -
- 添加 Proxmox VE 库到 /etc/apt/sources.list.d 文件夹下:
echo "deb http://download.proxmox.com/debian/pve buster pve-no-subscription" | sudo tee /etc/apt/sources.list.d/pve-install-repo.list
- 执行更新并安装需要的文件:
apt-get update
apt-get upgrade -y
apt-get install git nano screen patch fakeroot build-essential devscripts libncurses5 libncurses5-dev libssl-dev bc flex bison libelf-dev libaudit-dev libgtk2.0-dev libperl-dev asciidoc xmlto gnupg gnupg2 rsync lintian debhelper libdw-dev libnuma-dev libslang2-dev sphinx-common asciidoc-base automake cpio dh-python file gcc kmod libiberty-dev libpve-common-perl libtool perl-modules python-minimal sed tar zlib1g-dev
注意:如果没有导入 PVE 的 GPG 密钥,可能会导致无法安装 libpve-common-perl
- 下载 PVE 源码:###需要国外下载,若没有梯子,请看最后的技巧部分###
Git clone git://git.proxmox.com/git/pve-kernel.git
- 修改 \pve-kernel\patches\kernel 路径下的 “0003-pci-Enable-overrides-for-missing-ACS-capabilities-4..patch” 文件:
此处的“106” 改为 “105”,因为代码行数由 106 变为 105.
--- a/drivers/pci/quirks.c
+++ b/drivers/pci/quirks.c
@@ -193,6 +193,106 @@ static int __init pci_apply_final_quirks(void)
再修改:
+ if (!pci_is_pcie(dev) ||
+ pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ACS))
+ return -ENOTTY;
改成:
+ if (!pci_is_pcie(dev))
+ return -ENOTTY;
- 最后开始执行编译:###需要国外下载,若没有梯子,请看最后的技巧部分###
cd pev-kernel
make V=s
- 如果顺利的话那么会在 pve-kernel 目录得到 4 个 deb 文件。
- 将以上 4 个 deb 文件传到 pve 的 root 目录下,执行安装,安装后重启即可。(请自行备份,以防万一)
dpkg -i *.deb
reboot
技巧:
PVE 官方的源码在国外,直接下载速度很慢,而且编译过程会下载很多的 submodule,我们可以先将相关的源码拉到国内的“码云”上,再下载速度会快许多。我已经把所有需要的库全部拉到了码云上,供大家参考:
[email protected]:yfdoor/pve-kernel.git
[email protected]:yfdoor/pve-mirror_ubuntu-eoan-kernel.git
[email protected]:yfdoor/pve-zfsonlinux.git
[email protected]:yfdoor/pve-mirror_zfs.git
[email protected]:yfdoor/pve-zfs-images.git
PVE 的各个项目间通过 Git submodule 关联,他们之间的关系为:
- 一级目录 pve-kernel:submodules 文件夹 关联
- mirror_ubuntu-eoan-kernel
- zfsonlinux
- 二级目录 zfsonlinux:upstream 文件夹关联
- mirror_zfs
- 三级目录 mirror_zfs:scripts/zfs-images 文件夹关联
- zfs-images
每个项目下的 .gitmodules 文件来定义 submodule 的链接,用法请自己百度,常用的命令:
Git clone
Git pull
Git submodule init
Git submodule update