GVT-g
Intel GVT-g是一项GPU虚拟化技术。 可以将一个Intel核心显卡划分为多个虚拟GPU,每个虚拟GPU可以分配给一个虚拟机。 提供接近原先显卡的性能。适合Windows和Linux的客户机,黑苹果没有成功驱动起来的案例。
适用CPU
适用于Intel Broadwell (5代) 到 Comet Lake (10代)的CPU,10代以后更换成了SR-IOV技术。
内核启用
内核增加intel_iommu=on
,启用IOMMU。
内核启用kvmgt, vfio-iommu-type1 和 mdev 模块。
内核增加enable_gvt=1
参数,开启GPU虚拟化。
内核增加i915.enable_guc=0
参数,因为当 GuC/HuC 也启用时,不支持通过设置 enable_gvt=1
使用 GVT-g 图形虚拟化。
内核增加iommu=pt
参数,只对穿透的设备启用IOMMU,可以避免宿主机的PCIe设备性能的转换浪费。此参数源码中的说明如下:
/*
* This variable becomes 1 if iommu=pt is passed on the kernel command line.
* If this variable is 1, IOMMU implementations do no DMA translation for
* devices and allow every device to access to whole physical memory. This is
* useful if a user wants to use an IOMMU only for KVM device assignment to
* guests and not for driver dma translation.
*/
int iommu_pass_through __read_mostly = 1;
下面汇总,操作如下:
创建/etc/modules-load.d/intel-gvt-g.conf
,写入
kvmgt
vfio-iommu-type1
mdev
修改内核参数以最常见的GRUB为例,编辑/etc/default/grub
GRUB_CMDLINE_LINUX_DEFAULT="quiet intel_iommu=on iommu=pt i915.enable_guc=0 i915.enable_gvt=1"
找到GRUB_CMDLINE_LINUX_DEFAULT,在原来可能是"quiet"或是"quiet splash"中加上新加的内核参数。 然后重新生成 grub.cfg 文件:
grub-mkconfig -o /boot/grub/grub.cfg
重启系统,使其生效。
可用类型
find /sys/devices -name "mdev_supported_types"
可能的路径是/sys/devices/pci0000:00/0000:00:02.0/mdev_supported_types
,输出如下:
i915-GVTg_V5_1 # Video memory: <512MB, 2048MB>, resolution: up to 1920x1200
i915-GVTg_V5_2 # Video memory: <256MB, 1024MB>, resolution: up to 1920x1200
i915-GVTg_V5_4 # Video memory: <128MB, 512MB>, resolution: up to 1920x1200
i915-GVTg_V5_8 # Video memory: <64MB, 384MB>, resolution: up to 1024x768
可以看到最大分辨率为1920x1200,现在来看还是比较低的。
上述可用类型还和主板上分配给核显的内存大小有关。
创建虚拟GPU
echo "$GVT_GUID" > "/sys/devices/pci${GVT_DOM}/$GVT_PCI/mdev_supported_types/$GVT_TYPE/create"
$GVT_GUID
可以用uuidgen命令生成一个随机的uuid。
移除虚拟GPU
echo 1 > /sys/devices/pci0000\:00/$GVT_PCI/$GVT_GUID/remove
qemu hook
使用qemu hook可以在虚拟机启动和关闭时自动创建和移除虚拟GPU。
创建/etc/libvirt/hooks/qemu
,内容如下:
#!/bin/sh
GVT_PCI=<GVT_PCI>
GVT_GUID=<GVT_GUID>
MDEV_TYPE=<GVT_TYPE>
DOMAIN=<DOMAIN name>
if [ $# -ge 3 ]; then
if [[ " $DOMAIN " =~ .*\ $1\ .* ]] && [ "$2" = "prepare" ] && [ "$3" = "begin" ]; then
echo "$GVT_GUID" > "/sys/devices/pci0000:00/$GVT_PCI/mdev_supported_types/$MDEV_TYPE/create"
elif [[ " $DOMAIN " =~ .*\ $1\ .* ]] && [ "$2" = "release" ] && [ "$3" = "end" ]; then
echo 1 > "/sys/devices/pci0000:00/$GVT_PCI/$GVT_GUID/remove"
fi
fi
变量位置根据自己电脑填上内容。最后别忘了给脚本加上可执行权限:
sudo chmod +x /etc/libvirt/hooks/qemu
分配虚拟GPU
最后在虚拟机的xml文件中加入如下内容:(加在所有其他hostdev之前,不然后面获取显示时hostdev0
还要改)
<hostdev mode='subsystem' type='mdev' managed='no' model='vfio-pci' display='off'>
<source>
<address uuid=GVT_GUID/>
</source>
</hostdev>
GVT_GUID
是之前创建虚拟GPU时的uuid。
获取显示
启用OpRegion,使虚拟机支持虚拟GPU。
修改虚拟机的xml配置,第一行改为如下内容:(否则后面的配置会保存不了)
<domain xmlns:qemu='http://libvirt.org/schemas/domain/qemu/1.0' type='kvm'>
在</domain>
之前,加入如下内容:
<qemu:override>
<qemu:device alias="hostdev0">
<qemu:frontend>
...
<qemu:property name="x-igd-opregion" type="bool" value="true"/>
</qemu:frontend>
</qemu:device>
</qemu:override>
UEFI
如果固件类型是UEFI的,需要使用修改版的vbios_gvt_uefi.rom才能支持显示内容。如果是BIOS类型的,可以跳过这一步。
固件可以放到/usr/share/vgabios/
,随意放可能会提示找不到rom。下面是允许访问的目录:
# access to firmware's etc
/usr/share/kvm/** r,
/usr/share/qemu/** r,
/usr/share/qemu-kvm/** r,
/usr/share/bochs/** r,
/usr/share/openbios/** r,
/usr/share/openhackware/** r,
/usr/share/proll/** r,
/usr/share/vgabios/** r,
/usr/share/seabios/** r,
/usr/share/misc/sgabios.bin r,
/usr/share/ovmf/** r,
/usr/share/OVMF/** r,
/usr/share/AAVMF/** r,
/usr/share/qemu-efi/** r,
/usr/share/slof/** r,
然后修改xml,增加一行设置romfile:
<qemu:override>
<qemu:device alias="hostdev0">
<qemu:frontend>
...
<qemu:property name="romfile" type="string" value="/usr/share/vgabios/vbios_gvt_uefi.rom"/>
...
</qemu:frontend>
</qemu:device>
</qemu:override>
之前的hostdev配置中display='off'
,在虚拟机里可以看到有显卡和显示器,但是虚拟机界面上看不到它输出的画面。
修改xml配置,override中把display改为on。并且将安装后自带的video改为None。
<qemu:override>
<qemu:device alias="hostdev0">
<qemu:frontend>
...
<qemu:property name="display" type="string" value="on"/>
...
</qemu:frontend>
</qemu:device>
</qemu:override>
<video>
<model type="none"/>
</video>
这样重启后,就可以看到虚拟机的画面了。但是看不到进入系统前的画面。
启用RAMFB,可以显示启动画面。修改xml配置:
<qemu:override>
<qemu:device alias="hostdev0">
<qemu:frontend>
...
<qemu:property name="driver" type="string" value="vfio-pci-nohotplug"/>
<qemu:property name="ramfb" type="bool" value="true"/>
</qemu:frontend>
</qemu:device>
</qemu:override>
至此,GVT-g的配置就完成了。