PVE 版本:8.1.4 ,显卡:NVIDIA GTX 745

# 宿主机配置

# IOMMU

shell
nano /etc/default/grub

GRUB_CMDLINE_LINUX_DEFAULT="..." 中的内容修改为如下:

shell
GRUB_CMDLINE_LINUX_DEFAULT="quiet intel_iommu=on iommu=pt video=efifb:off"

准确来说是在 "..." 原来的内容后面增加这些内容,其中:

  • quiet 一般是原来就有的
  • intel_iommu=oniommu=pt 是必须的
  • video=efifb:off 如果你是给 Windows VM 直通显卡串流玩游戏的话是需要的

然后更新配置文件:

shell
update-grub

检查 IOMMU 是否启动:

shell
dmesg | grep -e DMAR -e IOMMU

看到有 DMAR 或 IOMMU 输出就行,例如我们就只看到了 DMAR 的输出。

# 配置显卡

找到自己的显卡的相关信息:

shell
lspci -knn | grep VGA

我们需要如下内容:

shell
01:00.0 VGA compatible controller [0300]: NVIDIA Corporation GM107 [GeForce GTX 745] [10de:1382] (rev a2)
        Subsystem: NVIDIA Corporation GM107 [GeForce GTX 745] [10de:1065] # these ids
        Kernel modules: nvidiafb, nouveau # these modules
  • [10de:1065]<vendor id>:<device id> 形式的厂商 id 和设备 id
  • nvidiafbnouveau 是我们的显卡所使用的驱动模块

将厂商 id 和设备 id 组合添加到 vfio 配置文件中:

shell
nano /etc/modprobe.d/vfio.conf

增加如下内容:

shell
options vfio-pci ids=10de:1382 disable_vga=1

如果你有多张显卡需要直通,那么不同显卡对应的 <vendor id>:<device id> 就以逗号分隔加在 ids= 后面即可,例如:

shell
options vfio-pci ids=1145:1400,1919:1800 disable_vga=1

屏蔽显卡驱动模块:

shell
echo "blacklist <some-module>" >> /etc/modprobe.d/blacklist.conf

对每一个模块都需要加单独一行,例如我们是 nvidiafbnouveau ,则需要:

shell
echo "blacklist nvidiafb" >> /etc/modprobe.d/blacklist.conf
echo "blacklist nouveau" >> /etc/modprobe.d/blacklist.conf

有一些教程说是修改配置文件 /etc/modprobe.d/pve-blacklist.conf ,但是官方文档(目前)说的是 /etc/modprobe.d/blacklist.conf ,两者不知道有没有区别

# vfio

shell
nano /etc/modules

增加如下几行:

shell
vfio
vfio_iommu_type1
vfio_pci
vfio_virqfd #not needed if on kernel 6.2 or newer

最后执行如下指令,并且重启:

shell
update-initramfs -u -k all

最后使用如下指令检查配置是否成功:

shell
lspci -k

预期是得到对应的显卡部分有如下输出结果:

shell
01:00.0 VGA compatible controller: NVIDIA Corporation GP108 [GeForce GT 1030] (rev a1)
        Subsystem: Micro-Star International Co., Ltd. [MSI] GP108 [GeForce GT 1030]
        Kernel driver in use: <some-module> # 预期是 vfio
        Kernel modules: <some-module>

# 问题

执行最后一句指令时,我们却遇到了这个输出:

shell
...
Re-executing '/etc/kernel/postinst.d/zz-proxmox-boot' in new private mount namespace..
No /etc/kernel/proxmox-boot-uuids found, skipping ESP sync.

然后 lspci -k 检查也没有预期的输出,虚拟机添加显卡设备后无法开机。

我尝试了官方文档中 Host Device Passthrough 部分的方法:

For both methods you need to update the initramfs again and reboot after that.

Should this not work, you might need to set a soft dependency to load the gpu modules before loading vfio-pci. This can be done with the softdep flag, see also the manpages on modprobe.d for more information.

For example, if you are using drivers named <some-module> :

shell
# echo "softdep <some-module> pre: vfio-pci" >> /etc/modprobe.d/<some-module>.conf

但仍然没有效果。

所幸,似乎有不少人也遇到了这个问题,我找到了这个帖子,似乎说是因为没有同步连接 ESP 导致的,接下来我按照里面一个解决方案走:

然后我先尝试了重新挂载 /boot/efi ,首先 lsblk -o +FSTYPE 查看 /boot/efi 挂载的磁盘分区,例如我这里是 sda2 ,然后重新挂载一下:

shell
umount /boot/efi
proxmox-boot-tool init /dev/sda2

然后先前类似 No /etc/kernel/proxmox-boot-uuids found, skipping ESP sync. 的输出就没有了,最后成功了。

# VM 配置

选中 VM ,在 == 硬件(Hardware)== 部分中,== 机型(Machine)== 应该(尽量)选择 q35 类型,如果不是的话可以在关机状态下修改。

然后还是在硬件(Hardware)部分,点击添加(add),选择 PCI 设备,找到自己的显卡添加设备。

或者 CLI 版本操作:

shell
qm set VMID -hostpci0 00:02.0
# or add these to vm config file:
# hostpci0: 00:02.0

启动虚拟机,一切无误的话就能够正常启动,然后在虚拟机中就可以当作真实物理机插着显卡进一步安装驱动操作啦