Debian12启用Intel核显SR-IOV虚拟化

折腾这玩意主要是为了可以让OctaneLab上开的KVM虚拟机用核显实现远程玩gal。实际上安装过程比较简单,但有些需要注意的地方。在这里简单记录一下步骤。

Intel的显卡对GPU虚拟化的支持算是比较好的。对于5-10代的核显有GVT-g虚拟化。而对于较新的Xe显卡则有更先进的SR-IOV。这玩意似乎是在pcie上的虚拟化,最初主要用来虚拟化pcie网卡,现在显卡居然也能支持了。

Intel显卡的Linux驱动叫i915。mainline中的i915还没有实现对SR-IOV的支持(大概就快有了,但显然不关6.1 LTS啥事了已经),目前能支持的只在Intel自家的Linux内核中有(https://github.com/intel/linux-intel-lts)。但现在GitHub和Arch的软件包仓库上已经有该驱动的dkms模块了,支持内核版本6.0-6.2,使用dkms就可以轻易给自用系统的Linux内核装上。

基本条件

  • 12代Intel处理器主机,带核显,BIOS开启VT-x虚拟化(如果BIOS有VT-d选项就也要开启)
  • Debian12系统,6.1内核
  • libvirt KVM环境

安装支持SR-IOV的驱动模块

GitHub地址:https://github.com/strongtz/i915-sriov-dkms

首先下载该dkms的源代码,然后移动到/usr/src/下,准备安装模块

git clone https://github.com/strongtz/i915-sriov-dkms.git
cp -r ./i915-sriov-dkms /usr/src/i915-sriov-dkms-6.1/
cd /usr/src/i915-sriov-dkms-6.1/

然后更改dkms.conf中的模块名称,将模块名PACKAGE_NAME改为i915-sriov-dkms,版本PACKAGE_VERSION改为自用Linux内核的版本即可。

需要注意的是,官方Readme的安装步骤是针对PVE的。但与PVE不同,Debian12的默认内核大概没有对PXP(Protected Xe Path)机制的支持。如果按照Readme直接install模块,在编译和安装过程中可能并不会报错,但在启动时整个驱动模块会因为PXP而无法加载,该情况在启动时的dmesg记录中会表现为:


i915: Unknown symbol intel_pxp_irq_enable (err -2)
i915: Unknown symbol intel_pxp_debugfs_register (err -2)
i915: Unknown symbol intel_pxp_resume_complete (err -2)
i915: Unknown symbol intel_pxp_terminate (err -2)
i915: Unknown symbol intel_pxp_runtime_suspend (err -2)
i915: Unknown symbol intel_pxp_session_management_init (err -2)
i915: Unknown symbol intel_pxp_irq_handler (err -2)
i915: Unknown symbol intel_pxp_suspend (err -2)
i915: Unknown symbol intel_pxp_gsccs_init (err -2)
i915: Unknown symbol intel_pxp_gsccs_fini (err -2)
i915: Unknown symbol intel_pxp_suspend_prepare (err -2)
i915: Unknown symbol intel_pxp_irq_disable (err -2)

所以这么做行不通。

对于该情况的解决方法,除了重新编译一个启用PXP的内核外,我们也可以通过在Makefile中去掉相关的cflags(DCONFIG_DRM_I915_PXP)来直接禁用掉它,再正常安装到当前内核中。(参考issue15)

Makefile

PXP作为i915驱动的一个component,主要为12代以上的GPU提供一些额外的安全和加密机制,但这些机制貌似都是针对DRM内容保护的,所以禁用掉大概也不会有什么问题…那就先禁用了吧(

修改完Makefile后,使用dkms命令安装模块即可。由于内核中本来就有i915,所以需要用--force强制安装。但这样原来的i915也被覆盖了。

dkms install --force -m i915-sriov-dkms -v 6.1
dkms status

然后查看dkms status,模块显示为installed即为安装成功

i915-sriov-dkms/6.1, 6.1.0-12-amd64, x86_64: installed

启用模块

安装了模块之后,在启动内核的command line中添加相关参数就可以直接启用虚拟化了。Debian下启动内核的command line可以于/etc/default/grub中配置。

/etc/default/grubGRUB_CMDLINE_LINUX_DEFAULT添加参数intel_iommu=on iommu=pt i915.enable_guc=3 i915.max_vfs=4即可。i915.max_vfs可以设置为需要的虚拟化gpu的最大数量。


GRUB_CMDLINE_LINUX_DEFAULT=”quiet intel_iommu=on iommu=pt i915.enable_guc=3 i915.max_vfs=4”

设置完之后更新grub

update-grub
update-initramfs -u

然后尝试重新启动。如果一切顺利,就可以启用vGPU了。首先用lspci查看物理GPU在pci总线上的位置。比如

00:03.0 VGA compatible controller: Intel Corporation

这表示核显在pci上位于00:03.0,即总线0设备3功能0。根据该设备位置找到sysfs下对应的目录,将sriov_numvfs设置为需要启用的vGPU数量即可。

echo 4 > /sys/devices/pci0000:00/0000:00:03.0/sriov_numvfs

然后再lspci,应该能看到启用的vGPU了。启用的vGPU与物理GPU位于相同的pci总线和设备下,但pci功能号不同。若启用四个vGPU,则物理gpu的功能为0,四个vGPU的功能分别为1-4。

00:03.0 VGA compatible controller: Intel Corporation
00:03.1 VGA compatible controller: Intel Corporation
00:03.2 VGA compatible controller: Intel Corporation
00:03.3 VGA compatible controller: Intel Corporation
00:03.4 VGA compatible controller: Intel Corporation

另外可以使用sysfsutils来实现系统启动时自动初始化vGPU。安装sysfsutils,将vGPU的初始化参数添加在/etc/sysfs.conf中即可。

#/etc/sysfs.conf

devices/pci0000:00/0000:00:03.0/sriov_numvfs = 4

将vGPU分配到虚拟机(win10)中

vGPU也相当于普通的pci设备,所以就按照一般的方法把vGPU作为pci设备直通到虚拟机上就可以给虚拟机使用了。用virsh编辑虚拟机xml:

virsh edit windows10 # 虚拟机的domain

<devices>标签里添加pci设备的标签。注意标签中的pci设备的位置号。<source>标签内部的<address>标签需要指定主机下vGPU在pci总线中的位置。而<source>标签外部的<address>则表示vGPU在虚拟机中对应的pci位置,注意不要与xml中定义的其他pci设备重复。

<hostdev mode='subsystem' type='pci' managed='yes'>
<driver name='vfio'/>
<source>
<address domain='0x0000' bus='0x00' slot='0x03' function='0x4'/>
</source>
<address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/>
</hostdev>

这样就把在主机的lspci中对应00:03.4的vGPU设备映射到虚拟机中的00:03.0上了。

此外,对于win虚拟机,还需要在features.hyperv下设置venderid标签。设置成什么都无所谓,但必须要设置,否则vGPU在虚拟机中会产生错误43而无法使用。win的奇怪特性…

<features>
...
<hyperv mode='custom'>
...
<vendor_id state='on' value='foo'/>
</hyperv>
</features>

退出edit,virsh不报错就可以使用了。

然后启动虚拟机,等win自动识别并安装Intel显卡驱动(或者手动安装)之后就可以正常使用虚拟化的核显了。但要注意libvirt的VNC和SPICE连接方式都只能用CPU渲染显示。需要使用win10的RDP或者别的远程桌面程序才能使用vGPU进行显示。物理接口的连接方法,咱还没有实验过。

实测win10自己自动安装的显卡驱动就已经能很好地支持了,不需要另外去试驱动版本。RDP桌面的体验要比无vGPU时流畅很多。基本的AVC硬件解码视频播放也没有问题。简单的游戏也算能玩了。但RDP对CPU还是有一定的额外占用的,对于更大些的游戏多少会有影响。

一些动画片~

一些游戏~


由于启用的vGPU对于程序来说都是完全不同的设备,因此开启了vGPU后再在主机使用显卡时也需要注意,尽量指定程序使用的GPU设备,避免让调用GPU的程序同时使用多个vGPU。比如使用opencl的hashcat默认调用所有GPU进行计算。对于单个物理GPU衍生出的多个vGPU,hashcat会当作不同的GPU设备全部同时调用,分配的内存和核显显存占用会翻数倍,浪费资源的同时计算速率反而会降低,也会引起分配到其中的vGPU的虚拟机崩溃。对于hashcat,需要用-d 1来指定使用第一个GPU设备,即可正常运行。

评论