概述
virtio-gpu是GPU分时复用方案,相对于透传方案,virito-gpu的优点时可以模拟更多的gpu,缺点是因为GPU需要处理更多的请求,相比透传方案,调度的损耗多,牺牲了GPU部分性能。 本文的实践主要基于virtio-gpu官方博客 的搭建指导。
基本环境搭建
选择centos 8图形界面,CentOS Linux release 8.1.1911
安装OS之后,如果不被墙,可以使用默认的yum源,如果没有yum源配置,安装centos-repos-8.1-1.1911.0.8.el8.x86_64.rpm
yum高级工具yumdownloader安装yum -y install yum-utils.noarch
基本编译开发套件安装yum -y groupinstall Development
组件编译
mesa
git clone https://github.com/mesa3d/mesa.git
yum-builddep mesa
yum install -y meson
mkdir build; cd build;
meson ..
cd .. ; meson reconfigure --prefix=/usr -Dgallium-drivers=virgl
cd build
ninja
ninja install
libvirt
wget http://vault.centos.org/8.0.1905/virt/Source/advanced-virtualization/libvirt-5.6.0-10.el8.src.rpm
安装libvirt源码包rpm -ivh libvirt-5.6.0-10.el8.src.rpm
安装libvirt编译环境依赖包yum-builddep libvirt
编译libvirt源码包cd $HOME/rpmbuild && rpmbuild -bb SPECS/libvirt.spec --define "_topdir $(pwd)"
进入RPMS目录安装rpm包
qemu-kvm
wget http://vault.centos.org/8.0.1905/virt/Source/advanced-virtualization/qemu-kvm-4.1.0-23.el8.1.src.rpm
安装qemu-kvm源码包rpm -ivh qemu-kvm-4.1.0-23.el8.1.src.rpm
安装qemu-kvm编译环境依赖包yum-builddep qemu-kvm
高版本qemu直接rpmbuild编译会报缺少virglrenderer-devel
,这个依赖在centos上没有找到,直接下载源码编译解决这个依赖问题,步骤在下一节介绍,假设现在qemu编译依赖已经解决 取出qemu-kvm源码包cd $HOME/rpmbuild/SOURCES && tar -xf qemu-4.1.0.tar.xz"
进入源码目录配置./configure --target-list=x86_64-softmmu --prefix=/usr --enable-kvm --enable-virglrenderer
编译并安装make -j$(nproc --ignore=1) && make install
virglrenderer
virglrenderer是一个开源项目virgil3d提供的开源库,它的主要功能是针对虚拟化场景,为QEMU提供一个具有3D图形处理的显卡,其使用方式就是为QEMU提供一组3D图形处理的接口。QEMU通过调用virglrenderer的库接口实现主机侧的3D图形加速处理。 virglrenderer编译依赖两个工具分别是cmak和ninja,分别安装yum install -y cmake ninja-build
virglrenderer还依赖一个libepoxy库,分别下载这两个组件的源码 下载libepoxy git clone https://github.com/anholt/libepoxy.git
下载virglrenderer git clone git://anongit.freedesktop.org/virglrenderer
编译libexpoxy依赖glesv2,安装yum install mesa-libGLES-devel
编译libexpoxy,只能用ninja方式编译:
mkdir _build && cd _build
meson --prefix=/usr
ninja
sudo ninja install
编译virglrender,可以用ninja方式编译,也可以用make编译,步骤如下:
./configure --enable-autotools --enable-debug --prefix=/usr
make -j$(nproc --ignore=1)
make install
在上述所有组件编译安装完成后,运行virsh version
查看虚拟化组件版本,成功的输出应该是这样:
应用
准备磁盘文件qemu-img create -f qcow2 /home/test_vm.qcow2 80G
创建测试虚机的xml文件test_vm.xml如下:
<domain type='kvm' id='2'>
<name>test_vm</name>
<uuid>720a0f9f-2893-4712-87e4-b7a61454dd7a</uuid>
<maxMemory slots='16' unit='KiB'>16777216</maxMemory>
<memory unit='KiB'>4194304</memory>
<currentMemory unit='KiB'>4194304</currentMemory>
<vcpu placement='static'>4</vcpu>
<resource>
<partition>/machine</partition>
</resource>
<os>
<type arch='x86_64' machine='pc-i440fx-4.1'>hvm</type>
<boot dev='hd'/>
</os>
<features>
<acpi/>
<apic/>
</features>
<cpu>
<numa>
<cell id='0' cpus='0-1' memory='2097152' unit='KiB'/>
<cell id='1' cpus='2-3' memory='2097152' unit='KiB'/>
</numa>
</cpu>
<clock offset='utc'/>
<on_poweroff>destroy</on_poweroff>
<on_reboot>restart</on_reboot>
<on_crash>destroy</on_crash>
<devices>
<emulator>/usr/bin/qemu-system-x86_64</emulator>
<disk type='file' device='disk'>
<driver name='qemu' type='qcow2'/>
<source file='/home/test_vm.qcow2'/>
<backingStore/>
<target dev='vda' bus='virtio'/>
<alias name='virtio-disk0'/>
<address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/>
</disk>
<controller type='usb' index='0' model='piix3-uhci'>
<alias name='usb'/>
<address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x2'/>
</controller>
<controller type='pci' index='0' model='pci-root'>
<alias name='pci.0'/>
</controller>
<input type='mouse' bus='ps2'>
<alias name='input0'/>
</input>
<input type='keyboard' bus='ps2'>
<alias name='input1'/>
</input>
<graphics type='vnc' port='5900' autoport='yes' listen='127.0.0.1' keymap='en-us'>
<listen type='address' address='127.0.0.1'/>
</graphics>
<video>
<model type='cirrus' vram='16384' heads='1' primary='yes'/>
<alias name='video0'/>
<address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x0'/>
</video>
<memballoon model='virtio'>
<alias name='balloon0'/>
<address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x0'/>
</memballoon>
</devices>
<seclabel type='dynamic' model='selinux' relabel='yes'>
<label>system_u:system_r:svirt_t:s0:c799,c857</label>
<imagelabel>system_u:object_r:svirt_image_t:s0:c799,c857</imagelabel>
</seclabel>
<seclabel type='dynamic' model='dac' relabel='yes'>
<label>+0:+0</label>
<imagelabel>+0:+0</imagelabel>
</seclabel>
</domain>
定义虚拟机virsh define test_vm.xml
关闭防火墙,设置qemu访问权限:
cat /etc/sysconfig/selinux
SELINUX=disabled
cat /etc/libvirt/qemu.conf
user = "root"
group = "root"
启动虚机virsh start test_vm
,这时启动的虚机还没有配置virtio-gpu
libvirt默认将第一个显卡配置成vga模式保持兼容性,同时如果显卡设置成virtio,默认使用virtio-gpu-pci设备,因此修改libvirt,让其默认使用virtio-gpu,重新编译libvirt。
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index a5958c3..0e1a5cf 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -4660,9 +4660,11 @@ qemuBuildDeviceVideoStr(const virDomainDef *def,
* model with VGA compatibility mode. For some video devices on some
* architectures there might not be such model so fallback to one
* without VGA compatibility mode. */
+#if 0
if (video->primary && qemuDomainSupportsVideoVga(video, qemuCaps))
model = qemuDeviceVideoTypeToString(video->type);
else
+#endif
model = qemuDeviceVideoSecondaryTypeToString(video->type);
if (!model || STREQ(model, "")) {
@@ -4673,11 +4675,13 @@ qemuBuildDeviceVideoStr(const virDomainDef *def,
}
if (STREQ(model, "virtio-gpu")) {
+#if 0
if (qemuBuildVirtioDevStr(&buf, "virtio-gpu", qemuCaps,
VIR_DOMAIN_DEVICE_VIDEO, video) < 0) {
goto error;
}
} else {
+#endif
virBufferAsprintf(&buf, "%s", model);
}
启动虚机时在libvirt xml中添加如下内容:
<graphics type='vnc' port='-1' autoport='yes' listen='0.0.0.0'/> /* 1 */
<graphics type='egl-headless'> /* 2 */
<gl rendernode='/dev/dri/renderD128'/>
</graphics>
<video> /* 3 */
<model type='virtio' vram='16384' heads='1' primary='yes'/>
</video>
<video> /* 4 */
<model type='virtio' vram='16384' heads='1'/>
</video>
1. 启动qemu vnc server,客户端使用vnc client远程连接虚机
2. 添加一个显示器设备,设备类型为egl-headless,与vnc/spic/sdl显示设备不同,egl-headless没有提供显示窗口或者终端,它只是用来指示qemu在执行图形处理时使用OpenGL加速。rendernode指示qemu在处理图形时使用host上的那个DRI设备加速,通常情况下不需要设置,qemu默认使用第一个显卡对应的DRI设备,只有在有多个显卡时才有用。
3. 添加一张virtio-vga的显卡作为主显卡,virtio-vga显示是virtio-gpu加上stdvga的结合。它兼容vga模式。
4. 添加一张virtio-gpu的显卡
-vnc 0.0.0.0:0 /* 5 */
-display egl-headless,rendernode=/dev/dri/renderD128 /* 6 */
-device virtio-vga,id=video0,max_outputs=1,bus=pci.0,addr=0xb /* 7 */
-device virtio-gpu-pci,id=video1,max_outputs=1,bus=pci.0,addr=0x2 /* 8 */
5. vnc server,端口5900
6. 设置qemu处理GL操作时使用host上的DRI设备
7. 增加virtio-gpu兼容vga模式的显卡
8. 增加virtio-gpu显卡