在虚拟化领域,gpu的虚拟化是一个很头疼的问题,因为各显卡厂家的gpu虚拟化方案各不相同,导致必须得针对每种方案做个性化处理,从宏观上看,有3种虚拟化模式
- passthrough直通模式
在直通模式下,显卡硬件完全由1个虚拟机独占,宿主机无法使用此设备,也无法提供给多个虚拟机使用 - virtio-gpu模式
严格意义上,这不属于gpu虚拟化方案,virtio-gpu是一种GPU分时复用方案,优点是具有通用性,缺点是因为GPU需要处理更多的请求,调度上的损耗大,牺牲了较多GPU的性能,导致在使用3D渲染等场景下表现极差 - vGPU模式
通过显卡硬件及驱动的支持,将1个显卡拆分成多个虚拟显卡,虚拟机内使用的是虚拟显卡,此时可以实现多个虚拟机及宿主机共用一块物理显卡
大多数场景下,如果要满足3D渲染需要,vGPU模式是不二之选,但是,Nvidia、AMD和Intel各自的方案又彼此不同,且依旧在不断的技术演进中,对于期望轻量3D渲染的场景,直接利用Intel CPU内置的GPU来实现可以理解为是最实惠的方案。
Intel的gpu虚拟化技术,也因架构的升级而经历了从GVT-g到SR-IOV的发展,从6代Skylake到11代Rocket Lake架构,采用的是GVT-g,而从11代的Tiger Lake后,采用的则是SR-IOV。具体的支持信息可以从网址https://www.intel.com/content/www/us/en/support/articles/000093216/graphics.html
获得
intel关于GVT-g的项目地址是https://github.com/intel/gvt-linux
,可以从其wikihttps://github.com/intel/gvt-linux/wiki/GVTg_Setup_Guide
中获取到较多的安装及操作信息
本文讲述在linux环境下,利用qemu + GVT-g技术实现虚拟机内对intel gpu的支持,本文内容的验证环境是:
- Asus PRIME Z370-A
- Intel i7-8700
- Fedora 37
- QEMU x86_64 7.2.0
- 首先,升级主板bios为最新版本(成文时为3004),此操作非必需,但强烈建议以避免出现各种无意义的坑。
- 确认bios已正确开启虚拟化支持,bios界面,Advanced Mode模式,Advanced => CPU Configuration,设置Intel Virtulazition Technology为Enabled。
- 配置内核参数
因为Fedora 37使用的是6.0+内核,已经包含了对intel gvt-g的支持,故不再需要自行构建内核,只需要添加内核参数即可,具体操作为:
- 修改/etc/default/grub中GRUB_CMDLINE_LINUX条目,在原有参数基础上添加如下参数
i915.enable_gvt=1 kvm.ignore_msrs=1 intel_iommu=igfx_off
- 执行命令,
grub2-mkconfig -o /boot/grub2/grub.cfg
,以重建grub.cfg配置文件 - 重启操作系统,执行
dmesg | grep "Command line"
确认添加的参数已经存在
- 加载必需的kernel module
实测加载模块并不需要通过dracut重新生成/boot/initramfs.img来完成,只需要将模块列表以配置文件形式添加到/etc/modules-load.d目录下即可
cat <<EOF>/etc/modules-load.d/gvt-g.conf
vfio
mdev
kvmgt
vfio_iommu_type1
vfio_virqfd
vfio_pci
EOF
重启机器,通过lsmod确认上述module已被加载
- 创建vGPU
在修改内核启动参数及加载必需模块后,我们能够在内核目录/sys/devices/pci0000:00/0000:00:02.0/mdev_supported_types
看到所支持的vGPU类型,支持类型和硬件及bios有关,ASUS Z370-A缺省支持2种类型:
[root@fedora ~]# ls -lF /sys/devices/pci0000:00/0000:00:02.0/mdev_supported_types
total 0
drwxr-xr-x. 3 root root 0 4月15日 12:05 i915-GVTg_V5_4/
drwxr-xr-x. 3 root root 0 4月15日 12:05 i915-GVTg_V5_8/
i915-GVTg_V5_4是vGPU的类型名称。名称i915-GVTg_Vx_y用于表示不同的vGPU类型:“x”表示英特尔GPU工艺级别。V4是英特尔GPU GEN8,V5是英特尔GPU GEN9;“y”是类型ID。ID越小,类型拥有的资源就越多。下表中提供了资源映射信息。每种类型也有权重设置。权重值较高的vGPU将获得更多物理GPU时间片
y | aperture memory size | hidden memory size | fence size | weight |
---|---|---|---|---|
8 | 64 | 384 | 4 | 2 |
4 | 128 | 512 | 4 | 4 |
2 | 256 | 1024 | 4 | 8 |
1 | 512 | 2048 | 4 | 16 |
在每种vGPU类型目录下,均存在description和available_instances文件,前者描述了vGPU的规格,后者说明可创建vGPU的数量
[root@fedora ~]# cat /sys/devices/pci0000:00/0000:00:02.0/mdev_supported_types/i915-GVTg_V5_4/description
low_gm_size: 128MB
high_gm_size: 512MB
fence: 4
resolution: 1920x1200
weight: 4
[root@fedora ~]# cat /sys/devices/pci0000:00/0000:00:02.0/mdev_supported_types/i915-GVTg_V5_4/available_instances
1
[root@fedora ~]# cat /sys/devices/pci0000:00/0000:00:02.0/mdev_supported_types/i915-GVTg_V5_8/description
low_gm_size: 64MB
high_gm_size: 384MB
fence: 4
resolution: 1024x768
weight: 2
[root@fedora ~]# cat /sys/devices/pci0000:00/0000:00:02.0/mdev_supported_types/i915-GVTg_V5_8/available_instances
2
此时能够看到,我们可以创建1个最大分辨率为1920x1200或者2个最大分辨率为1024x768的vGPU。
是不是瞬间感觉很鸡肋了?1024x768分辨率太小,而1920x1200则只能创建1个,太太太少了,没问题,预期我形成的下一篇文章会说明如何将这个限制拓宽
我们先来看如何创建vGPU吧,在vGPU类型目录下,还有一个名称为create的具有只写权限的文件,向此文件写入uuid,则会创建对应类型的vGPU设备
uuid可以通过系统命令uuidgen
生成,也可以自行设置,但是必需满足uuid规则
创建类型为i915-GVTg_V5_4的vGPU
echo 62039957-a278-4d7a-878c-fb0b522a9c8c > /sys/devices/pci0000:00/0000:00:02.0/mdev_supported_types/i915-GVTg_V5_4/create
此时该vGPU设备将出现在/sys/bus/pci/devices/0000:00:02.0/62039957-a278-4d7a-878c-fb0b522a9c8c下,向该设备目录的remove文件写入1,则删除该设备
echo 1 > /sys/bus/pci/devices/0000:00:02.0/62039957-a278-4d7a-878c-fb0b522a9c8c/remove
因为所有vGPU共享同一个物理GPU,可创建vGPU总数受名称为GPU Aperture size的bios参数限制,如本实验机,在创建1个i915-GVTg_V5_4型号的vGPU后,就无法再创建其他vGPU了,此时创建会出现“设备上没有空间”的提示
- 创建虚拟机
在vGPU准备好后,接下就是创建虚拟机了,因为edk2同igd之间的一些兼容性问题,要做到普适并不是一件很容易的事情,为了更突出本文主题,此处暂以最简单的ubuntu为例来说明可用性,相关运行命令如下
# 生成uuid
uuid=$(uuidgen)
# 创建vGPU
echo ${uuid} > /sys/devices/pci0000:00/0000:00:02.0/mdev_supported_types/i915-GVTg_V5_4/create
# 创建磁盘镜像
qemu-img create -f qcow2 system.qcow2 64G
# 运行虚拟机
qemu-system-x86_64 \
--nodefaults \
-machine q35,accel=kvm \
-cpu host \
-m 8192 -smp 2 \
-display egl-headless \
-device vfio-pci-nohotplug,sysfsdev=/sys/bus/pci/devices/0000:00:02.0/${uuid},display=on,x-igd-opregion=on,ramfb=on \
-display vnc=:0 \
-cdrom ./ubuntu-22.04.2-desktop-amd64.iso \
-hda ./system.qcow2 \
-netdev bridge,id=nic0,br=br0 -device virtio-net-pci,netdev=nic0,mac=52:54:00:12:34:56 \
-device qemu-xhci -device usb-tablet
# 移除vGPU
echo 1 > /sys/bus/pci/devices/0000:00:02.0/${uuid}/remove
关于此虚拟机,有如下注意点:
- 使用bios而非uefi模式启动
- 为摈除缺省硬件干扰,使用了--nodefaults参数
- 运行时需要mesa-libEGL库的支持
- 为安装操作系统,当前目录下需要存在ubuntu的系统iso文件ubuntu-22.04.2-desktop-amd64.iso,如已经存在操作系统,则该行可以去除(无光驱)
- 网络部分使用了网桥模式,设备为br0,需要额外自行创建,如果仅为验证gpu支持,可以去掉此行(无网卡)
安装并进入ubuntu系统后,终端内执行lspci,能够看到00:01.0 VGA compatible controller: Intel Corporation CoffeeLake-S GT2 [UHD Graphics 630]
,表示已经正确的实现显卡虚拟化
终于写完一版了,同时也遗留了2个问题
- 在Z370-A主板bios并未将相关参数提供给用户的情况下,如何在一个物理机上支持更多的vGPU?
- 如何让vGPU支持多种操作系统,尤其是windows操作系统?
后面,如果老苍子有精力,会就这两个话题分享一下我的进展信息
为了写完这篇文章,做了很多验证,也查了不少资料,将最为重要的罗列一下:
- Graphics Virtualization Technologies Support for Each Intel® Graphics Family
- intel GVTg setup guide
- Intel GVT-g technical article from archlinux wiki
老苍子,完稿于2023年4月17日