On 24/07/2025 12.59, Alex Bennée wrote:
> This is a simple test case that runs an image with kvmtool and
> kvm-unit-tests which can validate virtualisation works. This is useful
> for exercising TCG but can also be applied to any nested virt setup
> which is why it doesn't specify an accelerator.
>
> Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
> Cc: Philippe Mathieu-Daudé <philmd@linaro.org>
> Cc: Mark Burton <mburton@qti.qualcomm.com>
> ---
> tests/functional/meson.build | 1 +
> tests/functional/test_aarch64_kvm.py | 83 ++++++++++++++++++++++++++++
> 2 files changed, 84 insertions(+)
> create mode 100755 tests/functional/test_aarch64_kvm.py
>
> diff --git a/tests/functional/meson.build b/tests/functional/meson.build
> index 8bebcd4d94e..ecf965adc6c 100644
> --- a/tests/functional/meson.build
> +++ b/tests/functional/meson.build
> @@ -89,6 +89,7 @@ tests_aarch64_system_thorough = [
> 'aarch64_device_passthrough',
> 'aarch64_hotplug_pci',
> 'aarch64_imx8mp_evk',
> + 'aarch64_kvm',
> 'aarch64_raspi3',
> 'aarch64_raspi4',
> 'aarch64_replay',
> diff --git a/tests/functional/test_aarch64_kvm.py b/tests/functional/test_aarch64_kvm.py
> new file mode 100755
> index 00000000000..a42d82872af
> --- /dev/null
> +++ b/tests/functional/test_aarch64_kvm.py
> @@ -0,0 +1,83 @@
> +#!/usr/bin/env python3
> +#
> +# Functional test that runs subsets of kvm-unit-tests on Aarch64.
> +# These can run on TCG and any accelerator supporting nested
> +# virtualisation.
> +#
> +# Copyright (c) 2025 Linaro
> +#
> +# Author:
> +# Alex Bennée <alex.bennee@linaro.org>
> +#
> +# SPDX-License-Identifier: GPL-2.0-or-later
> +
> +from qemu.machine.machine import VMLaunchFailure
> +
> +from qemu_test import Asset
> +from qemu_test import exec_command_and_wait_for_pattern as ec_and_wait
> +from qemu_test.linuxkernel import LinuxKernelTest
> +
> +
> +class Aarch64VirtKVMTests(LinuxKernelTest):
> +
> + ASSET_KVM_TEST_KERNEL = Asset(
> + 'https://fileserver.linaro.org/s/HmjaxXXYHYSqbes/'
> + 'download?path=%2F&files='
> + 'image-with-kvm-tool-and-unit-tests.gz',
> + '34de4aaea90db5da42729e7d28b77f392c37a2f4da859f889a5234aaf0970696')
> +
> + # make it easier to detect successful return to shell
> + PS1 = 'RES=[$?] # '
> + OK_CMD = 'RES=[0] # '
> +
> + # base of tests
> + KUT_BASE = "/usr/share/kvm-unit-tests/"
> +
> + def _launch_guest(self, kvm_mode="nvhe"):
> +
> + self.set_machine('virt')
> + kernel_path = self.ASSET_KVM_TEST_KERNEL.fetch()
> +
> + self.vm.set_console()
> + kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE +
> + f"console=ttyAMA0 kvm-arm.mode={kvm_mode}")
> +
> + self.vm.add_args("-cpu", "cortex-a72")
> + self.vm.add_args("-machine", "virt,gic-version=3,virtualization=on",
> + '-kernel', kernel_path,
> + '-append', kernel_command_line)
> + self.vm.add_args("-smp", "2", "-m", "320")
> +
> + try:
> + self.vm.launch()
> + except VMLaunchFailure as excp:
> + self.log.info("unhandled launch failure: %s", excp.output)
> + raise excp
Unless you want to intercept certain launch failures, I think it's easier to
simply omit the "try:" and "except" here and call self.vm.launch() directly.
(you can also drop the "from qemu.machine.machine import VMLaunchFailure" in
that case).
> + self.wait_for_console_pattern('buildroot login:')
> + ec_and_wait(self, 'root', '#')
> + ec_and_wait(self, f"export PS1='{self.PS1}'", self.OK_CMD)
> +
> +
Cosmetical nit: We're normally only using one empty line between functions.
Apart from that, the test looks fine to me.
Thomas
> + def test_aarch64_nvhe_selftest(self):
> +
> + self._launch_guest("nvhe")
> +
> + ec_and_wait(self, f"{self.KUT_BASE}/selftest-setup", self.OK_CMD)
> + ec_and_wait(self, f"{self.KUT_BASE}/selftest-smp", self.OK_CMD)
> + ec_and_wait(self, f"{self.KUT_BASE}/selftest-vectors-kernel", self.OK_CMD)
> + ec_and_wait(self, f"{self.KUT_BASE}/selftest-vectors-user", self.OK_CMD)
> +
> +
> + def test_aarch64_vhe_selftest(self):
> +
> + self._launch_guest("vhe")
> +
> + ec_and_wait(self, f"{self.KUT_BASE}/selftest-setup", self.OK_CMD)
> + ec_and_wait(self, f"{self.KUT_BASE}/selftest-smp", self.OK_CMD)
> + ec_and_wait(self, f"{self.KUT_BASE}/selftest-vectors-kernel", self.OK_CMD)
> + ec_and_wait(self, f"{self.KUT_BASE}/selftest-vectors-user", self.OK_CMD)
> +
> +
> +if __name__ == '__main__':
> + LinuxKernelTest.main()