Files
buildroot/support/testing/tests/package/test_virglrenderer.py
Joseph Kogut 8b165e728e support/testing: add virglrenderer test
Add basic smoke test for glmark2 running in a nested qemu guest with
virtio-gpu-gl-pci.

The outer machine uses the Mesa softpipe driver for GLES support with
minimal dependencies. Just test virgl for now, as lavapipe
(software Vulkan driver) requires LLVM, and this validates
virglrenderer.

Signed-off-by: Joseph Kogut <joseph.kogut@gmail.com>
[Romain: add gitlab-runner "2xlarge" tag]
Signed-off-by: Romain Naour <romain.naour@smile.fr>
2026-06-22 23:21:04 +02:00

161 lines
6.0 KiB
Python

import os
import infra
import infra.basetest
from infra.builder import Builder
# gitlab-runner: 2xlarge
class TestVirglrendererNestedQemu(infra.basetest.BRTest):
outer_kern_frag = \
infra.filepath("tests/package/test_virglrenderer/linux-outer.fragment")
inner_kern_frag = \
infra.filepath("tests/package/test_virglrenderer/linux-inner.fragment")
rootfs_overlay = \
infra.filepath("tests/package/test_virglrenderer/rootfs-overlay")
# Softpipe has no hardware dependencies and does not pull LLVM into the
# outer build, unlike llvmpipe/lavapipe.
config = \
f"""
BR2_aarch64=y
BR2_TOOLCHAIN_EXTERNAL=y
BR2_TARGET_GENERIC_GETTY_PORT="ttyAMA0"
BR2_ROOTFS_OVERLAY="{rootfs_overlay}"
BR2_LINUX_KERNEL=y
BR2_LINUX_KERNEL_CUSTOM_VERSION=y
BR2_LINUX_KERNEL_CUSTOM_VERSION_VALUE="6.18.21"
BR2_LINUX_KERNEL_USE_CUSTOM_CONFIG=y
BR2_LINUX_KERNEL_CUSTOM_CONFIG_FILE="board/qemu/aarch64-virt/linux.config"
BR2_LINUX_KERNEL_CONFIG_FRAGMENT_FILES="{outer_kern_frag}"
BR2_LINUX_KERNEL_NEEDS_HOST_LIBELF=y
BR2_PACKAGE_LIBGLVND=y
BR2_PACKAGE_MESA3D=y
BR2_PACKAGE_MESA3D_GALLIUM_DRIVER_SOFTPIPE=y
BR2_PACKAGE_MESA3D_OPENGL_EGL=y
BR2_PACKAGE_QEMU=y
BR2_PACKAGE_QEMU_SYSTEM=y
# BR2_PACKAGE_QEMU_SYSTEM_KVM is not set
BR2_PACKAGE_QEMU_SYSTEM_TCG=y
# BR2_PACKAGE_QEMU_BLOBS is not set
BR2_PACKAGE_QEMU_CHOOSE_TARGETS=y
BR2_PACKAGE_QEMU_TARGET_AARCH64=y
BR2_PACKAGE_QEMU_VIRGLRENDERER=y
BR2_TARGET_ROOTFS_INITRAMFS=y
# BR2_TARGET_ROOTFS_TAR is not set
"""
inner_config = \
f"""
BR2_aarch64=y
BR2_TOOLCHAIN_EXTERNAL=y
BR2_TARGET_GENERIC_GETTY_PORT="ttyAMA0"
BR2_ROOTFS_OVERLAY="{rootfs_overlay}"
BR2_LINUX_KERNEL=y
BR2_LINUX_KERNEL_CUSTOM_VERSION=y
BR2_LINUX_KERNEL_CUSTOM_VERSION_VALUE="6.18.21"
BR2_LINUX_KERNEL_USE_CUSTOM_CONFIG=y
BR2_LINUX_KERNEL_CUSTOM_CONFIG_FILE="board/qemu/aarch64-virt/linux.config"
BR2_LINUX_KERNEL_CONFIG_FRAGMENT_FILES="{inner_kern_frag}"
BR2_LINUX_KERNEL_NEEDS_HOST_LIBELF=y
BR2_PACKAGE_KMSCUBE=y
BR2_PACKAGE_LIBDRM=y
BR2_PACKAGE_LIBGLVND=y
BR2_PACKAGE_MESA3D=y
BR2_PACKAGE_MESA3D_GALLIUM_DRIVER_VIRGL=y
BR2_PACKAGE_MESA3D_OPENGL_EGL=y
BR2_PACKAGE_MESA3D_OPENGL_ES=y
BR2_TARGET_ROOTFS_CPIO=y
# BR2_TARGET_ROOTFS_TAR is not set
"""
def setUp(self):
self.inner_builder = None
super().setUp()
self.inner_builddir = os.path.join(self.outputdir,
f"{self.testname}-inner")
config = self.inner_config
config += f'\nBR2_DL_DIR="{self.downloaddir}"\n'
config += f"\nBR2_JLEVEL={self.jlevel}\n"
self.inner_builder = Builder(config, self.inner_builddir,
self.logtofile, self.jlevel)
if not self.keepbuilds:
self.inner_builder.delete()
if not self.inner_builder.is_finished():
self.show_msg("Building inner")
self.inner_builder.configure(
make_extra_opts=[f"BR2_EXTERNAL={':'.join(self.br2_external)}"])
self.inner_builder.build()
self.show_msg("Building inner done")
def tearDown(self):
try:
super().tearDown()
finally:
if self.inner_builder and not self.keepbuilds:
self.inner_builder.delete()
def boot_outer(self):
kern = os.path.join(self.builddir, "images", "Image")
inner_img_dir = os.path.join(self.inner_builddir, "images")
virtfs_tag = "br-inner"
virtfs_opts = [
f"local,path={inner_img_dir}",
f"mount_tag={virtfs_tag}",
"security_model=mapped-xattr",
"readonly=on"
]
self.emulator.boot(arch="aarch64",
kernel=kern,
kernel_cmdline=["console=ttyAMA0"],
options=["-M", "virt",
"-cpu", "cortex-a57",
"-m", "1536M",
"-smp", "4",
"-vga", "none",
"-virtfs", ",".join(virtfs_opts)])
self.emulator.login()
self.assertRunOk(f"mount -t 9p {virtfs_tag} /mnt/")
def boot_inner(self):
qemu_cmd = "env LIBGL_ALWAYS_SOFTWARE=1 GALLIUM_DRIVER=softpipe"
qemu_cmd += " qemu-system-aarch64"
qemu_cmd += " -M virt,accel=tcg"
qemu_cmd += " -cpu cortex-a57"
qemu_cmd += " -m 512M"
qemu_cmd += " -nodefaults"
qemu_cmd += " -display egl-headless,gl=on"
qemu_cmd += " -device virtio-gpu-gl-pci"
qemu_cmd += " -serial stdio"
qemu_cmd += " -kernel /mnt/Image"
qemu_cmd += " -initrd /mnt/rootfs.cpio"
qemu_cmd += " -append 'console=ttyAMA0 br-inner-virgl'"
# qemu runs in the foreground on the current serial console. Once it
# starts, the next login prompt belongs to the inner guest.
self.emulator.qemu.sendline(qemu_cmd)
self.emulator.login(timeout=180)
def test_run(self):
self.boot_outer()
self.assertRunOk("while [ ! -e /dev/dri/renderD128 ]; do sleep 1; done",
timeout=30)
self.boot_inner()
out, ret = self.emulator.run("cat /proc/cmdline")
self.assertEqual(ret, 0)
self.assertIn("br-inner-virgl", out[0])
cmd = "env MESA_LOADER_DRIVER_OVERRIDE=virtio_gpu"
cmd += " kmscube --vmode=640x480 --count=10"
out, ret = self.emulator.run(cmd, timeout=60)
self.assertEqual(ret, 0)
renderer = "\n".join([line for line in out
if line.strip().startswith("renderer:")])
self.assertRegex(renderer, r'(?i)renderer:\s*"virgl \(softpipe\)"')