diff --git a/DEVELOPERS b/DEVELOPERS index 850978181c..5a09be9bff 100644 --- a/DEVELOPERS +++ b/DEVELOPERS @@ -1764,6 +1764,7 @@ F: package/sentry-cli/ F: package/sentry-native/ F: package/unclutter-xfixes/ F: package/virglrenderer/ +F: support/testing/tests/package/test_virglrenderer.py N: Joshua Henderson F: package/qt5/qt5wayland/ diff --git a/support/testing/tests/package/test_virglrenderer.py b/support/testing/tests/package/test_virglrenderer.py new file mode 100644 index 0000000000..5db9f32614 --- /dev/null +++ b/support/testing/tests/package/test_virglrenderer.py @@ -0,0 +1,160 @@ +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\)"') diff --git a/support/testing/tests/package/test_virglrenderer/linux-inner.fragment b/support/testing/tests/package/test_virglrenderer/linux-inner.fragment new file mode 100644 index 0000000000..f2a6b539f7 --- /dev/null +++ b/support/testing/tests/package/test_virglrenderer/linux-inner.fragment @@ -0,0 +1,4 @@ +CONFIG_BLK_DEV_INITRD=y +# The inner guest runs kmscube against the virgl renderer exposed by QEMU. +CONFIG_DRM=y +CONFIG_DRM_VIRTIO_GPU=y diff --git a/support/testing/tests/package/test_virglrenderer/linux-outer.fragment b/support/testing/tests/package/test_virglrenderer/linux-outer.fragment new file mode 100644 index 0000000000..1023aedc6f --- /dev/null +++ b/support/testing/tests/package/test_virglrenderer/linux-outer.fragment @@ -0,0 +1,6 @@ +CONFIG_BLK_DEV_INITRD=y +CONFIG_DRM_VGEM=y +CONFIG_NET_9P=y +CONFIG_NET_9P_VIRTIO=y +CONFIG_9P_FS=y +CONFIG_9P_FS_POSIX_ACL=y diff --git a/support/testing/tests/package/test_virglrenderer/rootfs-overlay/etc/profile.d/stty-raw.sh b/support/testing/tests/package/test_virglrenderer/rootfs-overlay/etc/profile.d/stty-raw.sh new file mode 100644 index 0000000000..4427e5a143 --- /dev/null +++ b/support/testing/tests/package/test_virglrenderer/rootfs-overlay/etc/profile.d/stty-raw.sh @@ -0,0 +1,3 @@ +# Avoid double-cooking the inner serial console, otherwise the test +# infrastructure cannot reliably retrieve return codes. +grep -Fq br-inner-virgl /proc/cmdline && stty raw