静看光阴荏苒
不管不顾不问不说也不念

Proxmox VE iGPU直通(SR-IOV)

几年前我配置过PVE的核显直通,当时也水过一篇文章,只不过那时候我配置的方法是最常见的,即一个核显就只分配给一台虚拟机。现在有了SR-IOV支持后,可玩性又增加了,一个核显可以分配给多台虚拟机用了。但由于目前SR-IOV还没有并入Linux内核主线,现在要体验的话需要用到这个DKMS模块:https://github.com/strongtz/i915-sriov-dkms,然而我在实际配置过程中踩了很多坑,所以这篇文章详细记录一下配置过程。

首先我的硬件(Hetzner的独立服务器)配置如下:

CPU:12th Gen Intel(R) Core(TM) i5-12500
GPU:Intel Alder Lake-S GT1 [UHD Graphics 770]
主板:ASUS PRIME Z690M-HZ
硬盘:Samsung MZVL2512HCJQ-00B00 x2
内存:32G RAM x2

PVE版本和当前使用的内核版本:

proxmox-ve: 8.2.0 (running kernel: 6.8.12-2-pve)
pve-manager: 8.2.7 (running version: 8.2.7/3e0176e6bb2ade3b)

我把硬件配置和内核版本详细的写在这里就是因为很多硬件和内核是用不了的,哪怕你和我的配置步骤一模一样,可能因为硬件或者内核的关系最终都是以失败告终。也许等到SR-IOV并入Linux内核主线后这种情况会有所改善。。

这个dkms模块的项目页面上说支持的内核是Linux 6.1 ~ Linux 6.11,但实际上由于内核编译时配置的选项与启用的功能不一定相同,很多内核版本即便在这个范围内也是用不了的,比如说Debian12默认的6.1内核就是如此。

硬件的话主要是CPU和主板,一些比较老的CPU不支持SR-IOV,主板有些也是不支持。。这些东西也不太好说,具体的得自己去查。。我找到一个Intel的支持列表,不知道是不是完整的。

如果你确定你的硬件不支持SR-IOV,可以考虑试试GVT-g,这个技术比较老,在老硬件上面的支持程度较好,有关详细信息可以看看Archlinux的Wiki

BIOS设置

首先我们要找Hetzner要一个KVM控制台,然后进到机器的BIOS界面。HZ的ASUS主板,进BIOS的按键一般是DEL,如果不是可以试试F1、F2之类的按键。

我们可以先在这里改成中文显示:

启用VT-d和IOMMU:

启用SR-IOV支持:

首选显卡选择:CPU Graphics,初始化iGPU选择启用:

保存并重启:

在Debian12上安装PVE

现在你可以使用Hetzner提供的救援系统安装一个Debian12,然后在Debian12内安装PVE:

添加PVE存储库:

echo "deb [arch=amd64] http://download.proxmox.com/debian/pve bookworm pve-no-subscription" > /etc/apt/sources.list.d/pve-install-repo.list
wget https://enterprise.proxmox.com/debian/proxmox-release-bookworm.gpg -O /etc/apt/trusted.gpg.d/proxmox-release-bookworm.gpg
apt update && apt full-upgrade

安装PVE内核并重启机器:

apt -y install proxmox-default-kernel
systemctl reboot

安装PVE:

apt -y install proxmox-ve postfix open-iscsi chrony

删除旧的内核:

apt remove linux-image-amd64 'linux-image-6.1*'

更新GRUB2配置:

update-grub

[可选]如果你的机器只有PVE这一个系统,可以删除os-prober:

apt remove os-prober

至此PVE的安装就完成了。你可以使用https://IP:8006访问到PVE的管理界面。

注:

1、有关PVE的网络配置,可以参考我的这篇文章来配置一个Simple SDN网络(NAT网络),当前的PVE版本按照这篇文章配置后可能会出现虚拟机访问不了外部网络的情况,应该是PVE的一个BUG,我在配置文件内看到实际是启用IP转发了的:

cat /etc/network/interfaces.d/sdn

可以看到有ip-forward on的配置:

auto vnet0
iface vnet0
        address 10.0.0.1/24
        post-up iptables -t nat -A POSTROUTING -s '10.0.0.0/24' -o eno1 -j SNAT --to-source 167.x.x.33
        post-down iptables -t nat -D POSTROUTING -s '10.0.0.0/24' -o eno1 -j SNAT --to-source 167.x.x.33
        post-up iptables -t raw -I PREROUTING -i fwbr+ -j CT --zone 1
        post-down iptables -t raw -D PREROUTING -i fwbr+ -j CT --zone 1
        bridge_ports none
        bridge_stp off
        bridge_fd 0
        ip-forward on

但不知为何没有生效,所以我们手动配置启用IP转发即可:

nano /etc/sysctl.conf

写入如下配置:

net.ipv4.ip_forward = 1
net.ipv6.conf.all.forwarding = 1

使其生效:

sysctl -p

本文后续的配置均使用这个Simple SDN网络。(vnet0)

2、你可能需要禁用PVE的企业存储库,以便后续可以更新、安装软件包:

PVE宿主机配置

现在需要在PVE宿主机安装DKMS模块,先安装内核头文件和需要用到的软件包:

apt -y install pve-headers-$(uname -r)
apt -y install build-essential dkms git
apt -y install sysfsutils

克隆DKMS模块的源码:

git clone https://github.com/strongtz/i915-sriov-dkms.git
cd i915-sriov-dkms/

安装dkms模块:

dkms add .
dkms install -m i915-sriov-dkms -v $(cat VERSION) --force

编辑GRUB2的配置文件:

nano /etc/default/grub

在GRUB_CMDLINE_LINUX_DEFAULT后面添加如下内容:

GRUB_CMDLINE_LINUX_DEFAULT="consoleblank=0 intel_iommu=on i915.enable_guc=3 i915.max_vfs=7"

更新GRUB2以及initramfs:

update-grub
update-initramfs -u

查找iGPU总线地址:

lspci

例如我的回显是00:02.0:

将查看到的总线地址替换到如下命令中:

echo "devices/pci0000:00/0000:00:02.0/sriov_numvfs = 7" > /etc/sysfs.conf

其中7就是最终要生成的VF数量,最多只支持7个。如果你不需要这么多,可以适当修改。

重启PVE宿主机:

systemctl reboot

登录到PVE宿主机验证一下配置,如果正常的话,现在可以看到更多的VF:

Debian12虚拟机配置

在PVE宿主机配置完成后,现在还需要在虚拟机进行配置。为了确保环境的一致性,这里我的虚拟机使用的系统是Debian12,并且我是直接用官方的cloud镜像来创建的系统模板。

除了虚拟机使用的系统以外,针对单个虚拟机的设置也非常重要:

虚拟机的BIOS:OVMF(UEFI)
机型:q35
显示:默认
BIOS安全启动:关闭

下载Debian12的cloud镜像:

cd /root
wget https://cloud.debian.org/images/cloud/bookworm/latest/debian-12-generic-amd64.qcow2

创建满足上述要求的虚拟机:

qm create 50000 \
--name debian12-template \
--cpu host \
--cores 2 \
--memory 2048 \
--machine q35 \
--bios ovmf \
--efidisk0 local:0,format=qcow2,efitype=4m,pre-enrolled-keys=1,size=528K \
--net0 virtio,bridge=vnet0 \
--scsihw virtio-scsi-single \
--agent enabled=1,freeze-fs-on-backup=1,fstrim_cloned_disks=1 \
--serial0 socket

导入cloud镜像:

qm set 50000 --scsi0 local:0,import-from=/root/debian-12-generic-amd64.qcow2,cache=writeback,iothread=1,discard=on,format=qcow2

创建cloud-init设备:

qm set 50000 --ide0 local:cloudinit

设置root密码:

qm set 50000 --ciuser=root --cipassword="password"

配置网络使用DHCP:

qm set 50000 --ipconfig0 ip=dhcp

修改启动顺序:

qm set 50000 --boot order=scsi0

转换成系统模板:

qm template 50000

最终这个系统模板的硬件配置应如下图所示:

克隆一台虚拟机并启动,登录进去执行如下命令检查BIOS是否启用了“安全启动”,如果启用了我们需要关闭掉:

mokutil --sb-state

如果回显如下所示,说明虚拟机的BIOS启用了“安全启动”:

重启虚拟机按DEL进入到虚拟机的BIOS,进入Device Manager:

进入Secure Boot Configuration:

按空格去掉选中Attempt Secure Boot:

保存BIOS设置重启虚拟机,再次执行之前的检查命令,如果回显“SecureBoot disabled”说明安全启动已经关闭了。

接下来编辑Debian的存储库配置文件:

apt edit-sources

添加backports存储库:

deb http://deb.debian.org/debian bookworm-backports main contrib non-free

从backports存储库安装6.9版本的内核以及头文件:

apt update
apt install -t bookworm-backports linux-image-6.9.10+bpo-amd64
apt install -t bookworm-backports linux-headers-6.9.10+bpo-amd64

重启虚拟机:

systemctl reboot

安装需要用到的软件包:

apt -y install build-essential dkms git

克隆dkms模块的源码:

git clone https://github.com/strongtz/i915-sriov-dkms.git
cd i915-sriov-dkms/

编辑dkms.conf:

nano dkms.conf

将版本改为6.9:

PACKAGE_VERSION="6.9"

安装模块:

dkms add .
dkms install -m i915-sriov-dkms -v 6.9 --force

编辑GRUB2配置文件:

nano /etc/default/grub

在GRUB_CMDLINE_LINUX_DEFAULT后面增加如下配置:

GRUB_CMDLINE_LINUX_DEFAULT="i915.enable_guc=3"

更新GRUB2配置并关闭虚拟机:

update-grub
update-initramfs -u
poweroff

在PVE的管理界面,为虚拟机添加PCI设备,切记永远不要为虚拟机分配PCI总线地址为0000:00:02.0的设备:

勾选主GPU选项,勾选PCI-Express选项,切记永远不要勾选“所有功能”选项:

勾选主GPU选项后,PVE会忽略显示选项,即虚拟机内只有你直通的这个显卡,不会有其他虚拟显卡。由此带来的一个问题是PVE自带的VNC控制台就无法使用了,但我在创建虚拟机的时候添加了一个串行端口,此时可以使用PVE提供的xterm.js来访问虚拟机。

启动虚拟机,登录进去后检查i915模块是否正常加载:

dmesg | grep i915
lsmod | grep i915

有类似如下回显说明正常:

如果你遇到了问题,有任何报错信息应该都可以通过dmesg查看到,我这里虽然也遇到个*ERROR* GT0: IOV: Unable to confirm version 1.13的错误,但实际并不影响使用,如果你强迫症硬要把这个错误给解决了的话,可以参考这里

检查直通的iGPU是否正常工作:

lspci | grep -i vga
lspci -vs 01:00.0

有类似如下回显说明正常:

Windows11虚拟机配置

说实话其实我不怎么用Windows的虚拟机,但还是想着折腾下吧,都搞到这里了,反正也花不了多少时间。。结果没想到的是,这不折腾还好,一折腾各种奇葩问题都来了。。

先是装系统,安装的时候就装好VirtIO网卡驱动了,安装过程中也是有网的,装完后莫名其妙网就没了。。排查半天最后发现是VirtIO网卡驱动莫名其妙挂了。。在设备管理器手动点一下启动又好了。。然后是核显直通的配置,一开始各种报ERROR 43,后面又神奇的好了。。期间机器还蓝屏一次。。

总之各种奇葩问题一大堆,最后也都解决了就是。。废话不多说了,下面记录下配置过程。。首先你需要准备Windows11的ISO和VirtIO驱动的ISO。这些步骤可以参考我的这篇文章

创建虚拟机,按下图配置:

系统按下图进行配置:

磁盘按下图进行配置:

CPU这里的类别选择host:

内存建议8GB或者更多:

网络选择之前创建的sdn网络(vnet0)模型选择VirtIO:

启动虚拟机,第一时间打开VNC控制台,按回车进入Windows11安装界面:

选择自定义安装:

点击加载驱动程序:

选择磁盘驱动程序:

安装磁盘驱动:

在这个界面不要急着分区,继续点击加载驱动程序:

之前创建虚拟机的时候网卡模型用的是VirtIO,现在还需要安装VirtIO网卡驱动,否则后续系统无法联网,找到NetKVM目录选中对应的系统版本:

安装网卡驱动:

之后创建分区,系统就开始安装了,过程基本都自动化了,就是什么配置键盘、输入法、等等的操作,这里就省略不详细说了。等待系统安装完成后,我们需要把剩下没安装的驱动都安装上去,找到virtio-win驱动器,双击virtio-win-gt-x64安装:

建议把virtio-win-guest-tools也安装一下,安装完成后把虚拟机关机。回到PVE管理界面,添加PCI设备:

将显示改为VirtIO-GPU:

说下这里为什么要这么改,因为之前我们没有配置Windows的远程桌面,在启用主GPU且显示为“默认”的时候,PVE的VNC控制台也就用不了了,这时候又没有远程桌面又没有VNC控制台那岂不是就访问不了虚拟机了?为了解决这个问题,我想到的一个办法就是改用VirtIO-GPU,因为之前在虚拟机内已经安装过VirtIO的驱动了,所以改成VirtIO-GPU可以让PVE的VNC控制台继续正常工作。

将虚拟机开机,通过PVE的VNC控制台访问虚拟机,现在要做的就是下载并安装Intel的驱动

先安装这个Intel® Driver & Support Assistant (Intel® DSA),然后右键检查驱动程序更新,会自动打开浏览器跳转到驱动下载页面:

重启虚拟机,打开设备管理器检查核显状态:

此时会发现虚拟机内实际是有2个显卡的,一个是直通进来的核显,还有一个就是之前的VirtIO-GPU。此时会有一个问题,在Windows11下面,程序可能不会主动去用直通进来的这个核显,这个时候就需要手动去指定程序用哪个显卡,在“系统”->“屏幕”->“显示卡”中设置每个程序要使用的图形首选项:

如果想让程序直接使用直通进来的核显,可以先在Windows中启用“远程桌面连接”,之后将虚拟机的显示改为“无”:

如果你选择这样的配置,那么PVE的VNC控制台将无法使用。总而言之是一个鱼和熊掌不可兼得的操作,你可能还需要配置端口转发才能连接上远程桌面,有关端口转发的配置,可以参考这篇文章

配置Jellyfin硬件加速

其实我折腾这个的最终目的就是想让Jellyfin用核显硬解,这里顺带把Jellyfin的配置记录一下。我的Jellyfin使用Docker安装在Debian12的虚拟机中。

先确认虚拟机内的设备名以及render组的ID,可以看到设备名是renderD128,ID是104:

在docker-compose.yml内增加相应的配置:

services:
  jellyfin:
    image: jellyfin/jellyfin
    container_name: jellyfin
    restart: 'unless-stopped'
    network_mode: 'host'
    group_add:
      - "104"
    volumes:
      - ./config:/config
      - ./cache:/cache
      - ./media:/media
    devices:
      - /dev/dri/renderD128:/dev/dri/renderD128

重启容器:

docker compose down
docker compose up -d

检查QSV以及VA-API codecs:

docker exec -it jellyfin /usr/lib/jellyfin-ffmpeg/vainfo

如果这里回显Intel iHD driver则说明同时支持QSV以及VA-API,如果回显Intel i965 driver说明只支持VA-API,QSV是目前的首选,因为性能更好:

检查OpenCL runtime状态:

docker exec -it jellyfin /usr/lib/jellyfin-ffmpeg/ffmpeg -v verbose -init_hw_device vaapi=va -init_hw_device opencl@va

如果正常则有类似回显:

打开Jellyfin的控制台,找到“播放”->“转码”,在硬件加速这里选择“Intel QuickSync (QSV)”,并在下方勾选支持的解码器:

现在你可以在这两个网站中下载测试视频来测试硬解是否正常:https://repo.jellyfin.org/jellyfish、https://kodi.wiki/view/Samples

有关Jellyfin硬件加速的更多信息见:https://jellyfin.org/docs/general/administration/hardware-acceleration/intel

赞(4)
未经允许不得转载:荒岛 » Proxmox VE iGPU直通(SR-IOV)
分享到: 更多 (0)

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址

分享创造快乐

广告合作资源投稿