yfdoor
yfdoor
发布于 2020-02-18 / 218 阅读 / 0 评论 / 0 点赞

【随笔】PVE(Proxmox VE) J3455 IOMMU分组及硬件直通探讨

序言

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 内核重编译

  1. 准备编译主机:推荐 debian,Ubuntu。
  2. 更新主机源为国内源,为后续下载更新准备。
  3. 导入 PVE GPG 密钥:
wget -qO - http://download.proxmox.com/debian/proxmox-ve-release-6.x.gpg | sudo apt-key add -
  1. 添加 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
  1. 执行更新并安装需要的文件:
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

  1. 下载 PVE 源码:###需要国外下载,若没有梯子,请看最后的技巧部分###
Git clone git://git.proxmox.com/git/pve-kernel.git
  1. 修改 \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;
  1. 最后开始执行编译:###需要国外下载,若没有梯子,请看最后的技巧部分###
cd pev-kernel
make V=s
  1. 如果顺利的话那么会在 pve-kernel 目录得到 4 个 deb 文件。
  2. 将以上 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

评论