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 |
然后更改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)
PXP作为i915驱动的一个component,主要为12代以上的GPU提供一些额外的安全和加密机制,但这些机制貌似都是针对DRM内容保护的,所以禁用掉大概也不会有什么问题…那就先禁用了吧(
修改完Makefile后,使用dkms命令安装模块即可。由于内核中本来就有i915,所以需要用--force
强制安装。但这样原来的i915也被覆盖了。
dkms install --force -m i915-sriov-dkms -v 6.1 |
然后查看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/grub
的GRUB_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 |
然后尝试重新启动。如果一切顺利,就可以启用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'> |
这样就把在主机的lspci中对应00:03.4的vGPU设备映射到虚拟机中的00:03.0上了。
此外,对于win虚拟机,还需要在features.hyperv下设置venderid标签。设置成什么都无所谓,但必须要设置,否则vGPU在虚拟机中会产生错误43而无法使用。win的奇怪特性…
<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设备,即可正常运行。