From 19ae064832dd915e14306c03b94a505abc13b873 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Tue, 26 Aug 2025 13:34:55 +0100 Subject: tests/functional/test_aarch64_virt_gpu: Skip test if EGL won't initialize MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If you are using the Nvidia drivers and have installed new versions of those packages but have not yet rebooted the host kernel, attempting to use the egl-headless display will cause QEMU to fail to start with $ qemu-system-aarch64 -M virt -display egl-headless qemu-system-aarch64: egl: eglInitialize failed: EGL_NOT_INITIALIZED qemu-system-aarch64: egl: render node init failed together with this complaint in the host kernel dmesg: [7874777.555649] NVRM: API mismatch: the client has the version 535.247.01, but NVRM: this kernel module has the version 535.230.02. Please NVRM: make sure that this kernel module and all NVIDIA driver NVRM: components have the same version. This isn't a problem with QEMU itself, so reporting this as a test failure is misleading. Instead skip the tests, as we already do for various other kinds of "host system can't actually run the EGL display" situation. Signed-off-by: Peter Maydell Message-ID: <20250826123455.2856988-1-peter.maydell@linaro.org> Reviewed-by: Manos Pitsidianakis Acked-by: Alex Bennée Acked-by: Dmitry Osipenko Signed-off-by: Thomas Huth --- tests/functional/test_aarch64_virt_gpu.py | 2 ++ 1 file changed, 2 insertions(+) (limited to 'tests') diff --git a/tests/functional/test_aarch64_virt_gpu.py b/tests/functional/test_aarch64_virt_gpu.py index 3844727..4e50887 100755 --- a/tests/functional/test_aarch64_virt_gpu.py +++ b/tests/functional/test_aarch64_virt_gpu.py @@ -76,6 +76,8 @@ class Aarch64VirtGPUMachine(LinuxKernelTest): self.skipTest("egl-headless support is not available") elif "'type' does not accept value 'dbus'" in excp.output: self.skipTest("dbus display support is not available") + elif "eglInitialize failed: EGL_NOT_INITIALIZED" in excp.output: + self.skipTest("EGL failed to initialize on this host") else: self.log.info("unhandled launch failure: %s", excp.output) raise excp -- cgit v1.1 From 36fb9796662e8d1f8626b1cacb1a6d5e35a8bd00 Mon Sep 17 00:00:00 2001 From: Gustavo Romero Date: Wed, 27 Aug 2025 00:10:08 +0000 Subject: tests/functional: Fix reverse_debugging asset precaching This commit fixes the asset precaching in the reverse_debugging test on aarch64. QemuBaseTest.main() precaches assets (kernel, rootfs, DT blobs, etc.) that are defined in variables with the ASSET_ prefix. This works because it ultimately calls Asset.precache_test(), which relies on introspection to locate these variables. If an asset variable is not named with the ASSET_ prefix, precache_test cannot find the asset and precaching silently fails. Hence, fix the asset precaching by fixing the asset variable name. Signed-off-by: Gustavo Romero Reviewed-by: Richard Henderson Reviewed-by: Manos Pitsidianakis Message-ID: <20250827001008.22112-1-gustavo.romero@linaro.org> Signed-off-by: Thomas Huth --- tests/functional/test_aarch64_reverse_debug.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'tests') diff --git a/tests/functional/test_aarch64_reverse_debug.py b/tests/functional/test_aarch64_reverse_debug.py index 58d4532..8bc91cc 100755 --- a/tests/functional/test_aarch64_reverse_debug.py +++ b/tests/functional/test_aarch64_reverse_debug.py @@ -21,7 +21,7 @@ class ReverseDebugging_AArch64(ReverseDebugging): REG_PC = 32 - KERNEL_ASSET = Asset( + ASSET_KERNEL = Asset( ('https://archives.fedoraproject.org/pub/archive/fedora/linux/' 'releases/29/Everything/aarch64/os/images/pxeboot/vmlinuz'), '7e1430b81c26bdd0da025eeb8fbd77b5dc961da4364af26e771bd39f379cbbf7') @@ -30,7 +30,7 @@ class ReverseDebugging_AArch64(ReverseDebugging): def test_aarch64_virt(self): self.set_machine('virt') self.cpu = 'cortex-a53' - kernel_path = self.KERNEL_ASSET.fetch() + kernel_path = self.ASSET_KERNEL.fetch() self.reverse_debugging(args=('-kernel', kernel_path)) -- cgit v1.1 From 0cdabf8adbaca4b370301366faab2d01121289c7 Mon Sep 17 00:00:00 2001 From: Thomas Huth Date: Thu, 21 Aug 2025 11:47:35 +0200 Subject: tests/functional: Use more fine-grained locking when looking for free ports MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently, we have one lock that is held while a test is looking for free ports. However, we are also using different ranges for looking for free ports nowadays (PORTS_START is based on the PID of the process), so instead of using only one lock, we should rather use a lock per range instead. This should help to allow running more tests in parallel. While we're at it, also create the lock files without executable bit (mode is 0o777 by default). Reviewed-by: Daniel P. Berrangé Signed-off-by: Thomas Huth Message-ID: <20250821094735.804210-1-thuth@redhat.com> --- tests/functional/qemu_test/ports.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'tests') diff --git a/tests/functional/qemu_test/ports.py b/tests/functional/qemu_test/ports.py index 631b77a..81174a6 100644 --- a/tests/functional/qemu_test/ports.py +++ b/tests/functional/qemu_test/ports.py @@ -23,8 +23,9 @@ class Ports(): PORTS_END = PORTS_START + PORTS_RANGE_SIZE def __enter__(self): - lock_file = os.path.join(BUILD_DIR, "tests", "functional", "port_lock") - self.lock_fh = os.open(lock_file, os.O_CREAT) + lock_file = os.path.join(BUILD_DIR, "tests", "functional", + f".port_lock.{self.PORTS_START}") + self.lock_fh = os.open(lock_file, os.O_CREAT, mode=0o666) fcntl.flock(self.lock_fh, fcntl.LOCK_EX) return self -- cgit v1.1 From 9845740a162f2d9a4c852068155e94f1a3c487f9 Mon Sep 17 00:00:00 2001 From: Thomas Huth Date: Tue, 19 Aug 2025 13:23:38 +0200 Subject: tests/functional: Rework the migration test to have target-specific files We are going to move the tests for each target into separate subdirectories. The migration test does not fit quite into this scheme, since it works for multiple targets, but not all. Rework the test to have a common test class, and target specific files with a target specific class, so that this will fit better into the new scheme. Reviewed-by: Pierrick Bouvier Signed-off-by: Thomas Huth Message-ID: <20250819112403.432587-2-thuth@redhat.com> --- tests/functional/meson.build | 22 +++---- tests/functional/migration.py | 79 ++++++++++++++++++++++++ tests/functional/test_aarch64_migration.py | 26 ++++++++ tests/functional/test_alpha_migration.py | 26 ++++++++ tests/functional/test_arm_migration.py | 26 ++++++++ tests/functional/test_i386_migration.py | 26 ++++++++ tests/functional/test_migration.py | 98 ------------------------------ tests/functional/test_ppc64_migration.py | 26 ++++++++ tests/functional/test_ppc_migration.py | 26 ++++++++ tests/functional/test_riscv32_migration.py | 26 ++++++++ tests/functional/test_riscv64_migration.py | 26 ++++++++ tests/functional/test_sparc64_migration.py | 26 ++++++++ tests/functional/test_sparc_migration.py | 26 ++++++++ tests/functional/test_x86_64_migration.py | 26 ++++++++ 14 files changed, 376 insertions(+), 109 deletions(-) create mode 100644 tests/functional/migration.py create mode 100755 tests/functional/test_aarch64_migration.py create mode 100755 tests/functional/test_alpha_migration.py create mode 100755 tests/functional/test_arm_migration.py create mode 100755 tests/functional/test_i386_migration.py delete mode 100755 tests/functional/test_migration.py create mode 100755 tests/functional/test_ppc64_migration.py create mode 100755 tests/functional/test_ppc_migration.py create mode 100755 tests/functional/test_riscv32_migration.py create mode 100755 tests/functional/test_riscv64_migration.py create mode 100755 tests/functional/test_sparc64_migration.py create mode 100755 tests/functional/test_sparc_migration.py create mode 100755 tests/functional/test_x86_64_migration.py (limited to 'tests') diff --git a/tests/functional/meson.build b/tests/functional/meson.build index 311c6f1..c32436d 100644 --- a/tests/functional/meson.build +++ b/tests/functional/meson.build @@ -80,7 +80,7 @@ tests_generic_bsduser = [ ] tests_aarch64_system_quick = [ - 'migration', + 'aarch64_migration', ] tests_aarch64_system_thorough = [ @@ -110,7 +110,7 @@ tests_aarch64_system_thorough = [ ] tests_alpha_system_quick = [ - 'migration', + 'alpha_migration', ] tests_alpha_system_thorough = [ @@ -119,7 +119,7 @@ tests_alpha_system_thorough = [ ] tests_arm_system_quick = [ - 'migration', + 'arm_migration', ] tests_arm_system_thorough = [ @@ -168,7 +168,7 @@ tests_hppa_system_quick = [ ] tests_i386_system_quick = [ - 'migration', + 'i386_migration', ] tests_i386_system_thorough = [ @@ -228,7 +228,7 @@ tests_or1k_system_thorough = [ ] tests_ppc_system_quick = [ - 'migration', + 'ppc_migration', 'ppc_74xx', ] @@ -245,7 +245,7 @@ tests_ppc_system_thorough = [ ] tests_ppc64_system_quick = [ - 'migration', + 'ppc64_migration', ] tests_ppc64_system_thorough = [ @@ -260,7 +260,7 @@ tests_ppc64_system_thorough = [ ] tests_riscv32_system_quick = [ - 'migration', + 'riscv32_migration', 'riscv_opensbi', ] @@ -269,7 +269,7 @@ tests_riscv32_system_thorough = [ ] tests_riscv64_system_quick = [ - 'migration', + 'riscv64_migration', 'riscv_opensbi', ] @@ -300,7 +300,7 @@ tests_sh4eb_system_thorough = [ ] tests_sparc_system_quick = [ - 'migration', + 'sparc_migration', ] tests_sparc_system_thorough = [ @@ -309,7 +309,7 @@ tests_sparc_system_thorough = [ ] tests_sparc64_system_quick = [ - 'migration', + 'sparc64_migration', ] tests_sparc64_system_thorough = [ @@ -320,7 +320,7 @@ tests_sparc64_system_thorough = [ tests_x86_64_system_quick = [ 'cpu_queries', 'mem_addr_space', - 'migration', + 'x86_64_migration', 'pc_cpu_hotplug_props', 'virtio_version', 'x86_cpu_model_versions', diff --git a/tests/functional/migration.py b/tests/functional/migration.py new file mode 100644 index 0000000..0739554 --- /dev/null +++ b/tests/functional/migration.py @@ -0,0 +1,79 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# +# Migration test base class +# +# Copyright (c) 2019 Red Hat, Inc. +# +# Authors: +# Cleber Rosa +# Caio Carrara +# +# This work is licensed under the terms of the GNU GPL, version 2 or +# later. See the COPYING file in the top-level directory. + +import tempfile +import time + +from qemu_test import QemuSystemTest, which +from qemu_test.ports import Ports + + +class MigrationTest(QemuSystemTest): + + timeout = 10 + + @staticmethod + def migration_finished(vm): + return vm.cmd('query-migrate')['status'] in ('completed', 'failed') + + def assert_migration(self, src_vm, dst_vm): + + end = time.monotonic() + self.timeout + while time.monotonic() < end and not self.migration_finished(src_vm): + time.sleep(0.1) + + end = time.monotonic() + self.timeout + while time.monotonic() < end and not self.migration_finished(dst_vm): + time.sleep(0.1) + + self.assertEqual(src_vm.cmd('query-migrate')['status'], 'completed') + self.assertEqual(dst_vm.cmd('query-migrate')['status'], 'completed') + self.assertEqual(dst_vm.cmd('query-status')['status'], 'running') + self.assertEqual(src_vm.cmd('query-status')['status'],'postmigrate') + + def do_migrate(self, dest_uri, src_uri=None): + dest_vm = self.get_vm('-incoming', dest_uri, name="dest-qemu") + dest_vm.add_args('-nodefaults') + dest_vm.launch() + if src_uri is None: + src_uri = dest_uri + source_vm = self.get_vm(name="source-qemu") + source_vm.add_args('-nodefaults') + source_vm.launch() + source_vm.qmp('migrate', uri=src_uri) + self.assert_migration(source_vm, dest_vm) + + def _get_free_port(self, ports): + port = ports.find_free_port() + if port is None: + self.skipTest('Failed to find a free port') + return port + + def migration_with_tcp_localhost(self): + with Ports() as ports: + dest_uri = 'tcp:localhost:%u' % self._get_free_port(ports) + self.do_migrate(dest_uri) + + def migration_with_unix(self): + with tempfile.TemporaryDirectory(prefix='socket_') as socket_path: + dest_uri = 'unix:%s/qemu-test.sock' % socket_path + self.do_migrate(dest_uri) + + def migration_with_exec(self): + if not which('ncat'): + self.skipTest('ncat is not available') + with Ports() as ports: + free_port = self._get_free_port(ports) + dest_uri = 'exec:ncat -l localhost %u' % free_port + src_uri = 'exec:ncat localhost %u' % free_port + self.do_migrate(dest_uri, src_uri) diff --git a/tests/functional/test_aarch64_migration.py b/tests/functional/test_aarch64_migration.py new file mode 100755 index 0000000..70267e7 --- /dev/null +++ b/tests/functional/test_aarch64_migration.py @@ -0,0 +1,26 @@ +#!/usr/bin/env python3 +# +# SPDX-License-Identifier: GPL-2.0-or-later +# +# aarch64 migration test + +from migration import MigrationTest + + +class Aarch64MigrationTest(MigrationTest): + + def test_migration_with_tcp_localhost(self): + self.set_machine('quanta-gsj') + self.migration_with_tcp_localhost() + + def test_migration_with_unix(self): + self.set_machine('quanta-gsj') + self.migration_with_unix() + + def test_migration_with_exec(self): + self.set_machine('quanta-gsj') + self.migration_with_exec() + + +if __name__ == '__main__': + MigrationTest.main() diff --git a/tests/functional/test_alpha_migration.py b/tests/functional/test_alpha_migration.py new file mode 100755 index 0000000..f11b523 --- /dev/null +++ b/tests/functional/test_alpha_migration.py @@ -0,0 +1,26 @@ +#!/usr/bin/env python3 +# +# SPDX-License-Identifier: GPL-2.0-or-later +# +# Alpha migration test + +from migration import MigrationTest + + +class AlphaMigrationTest(MigrationTest): + + def test_migration_with_tcp_localhost(self): + self.set_machine('clipper') + self.migration_with_tcp_localhost() + + def test_migration_with_unix(self): + self.set_machine('clipper') + self.migration_with_unix() + + def test_migration_with_exec(self): + self.set_machine('clipper') + self.migration_with_exec() + + +if __name__ == '__main__': + MigrationTest.main() diff --git a/tests/functional/test_arm_migration.py b/tests/functional/test_arm_migration.py new file mode 100755 index 0000000..0aa89f4 --- /dev/null +++ b/tests/functional/test_arm_migration.py @@ -0,0 +1,26 @@ +#!/usr/bin/env python3 +# +# SPDX-License-Identifier: GPL-2.0-or-later +# +# arm migration test + +from migration import MigrationTest + + +class ArmMigrationTest(MigrationTest): + + def test_migration_with_tcp_localhost(self): + self.set_machine('npcm750-evb') + self.migration_with_tcp_localhost() + + def test_migration_with_unix(self): + self.set_machine('npcm750-evb') + self.migration_with_unix() + + def test_migration_with_exec(self): + self.set_machine('npcm750-evb') + self.migration_with_exec() + + +if __name__ == '__main__': + MigrationTest.main() diff --git a/tests/functional/test_i386_migration.py b/tests/functional/test_i386_migration.py new file mode 100755 index 0000000..a57f316 --- /dev/null +++ b/tests/functional/test_i386_migration.py @@ -0,0 +1,26 @@ +#!/usr/bin/env python3 +# +# SPDX-License-Identifier: GPL-2.0-or-later +# +# i386 migration test + +from migration import MigrationTest + + +class I386MigrationTest(MigrationTest): + + def test_migration_with_tcp_localhost(self): + self.set_machine('isapc') + self.migration_with_tcp_localhost() + + def test_migration_with_unix(self): + self.set_machine('isapc') + self.migration_with_unix() + + def test_migration_with_exec(self): + self.set_machine('isapc') + self.migration_with_exec() + + +if __name__ == '__main__': + MigrationTest.main() diff --git a/tests/functional/test_migration.py b/tests/functional/test_migration.py deleted file mode 100755 index c4393c3..0000000 --- a/tests/functional/test_migration.py +++ /dev/null @@ -1,98 +0,0 @@ -#!/usr/bin/env python3 -# -# Migration test -# -# Copyright (c) 2019 Red Hat, Inc. -# -# Authors: -# Cleber Rosa -# Caio Carrara -# -# This work is licensed under the terms of the GNU GPL, version 2 or -# later. See the COPYING file in the top-level directory. - -import tempfile -import time - -from qemu_test import QemuSystemTest, skipIfMissingCommands -from qemu_test.ports import Ports - - -class MigrationTest(QemuSystemTest): - - timeout = 10 - - @staticmethod - def migration_finished(vm): - return vm.cmd('query-migrate')['status'] in ('completed', 'failed') - - def assert_migration(self, src_vm, dst_vm): - - end = time.monotonic() + self.timeout - while time.monotonic() < end and not self.migration_finished(src_vm): - time.sleep(0.1) - - end = time.monotonic() + self.timeout - while time.monotonic() < end and not self.migration_finished(dst_vm): - time.sleep(0.1) - - self.assertEqual(src_vm.cmd('query-migrate')['status'], 'completed') - self.assertEqual(dst_vm.cmd('query-migrate')['status'], 'completed') - self.assertEqual(dst_vm.cmd('query-status')['status'], 'running') - self.assertEqual(src_vm.cmd('query-status')['status'],'postmigrate') - - def select_machine(self): - target_machine = { - 'aarch64': 'quanta-gsj', - 'alpha': 'clipper', - 'arm': 'npcm750-evb', - 'i386': 'isapc', - 'ppc': 'sam460ex', - 'ppc64': 'mac99', - 'riscv32': 'spike', - 'riscv64': 'virt', - 'sparc': 'SS-4', - 'sparc64': 'sun4u', - 'x86_64': 'microvm', - } - self.set_machine(target_machine[self.arch]) - - def do_migrate(self, dest_uri, src_uri=None): - self.select_machine() - dest_vm = self.get_vm('-incoming', dest_uri, name="dest-qemu") - dest_vm.add_args('-nodefaults') - dest_vm.launch() - if src_uri is None: - src_uri = dest_uri - source_vm = self.get_vm(name="source-qemu") - source_vm.add_args('-nodefaults') - source_vm.launch() - source_vm.qmp('migrate', uri=src_uri) - self.assert_migration(source_vm, dest_vm) - - def _get_free_port(self, ports): - port = ports.find_free_port() - if port is None: - self.skipTest('Failed to find a free port') - return port - - def test_migration_with_tcp_localhost(self): - with Ports() as ports: - dest_uri = 'tcp:localhost:%u' % self._get_free_port(ports) - self.do_migrate(dest_uri) - - def test_migration_with_unix(self): - with tempfile.TemporaryDirectory(prefix='socket_') as socket_path: - dest_uri = 'unix:%s/qemu-test.sock' % socket_path - self.do_migrate(dest_uri) - - @skipIfMissingCommands('ncat') - def test_migration_with_exec(self): - with Ports() as ports: - free_port = self._get_free_port(ports) - dest_uri = 'exec:ncat -l localhost %u' % free_port - src_uri = 'exec:ncat localhost %u' % free_port - self.do_migrate(dest_uri, src_uri) - -if __name__ == '__main__': - QemuSystemTest.main() diff --git a/tests/functional/test_ppc64_migration.py b/tests/functional/test_ppc64_migration.py new file mode 100755 index 0000000..5dfdaaf --- /dev/null +++ b/tests/functional/test_ppc64_migration.py @@ -0,0 +1,26 @@ +#!/usr/bin/env python3 +# +# SPDX-License-Identifier: GPL-2.0-or-later +# +# ppc migration test + +from migration import MigrationTest + + +class PpcMigrationTest(MigrationTest): + + def test_migration_with_tcp_localhost(self): + self.set_machine('mac99') + self.migration_with_tcp_localhost() + + def test_migration_with_unix(self): + self.set_machine('mac99') + self.migration_with_unix() + + def test_migration_with_exec(self): + self.set_machine('mac99') + self.migration_with_exec() + + +if __name__ == '__main__': + MigrationTest.main() diff --git a/tests/functional/test_ppc_migration.py b/tests/functional/test_ppc_migration.py new file mode 100755 index 0000000..a869282 --- /dev/null +++ b/tests/functional/test_ppc_migration.py @@ -0,0 +1,26 @@ +#!/usr/bin/env python3 +# +# SPDX-License-Identifier: GPL-2.0-or-later +# +# ppc migration test + +from migration import MigrationTest + + +class PpcMigrationTest(MigrationTest): + + def test_migration_with_tcp_localhost(self): + self.set_machine('sam460ex') + self.migration_with_tcp_localhost() + + def test_migration_with_unix(self): + self.set_machine('sam460ex') + self.migration_with_unix() + + def test_migration_with_exec(self): + self.set_machine('sam460ex') + self.migration_with_exec() + + +if __name__ == '__main__': + MigrationTest.main() diff --git a/tests/functional/test_riscv32_migration.py b/tests/functional/test_riscv32_migration.py new file mode 100755 index 0000000..30acbbe --- /dev/null +++ b/tests/functional/test_riscv32_migration.py @@ -0,0 +1,26 @@ +#!/usr/bin/env python3 +# +# SPDX-License-Identifier: GPL-2.0-or-later +# +# riscv32 migration test + +from migration import MigrationTest + + +class Rv32MigrationTest(MigrationTest): + + def test_migration_with_tcp_localhost(self): + self.set_machine('spike') + self.migration_with_tcp_localhost() + + def test_migration_with_unix(self): + self.set_machine('virt') + self.migration_with_unix() + + def test_migration_with_exec(self): + self.set_machine('spike') + self.migration_with_exec() + + +if __name__ == '__main__': + MigrationTest.main() diff --git a/tests/functional/test_riscv64_migration.py b/tests/functional/test_riscv64_migration.py new file mode 100755 index 0000000..2d613a2 --- /dev/null +++ b/tests/functional/test_riscv64_migration.py @@ -0,0 +1,26 @@ +#!/usr/bin/env python3 +# +# SPDX-License-Identifier: GPL-2.0-or-later +# +# riscv64 migration test + +from migration import MigrationTest + + +class Rv64MigrationTest(MigrationTest): + + def test_migration_with_tcp_localhost(self): + self.set_machine('virt') + self.migration_with_tcp_localhost() + + def test_migration_with_unix(self): + self.set_machine('spike') + self.migration_with_unix() + + def test_migration_with_exec(self): + self.set_machine('virt') + self.migration_with_exec() + + +if __name__ == '__main__': + MigrationTest.main() diff --git a/tests/functional/test_sparc64_migration.py b/tests/functional/test_sparc64_migration.py new file mode 100755 index 0000000..a8a6c73 --- /dev/null +++ b/tests/functional/test_sparc64_migration.py @@ -0,0 +1,26 @@ +#!/usr/bin/env python3 +# +# SPDX-License-Identifier: GPL-2.0-or-later +# +# Sparc64 migration test + +from migration import MigrationTest + + +class Sparc64MigrationTest(MigrationTest): + + def test_migration_with_tcp_localhost(self): + self.set_machine('sun4u') + self.migration_with_tcp_localhost() + + def test_migration_with_unix(self): + self.set_machine('sun4u') + self.migration_with_unix() + + def test_migration_with_exec(self): + self.set_machine('sun4u') + self.migration_with_exec() + + +if __name__ == '__main__': + MigrationTest.main() diff --git a/tests/functional/test_sparc_migration.py b/tests/functional/test_sparc_migration.py new file mode 100755 index 0000000..dd6d578 --- /dev/null +++ b/tests/functional/test_sparc_migration.py @@ -0,0 +1,26 @@ +#!/usr/bin/env python3 +# +# SPDX-License-Identifier: GPL-2.0-or-later +# +# Sparc migration test + +from migration import MigrationTest + + +class SparcMigrationTest(MigrationTest): + + def test_migration_with_tcp_localhost(self): + self.set_machine('SS-4') + self.migration_with_tcp_localhost() + + def test_migration_with_unix(self): + self.set_machine('SS-5') + self.migration_with_unix() + + def test_migration_with_exec(self): + self.set_machine('SS-4') + self.migration_with_exec() + + +if __name__ == '__main__': + MigrationTest.main() diff --git a/tests/functional/test_x86_64_migration.py b/tests/functional/test_x86_64_migration.py new file mode 100755 index 0000000..f3a517a --- /dev/null +++ b/tests/functional/test_x86_64_migration.py @@ -0,0 +1,26 @@ +#!/usr/bin/env python3 +# +# SPDX-License-Identifier: GPL-2.0-or-later +# +# x86_64 migration test + +from migration import MigrationTest + + +class X8664MigrationTest(MigrationTest): + + def test_migration_with_tcp_localhost(self): + self.set_machine('microvm') + self.migration_with_tcp_localhost() + + def test_migration_with_unix(self): + self.set_machine('microvm') + self.migration_with_unix() + + def test_migration_with_exec(self): + self.set_machine('microvm') + self.migration_with_exec() + + +if __name__ == '__main__': + MigrationTest.main() -- cgit v1.1 From b19c560e4ac730799f45730020fae63e4727a8e0 Mon Sep 17 00:00:00 2001 From: Thomas Huth Date: Tue, 19 Aug 2025 13:23:39 +0200 Subject: tests/functional: Rework the multiprocess test to have target-specific files We are going to move the tests for each target into separate subdirectories. The multiprocess test currently contains code for both, x86 and aarch64, so it does not quite fit into this scheme. Rework the test to have a common test class, and target specific files with a target specific class, so that this will fit better into the new scheme. Reviewed-by: Pierrick Bouvier Signed-off-by: Thomas Huth Message-ID: <20250819112403.432587-3-thuth@redhat.com> --- tests/functional/meson.build | 4 +- tests/functional/multiprocess.py | 67 +++++++++++++++++ tests/functional/test_aarch64_multiprocess.py | 31 ++++++++ tests/functional/test_multiprocess.py | 103 -------------------------- tests/functional/test_x86_64_multiprocess.py | 31 ++++++++ 5 files changed, 131 insertions(+), 105 deletions(-) create mode 100644 tests/functional/multiprocess.py create mode 100755 tests/functional/test_aarch64_multiprocess.py delete mode 100755 tests/functional/test_multiprocess.py create mode 100755 tests/functional/test_x86_64_multiprocess.py (limited to 'tests') diff --git a/tests/functional/meson.build b/tests/functional/meson.build index c32436d..38ae0d6 100644 --- a/tests/functional/meson.build +++ b/tests/functional/meson.build @@ -90,6 +90,7 @@ tests_aarch64_system_thorough = [ 'aarch64_hotplug_pci', 'aarch64_imx8mp_evk', 'aarch64_kvm', + 'aarch64_multiprocess', 'aarch64_raspi3', 'aarch64_raspi4', 'aarch64_replay', @@ -106,7 +107,6 @@ tests_aarch64_system_thorough = [ 'aarch64_virt_gpu', 'aarch64_xen', 'aarch64_xlnx_versal', - 'multiprocess', ] tests_alpha_system_quick = [ @@ -332,7 +332,7 @@ tests_x86_64_system_thorough = [ 'acpi_bits', 'intel_iommu', 'linux_initrd', - 'multiprocess', + 'x86_64_multiprocess', 'netdev_ethtool', 'virtio_balloon', 'virtio_gpu', diff --git a/tests/functional/multiprocess.py b/tests/functional/multiprocess.py new file mode 100644 index 0000000..6a06c1e --- /dev/null +++ b/tests/functional/multiprocess.py @@ -0,0 +1,67 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# +# Test for multiprocess qemu +# +# This work is licensed under the terms of the GNU GPL, version 2 or +# later. See the COPYING file in the top-level directory. + + +import os +import socket + +from qemu_test import QemuSystemTest, wait_for_console_pattern +from qemu_test import exec_command, exec_command_and_wait_for_pattern + +class Multiprocess(QemuSystemTest): + + KERNEL_COMMON_COMMAND_LINE = 'printk.time=0 ' + + def do_test(self, kernel_asset, initrd_asset, + kernel_command_line, machine_type): + """Main test method""" + self.require_accelerator('kvm') + self.require_device('x-pci-proxy-dev') + + # Create socketpair to connect proxy and remote processes + proxy_sock, remote_sock = socket.socketpair(socket.AF_UNIX, + socket.SOCK_STREAM) + os.set_inheritable(proxy_sock.fileno(), True) + os.set_inheritable(remote_sock.fileno(), True) + + kernel_path = kernel_asset.fetch() + initrd_path = initrd_asset.fetch() + + # Create remote process + remote_vm = self.get_vm() + remote_vm.add_args('-machine', 'x-remote') + remote_vm.add_args('-nodefaults') + remote_vm.add_args('-device', 'lsi53c895a,id=lsi1') + remote_vm.add_args('-object', 'x-remote-object,id=robj1,' + 'devid=lsi1,fd='+str(remote_sock.fileno())) + remote_vm.launch() + + # Create proxy process + self.vm.set_console() + self.vm.add_args('-machine', machine_type) + self.vm.add_args('-accel', 'kvm') + self.vm.add_args('-cpu', 'host') + self.vm.add_args('-object', + 'memory-backend-memfd,id=sysmem-file,size=2G') + self.vm.add_args('--numa', 'node,memdev=sysmem-file') + self.vm.add_args('-m', '2048') + self.vm.add_args('-kernel', kernel_path, + '-initrd', initrd_path, + '-append', kernel_command_line) + self.vm.add_args('-device', + 'x-pci-proxy-dev,' + 'id=lsi1,fd='+str(proxy_sock.fileno())) + self.vm.launch() + wait_for_console_pattern(self, 'as init process', + 'Kernel panic - not syncing') + exec_command(self, 'mount -t sysfs sysfs /sys') + exec_command_and_wait_for_pattern(self, + 'cat /sys/bus/pci/devices/*/uevent', + 'PCI_ID=1000:0012') + + proxy_sock.close() + remote_sock.close() diff --git a/tests/functional/test_aarch64_multiprocess.py b/tests/functional/test_aarch64_multiprocess.py new file mode 100755 index 0000000..1c6e45e --- /dev/null +++ b/tests/functional/test_aarch64_multiprocess.py @@ -0,0 +1,31 @@ +#!/usr/bin/env python3 +# +# SPDX-License-Identifier: GPL-2.0-or-later +# +# Test for multiprocess qemu on aarch64 + +from multiprocess import Multiprocess +from qemu_test import Asset + + +class Aarch64Multiprocess(Multiprocess): + + ASSET_KERNEL_AARCH64 = Asset( + ('https://archives.fedoraproject.org/pub/archive/fedora/linux' + '/releases/31/Everything/aarch64/os/images/pxeboot/vmlinuz'), + '3ae07fcafbfc8e4abeb693035a74fe10698faae15e9ccd48882a9167800c1527') + + ASSET_INITRD_AARCH64 = Asset( + ('https://archives.fedoraproject.org/pub/archive/fedora/linux' + '/releases/31/Everything/aarch64/os/images/pxeboot/initrd.img'), + '9fd230cab10b1dafea41cf00150e6669d37051fad133bd618d2130284e16d526') + + def test_multiprocess(self): + kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE + + 'rdinit=/bin/bash console=ttyAMA0') + self.do_test(self.ASSET_KERNEL_AARCH64, self.ASSET_INITRD_AARCH64, + kernel_command_line, 'virt,gic-version=3') + + +if __name__ == '__main__': + Multiprocess.main() diff --git a/tests/functional/test_multiprocess.py b/tests/functional/test_multiprocess.py deleted file mode 100755 index 92d5207..0000000 --- a/tests/functional/test_multiprocess.py +++ /dev/null @@ -1,103 +0,0 @@ -#!/usr/bin/env python3 -# -# Test for multiprocess qemu -# -# This work is licensed under the terms of the GNU GPL, version 2 or -# later. See the COPYING file in the top-level directory. - - -import os -import socket - -from qemu_test import QemuSystemTest, Asset, wait_for_console_pattern -from qemu_test import exec_command, exec_command_and_wait_for_pattern - -class Multiprocess(QemuSystemTest): - - KERNEL_COMMON_COMMAND_LINE = 'printk.time=0 ' - - ASSET_KERNEL_X86 = Asset( - ('https://archives.fedoraproject.org/pub/archive/fedora/linux' - '/releases/31/Everything/x86_64/os/images/pxeboot/vmlinuz'), - 'd4738d03dbbe083ca610d0821d0a8f1488bebbdccef54ce33e3adb35fda00129') - - ASSET_INITRD_X86 = Asset( - ('https://archives.fedoraproject.org/pub/archive/fedora/linux' - '/releases/31/Everything/x86_64/os/images/pxeboot/initrd.img'), - '3b6cb5c91a14c42e2f61520f1689264d865e772a1f0069e660a800d31dd61fb9') - - ASSET_KERNEL_AARCH64 = Asset( - ('https://archives.fedoraproject.org/pub/archive/fedora/linux' - '/releases/31/Everything/aarch64/os/images/pxeboot/vmlinuz'), - '3ae07fcafbfc8e4abeb693035a74fe10698faae15e9ccd48882a9167800c1527') - - ASSET_INITRD_AARCH64 = Asset( - ('https://archives.fedoraproject.org/pub/archive/fedora/linux' - '/releases/31/Everything/aarch64/os/images/pxeboot/initrd.img'), - '9fd230cab10b1dafea41cf00150e6669d37051fad133bd618d2130284e16d526') - - def do_test(self, kernel_asset, initrd_asset, - kernel_command_line, machine_type): - """Main test method""" - self.require_accelerator('kvm') - self.require_device('x-pci-proxy-dev') - - # Create socketpair to connect proxy and remote processes - proxy_sock, remote_sock = socket.socketpair(socket.AF_UNIX, - socket.SOCK_STREAM) - os.set_inheritable(proxy_sock.fileno(), True) - os.set_inheritable(remote_sock.fileno(), True) - - kernel_path = kernel_asset.fetch() - initrd_path = initrd_asset.fetch() - - # Create remote process - remote_vm = self.get_vm() - remote_vm.add_args('-machine', 'x-remote') - remote_vm.add_args('-nodefaults') - remote_vm.add_args('-device', 'lsi53c895a,id=lsi1') - remote_vm.add_args('-object', 'x-remote-object,id=robj1,' - 'devid=lsi1,fd='+str(remote_sock.fileno())) - remote_vm.launch() - - # Create proxy process - self.vm.set_console() - self.vm.add_args('-machine', machine_type) - self.vm.add_args('-accel', 'kvm') - self.vm.add_args('-cpu', 'host') - self.vm.add_args('-object', - 'memory-backend-memfd,id=sysmem-file,size=2G') - self.vm.add_args('--numa', 'node,memdev=sysmem-file') - self.vm.add_args('-m', '2048') - self.vm.add_args('-kernel', kernel_path, - '-initrd', initrd_path, - '-append', kernel_command_line) - self.vm.add_args('-device', - 'x-pci-proxy-dev,' - 'id=lsi1,fd='+str(proxy_sock.fileno())) - self.vm.launch() - wait_for_console_pattern(self, 'as init process', - 'Kernel panic - not syncing') - exec_command(self, 'mount -t sysfs sysfs /sys') - exec_command_and_wait_for_pattern(self, - 'cat /sys/bus/pci/devices/*/uevent', - 'PCI_ID=1000:0012') - - proxy_sock.close() - remote_sock.close() - - def test_multiprocess(self): - kernel_command_line = self.KERNEL_COMMON_COMMAND_LINE - if self.arch == 'x86_64': - kernel_command_line += 'console=ttyS0 rdinit=/bin/bash' - self.do_test(self.ASSET_KERNEL_X86, self.ASSET_INITRD_X86, - kernel_command_line, 'pc') - elif self.arch == 'aarch64': - kernel_command_line += 'rdinit=/bin/bash console=ttyAMA0' - self.do_test(self.ASSET_KERNEL_AARCH64, self.ASSET_INITRD_AARCH64, - kernel_command_line, 'virt,gic-version=3') - else: - assert False - -if __name__ == '__main__': - QemuSystemTest.main() diff --git a/tests/functional/test_x86_64_multiprocess.py b/tests/functional/test_x86_64_multiprocess.py new file mode 100755 index 0000000..756629d --- /dev/null +++ b/tests/functional/test_x86_64_multiprocess.py @@ -0,0 +1,31 @@ +#!/usr/bin/env python3 +# +# SPDX-License-Identifier: GPL-2.0-or-later +# +# Test for multiprocess qemu on x86 + +from multiprocess import Multiprocess +from qemu_test import Asset + + +class X86Multiprocess(Multiprocess): + + ASSET_KERNEL_X86 = Asset( + ('https://archives.fedoraproject.org/pub/archive/fedora/linux' + '/releases/31/Everything/x86_64/os/images/pxeboot/vmlinuz'), + 'd4738d03dbbe083ca610d0821d0a8f1488bebbdccef54ce33e3adb35fda00129') + + ASSET_INITRD_X86 = Asset( + ('https://archives.fedoraproject.org/pub/archive/fedora/linux' + '/releases/31/Everything/x86_64/os/images/pxeboot/initrd.img'), + '3b6cb5c91a14c42e2f61520f1689264d865e772a1f0069e660a800d31dd61fb9') + + def test_multiprocess(self): + kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE + + 'console=ttyS0 rdinit=/bin/bash') + self.do_test(self.ASSET_KERNEL_X86, self.ASSET_INITRD_X86, + kernel_command_line, 'pc') + + +if __name__ == '__main__': + Multiprocess.main() -- cgit v1.1 From b8103f56d97c2e6554af2c365b366989005a666c Mon Sep 17 00:00:00 2001 From: Thomas Huth Date: Tue, 19 Aug 2025 13:23:40 +0200 Subject: tests/functional/meson.build: Split timeout settings by target We are going to move these settings into target-specific subfolders. As a first step, split the big test_timeouts array up into individual ones. Reviewed-by: Pierrick Bouvier Signed-off-by: Thomas Huth Message-ID: <20250819112403.432587-4-thuth@redhat.com> --- tests/functional/meson.build | 50 ++++++++++++++++++++++++++++++++++++++------ 1 file changed, 44 insertions(+), 6 deletions(-) (limited to 'tests') diff --git a/tests/functional/meson.build b/tests/functional/meson.build index 38ae0d6..356aad1 100644 --- a/tests/functional/meson.build +++ b/tests/functional/meson.build @@ -10,7 +10,7 @@ if get_option('tcg_interpreter') endif # Timeouts for individual tests that can be slow e.g. with debugging enabled -test_timeouts = { +test_aarch64_timeouts = { 'aarch64_aspeed_ast2700' : 600, 'aarch64_aspeed_ast2700fc' : 600, 'aarch64_device_passthrough' : 720, @@ -25,7 +25,9 @@ test_timeouts = { 'aarch64_tuxrun' : 240, 'aarch64_virt' : 360, 'aarch64_virt_gpu' : 480, - 'acpi_bits' : 420, +} + +test_arm_timeouts = { 'arm_aspeed_palmetto' : 120, 'arm_aspeed_romulus' : 120, 'arm_aspeed_witherspoon' : 120, @@ -44,24 +46,55 @@ test_timeouts = { 'arm_replay' : 240, 'arm_tuxrun' : 240, 'arm_sx1' : 360, - 'intel_iommu': 300, +} + +test_mips_timeouts = { 'mips_malta' : 480, +} + +test_mipsel_timeouts = { 'mipsel_malta' : 420, 'mipsel_replay' : 480, +} + +test_mips64_timeouts = { 'mips64_malta' : 240, +} + +test_mips64el_timeouts = { 'mips64el_malta' : 420, 'mips64el_replay' : 180, - 'netdev_ethtool' : 180, +} + +test_ppc_timeouts = { 'ppc_40p' : 240, +} + +test_ppc64_timeouts = { 'ppc64_hv' : 1000, 'ppc64_powernv' : 480, 'ppc64_pseries' : 480, 'ppc64_replay' : 210, 'ppc64_tuxrun' : 420, 'ppc64_mac99' : 120, +} + +test_riscv64_timeouts = { 'riscv64_tuxrun' : 120, +} + +test_s390x_timeouts = { 's390x_ccw_virtio' : 420, +} + +test_sh4_timeouts = { 'sh4_tuxrun' : 240, +} + +test_x86_64_timeouts = { + 'acpi_bits' : 420, + 'intel_iommu': 300, + 'netdev_ethtool' : 180, 'virtio_balloon': 120, 'x86_64_kvm_xen' : 180, 'x86_64_replay' : 480, @@ -404,6 +437,11 @@ foreach speed : ['quick', 'thorough'] build_by_default: false, env: test_precache_env) precache_all += precache + if is_variable('test_' + target_base + '_timeouts') + time_out = get_variable('test_' + target_base + '_timeouts').get(test, 90) + else + time_out = 90 + endif # Ideally we would add 'precache' to 'depends' here, such that # 'build_by_default: false' lets the pre-caching automatically @@ -419,8 +457,8 @@ foreach speed : ['quick', 'thorough'] env: test_env, args: [testpath], protocol: 'tap', - timeout: test_timeouts.get(test, 90), - priority: test_timeouts.get(test, 90), + timeout: time_out, + priority: time_out, suite: suites) endforeach endforeach -- cgit v1.1 From 9c9efb1e36ddb2e636c7f6aafda49cddaee88a0c Mon Sep 17 00:00:00 2001 From: Thomas Huth Date: Tue, 19 Aug 2025 13:23:41 +0200 Subject: tests/functional/meson.build: Allow tests to reside in subfolders We are going to move target-specific tests to subfolders that are named after the target (and generic tests will be put into a "generic" folder), so prepare the meson.build file to allow such locations, too. Reviewed-by: Pierrick Bouvier Signed-off-by: Thomas Huth Message-ID: <20250819112403.432587-5-thuth@redhat.com> --- tests/functional/meson.build | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'tests') diff --git a/tests/functional/meson.build b/tests/functional/meson.build index 356aad1..8c24ac1 100644 --- a/tests/functional/meson.build +++ b/tests/functional/meson.build @@ -423,7 +423,13 @@ foreach speed : ['quick', 'thorough'] foreach test : target_tests testname = '@0@-@1@'.format(target_base, test) - testfile = 'test_' + test + '.py' + if fs.exists('test_' + test + '.py') + testfile = 'test_' + test + '.py' + elif fs.exists('generic' / 'test_' + test + '.py') + testfile = 'generic' / 'test_' + test + '.py' + else + testfile = target_base / 'test_' + test + '.py' + endif testpath = meson.current_source_dir() / testfile teststamp = testname + '.tstamp' test_precache_env = environment() -- cgit v1.1 From 96ced85b0c5664426518ad43f0e423092fbee933 Mon Sep 17 00:00:00 2001 From: Thomas Huth Date: Tue, 19 Aug 2025 13:23:42 +0200 Subject: tests/functional: Move aarch64 tests into architecture specific folder The tests/functional folder has become quite crowded already, some restructuring would be helpful here. Thus move the aarch64 tests into a target-specific subfolder. Reviewed-by: Pierrick Bouvier Signed-off-by: Thomas Huth Message-ID: <20250819112403.432587-6-thuth@redhat.com> --- tests/functional/aarch64/meson.build | 48 +++++ tests/functional/aarch64/test_aspeed_ast2700.py | 140 ++++++++++++++ tests/functional/aarch64/test_aspeed_ast2700fc.py | 135 +++++++++++++ .../functional/aarch64/test_device_passthrough.py | 142 ++++++++++++++ tests/functional/aarch64/test_hotplug_pci.py | 72 +++++++ tests/functional/aarch64/test_imx8mp_evk.py | 68 +++++++ tests/functional/aarch64/test_kvm.py | 71 +++++++ tests/functional/aarch64/test_migration.py | 26 +++ tests/functional/aarch64/test_multiprocess.py | 31 +++ tests/functional/aarch64/test_raspi3.py | 34 ++++ tests/functional/aarch64/test_raspi4.py | 96 ++++++++++ tests/functional/aarch64/test_replay.py | 51 +++++ tests/functional/aarch64/test_reverse_debug.py | 38 ++++ tests/functional/aarch64/test_rme_sbsaref.py | 69 +++++++ tests/functional/aarch64/test_rme_virt.py | 101 ++++++++++ tests/functional/aarch64/test_sbsaref.py | 101 ++++++++++ tests/functional/aarch64/test_sbsaref_alpine.py | 62 ++++++ tests/functional/aarch64/test_sbsaref_freebsd.py | 63 ++++++ tests/functional/aarch64/test_smmu.py | 211 +++++++++++++++++++++ tests/functional/aarch64/test_tcg_plugins.py | 118 ++++++++++++ tests/functional/aarch64/test_tuxrun.py | 50 +++++ tests/functional/aarch64/test_virt.py | 135 +++++++++++++ tests/functional/aarch64/test_virt_gpu.py | 142 ++++++++++++++ tests/functional/aarch64/test_xen.py | 91 +++++++++ tests/functional/aarch64/test_xlnx_versal.py | 37 ++++ tests/functional/meson.build | 48 +---- tests/functional/test_aarch64_aspeed_ast2700.py | 140 -------------- tests/functional/test_aarch64_aspeed_ast2700fc.py | 135 ------------- .../functional/test_aarch64_device_passthrough.py | 142 -------------- tests/functional/test_aarch64_hotplug_pci.py | 72 ------- tests/functional/test_aarch64_imx8mp_evk.py | 68 ------- tests/functional/test_aarch64_kvm.py | 71 ------- tests/functional/test_aarch64_migration.py | 26 --- tests/functional/test_aarch64_multiprocess.py | 31 --- tests/functional/test_aarch64_raspi3.py | 34 ---- tests/functional/test_aarch64_raspi4.py | 96 ---------- tests/functional/test_aarch64_replay.py | 51 ----- tests/functional/test_aarch64_reverse_debug.py | 38 ---- tests/functional/test_aarch64_rme_sbsaref.py | 69 ------- tests/functional/test_aarch64_rme_virt.py | 101 ---------- tests/functional/test_aarch64_sbsaref.py | 101 ---------- tests/functional/test_aarch64_sbsaref_alpine.py | 62 ------ tests/functional/test_aarch64_sbsaref_freebsd.py | 63 ------ tests/functional/test_aarch64_smmu.py | 211 --------------------- tests/functional/test_aarch64_tcg_plugins.py | 118 ------------ tests/functional/test_aarch64_tuxrun.py | 50 ----- tests/functional/test_aarch64_virt.py | 135 ------------- tests/functional/test_aarch64_virt_gpu.py | 142 -------------- tests/functional/test_aarch64_xen.py | 91 --------- tests/functional/test_aarch64_xlnx_versal.py | 37 ---- 50 files changed, 2133 insertions(+), 2131 deletions(-) create mode 100644 tests/functional/aarch64/meson.build create mode 100755 tests/functional/aarch64/test_aspeed_ast2700.py create mode 100755 tests/functional/aarch64/test_aspeed_ast2700fc.py create mode 100755 tests/functional/aarch64/test_device_passthrough.py create mode 100755 tests/functional/aarch64/test_hotplug_pci.py create mode 100755 tests/functional/aarch64/test_imx8mp_evk.py create mode 100755 tests/functional/aarch64/test_kvm.py create mode 100755 tests/functional/aarch64/test_migration.py create mode 100755 tests/functional/aarch64/test_multiprocess.py create mode 100755 tests/functional/aarch64/test_raspi3.py create mode 100755 tests/functional/aarch64/test_raspi4.py create mode 100755 tests/functional/aarch64/test_replay.py create mode 100755 tests/functional/aarch64/test_reverse_debug.py create mode 100755 tests/functional/aarch64/test_rme_sbsaref.py create mode 100755 tests/functional/aarch64/test_rme_virt.py create mode 100755 tests/functional/aarch64/test_sbsaref.py create mode 100755 tests/functional/aarch64/test_sbsaref_alpine.py create mode 100755 tests/functional/aarch64/test_sbsaref_freebsd.py create mode 100755 tests/functional/aarch64/test_smmu.py create mode 100755 tests/functional/aarch64/test_tcg_plugins.py create mode 100755 tests/functional/aarch64/test_tuxrun.py create mode 100755 tests/functional/aarch64/test_virt.py create mode 100755 tests/functional/aarch64/test_virt_gpu.py create mode 100755 tests/functional/aarch64/test_xen.py create mode 100755 tests/functional/aarch64/test_xlnx_versal.py delete mode 100755 tests/functional/test_aarch64_aspeed_ast2700.py delete mode 100755 tests/functional/test_aarch64_aspeed_ast2700fc.py delete mode 100755 tests/functional/test_aarch64_device_passthrough.py delete mode 100755 tests/functional/test_aarch64_hotplug_pci.py delete mode 100755 tests/functional/test_aarch64_imx8mp_evk.py delete mode 100755 tests/functional/test_aarch64_kvm.py delete mode 100755 tests/functional/test_aarch64_migration.py delete mode 100755 tests/functional/test_aarch64_multiprocess.py delete mode 100755 tests/functional/test_aarch64_raspi3.py delete mode 100755 tests/functional/test_aarch64_raspi4.py delete mode 100755 tests/functional/test_aarch64_replay.py delete mode 100755 tests/functional/test_aarch64_reverse_debug.py delete mode 100755 tests/functional/test_aarch64_rme_sbsaref.py delete mode 100755 tests/functional/test_aarch64_rme_virt.py delete mode 100755 tests/functional/test_aarch64_sbsaref.py delete mode 100755 tests/functional/test_aarch64_sbsaref_alpine.py delete mode 100755 tests/functional/test_aarch64_sbsaref_freebsd.py delete mode 100755 tests/functional/test_aarch64_smmu.py delete mode 100755 tests/functional/test_aarch64_tcg_plugins.py delete mode 100755 tests/functional/test_aarch64_tuxrun.py delete mode 100755 tests/functional/test_aarch64_virt.py delete mode 100755 tests/functional/test_aarch64_virt_gpu.py delete mode 100755 tests/functional/test_aarch64_xen.py delete mode 100755 tests/functional/test_aarch64_xlnx_versal.py (limited to 'tests') diff --git a/tests/functional/aarch64/meson.build b/tests/functional/aarch64/meson.build new file mode 100644 index 0000000..04846c6 --- /dev/null +++ b/tests/functional/aarch64/meson.build @@ -0,0 +1,48 @@ +# SPDX-License-Identifier: GPL-2.0-or-later + +test_aarch64_timeouts = { + 'aspeed_ast2700' : 600, + 'aspeed_ast2700fc' : 600, + 'device_passthrough' : 720, + 'imx8mp_evk' : 240, + 'raspi4' : 480, + 'reverse_debug' : 180, + 'rme_virt' : 1200, + 'rme_sbsaref' : 1200, + 'sbsaref_alpine' : 1200, + 'sbsaref_freebsd' : 720, + 'smmu' : 720, + 'tuxrun' : 240, + 'virt' : 360, + 'virt_gpu' : 480, +} + +tests_aarch64_system_quick = [ + 'migration', +] + +tests_aarch64_system_thorough = [ + 'aspeed_ast2700', + 'aspeed_ast2700fc', + 'device_passthrough', + 'hotplug_pci', + 'imx8mp_evk', + 'kvm', + 'multiprocess', + 'raspi3', + 'raspi4', + 'replay', + 'reverse_debug', + 'rme_virt', + 'rme_sbsaref', + 'sbsaref', + 'sbsaref_alpine', + 'sbsaref_freebsd', + 'smmu', + 'tcg_plugins', + 'tuxrun', + 'virt', + 'virt_gpu', + 'xen', + 'xlnx_versal', +] diff --git a/tests/functional/aarch64/test_aspeed_ast2700.py b/tests/functional/aarch64/test_aspeed_ast2700.py new file mode 100755 index 0000000..d02dc79 --- /dev/null +++ b/tests/functional/aarch64/test_aspeed_ast2700.py @@ -0,0 +1,140 @@ +#!/usr/bin/env python3 +# +# Functional test that boots the ASPEED SoCs with firmware +# +# Copyright (C) 2022 ASPEED Technology Inc +# +# SPDX-License-Identifier: GPL-2.0-or-later + +import os + +from qemu_test import QemuSystemTest, Asset +from qemu_test import wait_for_console_pattern +from qemu_test import exec_command_and_wait_for_pattern + + +class AST2x00MachineSDK(QemuSystemTest): + + def do_test_aarch64_aspeed_sdk_start(self, image): + self.require_netdev('user') + self.vm.set_console() + self.vm.add_args('-device', + 'tmp105,bus=aspeed.i2c.bus.1,address=0x4d,id=tmp-test') + self.vm.add_args('-drive', 'file=' + image + ',if=mtd,format=raw', + '-net', 'nic', '-net', 'user', '-snapshot') + + self.vm.launch() + + def verify_vbootrom_firmware_flow(self): + wait_for_console_pattern(self, 'Found valid FIT image') + wait_for_console_pattern(self, '[uboot] loading') + wait_for_console_pattern(self, 'done') + wait_for_console_pattern(self, '[fdt] loading') + wait_for_console_pattern(self, 'done') + wait_for_console_pattern(self, '[tee] loading') + wait_for_console_pattern(self, 'done') + wait_for_console_pattern(self, '[atf] loading') + wait_for_console_pattern(self, 'done') + wait_for_console_pattern(self, 'Jumping to BL31 (Trusted Firmware-A)') + + def verify_openbmc_boot_and_login(self, name): + wait_for_console_pattern(self, 'U-Boot 2023.10') + wait_for_console_pattern(self, '## Loading kernel from FIT Image') + wait_for_console_pattern(self, 'Starting kernel ...') + + wait_for_console_pattern(self, f'{name} login:') + exec_command_and_wait_for_pattern(self, 'root', 'Password:') + exec_command_and_wait_for_pattern(self, '0penBmc', f'root@{name}:~#') + + ASSET_SDK_V906_AST2700 = Asset( + 'https://github.com/AspeedTech-BMC/openbmc/releases/download/v09.06/ast2700-a0-default-obmc.tar.gz', + '7247b6f19dbfb700686f8d9f723ac23f3eb229226c0589cb9b06b80d1b61f3cb') + + ASSET_SDK_V906_AST2700A1 = Asset( + 'https://github.com/AspeedTech-BMC/openbmc/releases/download/v09.06/ast2700-default-obmc.tar.gz', + 'f1d53e0be8a404ecce3e105f72bc50fa4e090ad13160ffa91b10a6e0233a9dc6') + + def do_ast2700_i2c_test(self): + exec_command_and_wait_for_pattern(self, + 'echo lm75 0x4d > /sys/class/i2c-dev/i2c-1/device/new_device ', + 'i2c i2c-1: new_device: Instantiated device lm75 at 0x4d') + exec_command_and_wait_for_pattern(self, + 'cat /sys/bus/i2c/devices/1-004d/hwmon/hwmon*/temp1_input', '0') + self.vm.cmd('qom-set', path='/machine/peripheral/tmp-test', + property='temperature', value=18000) + exec_command_and_wait_for_pattern(self, + 'cat /sys/bus/i2c/devices/1-004d/hwmon/hwmon*/temp1_input', '18000') + + def start_ast2700_test(self, name): + num_cpu = 4 + uboot_size = os.path.getsize(self.scratch_file(name, + 'u-boot-nodtb.bin')) + uboot_dtb_load_addr = hex(0x400000000 + uboot_size) + + load_images_list = [ + { + 'addr': '0x400000000', + 'file': self.scratch_file(name, + 'u-boot-nodtb.bin') + }, + { + 'addr': str(uboot_dtb_load_addr), + 'file': self.scratch_file(name, 'u-boot.dtb') + }, + { + 'addr': '0x430000000', + 'file': self.scratch_file(name, 'bl31.bin') + }, + { + 'addr': '0x430080000', + 'file': self.scratch_file(name, 'optee', + 'tee-raw.bin') + } + ] + + for load_image in load_images_list: + addr = load_image['addr'] + file = load_image['file'] + self.vm.add_args('-device', + f'loader,force-raw=on,addr={addr},file={file}') + + for i in range(num_cpu): + self.vm.add_args('-device', + f'loader,addr=0x430000000,cpu-num={i}') + + self.vm.add_args('-smp', str(num_cpu)) + self.do_test_aarch64_aspeed_sdk_start( + self.scratch_file(name, 'image-bmc')) + + def start_ast2700_test_vbootrom(self, name): + self.vm.add_args('-bios', 'ast27x0_bootrom.bin') + self.do_test_aarch64_aspeed_sdk_start( + self.scratch_file(name, 'image-bmc')) + + def test_aarch64_ast2700_evb_sdk_v09_06(self): + self.set_machine('ast2700-evb') + + self.archive_extract(self.ASSET_SDK_V906_AST2700) + self.start_ast2700_test('ast2700-a0-default') + self.verify_openbmc_boot_and_login('ast2700-a0-default') + self.do_ast2700_i2c_test() + + def test_aarch64_ast2700a1_evb_sdk_v09_06(self): + self.set_machine('ast2700a1-evb') + + self.archive_extract(self.ASSET_SDK_V906_AST2700A1) + self.start_ast2700_test('ast2700-default') + self.verify_openbmc_boot_and_login('ast2700-default') + self.do_ast2700_i2c_test() + + def test_aarch64_ast2700a1_evb_sdk_vbootrom_v09_06(self): + self.set_machine('ast2700a1-evb') + + self.archive_extract(self.ASSET_SDK_V906_AST2700A1) + self.start_ast2700_test_vbootrom('ast2700-default') + self.verify_vbootrom_firmware_flow() + self.verify_openbmc_boot_and_login('ast2700-default') + self.do_ast2700_i2c_test() + +if __name__ == '__main__': + QemuSystemTest.main() diff --git a/tests/functional/aarch64/test_aspeed_ast2700fc.py b/tests/functional/aarch64/test_aspeed_ast2700fc.py new file mode 100755 index 0000000..b85370e --- /dev/null +++ b/tests/functional/aarch64/test_aspeed_ast2700fc.py @@ -0,0 +1,135 @@ +#!/usr/bin/env python3 +# +# Functional test that boots the ASPEED SoCs with firmware +# +# Copyright (C) 2022 ASPEED Technology Inc +# +# SPDX-License-Identifier: GPL-2.0-or-later + +import os + +from qemu_test import QemuSystemTest, Asset +from qemu_test import wait_for_console_pattern +from qemu_test import exec_command_and_wait_for_pattern + + +class AST2x00MachineSDK(QemuSystemTest): + + def do_test_aarch64_aspeed_sdk_start(self, image): + self.require_netdev('user') + self.vm.set_console() + self.vm.add_args('-device', + 'tmp105,bus=aspeed.i2c.bus.1,address=0x4d,id=tmp-test') + self.vm.add_args('-drive', 'file=' + image + ',if=mtd,format=raw', + '-net', 'nic', '-net', 'user', '-snapshot') + + self.vm.launch() + + def verify_openbmc_boot_and_login(self, name): + wait_for_console_pattern(self, 'U-Boot 2023.10') + wait_for_console_pattern(self, '## Loading kernel from FIT Image') + wait_for_console_pattern(self, 'Starting kernel ...') + + wait_for_console_pattern(self, f'{name} login:') + exec_command_and_wait_for_pattern(self, 'root', 'Password:') + exec_command_and_wait_for_pattern(self, '0penBmc', f'root@{name}:~#') + + ASSET_SDK_V906_AST2700 = Asset( + 'https://github.com/AspeedTech-BMC/openbmc/releases/download/v09.06/ast2700-default-obmc.tar.gz', + 'f1d53e0be8a404ecce3e105f72bc50fa4e090ad13160ffa91b10a6e0233a9dc6') + + def do_ast2700_i2c_test(self): + exec_command_and_wait_for_pattern(self, + 'echo lm75 0x4d > /sys/class/i2c-dev/i2c-1/device/new_device ', + 'i2c i2c-1: new_device: Instantiated device lm75 at 0x4d') + exec_command_and_wait_for_pattern(self, + 'cat /sys/bus/i2c/devices/1-004d/hwmon/hwmon*/temp1_input', '0') + self.vm.cmd('qom-set', path='/machine/peripheral/tmp-test', + property='temperature', value=18000) + exec_command_and_wait_for_pattern(self, + 'cat /sys/bus/i2c/devices/1-004d/hwmon/hwmon*/temp1_input', '18000') + + def do_ast2700fc_ssp_test(self): + self.vm.shutdown() + self.vm.set_console(console_index=1) + self.vm.launch() + + exec_command_and_wait_for_pattern(self, '\012', 'ssp:~$') + exec_command_and_wait_for_pattern(self, 'version', + 'Zephyr version 3.7.1') + exec_command_and_wait_for_pattern(self, 'md 72c02000 1', + '[72c02000] 06010103') + + def do_ast2700fc_tsp_test(self): + self.vm.shutdown() + self.vm.set_console(console_index=2) + self.vm.launch() + + exec_command_and_wait_for_pattern(self, '\012', 'tsp:~$') + exec_command_and_wait_for_pattern(self, 'version', + 'Zephyr version 3.7.1') + exec_command_and_wait_for_pattern(self, 'md 72c02000 1', + '[72c02000] 06010103') + + def start_ast2700fc_test(self, name): + ca35_core = 4 + uboot_size = os.path.getsize(self.scratch_file(name, + 'u-boot-nodtb.bin')) + uboot_dtb_load_addr = hex(0x400000000 + uboot_size) + + load_images_list = [ + { + 'addr': '0x400000000', + 'file': self.scratch_file(name, + 'u-boot-nodtb.bin') + }, + { + 'addr': str(uboot_dtb_load_addr), + 'file': self.scratch_file(name, 'u-boot.dtb') + }, + { + 'addr': '0x430000000', + 'file': self.scratch_file(name, 'bl31.bin') + }, + { + 'addr': '0x430080000', + 'file': self.scratch_file(name, 'optee', + 'tee-raw.bin') + } + ] + + for load_image in load_images_list: + addr = load_image['addr'] + file = load_image['file'] + self.vm.add_args('-device', + f'loader,force-raw=on,addr={addr},file={file}') + + for i in range(ca35_core): + self.vm.add_args('-device', + f'loader,addr=0x430000000,cpu-num={i}') + + load_elf_list = { + 'ssp': self.scratch_file(name, 'zephyr-aspeed-ssp.elf'), + 'tsp': self.scratch_file(name, 'zephyr-aspeed-tsp.elf') + } + + for cpu_num, key in enumerate(load_elf_list, start=4): + file = load_elf_list[key] + self.vm.add_args('-device', + f'loader,file={file},cpu-num={cpu_num}') + + self.do_test_aarch64_aspeed_sdk_start( + self.scratch_file(name, 'image-bmc')) + + def test_aarch64_ast2700fc_sdk_v09_06(self): + self.set_machine('ast2700fc') + + self.archive_extract(self.ASSET_SDK_V906_AST2700) + self.start_ast2700fc_test('ast2700-default') + self.verify_openbmc_boot_and_login('ast2700-default') + self.do_ast2700_i2c_test() + self.do_ast2700fc_ssp_test() + self.do_ast2700fc_tsp_test() + +if __name__ == '__main__': + QemuSystemTest.main() diff --git a/tests/functional/aarch64/test_device_passthrough.py b/tests/functional/aarch64/test_device_passthrough.py new file mode 100755 index 0000000..1f3f158 --- /dev/null +++ b/tests/functional/aarch64/test_device_passthrough.py @@ -0,0 +1,142 @@ +#!/usr/bin/env python3 +# +# Boots a nested guest and compare content of a device (passthrough) to a +# reference image. Both vfio group and iommufd passthrough methods are tested. +# +# Copyright (c) 2025 Linaro Ltd. +# +# Author: Pierrick Bouvier +# +# SPDX-License-Identifier: GPL-2.0-or-later + +import os + +from qemu_test import QemuSystemTest, Asset +from qemu_test import exec_command, wait_for_console_pattern +from qemu_test import exec_command_and_wait_for_pattern +from random import randbytes + +guest_script = ''' +#!/usr/bin/env bash + +set -euo pipefail +set -x + +# find disks from nvme serial +dev_vfio=$(lsblk --nvme | grep vfio | cut -f 1 -d ' ') +dev_iommufd=$(lsblk --nvme | grep iommufd | cut -f 1 -d ' ') +pci_vfio=$(basename $(readlink -f /sys/block/$dev_vfio/../../../)) +pci_iommufd=$(basename $(readlink -f /sys/block/$dev_iommufd/../../../)) + +# bind disks to vfio +for p in "$pci_vfio" "$pci_iommufd"; do + if [ "$(cat /sys/bus/pci/devices/$p/driver_override)" == vfio-pci ]; then + continue + fi + echo $p > /sys/bus/pci/drivers/nvme/unbind + echo vfio-pci > /sys/bus/pci/devices/$p/driver_override + echo $p > /sys/bus/pci/drivers/vfio-pci/bind +done + +# boot nested guest and execute /host/nested_guest.sh +# one disk is passed through vfio group, the other, through iommufd +qemu-system-aarch64 \ +-M virt \ +-display none \ +-serial stdio \ +-cpu host \ +-enable-kvm \ +-m 1G \ +-kernel /host/Image.gz \ +-drive format=raw,file=/host/guest.ext4,if=virtio \ +-append "root=/dev/vda init=/init -- bash /host/nested_guest.sh" \ +-virtfs local,path=/host,mount_tag=host,security_model=mapped,readonly=off \ +-device vfio-pci,host=$pci_vfio \ +-object iommufd,id=iommufd0 \ +-device vfio-pci,host=$pci_iommufd,iommufd=iommufd0 +''' + +nested_guest_script = ''' +#!/usr/bin/env bash + +set -euo pipefail +set -x + +image_vfio=/host/disk_vfio +image_iommufd=/host/disk_iommufd + +dev_vfio=$(lsblk --nvme | grep vfio | cut -f 1 -d ' ') +dev_iommufd=$(lsblk --nvme | grep iommufd | cut -f 1 -d ' ') + +# compare if devices are identical to original images +diff $image_vfio /dev/$dev_vfio +diff $image_iommufd /dev/$dev_iommufd + +echo device_passthrough_test_ok +''' + +class Aarch64DevicePassthrough(QemuSystemTest): + + # https://github.com/pbo-linaro/qemu-linux-stack + # + # Linux kernel is compiled with defconfig + + # IOMMUFD + VFIO_DEVICE_CDEV + ARM_SMMU_V3_IOMMUFD + # https://docs.kernel.org/driver-api/vfio.html#vfio-device-cde + ASSET_DEVICE_PASSTHROUGH_STACK = Asset( + ('https://fileserver.linaro.org/s/fx5DXxBYme8dw2G/' + 'download/device_passthrough.tar.xz'), + '812750b664d61c2986f2b149939ae28cafbd60d53e9c7e4b16e97143845e196d') + + # This tests the device passthrough implementation, by booting a VM + # supporting it with two nvme disks attached, and launching a nested VM + # reading their content. + def test_aarch64_device_passthrough(self): + self.set_machine('virt') + self.require_accelerator('tcg') + + self.vm.set_console() + + stack_path_tar_gz = self.ASSET_DEVICE_PASSTHROUGH_STACK.fetch() + self.archive_extract(stack_path_tar_gz, format="tar") + + stack = self.scratch_file('out') + kernel = os.path.join(stack, 'Image.gz') + rootfs_host = os.path.join(stack, 'host.ext4') + disk_vfio = os.path.join(stack, 'disk_vfio') + disk_iommufd = os.path.join(stack, 'disk_iommufd') + guest_cmd = os.path.join(stack, 'guest.sh') + nested_guest_cmd = os.path.join(stack, 'nested_guest.sh') + # we generate two random disks + with open(disk_vfio, "wb") as d: d.write(randbytes(512)) + with open(disk_iommufd, "wb") as d: d.write(randbytes(1024)) + with open(guest_cmd, 'w') as s: s.write(guest_script) + with open(nested_guest_cmd, 'w') as s: s.write(nested_guest_script) + + self.vm.add_args('-cpu', 'max') + self.vm.add_args('-m', '2G') + self.vm.add_args('-M', 'virt,' + 'virtualization=on,' + 'gic-version=max,' + 'iommu=smmuv3') + self.vm.add_args('-kernel', kernel) + self.vm.add_args('-drive', f'format=raw,file={rootfs_host}') + self.vm.add_args('-drive', + f'file={disk_vfio},if=none,id=vfio,format=raw') + self.vm.add_args('-device', 'nvme,serial=vfio,drive=vfio') + self.vm.add_args('-drive', + f'file={disk_iommufd},if=none,id=iommufd,format=raw') + self.vm.add_args('-device', 'nvme,serial=iommufd,drive=iommufd') + self.vm.add_args('-virtfs', + f'local,path={stack}/,mount_tag=host,' + 'security_model=mapped,readonly=off') + # boot and execute guest script + # init will trigger a kernel panic if script fails + self.vm.add_args('-append', + 'root=/dev/vda init=/init -- bash /host/guest.sh') + + self.vm.launch() + wait_for_console_pattern(self, 'device_passthrough_test_ok', + failure_message='Kernel panic') + +if __name__ == '__main__': + QemuSystemTest.main() diff --git a/tests/functional/aarch64/test_hotplug_pci.py b/tests/functional/aarch64/test_hotplug_pci.py new file mode 100755 index 0000000..0c67991 --- /dev/null +++ b/tests/functional/aarch64/test_hotplug_pci.py @@ -0,0 +1,72 @@ +#!/usr/bin/env python3 +# +# The test hotplugs a PCI device and checks it on a Linux guest. +# +# Copyright (c) 2025 Linaro Ltd. +# +# Author: +# Gustavo Romero +# +# SPDX-License-Identifier: GPL-2.0-or-later + +from qemu_test import LinuxKernelTest, Asset, exec_command_and_wait_for_pattern +from qemu_test import BUILD_DIR + +class HotplugPCI(LinuxKernelTest): + + ASSET_KERNEL = Asset( + ('https://ftp.debian.org/debian/dists/bookworm/main/installer-arm64/' + '20230607+deb12u11/images/netboot/debian-installer/arm64/linux'), + 'd92a60392ce1e379ca198a1a820899f8f0d39a62d047c41ab79492f81541a9d9') + + ASSET_INITRD = Asset( + ('https://ftp.debian.org/debian/dists/bookworm/main/installer-arm64/' + '20230607+deb12u11/images/netboot/debian-installer/arm64/initrd.gz'), + '9f817f76951f3237bca8216bee35267bfb826815687f4b2fcdd5e6c2a917790c') + + def test_hotplug_pci(self): + + self.set_machine('virt') + + self.vm.add_args('-m', '512M', + '-cpu', 'cortex-a57', + '-append', + 'console=ttyAMA0,115200 init=/bin/sh', + '-device', + 'pcie-root-port,bus=pcie.0,chassis=1,slot=1,id=pcie.1', + '-bios', + self.build_file('pc-bios', 'edk2-aarch64-code.fd')) + + # BusyBox prompt + prompt = "~ #" + self.launch_kernel(self.ASSET_KERNEL.fetch(), + self.ASSET_INITRD.fetch(), + wait_for=prompt) + + # Check for initial state: 2 network adapters, lo and enp0s1. + exec_command_and_wait_for_pattern(self, + 'ls /sys/class/net | wc -l', + '2') + + # Hotplug one network adapter to the root port, i.e. pcie.1 bus. + self.vm.cmd('device_add', + driver='virtio-net-pci', + bus='pcie.1', + addr=0, + id='na') + # Wait for the kernel to recognize the new device. + self.wait_for_console_pattern('virtio-pci') + self.wait_for_console_pattern('virtio_net') + + # Check if there is a new network adapter. + exec_command_and_wait_for_pattern(self, + 'ls /sys/class/net | wc -l', + '3') + + self.vm.cmd('device_del', id='na') + exec_command_and_wait_for_pattern(self, + 'ls /sys/class/net | wc -l', + '2') + +if __name__ == '__main__': + LinuxKernelTest.main() diff --git a/tests/functional/aarch64/test_imx8mp_evk.py b/tests/functional/aarch64/test_imx8mp_evk.py new file mode 100755 index 0000000..99ddcde --- /dev/null +++ b/tests/functional/aarch64/test_imx8mp_evk.py @@ -0,0 +1,68 @@ +#!/usr/bin/env python3 +# +# Functional test that boots a Linux kernel and checks the console +# +# SPDX-License-Identifier: GPL-2.0-or-later + +from qemu_test import LinuxKernelTest, Asset + + +class Imx8mpEvkMachine(LinuxKernelTest): + + ASSET_IMAGE = Asset( + ('https://cloud.debian.org/images/cloud/bookworm/20231210-1590/' + 'debian-12-generic-arm64-20231210-1590.tar.xz'), + '7ebf1577b32d5af6204df74b54ca2e4675de9b5a9fa14f3ff70b88eeb7b3b359') + + KERNEL_OFFSET = 0x51000000 + KERNEL_SIZE = 32622528 + INITRD_OFFSET = 0x76000000 + INITRD_SIZE = 30987766 + DTB_OFFSET = 0x64F51000 + DTB_SIZE = 45 * 1024 + + def extract(self, in_path, out_path, offset, size): + try: + with open(in_path, "rb") as source: + source.seek(offset) + data = source.read(size) + with open(out_path, "wb") as target: + target.write(data) + except (IOError, ValueError) as e: + self.log.error(f"Failed to extract {out_path}: {e}") + raise + + def setUp(self): + super().setUp() + + self.image_path = self.scratch_file("disk.raw") + self.kernel_path = self.scratch_file("linux") + self.initrd_path = self.scratch_file("initrd.zstd") + self.dtb_path = self.scratch_file("imx8mp-evk.dtb") + + self.archive_extract(self.ASSET_IMAGE) + self.extract(self.image_path, self.kernel_path, + self.KERNEL_OFFSET, self.KERNEL_SIZE) + self.extract(self.image_path, self.initrd_path, + self.INITRD_OFFSET, self.INITRD_SIZE) + self.extract(self.image_path, self.dtb_path, + self.DTB_OFFSET, self.DTB_SIZE) + + def test_aarch64_imx8mp_evk_usdhc(self): + self.require_accelerator("tcg") + self.set_machine('imx8mp-evk') + self.vm.set_console(console_index=1) + self.vm.add_args('-m', '2G', + '-smp', '4', + '-kernel', self.kernel_path, + '-initrd', self.initrd_path, + '-dtb', self.dtb_path, + '-append', 'root=/dev/mmcblk2p1', + '-drive', f'file={self.image_path},if=sd,bus=2,' + 'format=raw,id=mmcblk2,snapshot=on') + + self.vm.launch() + self.wait_for_console_pattern('Welcome to ') + +if __name__ == '__main__': + LinuxKernelTest.main() diff --git a/tests/functional/aarch64/test_kvm.py b/tests/functional/aarch64/test_kvm.py new file mode 100755 index 0000000..9fb9286 --- /dev/null +++ b/tests/functional/aarch64/test_kvm.py @@ -0,0 +1,71 @@ +#!/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 +# +# SPDX-License-Identifier: GPL-2.0-or-later + +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") + + self.vm.launch() + + self.wait_for_console_pattern('buildroot login:') + ec_and_wait(self, 'root', '#') + ec_and_wait(self, f"export PS1='{self.PS1}'", self.OK_CMD) + + # this is just a smoketest, we don't run all the tests in the image + def _smoketest_kvm(self): + 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_nvhe_selftest(self): + self._launch_guest("nvhe") + self._smoketest_kvm() + + def test_aarch64_vhe_selftest(self): + self._launch_guest("vhe") + self._smoketest_kvm() + +if __name__ == '__main__': + LinuxKernelTest.main() diff --git a/tests/functional/aarch64/test_migration.py b/tests/functional/aarch64/test_migration.py new file mode 100755 index 0000000..70267e7 --- /dev/null +++ b/tests/functional/aarch64/test_migration.py @@ -0,0 +1,26 @@ +#!/usr/bin/env python3 +# +# SPDX-License-Identifier: GPL-2.0-or-later +# +# aarch64 migration test + +from migration import MigrationTest + + +class Aarch64MigrationTest(MigrationTest): + + def test_migration_with_tcp_localhost(self): + self.set_machine('quanta-gsj') + self.migration_with_tcp_localhost() + + def test_migration_with_unix(self): + self.set_machine('quanta-gsj') + self.migration_with_unix() + + def test_migration_with_exec(self): + self.set_machine('quanta-gsj') + self.migration_with_exec() + + +if __name__ == '__main__': + MigrationTest.main() diff --git a/tests/functional/aarch64/test_multiprocess.py b/tests/functional/aarch64/test_multiprocess.py new file mode 100755 index 0000000..1c6e45e --- /dev/null +++ b/tests/functional/aarch64/test_multiprocess.py @@ -0,0 +1,31 @@ +#!/usr/bin/env python3 +# +# SPDX-License-Identifier: GPL-2.0-or-later +# +# Test for multiprocess qemu on aarch64 + +from multiprocess import Multiprocess +from qemu_test import Asset + + +class Aarch64Multiprocess(Multiprocess): + + ASSET_KERNEL_AARCH64 = Asset( + ('https://archives.fedoraproject.org/pub/archive/fedora/linux' + '/releases/31/Everything/aarch64/os/images/pxeboot/vmlinuz'), + '3ae07fcafbfc8e4abeb693035a74fe10698faae15e9ccd48882a9167800c1527') + + ASSET_INITRD_AARCH64 = Asset( + ('https://archives.fedoraproject.org/pub/archive/fedora/linux' + '/releases/31/Everything/aarch64/os/images/pxeboot/initrd.img'), + '9fd230cab10b1dafea41cf00150e6669d37051fad133bd618d2130284e16d526') + + def test_multiprocess(self): + kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE + + 'rdinit=/bin/bash console=ttyAMA0') + self.do_test(self.ASSET_KERNEL_AARCH64, self.ASSET_INITRD_AARCH64, + kernel_command_line, 'virt,gic-version=3') + + +if __name__ == '__main__': + Multiprocess.main() diff --git a/tests/functional/aarch64/test_raspi3.py b/tests/functional/aarch64/test_raspi3.py new file mode 100755 index 0000000..74f6630 --- /dev/null +++ b/tests/functional/aarch64/test_raspi3.py @@ -0,0 +1,34 @@ +#!/usr/bin/env python3 +# +# Functional test that boots a Linux kernel on a Raspberry Pi machine +# and checks the console +# +# Copyright (c) 2020 Philippe Mathieu-Daudé +# +# SPDX-License-Identifier: GPL-2.0-or-later + +from qemu_test import LinuxKernelTest, Asset + + +class Aarch64Raspi3Machine(LinuxKernelTest): + + ASSET_RPI3_UEFI = Asset( + ('https://github.com/pbatard/RPi3/releases/download/' + 'v1.15/RPi3_UEFI_Firmware_v1.15.zip'), + '8cff2e979560048b4c84921f41a91893240b9fb71a88f0b5c5d6c8edd994bd5b') + + def test_aarch64_raspi3_atf(self): + efi_name = 'RPI_EFI.fd' + efi_fd = self.archive_extract(self.ASSET_RPI3_UEFI, member=efi_name) + + self.set_machine('raspi3b') + self.vm.set_console(console_index=1) + self.vm.add_args('-cpu', 'cortex-a53', + '-nodefaults', + '-device', f'loader,file={efi_fd},force-raw=true') + self.vm.launch() + self.wait_for_console_pattern('version UEFI Firmware v1.15') + + +if __name__ == '__main__': + LinuxKernelTest.main() diff --git a/tests/functional/aarch64/test_raspi4.py b/tests/functional/aarch64/test_raspi4.py new file mode 100755 index 0000000..7a4302b --- /dev/null +++ b/tests/functional/aarch64/test_raspi4.py @@ -0,0 +1,96 @@ +#!/usr/bin/env python3 +# +# Functional test that boots a Linux kernel on a Raspberry Pi machine +# and checks the console +# +# SPDX-License-Identifier: GPL-2.0-or-later + +from qemu_test import LinuxKernelTest, Asset +from qemu_test import exec_command_and_wait_for_pattern + + +class Aarch64Raspi4Machine(LinuxKernelTest): + + """ + The kernel can be rebuilt using the kernel source referenced + and following the instructions on the on: + https://www.raspberrypi.org/documentation/linux/kernel/building.md + """ + ASSET_KERNEL_20190215 = Asset( + ('http://archive.raspberrypi.org/debian/' + 'pool/main/r/raspberrypi-firmware/' + 'raspberrypi-kernel_1.20230106-1_arm64.deb'), + '56d5713c8f6eee8a0d3f0e73600ec11391144fef318b08943e9abd94c0a9baf7') + + ASSET_INITRD = Asset( + ('https://github.com/groeck/linux-build-test/raw/' + '86b2be1384d41c8c388e63078a847f1e1c4cb1de/rootfs/' + 'arm64/rootfs.cpio.gz'), + '7c0b16d1853772f6f4c3ca63e789b3b9ff4936efac9c8a01fb0c98c05c7a7648') + + def test_arm_raspi4(self): + kernel_path = self.archive_extract(self.ASSET_KERNEL_20190215, + member='boot/kernel8.img') + dtb_path = self.archive_extract(self.ASSET_KERNEL_20190215, + member='boot/bcm2711-rpi-4-b.dtb') + + self.set_machine('raspi4b') + self.vm.set_console() + kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE + + 'earlycon=pl011,mmio32,0xfe201000 ' + + 'console=ttyAMA0,115200 ' + + 'root=/dev/mmcblk1p2 rootwait ' + + 'dwc_otg.fiq_fsm_enable=0') + self.vm.add_args('-kernel', kernel_path, + '-dtb', dtb_path, + '-append', kernel_command_line) + # When PCI is supported we can add a USB controller: + # '-device', 'qemu-xhci,bus=pcie.1,id=xhci', + # '-device', 'usb-kbd,bus=xhci.0', + self.vm.launch() + console_pattern = 'Kernel command line: %s' % kernel_command_line + self.wait_for_console_pattern(console_pattern) + # When USB is enabled we can look for this + # console_pattern = 'Product: QEMU USB Keyboard' + # self.wait_for_console_pattern(console_pattern) + console_pattern = 'Waiting for root device' + self.wait_for_console_pattern(console_pattern) + + + def test_arm_raspi4_initrd(self): + kernel_path = self.archive_extract(self.ASSET_KERNEL_20190215, + member='boot/kernel8.img') + dtb_path = self.archive_extract(self.ASSET_KERNEL_20190215, + member='boot/bcm2711-rpi-4-b.dtb') + initrd_path = self.uncompress(self.ASSET_INITRD) + + self.set_machine('raspi4b') + self.vm.set_console() + kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE + + 'earlycon=pl011,mmio32,0xfe201000 ' + + 'console=ttyAMA0,115200 ' + + 'panic=-1 noreboot ' + + 'dwc_otg.fiq_fsm_enable=0') + self.vm.add_args('-kernel', kernel_path, + '-dtb', dtb_path, + '-initrd', initrd_path, + '-append', kernel_command_line, + '-no-reboot') + # When PCI is supported we can add a USB controller: + # '-device', 'qemu-xhci,bus=pcie.1,id=xhci', + # '-device', 'usb-kbd,bus=xhci.0', + self.vm.launch() + self.wait_for_console_pattern('Boot successful.') + + exec_command_and_wait_for_pattern(self, 'cat /proc/cpuinfo', + 'BCM2835') + exec_command_and_wait_for_pattern(self, 'cat /proc/iomem', + 'cprman@7e101000') + exec_command_and_wait_for_pattern(self, 'halt', 'reboot: System halted') + # TODO: Raspberry Pi4 doesn't shut down properly with recent kernels + # Wait for VM to shut down gracefully + #self.vm.wait() + + +if __name__ == '__main__': + LinuxKernelTest.main() diff --git a/tests/functional/aarch64/test_replay.py b/tests/functional/aarch64/test_replay.py new file mode 100755 index 0000000..db12e76 --- /dev/null +++ b/tests/functional/aarch64/test_replay.py @@ -0,0 +1,51 @@ +#!/usr/bin/env python3 +# +# Replay test that boots a Linux kernel on an aarch64 machine +# and checks the console +# +# SPDX-License-Identifier: GPL-2.0-or-later + +from subprocess import check_call, DEVNULL + +from qemu_test import Asset, skipIfOperatingSystem, get_qemu_img +from replay_kernel import ReplayKernelBase + + +class Aarch64Replay(ReplayKernelBase): + + ASSET_KERNEL = Asset( + 'https://storage.tuxboot.com/buildroot/20241119/arm64/Image', + 'b74743c5e89e1cea0f73368d24ae0ae85c5204ff84be3b5e9610417417d2f235') + + ASSET_ROOTFS = Asset( + 'https://storage.tuxboot.com/buildroot/20241119/arm64/rootfs.ext4.zst', + 'a1acaaae2068df4648d04ff75f532aaa8c5edcd6b936122b6f0db4848a07b465') + + def test_aarch64_virt(self): + self.require_netdev('user') + self.set_machine('virt') + self.cpu = 'cortex-a57' + kernel_path = self.ASSET_KERNEL.fetch() + + raw_disk = self.uncompress(self.ASSET_ROOTFS) + disk = self.scratch_file('scratch.qcow2') + qemu_img = get_qemu_img(self) + check_call([qemu_img, 'create', '-f', 'qcow2', '-b', raw_disk, + '-F', 'raw', disk], stdout=DEVNULL, stderr=DEVNULL) + + args = ('-drive', 'file=%s,snapshot=on,id=hd0,if=none' % disk, + '-drive', 'driver=blkreplay,id=hd0-rr,if=none,image=hd0', + '-device', 'virtio-blk-device,drive=hd0-rr', + '-netdev', 'user,id=vnet,hostfwd=:127.0.0.1:0-:22', + '-device', 'virtio-net,netdev=vnet', + '-object', 'filter-replay,id=replay,netdev=vnet') + + kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE + + 'console=ttyAMA0 root=/dev/vda') + console_pattern = 'Welcome to TuxTest' + self.run_rr(kernel_path, kernel_command_line, console_pattern, + args=args) + + +if __name__ == '__main__': + ReplayKernelBase.main() diff --git a/tests/functional/aarch64/test_reverse_debug.py b/tests/functional/aarch64/test_reverse_debug.py new file mode 100755 index 0000000..8bc91cc --- /dev/null +++ b/tests/functional/aarch64/test_reverse_debug.py @@ -0,0 +1,38 @@ +#!/usr/bin/env python3 +# +# SPDX-License-Identifier: GPL-2.0-or-later +# +# Reverse debugging test +# +# Copyright (c) 2020 ISP RAS +# +# Author: +# Pavel Dovgalyuk +# +# This work is licensed under the terms of the GNU GPL, version 2 or +# later. See the COPYING file in the top-level directory. + +from qemu_test import Asset, skipIfMissingImports, skipFlakyTest +from reverse_debugging import ReverseDebugging + + +@skipIfMissingImports('avocado.utils') +class ReverseDebugging_AArch64(ReverseDebugging): + + REG_PC = 32 + + ASSET_KERNEL = Asset( + ('https://archives.fedoraproject.org/pub/archive/fedora/linux/' + 'releases/29/Everything/aarch64/os/images/pxeboot/vmlinuz'), + '7e1430b81c26bdd0da025eeb8fbd77b5dc961da4364af26e771bd39f379cbbf7') + + @skipFlakyTest("https://gitlab.com/qemu-project/qemu/-/issues/2921") + def test_aarch64_virt(self): + self.set_machine('virt') + self.cpu = 'cortex-a53' + kernel_path = self.ASSET_KERNEL.fetch() + self.reverse_debugging(args=('-kernel', kernel_path)) + + +if __name__ == '__main__': + ReverseDebugging.main() diff --git a/tests/functional/aarch64/test_rme_sbsaref.py b/tests/functional/aarch64/test_rme_sbsaref.py new file mode 100755 index 0000000..100f1c7 --- /dev/null +++ b/tests/functional/aarch64/test_rme_sbsaref.py @@ -0,0 +1,69 @@ +#!/usr/bin/env python3 +# +# Functional test that boots a Realms environment on sbsa-ref machine and a +# nested guest VM using it. +# +# Copyright (c) 2024 Linaro Ltd. +# +# Author: Pierrick Bouvier +# +# SPDX-License-Identifier: GPL-2.0-or-later + +import os + +from qemu_test import QemuSystemTest, Asset, wait_for_console_pattern +from qemu_test import exec_command_and_wait_for_pattern +from test_rme_virt import test_realms_guest + + +class Aarch64RMESbsaRefMachine(QemuSystemTest): + + # Stack is built with OP-TEE build environment from those instructions: + # https://linaro.atlassian.net/wiki/spaces/QEMU/pages/29051027459/ + # https://github.com/pbo-linaro/qemu-rme-stack + ASSET_RME_STACK_SBSA = Asset( + ('https://fileserver.linaro.org/s/KJyeBxL82mz2r7F/' + 'download/rme-stack-op-tee-4.2.0-cca-v4-sbsa.tar.gz'), + 'dd9ab28ec869bdf3b5376116cb3689103b43433fd5c4bca0f4a8d8b3c104999e') + + # This tests the FEAT_RME cpu implementation, by booting a VM supporting it, + # and launching a nested VM using it. + def test_aarch64_rme_sbsaref(self): + self.set_machine('sbsa-ref') + self.require_accelerator('tcg') + self.require_netdev('user') + + self.vm.set_console() + + stack_path_tar_gz = self.ASSET_RME_STACK_SBSA.fetch() + self.archive_extract(stack_path_tar_gz, format="tar") + + rme_stack = self.scratch_file('rme-stack-op-tee-4.2.0-cca-v4-sbsa') + pflash0 = os.path.join(rme_stack, 'images', 'SBSA_FLASH0.fd') + pflash1 = os.path.join(rme_stack, 'images', 'SBSA_FLASH1.fd') + virtual = os.path.join(rme_stack, 'images', 'disks', 'virtual') + drive = os.path.join(rme_stack, 'out-br', 'images', 'rootfs.ext4') + + self.vm.add_args('-cpu', 'max,x-rme=on,pauth-impdef=on') + self.vm.add_args('-m', '2G') + self.vm.add_args('-M', 'sbsa-ref') + self.vm.add_args('-drive', f'file={pflash0},format=raw,if=pflash') + self.vm.add_args('-drive', f'file={pflash1},format=raw,if=pflash') + self.vm.add_args('-drive', f'file=fat:rw:{virtual},format=raw') + self.vm.add_args('-drive', f'format=raw,if=none,file={drive},id=hd0') + self.vm.add_args('-device', 'virtio-blk-pci,drive=hd0') + self.vm.add_args('-device', 'virtio-9p-pci,fsdev=shr0,mount_tag=shr0') + self.vm.add_args('-fsdev', f'local,security_model=none,path={rme_stack},id=shr0') + self.vm.add_args('-device', 'virtio-net-pci,netdev=net0') + self.vm.add_args('-netdev', 'user,id=net0') + + self.vm.launch() + # Wait for host VM boot to complete. + wait_for_console_pattern(self, 'Welcome to Buildroot', + failure_message='Synchronous Exception at') + exec_command_and_wait_for_pattern(self, 'root', '#') + + test_realms_guest(self) + +if __name__ == '__main__': + QemuSystemTest.main() diff --git a/tests/functional/aarch64/test_rme_virt.py b/tests/functional/aarch64/test_rme_virt.py new file mode 100755 index 0000000..8452d27 --- /dev/null +++ b/tests/functional/aarch64/test_rme_virt.py @@ -0,0 +1,101 @@ +#!/usr/bin/env python3 +# +# Functional test that boots a Realms environment on virt machine and a nested +# guest VM using it. +# +# Copyright (c) 2024 Linaro Ltd. +# +# Author: Pierrick Bouvier +# +# SPDX-License-Identifier: GPL-2.0-or-later + +import os + +from qemu_test import QemuSystemTest, Asset +from qemu_test import exec_command, wait_for_console_pattern +from qemu_test import exec_command_and_wait_for_pattern + +def test_realms_guest(test_rme_instance): + + # Boot the (nested) guest VM + exec_command(test_rme_instance, + 'qemu-system-aarch64 -M virt,gic-version=3 ' + '-cpu host -enable-kvm -m 512M ' + '-M confidential-guest-support=rme0 ' + '-object rme-guest,id=rme0 ' + '-device virtio-net-pci,netdev=net0,romfile= ' + '-netdev user,id=net0 ' + '-kernel /mnt/out/bin/Image ' + '-initrd /mnt/out-br/images/rootfs.cpio ' + '-serial stdio') + # Detect Realm activation during (nested) guest boot. + wait_for_console_pattern(test_rme_instance, + 'SMC_RMI_REALM_ACTIVATE') + # Wait for (nested) guest boot to complete. + wait_for_console_pattern(test_rme_instance, + 'Welcome to Buildroot') + exec_command_and_wait_for_pattern(test_rme_instance, 'root', '#') + # query (nested) guest cca report + exec_command(test_rme_instance, 'cca-workload-attestation report') + wait_for_console_pattern(test_rme_instance, + '"cca-platform-hash-algo-id": "sha-256"') + wait_for_console_pattern(test_rme_instance, + '"cca-realm-hash-algo-id": "sha-512"') + wait_for_console_pattern(test_rme_instance, + '"cca-realm-public-key-hash-algo-id": "sha-256"') + +class Aarch64RMEVirtMachine(QemuSystemTest): + + # Stack is built with OP-TEE build environment from those instructions: + # https://linaro.atlassian.net/wiki/spaces/QEMU/pages/29051027459/ + # https://github.com/pbo-linaro/qemu-rme-stack + ASSET_RME_STACK_VIRT = Asset( + ('https://fileserver.linaro.org/s/iaRsNDJp2CXHMSJ/' + 'download/rme-stack-op-tee-4.2.0-cca-v4-qemu_v8.tar.gz'), + '1851adc232b094384d8b879b9a2cfff07ef3d6205032b85e9b3a4a9ae6b0b7ad') + + # This tests the FEAT_RME cpu implementation, by booting a VM supporting it, + # and launching a nested VM using it. + def test_aarch64_rme_virt(self): + self.set_machine('virt') + self.require_accelerator('tcg') + self.require_netdev('user') + + self.vm.set_console() + + stack_path_tar_gz = self.ASSET_RME_STACK_VIRT.fetch() + self.archive_extract(stack_path_tar_gz, format="tar") + + rme_stack = self.scratch_file('rme-stack-op-tee-4.2.0-cca-v4-qemu_v8') + kernel = os.path.join(rme_stack, 'out', 'bin', 'Image') + bios = os.path.join(rme_stack, 'out', 'bin', 'flash.bin') + drive = os.path.join(rme_stack, 'out-br', 'images', 'rootfs.ext4') + + self.vm.add_args('-cpu', 'max,x-rme=on,pauth-impdef=on') + self.vm.add_args('-m', '2G') + self.vm.add_args('-M', 'virt,acpi=off,' + 'virtualization=on,' + 'secure=on,' + 'gic-version=3') + self.vm.add_args('-bios', bios) + self.vm.add_args('-kernel', kernel) + self.vm.add_args('-drive', f'format=raw,if=none,file={drive},id=hd0') + self.vm.add_args('-device', 'virtio-blk-pci,drive=hd0') + self.vm.add_args('-device', 'virtio-9p-device,fsdev=shr0,mount_tag=shr0') + self.vm.add_args('-fsdev', f'local,security_model=none,path={rme_stack},id=shr0') + self.vm.add_args('-device', 'virtio-net-pci,netdev=net0') + self.vm.add_args('-netdev', 'user,id=net0') + # We need to add nokaslr to avoid triggering this sporadic bug: + # https://gitlab.com/qemu-project/qemu/-/issues/2823 + self.vm.add_args('-append', 'root=/dev/vda nokaslr') + + self.vm.launch() + # Wait for host VM boot to complete. + wait_for_console_pattern(self, 'Welcome to Buildroot', + failure_message='Synchronous Exception at') + exec_command_and_wait_for_pattern(self, 'root', '#') + + test_realms_guest(self) + +if __name__ == '__main__': + QemuSystemTest.main() diff --git a/tests/functional/aarch64/test_sbsaref.py b/tests/functional/aarch64/test_sbsaref.py new file mode 100755 index 0000000..d3402f5 --- /dev/null +++ b/tests/functional/aarch64/test_sbsaref.py @@ -0,0 +1,101 @@ +#!/usr/bin/env python3 +# +# Functional test that boots a kernel and checks the console +# +# Copyright (c) 2023-2024 Linaro Ltd. +# +# Authors: +# Philippe Mathieu-Daudé +# Marcin Juszkiewicz +# +# SPDX-License-Identifier: GPL-2.0-or-later + +from qemu_test import QemuSystemTest, Asset +from qemu_test import wait_for_console_pattern +from qemu_test import interrupt_interactive_console_until_pattern + + +def fetch_firmware(test): + """ + Flash volumes generated using: + + Toolchain from Debian: + aarch64-linux-gnu-gcc (Debian 12.2.0-14) 12.2.0 + + Used components: + + - Trusted Firmware v2.12.0 + - Tianocore EDK2 edk2-stable202411 + - Tianocore EDK2-platforms 4b3530d + + """ + + # Secure BootRom (TF-A code) + fs0_path = test.uncompress(Aarch64SbsarefMachine.ASSET_FLASH0) + + # Non-secure rom (UEFI and EFI variables) + fs1_path = test.uncompress(Aarch64SbsarefMachine.ASSET_FLASH1) + + for path in [fs0_path, fs1_path]: + with open(path, "ab+") as fd: + fd.truncate(256 << 20) # Expand volumes to 256MiB + + test.vm.add_args( + "-drive", f"if=pflash,file={fs0_path},format=raw", + "-drive", f"if=pflash,file={fs1_path},format=raw", + ) + + +class Aarch64SbsarefMachine(QemuSystemTest): + """ + As firmware runs at a higher privilege level than the hypervisor we + can only run these tests under TCG emulation. + """ + + timeout = 180 + + ASSET_FLASH0 = Asset( + ('https://artifacts.codelinaro.org/artifactory/linaro-419-sbsa-ref/' + '20241122-189881/edk2/SBSA_FLASH0.fd.xz'), + '76eb89d42eebe324e4395329f47447cda9ac920aabcf99aca85424609c3384a5') + + ASSET_FLASH1 = Asset( + ('https://artifacts.codelinaro.org/artifactory/linaro-419-sbsa-ref/' + '20241122-189881/edk2/SBSA_FLASH1.fd.xz'), + 'f850f243bd8dbd49c51e061e0f79f1697546938f454aeb59ab7d93e5f0d412fc') + + def test_sbsaref_edk2_firmware(self): + + self.set_machine('sbsa-ref') + + fetch_firmware(self) + + self.vm.set_console() + self.vm.add_args('-cpu', 'cortex-a57') + self.vm.launch() + + # TF-A boot sequence: + # + # https://github.com/ARM-software/arm-trusted-firmware/blob/v2.8.0/\ + # docs/design/trusted-board-boot.rst#trusted-board-boot-sequence + # https://trustedfirmware-a.readthedocs.io/en/v2.8/\ + # design/firmware-design.html#cold-boot + + # AP Trusted ROM + wait_for_console_pattern(self, "Booting Trusted Firmware") + wait_for_console_pattern(self, "BL1: v2.12.0(release):") + wait_for_console_pattern(self, "BL1: Booting BL2") + + # Trusted Boot Firmware + wait_for_console_pattern(self, "BL2: v2.12.0(release)") + wait_for_console_pattern(self, "Booting BL31") + + # EL3 Runtime Software + wait_for_console_pattern(self, "BL31: v2.12.0(release)") + + # Non-trusted Firmware + wait_for_console_pattern(self, "UEFI firmware (version 1.0") + interrupt_interactive_console_until_pattern(self, "QEMU SBSA-REF Machine") + +if __name__ == '__main__': + QemuSystemTest.main() diff --git a/tests/functional/aarch64/test_sbsaref_alpine.py b/tests/functional/aarch64/test_sbsaref_alpine.py new file mode 100755 index 0000000..abb8f51 --- /dev/null +++ b/tests/functional/aarch64/test_sbsaref_alpine.py @@ -0,0 +1,62 @@ +#!/usr/bin/env python3 +# +# Functional test that boots a kernel and checks the console +# +# Copyright (c) 2023-2024 Linaro Ltd. +# +# Authors: +# Philippe Mathieu-Daudé +# Marcin Juszkiewicz +# +# SPDX-License-Identifier: GPL-2.0-or-later + +from qemu_test import QemuSystemTest, Asset, skipSlowTest +from qemu_test import wait_for_console_pattern +from test_sbsaref import fetch_firmware + + +class Aarch64SbsarefAlpine(QemuSystemTest): + + ASSET_ALPINE_ISO = Asset( + ('https://dl-cdn.alpinelinux.org/' + 'alpine/v3.17/releases/aarch64/alpine-standard-3.17.2-aarch64.iso'), + '5a36304ecf039292082d92b48152a9ec21009d3a62f459de623e19c4bd9dc027') + + # This tests the whole boot chain from EFI to Userspace + # We only boot a whole OS for the current top level CPU and GIC + # Other test profiles should use more minimal boots + def boot_alpine_linux(self, cpu=None): + self.set_machine('sbsa-ref') + + fetch_firmware(self) + iso_path = self.ASSET_ALPINE_ISO.fetch() + + self.vm.set_console() + self.vm.add_args( + "-drive", f"file={iso_path},media=cdrom,format=raw", + ) + if cpu: + self.vm.add_args("-cpu", cpu) + + self.vm.launch() + wait_for_console_pattern(self, "Welcome to Alpine Linux 3.17") + + def test_sbsaref_alpine_linux_cortex_a57(self): + self.boot_alpine_linux("cortex-a57") + + def test_sbsaref_alpine_linux_default_cpu(self): + self.boot_alpine_linux() + + def test_sbsaref_alpine_linux_max_pauth_off(self): + self.boot_alpine_linux("max,pauth=off") + + def test_sbsaref_alpine_linux_max_pauth_impdef(self): + self.boot_alpine_linux("max,pauth-impdef=on") + + @skipSlowTest() # Test might timeout due to PAuth emulation + def test_sbsaref_alpine_linux_max(self): + self.boot_alpine_linux("max") + + +if __name__ == '__main__': + QemuSystemTest.main() diff --git a/tests/functional/aarch64/test_sbsaref_freebsd.py b/tests/functional/aarch64/test_sbsaref_freebsd.py new file mode 100755 index 0000000..3b942f7 --- /dev/null +++ b/tests/functional/aarch64/test_sbsaref_freebsd.py @@ -0,0 +1,63 @@ +#!/usr/bin/env python3 +# +# Functional test that boots a kernel and checks the console +# +# Copyright (c) 2023-2024 Linaro Ltd. +# +# Authors: +# Philippe Mathieu-Daudé +# Marcin Juszkiewicz +# +# SPDX-License-Identifier: GPL-2.0-or-later + +from qemu_test import QemuSystemTest, Asset, skipSlowTest +from qemu_test import wait_for_console_pattern +from test_sbsaref import fetch_firmware + + +class Aarch64SbsarefFreeBSD(QemuSystemTest): + + ASSET_FREEBSD_ISO = Asset( + ('http://ftp-archive.freebsd.org/pub/FreeBSD-Archive/old-releases/arm64' + '/aarch64/ISO-IMAGES/14.1/FreeBSD-14.1-RELEASE-arm64-aarch64-bootonly.iso.xz'), + '7313a4495ffd71ab77b49b1e83f571521c32756e1d75bf48bd890e0ab0f75827') + + # This tests the whole boot chain from EFI to Userspace + # We only boot a whole OS for the current top level CPU and GIC + # Other test profiles should use more minimal boots + def boot_freebsd14(self, cpu=None): + self.set_machine('sbsa-ref') + + fetch_firmware(self) + img_path = self.uncompress(self.ASSET_FREEBSD_ISO) + + self.vm.set_console() + self.vm.add_args( + "-drive", f"file={img_path},format=raw,snapshot=on", + ) + if cpu: + self.vm.add_args("-cpu", cpu) + + self.vm.launch() + wait_for_console_pattern(self, 'Welcome to FreeBSD!') + + def test_sbsaref_freebsd14_cortex_a57(self): + self.boot_freebsd14("cortex-a57") + + def test_sbsaref_freebsd14_default_cpu(self): + self.boot_freebsd14() + + def test_sbsaref_freebsd14_max_pauth_off(self): + self.boot_freebsd14("max,pauth=off") + + @skipSlowTest() # Test might timeout due to PAuth emulation + def test_sbsaref_freebsd14_max_pauth_impdef(self): + self.boot_freebsd14("max,pauth-impdef=on") + + @skipSlowTest() # Test might timeout due to PAuth emulation + def test_sbsaref_freebsd14_max(self): + self.boot_freebsd14("max") + + +if __name__ == '__main__': + QemuSystemTest.main() diff --git a/tests/functional/aarch64/test_smmu.py b/tests/functional/aarch64/test_smmu.py new file mode 100755 index 0000000..e0f4a92 --- /dev/null +++ b/tests/functional/aarch64/test_smmu.py @@ -0,0 +1,211 @@ +#!/usr/bin/env python3 +# +# SPDX-License-Identifier: GPL-2.0-or-later +# +# SMMUv3 Functional tests +# +# Copyright (c) 2021 Red Hat, Inc. +# +# Author: +# Eric Auger +# +# This work is licensed under the terms of the GNU GPL, version 2 or +# later. See the COPYING file in the top-level directory. + +import os +import time + +from qemu_test import LinuxKernelTest, Asset, exec_command_and_wait_for_pattern +from qemu_test import BUILD_DIR +from qemu.utils import kvm_available, hvf_available + + +class SMMU(LinuxKernelTest): + + default_kernel_params = ('earlyprintk=pl011,0x9000000 no_timer_check ' + 'printk.time=1 rd_NO_PLYMOUTH net.ifnames=0 ' + 'console=ttyAMA0 rd.rescue') + IOMMU_ADDON = ',iommu_platform=on,disable-modern=off,disable-legacy=on' + kernel_path = None + initrd_path = None + kernel_params = None + + GUEST_PORT = 8080 + + def set_up_boot(self, path): + self.vm.add_args('-device', 'virtio-blk-pci,bus=pcie.0,' + + 'drive=drv0,id=virtio-disk0,bootindex=1,' + 'werror=stop,rerror=stop' + self.IOMMU_ADDON) + self.vm.add_args('-drive', + f'file={path},if=none,cache=writethrough,id=drv0,snapshot=on') + + self.vm.add_args('-netdev', + 'user,id=n1,hostfwd=tcp:127.0.0.1:0-:%d' % + self.GUEST_PORT) + self.vm.add_args('-device', 'virtio-net,netdev=n1' + self.IOMMU_ADDON) + + def common_vm_setup(self, kernel, initrd, disk): + if hvf_available(self.qemu_bin): + accel = "hvf" + elif kvm_available(self.qemu_bin): + accel = "kvm" + else: + self.skipTest("Neither HVF nor KVM accelerator is available") + self.require_accelerator(accel) + self.require_netdev('user') + self.set_machine("virt") + self.vm.add_args('-m', '1G') + self.vm.add_args("-accel", accel) + self.vm.add_args("-cpu", "host") + self.vm.add_args("-machine", "iommu=smmuv3") + self.vm.add_args("-d", "guest_errors") + self.vm.add_args('-bios', os.path.join(BUILD_DIR, 'pc-bios', + 'edk2-aarch64-code.fd')) + self.vm.add_args('-device', 'virtio-rng-pci,rng=rng0') + self.vm.add_args('-object', + 'rng-random,id=rng0,filename=/dev/urandom') + + self.kernel_path = kernel.fetch() + self.initrd_path = initrd.fetch() + self.set_up_boot(disk.fetch()) + + def run_and_check(self, filename, hashsum): + self.vm.add_args('-initrd', self.initrd_path) + self.vm.add_args('-append', self.kernel_params) + self.launch_kernel(self.kernel_path, initrd=self.initrd_path, + wait_for='attach it to a bug report.') + prompt = '# ' + # Fedora 33 requires 'return' to be pressed to enter the shell. + # There seems to be a small race between detecting the previous ':' + # and sending the newline, so we need to add a small delay here. + self.wait_for_console_pattern(':') + time.sleep(0.2) + exec_command_and_wait_for_pattern(self, '\n', prompt) + exec_command_and_wait_for_pattern(self, 'cat /proc/cmdline', + self.kernel_params) + + # Checking for SMMU enablement: + self.log.info("Checking whether SMMU has been enabled...") + exec_command_and_wait_for_pattern(self, 'dmesg | grep smmu', + 'arm-smmu-v3') + self.wait_for_console_pattern(prompt) + exec_command_and_wait_for_pattern(self, + 'find /sys/kernel/iommu_groups/ -type l', + 'devices/0000:00:') + self.wait_for_console_pattern(prompt) + + # Copy a file (checked later), umount afterwards to drop disk cache: + self.log.info("Checking hard disk...") + exec_command_and_wait_for_pattern(self, + "while ! (dmesg -c | grep vda:) ; do sleep 1 ; done", + "vda2") + exec_command_and_wait_for_pattern(self, 'mount /dev/vda2 /sysroot', + 'mounted filesystem') + exec_command_and_wait_for_pattern(self, 'cp /bin/vi /sysroot/root/vi', + prompt) + exec_command_and_wait_for_pattern(self, 'umount /sysroot', prompt) + # Switch from initrd to the cloud image filesystem: + exec_command_and_wait_for_pattern(self, 'mount /dev/vda2 /sysroot', + prompt) + exec_command_and_wait_for_pattern(self, + ('for d in dev proc sys run ; do ' + 'mount -o bind /$d /sysroot/$d ; done'), prompt) + exec_command_and_wait_for_pattern(self, 'chroot /sysroot', prompt) + # Check files on the hard disk: + exec_command_and_wait_for_pattern(self, + ('if diff -q /root/vi /usr/bin/vi ; then echo "file" "ok" ; ' + 'else echo "files differ"; fi'), 'file ok') + self.wait_for_console_pattern(prompt) + exec_command_and_wait_for_pattern(self, f'sha256sum {filename}', + hashsum) + + # Check virtio-net via HTTP: + exec_command_and_wait_for_pattern(self, 'dhclient eth0', prompt) + self.check_http_download(filename, hashsum, self.GUEST_PORT) + + + # 5.3 kernel without RIL # + + ASSET_KERNEL_F31 = Asset( + ('https://archives.fedoraproject.org/pub/archive/fedora/linux/' + 'releases/31/Server/aarch64/os/images/pxeboot/vmlinuz'), + '3ae07fcafbfc8e4abeb693035a74fe10698faae15e9ccd48882a9167800c1527') + + ASSET_INITRD_F31 = Asset( + ('https://archives.fedoraproject.org/pub/archive/fedora/linux/' + 'releases/31/Server/aarch64/os/images/pxeboot/initrd.img'), + '9f3146b28bc531c689f3c5f114cb74e4bd7bd548e0ba19fa77921d8bd256755a') + + ASSET_DISK_F31 = Asset( + ('https://archives.fedoraproject.org/pub/archive/fedora/linux/releases' + '/31/Cloud/aarch64/images/Fedora-Cloud-Base-31-1.9.aarch64.qcow2'), + '1e18d9c0cf734940c4b5d5ec592facaed2af0ad0329383d5639c997fdf16fe49') + + F31_FILENAME = '/boot/initramfs-5.3.7-301.fc31.aarch64.img' + F31_HSUM = '1a4beec6607d94df73d9dd1b4985c9c23dd0fdcf4e6ca1351d477f190df7bef9' + + def test_smmu_noril(self): + self.common_vm_setup(self.ASSET_KERNEL_F31, self.ASSET_INITRD_F31, + self.ASSET_DISK_F31) + self.kernel_params = self.default_kernel_params + self.run_and_check(self.F31_FILENAME, self.F31_HSUM) + + def test_smmu_noril_passthrough(self): + self.common_vm_setup(self.ASSET_KERNEL_F31, self.ASSET_INITRD_F31, + self.ASSET_DISK_F31) + self.kernel_params = (self.default_kernel_params + + ' iommu.passthrough=on') + self.run_and_check(self.F31_FILENAME, self.F31_HSUM) + + def test_smmu_noril_nostrict(self): + self.common_vm_setup(self.ASSET_KERNEL_F31, self.ASSET_INITRD_F31, + self.ASSET_DISK_F31) + self.kernel_params = (self.default_kernel_params + + ' iommu.strict=0') + self.run_and_check(self.F31_FILENAME, self.F31_HSUM) + + + # 5.8 kernel featuring range invalidation + # >= v5.7 kernel + + ASSET_KERNEL_F33 = Asset( + ('https://archives.fedoraproject.org/pub/archive/fedora/linux/' + 'releases/33/Server/aarch64/os/images/pxeboot/vmlinuz'), + 'd8b1e6f7241f339d8e7609c456cf0461ffa4583ed07e0b55c7d1d8a0c154aa89') + + ASSET_INITRD_F33 = Asset( + ('https://archives.fedoraproject.org/pub/archive/fedora/linux/' + 'releases/33/Server/aarch64/os/images/pxeboot/initrd.img'), + '92513f55295c2c16a777f7b6c35ccd70a438e9e1e40b6ba39e0e60900615b3df') + + ASSET_DISK_F33 = Asset( + ('https://archives.fedoraproject.org/pub/archive/fedora/linux/releases' + '/33/Cloud/aarch64/images/Fedora-Cloud-Base-33-1.2.aarch64.qcow2'), + 'e7f75cdfd523fe5ac2ca9eeece68edc1a81f386a17f969c1d1c7c87031008a6b') + + F33_FILENAME = '/boot/initramfs-5.8.15-301.fc33.aarch64.img' + F33_HSUM = '079cfad0caa82e84c8ca1fb0897a4999dd769f262216099f518619e807a550d9' + + def test_smmu_ril(self): + self.common_vm_setup(self.ASSET_KERNEL_F33, self.ASSET_INITRD_F33, + self.ASSET_DISK_F33) + self.kernel_params = self.default_kernel_params + self.run_and_check(self.F33_FILENAME, self.F33_HSUM) + + def test_smmu_ril_passthrough(self): + self.common_vm_setup(self.ASSET_KERNEL_F33, self.ASSET_INITRD_F33, + self.ASSET_DISK_F33) + self.kernel_params = (self.default_kernel_params + + ' iommu.passthrough=on') + self.run_and_check(self.F33_FILENAME, self.F33_HSUM) + + def test_smmu_ril_nostrict(self): + self.common_vm_setup(self.ASSET_KERNEL_F33, self.ASSET_INITRD_F33, + self.ASSET_DISK_F33) + self.kernel_params = (self.default_kernel_params + + ' iommu.strict=0') + self.run_and_check(self.F33_FILENAME, self.F33_HSUM) + + +if __name__ == '__main__': + LinuxKernelTest.main() diff --git a/tests/functional/aarch64/test_tcg_plugins.py b/tests/functional/aarch64/test_tcg_plugins.py new file mode 100755 index 0000000..cb7e929 --- /dev/null +++ b/tests/functional/aarch64/test_tcg_plugins.py @@ -0,0 +1,118 @@ +#!/usr/bin/env python3 +# +# TCG Plugins tests +# +# These are a little more involved than the basic tests run by check-tcg. +# +# Copyright (c) 2021 Linaro +# +# Author: +# Alex Bennée +# +# SPDX-License-Identifier: GPL-2.0-or-later + +import tempfile +import mmap +import re + +from qemu.machine.machine import VMLaunchFailure +from qemu_test import LinuxKernelTest, Asset + + +class PluginKernelBase(LinuxKernelTest): + """ + Boots a Linux kernel with a TCG plugin enabled. + """ + + timeout = 120 + KERNEL_COMMON_COMMAND_LINE = 'printk.time=1 panic=-1 ' + + def run_vm(self, kernel_path, kernel_command_line, + plugin, plugin_log, console_pattern, args=None): + + vm = self.get_vm() + vm.set_console() + vm.add_args('-kernel', kernel_path, + '-append', kernel_command_line, + '-plugin', plugin, + '-d', 'plugin', + '-D', plugin_log, + '-net', 'none', + '-no-reboot') + if args: + vm.add_args(*args) + + try: + vm.launch() + except VMLaunchFailure as excp: + if "plugin interface not enabled in this build" in excp.output: + self.skipTest("TCG plugins not enabled") + else: + self.log.info(f"unhandled launch failure: {excp.output}") + raise excp + + self.wait_for_console_pattern(console_pattern, vm) + # ensure logs are flushed + vm.shutdown() + + +class PluginKernelNormal(PluginKernelBase): + + ASSET_KERNEL = Asset( + ('https://storage.tuxboot.com/20230331/arm64/Image'), + 'ce95a7101a5fecebe0fe630deee6bd97b32ba41bc8754090e9ad8961ea8674c7') + + def test_aarch64_virt_insn(self): + self.set_machine('virt') + self.cpu='cortex-a53' + kernel_path = self.ASSET_KERNEL.fetch() + kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE + + 'console=ttyAMA0') + console_pattern = 'Please append a correct "root=" boot option' + + plugin_log = tempfile.NamedTemporaryFile(mode="r+t", prefix="plugin", + suffix=".log") + + self.run_vm(kernel_path, kernel_command_line, + self.plugin_file('libinsn'), plugin_log.name, + console_pattern) + + with plugin_log as lf, \ + mmap.mmap(lf.fileno(), 0, access=mmap.ACCESS_READ) as s: + + m = re.search(br"insns: (?P\d+)", s) + if "count" not in m.groupdict(): + self.fail("Failed to find instruction count") + else: + count = int(m.group("count")) + self.log.info(f"Counted: {count} instructions") + + + def test_aarch64_virt_insn_icount(self): + self.set_machine('virt') + self.cpu='cortex-a53' + kernel_path = self.ASSET_KERNEL.fetch() + kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE + + 'console=ttyAMA0') + console_pattern = 'Please append a correct "root=" boot option' + + plugin_log = tempfile.NamedTemporaryFile(mode="r+t", prefix="plugin", + suffix=".log") + + self.run_vm(kernel_path, kernel_command_line, + self.plugin_file('libinsn'), plugin_log.name, + console_pattern, + args=('-icount', 'shift=1')) + + with plugin_log as lf, \ + mmap.mmap(lf.fileno(), 0, access=mmap.ACCESS_READ) as s: + + m = re.search(br"insns: (?P\d+)", s) + if "count" not in m.groupdict(): + self.fail("Failed to find instruction count") + else: + count = int(m.group("count")) + self.log.info(f"Counted: {count} instructions") + +if __name__ == '__main__': + LinuxKernelTest.main() diff --git a/tests/functional/aarch64/test_tuxrun.py b/tests/functional/aarch64/test_tuxrun.py new file mode 100755 index 0000000..75adc8a --- /dev/null +++ b/tests/functional/aarch64/test_tuxrun.py @@ -0,0 +1,50 @@ +#!/usr/bin/env python3 +# +# Functional test that boots known good tuxboot images the same way +# that tuxrun (www.tuxrun.org) does. This tool is used by things like +# the LKFT project to run regression tests on kernels. +# +# Copyright (c) 2023 Linaro Ltd. +# +# Author: +# Alex Bennée +# +# SPDX-License-Identifier: GPL-2.0-or-later + +from qemu_test import Asset +from qemu_test.tuxruntest import TuxRunBaselineTest + +class TuxRunAarch64Test(TuxRunBaselineTest): + + ASSET_ARM64_KERNEL = Asset( + 'https://storage.tuxboot.com/buildroot/20241119/arm64/Image', + 'b74743c5e89e1cea0f73368d24ae0ae85c5204ff84be3b5e9610417417d2f235') + ASSET_ARM64_ROOTFS = Asset( + 'https://storage.tuxboot.com/buildroot/20241119/arm64/rootfs.ext4.zst', + 'a1acaaae2068df4648d04ff75f532aaa8c5edcd6b936122b6f0db4848a07b465') + + def test_arm64(self): + self.set_machine('virt') + self.cpu='cortex-a57' + self.console='ttyAMA0' + self.wait_for_shutdown=False + self.common_tuxrun(kernel_asset=self.ASSET_ARM64_KERNEL, + rootfs_asset=self.ASSET_ARM64_ROOTFS) + + ASSET_ARM64BE_KERNEL = Asset( + 'https://storage.tuxboot.com/buildroot/20241119/arm64be/Image', + 'fd6af4f16689d17a2c24fe0053cc212edcdf77abdcaf301800b8d38fa9f6e109') + ASSET_ARM64BE_ROOTFS = Asset( + 'https://storage.tuxboot.com/buildroot/20241119/arm64be/rootfs.ext4.zst', + 'f5e9371b62701aab8dead52592ca7488c8a9e255c9be8d7635c7f30f477c2c21') + + def test_arm64be(self): + self.set_machine('virt') + self.cpu='cortex-a57' + self.console='ttyAMA0' + self.wait_for_shutdown=False + self.common_tuxrun(kernel_asset=self.ASSET_ARM64BE_KERNEL, + rootfs_asset=self.ASSET_ARM64BE_ROOTFS) + +if __name__ == '__main__': + TuxRunBaselineTest.main() diff --git a/tests/functional/aarch64/test_virt.py b/tests/functional/aarch64/test_virt.py new file mode 100755 index 0000000..4d0ad90 --- /dev/null +++ b/tests/functional/aarch64/test_virt.py @@ -0,0 +1,135 @@ +#!/usr/bin/env python3 +# +# Functional test that boots a various Linux systems and checks the +# console output. +# +# Copyright (c) 2022 Linaro Ltd. +# +# Author: +# Alex Bennée +# +# SPDX-License-Identifier: GPL-2.0-or-later + +import logging +from subprocess import check_call, DEVNULL + +from qemu_test import QemuSystemTest, Asset, exec_command_and_wait_for_pattern +from qemu_test import wait_for_console_pattern, get_qemu_img + + +class Aarch64VirtMachine(QemuSystemTest): + KERNEL_COMMON_COMMAND_LINE = 'printk.time=0 ' + timeout = 360 + + def wait_for_console_pattern(self, success_message, vm=None): + wait_for_console_pattern(self, success_message, + failure_message='Kernel panic - not syncing', + vm=vm) + + ASSET_ALPINE_ISO = Asset( + ('https://dl-cdn.alpinelinux.org/' + 'alpine/v3.17/releases/aarch64/alpine-standard-3.17.2-aarch64.iso'), + '5a36304ecf039292082d92b48152a9ec21009d3a62f459de623e19c4bd9dc027') + + # This tests the whole boot chain from EFI to Userspace + # We only boot a whole OS for the current top level CPU and GIC + # Other test profiles should use more minimal boots + def test_alpine_virt_tcg_gic_max(self): + iso_path = self.ASSET_ALPINE_ISO.fetch() + + self.set_machine('virt') + self.require_accelerator("tcg") + + self.vm.set_console() + self.vm.add_args("-accel", "tcg") + self.vm.add_args("-cpu", "max,pauth-impdef=on") + self.vm.add_args("-machine", + "virt,acpi=on," + "virtualization=on," + "mte=on," + "gic-version=max,iommu=smmuv3") + self.vm.add_args("-smp", "2", "-m", "1024") + self.vm.add_args('-bios', self.build_file('pc-bios', + 'edk2-aarch64-code.fd')) + self.vm.add_args("-drive", f"file={iso_path},media=cdrom,format=raw") + self.vm.add_args('-device', 'virtio-rng-pci,rng=rng0') + self.vm.add_args('-object', 'rng-random,id=rng0,filename=/dev/urandom') + + self.vm.launch() + self.wait_for_console_pattern('Welcome to Alpine Linux 3.17') + + + ASSET_KERNEL = Asset( + ('https://fileserver.linaro.org/s/' + 'z6B2ARM7DQT3HWN/download'), + '12a54d4805cda6ab647cb7c7bbdb16fafb3df400e0d6f16445c1a0436100ef8d') + + def common_aarch64_virt(self, machine): + """ + Common code to launch basic virt machine with kernel+initrd + and a scratch disk. + """ + self.set_machine('virt') + self.require_accelerator("tcg") + + logger = logging.getLogger('aarch64_virt') + + kernel_path = self.ASSET_KERNEL.fetch() + + self.vm.set_console() + kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE + + 'console=ttyAMA0') + self.vm.add_args('-cpu', 'max,pauth-impdef=on', + '-machine', machine, + '-accel', 'tcg', + '-kernel', kernel_path, + '-append', kernel_command_line) + + # A RNG offers an easy way to generate a few IRQs + self.vm.add_args('-device', 'virtio-rng-pci,rng=rng0') + self.vm.add_args('-object', + 'rng-random,id=rng0,filename=/dev/urandom') + + # Also add a scratch block device + logger.info('creating scratch qcow2 image') + image_path = self.scratch_file('scratch.qcow2') + qemu_img = get_qemu_img(self) + check_call([qemu_img, 'create', '-f', 'qcow2', image_path, '8M'], + stdout=DEVNULL, stderr=DEVNULL) + + # Add the device + self.vm.add_args('-blockdev', + "driver=qcow2," + "file.driver=file," + f"file.filename={image_path},node-name=scratch") + self.vm.add_args('-device', + 'virtio-blk-device,drive=scratch') + + self.vm.launch() + + ps1='#' + self.wait_for_console_pattern('login:') + + commands = [ + ('root', ps1), + ('cat /proc/interrupts', ps1), + ('cat /proc/self/maps', ps1), + ('uname -a', ps1), + ('dd if=/dev/hwrng of=/dev/vda bs=512 count=4', ps1), + ('md5sum /dev/vda', ps1), + ('halt -n', 'reboot: System halted') + ] + + for cmd, pattern in commands: + exec_command_and_wait_for_pattern(self, cmd, pattern) + + def test_aarch64_virt_gicv3(self): + self.common_aarch64_virt("virt,gic_version=3") + + def test_aarch64_virt_gicv2(self): + self.common_aarch64_virt("virt,gic-version=2") + + + +if __name__ == '__main__': + QemuSystemTest.main() diff --git a/tests/functional/aarch64/test_virt_gpu.py b/tests/functional/aarch64/test_virt_gpu.py new file mode 100755 index 0000000..4e50887 --- /dev/null +++ b/tests/functional/aarch64/test_virt_gpu.py @@ -0,0 +1,142 @@ +#!/usr/bin/env python3 +# +# Functional tests for the various graphics modes we can support. +# +# Copyright (c) 2024, 2025 Linaro Ltd. +# +# Author: +# Alex Bennée +# +# 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 import skipIfMissingCommands + +from qemu_test.linuxkernel import LinuxKernelTest + +from re import search +from subprocess import check_output, CalledProcessError + +class Aarch64VirtGPUMachine(LinuxKernelTest): + + ASSET_VIRT_GPU_KERNEL = Asset( + 'https://fileserver.linaro.org/s/ce5jXBFinPxtEdx/' + 'download?path=%2F&files=' + 'Image.6.12.16.aarch64', + '7888c51c55d37e86bbbdeb5acea9f08c34e6b0f03c1f5b2463285f6a6f6eec8b') + + ASSET_VIRT_GPU_ROOTFS = Asset( + 'https://fileserver.linaro.org/s/ce5jXBFinPxtEdx/' + 'download?path=%2F&files=' + 'rootfs.aarch64.ext2.zstd', + 'd45118c899420b7e673f1539a37a35480134b3e36e3a59e2cb69b1781cbb14ef') + + def _launch_virt_gpu(self, gpu_device): + + self.set_machine('virt') + self.require_accelerator("tcg") + + kernel_path = self.ASSET_VIRT_GPU_KERNEL.fetch() + image_path = self.uncompress(self.ASSET_VIRT_GPU_ROOTFS, format="zstd") + + self.vm.set_console() + kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE + + 'console=ttyAMA0 root=/dev/vda') + + self.vm.add_args("-accel", "tcg") + self.vm.add_args("-cpu", "cortex-a72") + self.vm.add_args("-machine", "virt,gic-version=max", + '-kernel', kernel_path, + '-append', kernel_command_line) + self.vm.add_args("-smp", "2", "-m", "2048") + self.vm.add_args("-device", gpu_device) + self.vm.add_args("-display", "egl-headless") + self.vm.add_args("-display", "dbus,gl=on") + + self.vm.add_args("-device", "virtio-blk-device,drive=hd0") + self.vm.add_args("-blockdev", + "driver=raw,file.driver=file," + "node-name=hd0,read-only=on," + f"file.filename={image_path}") + self.vm.add_args("-snapshot") + + try: + self.vm.launch() + except VMLaunchFailure as excp: + if "old virglrenderer, blob resources unsupported" in excp.output: + self.skipTest("No blob support for virtio-gpu") + elif "old virglrenderer, venus unsupported" in excp.output: + self.skipTest("No venus support for virtio-gpu") + elif "egl: no drm render node available" in excp.output: + self.skipTest("Can't access host DRM render node") + elif "'type' does not accept value 'egl-headless'" in excp.output: + self.skipTest("egl-headless support is not available") + elif "'type' does not accept value 'dbus'" in excp.output: + self.skipTest("dbus display support is not available") + elif "eglInitialize failed: EGL_NOT_INITIALIZED" in excp.output: + self.skipTest("EGL failed to initialize on this host") + else: + self.log.info("unhandled launch failure: %s", excp.output) + raise excp + + self.wait_for_console_pattern('buildroot login:') + ec_and_wait(self, 'root', '#') + + def _run_virt_weston_test(self, cmd, fail = None): + + # make it easier to detect successful return to shell + PS1 = 'RES=[$?] # ' + OK_CMD = 'RES=[0] # ' + + ec_and_wait(self, 'export XDG_RUNTIME_DIR=/tmp', '#') + ec_and_wait(self, f"export PS1='{PS1}'", OK_CMD) + full_cmd = f"weston -B headless --renderer gl --shell kiosk -- {cmd}" + ec_and_wait(self, full_cmd, OK_CMD, fail) + + @skipIfMissingCommands('zstd') + def test_aarch64_virt_with_virgl_gpu(self): + + self.require_device('virtio-gpu-gl-pci') + + self._launch_virt_gpu("virtio-gpu-gl-pci") + + # subset of the glmark tests + tests = " ".join([f"-b {test}" for test in + ["build", "texture", "shading", + "bump", "desktop", "buffer"]]) + + self._run_virt_weston_test("glmark2-wayland --validate " + tests) + + @skipIfMissingCommands('zstd') + def test_aarch64_virt_with_virgl_blobs_gpu(self): + + self.require_device('virtio-gpu-gl-pci') + + self._launch_virt_gpu("virtio-gpu-gl-pci,hostmem=4G,blob=on") + self._run_virt_weston_test("glmark2-wayland -b:duration=1.0") + + @skipIfMissingCommands('zstd') + @skipIfMissingCommands('vulkaninfo') + def test_aarch64_virt_with_vulkan_gpu(self): + + self.require_device('virtio-gpu-gl-pci') + + try: + vk_info = check_output(["vulkaninfo", "--summary"], + encoding="utf-8") + except CalledProcessError as excp: + self.skipTest(f"Miss-configured host Vulkan: {excp.output}") + + if search(r"driverID\s+=\s+DRIVER_ID_NVIDIA_PROPRIETARY", vk_info): + self.skipTest("Test skipped on NVIDIA proprietary driver") + + self._launch_virt_gpu("virtio-gpu-gl-pci,hostmem=4G,blob=on,venus=on") + self._run_virt_weston_test("vkmark -b:duration=1.0", + "debug: stuck in fence wait with iter at") + + +if __name__ == '__main__': + LinuxKernelTest.main() diff --git a/tests/functional/aarch64/test_xen.py b/tests/functional/aarch64/test_xen.py new file mode 100755 index 0000000..261d796 --- /dev/null +++ b/tests/functional/aarch64/test_xen.py @@ -0,0 +1,91 @@ +#!/usr/bin/env python3 +# +# Functional test that boots a Xen hypervisor with a domU kernel and +# checks the console output is vaguely sane . +# +# Copyright (c) 2020 Linaro +# +# Author: +# Alex Bennée +# +# SPDX-License-Identifier: GPL-2.0-or-later +# +# This work is licensed under the terms of the GNU GPL, version 2 or +# later. See the COPYING file in the top-level directory. + +from qemu_test import Asset, LinuxKernelTest, wait_for_console_pattern + + +class BootXen(LinuxKernelTest): + """ + Boots a Xen hypervisor with a Linux DomU kernel. + """ + + timeout = 90 + XEN_COMMON_COMMAND_LINE = 'dom0_mem=128M loglvl=all guest_loglvl=all' + + ASSET_KERNEL = Asset( + ('https://fileserver.linaro.org/s/JSsewXGZ6mqxPr5/' + 'download?path=%2F&files=linux-5.9.9-arm64-ajb'), + '00366fa51ea957c19462d2e2aefd480bef80ce727120e714ae48e0c88f261edb') + + def launch_xen(self, xen_path): + """ + Launch Xen with a dom0 guest kernel + """ + self.require_accelerator("tcg") # virtualization=on + self.set_machine('virt') + self.cpu = "cortex-a57" + self.kernel_path = self.ASSET_KERNEL.fetch() + self.log.info("launch with xen_path: %s", xen_path) + + self.vm.set_console() + + self.vm.add_args('-machine', 'virtualization=on', + '-m', '768', + '-kernel', xen_path, + '-append', self.XEN_COMMON_COMMAND_LINE, + '-device', + 'guest-loader,addr=0x47000000,kernel=%s,bootargs=console=hvc0' + % (self.kernel_path)) + + self.vm.launch() + + console_pattern = 'VFS: Cannot open root device' + wait_for_console_pattern(self, console_pattern, "Panic on CPU 0:") + + ASSET_XEN_4_11 = Asset( + ('https://fileserver.linaro.org/s/JSsewXGZ6mqxPr5/download?path=%2F&' + 'files=xen-hypervisor-4.11-arm64_4.11.4%2B37-g3263f257ca-1_arm64.deb'), + 'b745c2631342f9fcc0147ddc364edb62c20ecfebd430e5a3546e7d7c6891c0bc') + + def test_arm64_xen_411_and_dom0(self): + # archive of file from https://deb.debian.org/debian/pool/main/x/xen/ + xen_path = self.archive_extract(self.ASSET_XEN_4_11, format='deb', + member="boot/xen-4.11-arm64") + self.launch_xen(xen_path) + + ASSET_XEN_4_14 = Asset( + ('https://fileserver.linaro.org/s/JSsewXGZ6mqxPr5/download?path=%2F&' + 'files=xen-hypervisor-4.14-arm64_4.14.0%2B80-gd101b417b7-1_arm64.deb'), + 'e930a3293248edabd367d5b4b3b6448b9c99c057096ea8b47228a7870661d5cb') + + def test_arm64_xen_414_and_dom0(self): + # archive of file from https://deb.debian.org/debian/pool/main/x/xen/ + xen_path = self.archive_extract(self.ASSET_XEN_4_14, format='deb', + member="boot/xen-4.14-arm64") + self.launch_xen(xen_path) + + ASSET_XEN_4_15 = Asset( + ('https://fileserver.linaro.org/s/JSsewXGZ6mqxPr5/download?path=%2F&' + 'files=xen-upstream-4.15-unstable.deb'), + '2a9a8af8acf0231844657cc28baab95bd918b0ee2d493ee4ee6f8846e1358bc9') + + def test_arm64_xen_415_and_dom0(self): + xen_path = self.archive_extract(self.ASSET_XEN_4_15, format='deb', + member="boot/xen-4.15-unstable") + self.launch_xen(xen_path) + + +if __name__ == '__main__': + LinuxKernelTest.main() diff --git a/tests/functional/aarch64/test_xlnx_versal.py b/tests/functional/aarch64/test_xlnx_versal.py new file mode 100755 index 0000000..4b9c49e --- /dev/null +++ b/tests/functional/aarch64/test_xlnx_versal.py @@ -0,0 +1,37 @@ +#!/usr/bin/env python3 +# +# Functional test that boots a Linux kernel and checks the console +# +# SPDX-License-Identifier: GPL-2.0-or-later + +from qemu_test import LinuxKernelTest, Asset + +class XlnxVersalVirtMachine(LinuxKernelTest): + + ASSET_KERNEL = Asset( + ('http://ports.ubuntu.com/ubuntu-ports/dists/bionic-updates/main/' + 'installer-arm64/20101020ubuntu543.19/images/netboot/' + 'ubuntu-installer/arm64/linux'), + 'ce54f74ab0b15cfd13d1a293f2d27ffd79d8a85b7bb9bf21093ae9513864ac79') + + ASSET_INITRD = Asset( + ('http://ports.ubuntu.com/ubuntu-ports/dists/bionic-updates/main/' + 'installer-arm64/20101020ubuntu543.19/images/netboot/' + '/ubuntu-installer/arm64/initrd.gz'), + 'e7a5e716b6f516d8be315c06e7331aaf16994fe4222e0e7cfb34bc015698929e') + + def test_aarch64_xlnx_versal_virt(self): + self.set_machine('xlnx-versal-virt') + kernel_path = self.ASSET_KERNEL.fetch() + initrd_path = self.ASSET_INITRD.fetch() + + self.vm.set_console() + self.vm.add_args('-m', '2G', + '-accel', 'tcg', + '-kernel', kernel_path, + '-initrd', initrd_path) + self.vm.launch() + self.wait_for_console_pattern('Checked W+X mappings: passed') + +if __name__ == '__main__': + LinuxKernelTest.main() diff --git a/tests/functional/meson.build b/tests/functional/meson.build index 8c24ac1..9cb6325 100644 --- a/tests/functional/meson.build +++ b/tests/functional/meson.build @@ -9,23 +9,7 @@ if get_option('tcg_interpreter') subdir_done() endif -# Timeouts for individual tests that can be slow e.g. with debugging enabled -test_aarch64_timeouts = { - 'aarch64_aspeed_ast2700' : 600, - 'aarch64_aspeed_ast2700fc' : 600, - 'aarch64_device_passthrough' : 720, - 'aarch64_imx8mp_evk' : 240, - 'aarch64_raspi4' : 480, - 'aarch64_reverse_debug' : 180, - 'aarch64_rme_virt' : 1200, - 'aarch64_rme_sbsaref' : 1200, - 'aarch64_sbsaref_alpine' : 1200, - 'aarch64_sbsaref_freebsd' : 720, - 'aarch64_smmu' : 720, - 'aarch64_tuxrun' : 240, - 'aarch64_virt' : 360, - 'aarch64_virt_gpu' : 480, -} +subdir('aarch64') test_arm_timeouts = { 'arm_aspeed_palmetto' : 120, @@ -112,36 +96,6 @@ tests_generic_linuxuser = [ tests_generic_bsduser = [ ] -tests_aarch64_system_quick = [ - 'aarch64_migration', -] - -tests_aarch64_system_thorough = [ - 'aarch64_aspeed_ast2700', - 'aarch64_aspeed_ast2700fc', - 'aarch64_device_passthrough', - 'aarch64_hotplug_pci', - 'aarch64_imx8mp_evk', - 'aarch64_kvm', - 'aarch64_multiprocess', - 'aarch64_raspi3', - 'aarch64_raspi4', - 'aarch64_replay', - 'aarch64_reverse_debug', - 'aarch64_rme_virt', - 'aarch64_rme_sbsaref', - 'aarch64_sbsaref', - 'aarch64_sbsaref_alpine', - 'aarch64_sbsaref_freebsd', - 'aarch64_smmu', - 'aarch64_tcg_plugins', - 'aarch64_tuxrun', - 'aarch64_virt', - 'aarch64_virt_gpu', - 'aarch64_xen', - 'aarch64_xlnx_versal', -] - tests_alpha_system_quick = [ 'alpha_migration', ] diff --git a/tests/functional/test_aarch64_aspeed_ast2700.py b/tests/functional/test_aarch64_aspeed_ast2700.py deleted file mode 100755 index d02dc79..0000000 --- a/tests/functional/test_aarch64_aspeed_ast2700.py +++ /dev/null @@ -1,140 +0,0 @@ -#!/usr/bin/env python3 -# -# Functional test that boots the ASPEED SoCs with firmware -# -# Copyright (C) 2022 ASPEED Technology Inc -# -# SPDX-License-Identifier: GPL-2.0-or-later - -import os - -from qemu_test import QemuSystemTest, Asset -from qemu_test import wait_for_console_pattern -from qemu_test import exec_command_and_wait_for_pattern - - -class AST2x00MachineSDK(QemuSystemTest): - - def do_test_aarch64_aspeed_sdk_start(self, image): - self.require_netdev('user') - self.vm.set_console() - self.vm.add_args('-device', - 'tmp105,bus=aspeed.i2c.bus.1,address=0x4d,id=tmp-test') - self.vm.add_args('-drive', 'file=' + image + ',if=mtd,format=raw', - '-net', 'nic', '-net', 'user', '-snapshot') - - self.vm.launch() - - def verify_vbootrom_firmware_flow(self): - wait_for_console_pattern(self, 'Found valid FIT image') - wait_for_console_pattern(self, '[uboot] loading') - wait_for_console_pattern(self, 'done') - wait_for_console_pattern(self, '[fdt] loading') - wait_for_console_pattern(self, 'done') - wait_for_console_pattern(self, '[tee] loading') - wait_for_console_pattern(self, 'done') - wait_for_console_pattern(self, '[atf] loading') - wait_for_console_pattern(self, 'done') - wait_for_console_pattern(self, 'Jumping to BL31 (Trusted Firmware-A)') - - def verify_openbmc_boot_and_login(self, name): - wait_for_console_pattern(self, 'U-Boot 2023.10') - wait_for_console_pattern(self, '## Loading kernel from FIT Image') - wait_for_console_pattern(self, 'Starting kernel ...') - - wait_for_console_pattern(self, f'{name} login:') - exec_command_and_wait_for_pattern(self, 'root', 'Password:') - exec_command_and_wait_for_pattern(self, '0penBmc', f'root@{name}:~#') - - ASSET_SDK_V906_AST2700 = Asset( - 'https://github.com/AspeedTech-BMC/openbmc/releases/download/v09.06/ast2700-a0-default-obmc.tar.gz', - '7247b6f19dbfb700686f8d9f723ac23f3eb229226c0589cb9b06b80d1b61f3cb') - - ASSET_SDK_V906_AST2700A1 = Asset( - 'https://github.com/AspeedTech-BMC/openbmc/releases/download/v09.06/ast2700-default-obmc.tar.gz', - 'f1d53e0be8a404ecce3e105f72bc50fa4e090ad13160ffa91b10a6e0233a9dc6') - - def do_ast2700_i2c_test(self): - exec_command_and_wait_for_pattern(self, - 'echo lm75 0x4d > /sys/class/i2c-dev/i2c-1/device/new_device ', - 'i2c i2c-1: new_device: Instantiated device lm75 at 0x4d') - exec_command_and_wait_for_pattern(self, - 'cat /sys/bus/i2c/devices/1-004d/hwmon/hwmon*/temp1_input', '0') - self.vm.cmd('qom-set', path='/machine/peripheral/tmp-test', - property='temperature', value=18000) - exec_command_and_wait_for_pattern(self, - 'cat /sys/bus/i2c/devices/1-004d/hwmon/hwmon*/temp1_input', '18000') - - def start_ast2700_test(self, name): - num_cpu = 4 - uboot_size = os.path.getsize(self.scratch_file(name, - 'u-boot-nodtb.bin')) - uboot_dtb_load_addr = hex(0x400000000 + uboot_size) - - load_images_list = [ - { - 'addr': '0x400000000', - 'file': self.scratch_file(name, - 'u-boot-nodtb.bin') - }, - { - 'addr': str(uboot_dtb_load_addr), - 'file': self.scratch_file(name, 'u-boot.dtb') - }, - { - 'addr': '0x430000000', - 'file': self.scratch_file(name, 'bl31.bin') - }, - { - 'addr': '0x430080000', - 'file': self.scratch_file(name, 'optee', - 'tee-raw.bin') - } - ] - - for load_image in load_images_list: - addr = load_image['addr'] - file = load_image['file'] - self.vm.add_args('-device', - f'loader,force-raw=on,addr={addr},file={file}') - - for i in range(num_cpu): - self.vm.add_args('-device', - f'loader,addr=0x430000000,cpu-num={i}') - - self.vm.add_args('-smp', str(num_cpu)) - self.do_test_aarch64_aspeed_sdk_start( - self.scratch_file(name, 'image-bmc')) - - def start_ast2700_test_vbootrom(self, name): - self.vm.add_args('-bios', 'ast27x0_bootrom.bin') - self.do_test_aarch64_aspeed_sdk_start( - self.scratch_file(name, 'image-bmc')) - - def test_aarch64_ast2700_evb_sdk_v09_06(self): - self.set_machine('ast2700-evb') - - self.archive_extract(self.ASSET_SDK_V906_AST2700) - self.start_ast2700_test('ast2700-a0-default') - self.verify_openbmc_boot_and_login('ast2700-a0-default') - self.do_ast2700_i2c_test() - - def test_aarch64_ast2700a1_evb_sdk_v09_06(self): - self.set_machine('ast2700a1-evb') - - self.archive_extract(self.ASSET_SDK_V906_AST2700A1) - self.start_ast2700_test('ast2700-default') - self.verify_openbmc_boot_and_login('ast2700-default') - self.do_ast2700_i2c_test() - - def test_aarch64_ast2700a1_evb_sdk_vbootrom_v09_06(self): - self.set_machine('ast2700a1-evb') - - self.archive_extract(self.ASSET_SDK_V906_AST2700A1) - self.start_ast2700_test_vbootrom('ast2700-default') - self.verify_vbootrom_firmware_flow() - self.verify_openbmc_boot_and_login('ast2700-default') - self.do_ast2700_i2c_test() - -if __name__ == '__main__': - QemuSystemTest.main() diff --git a/tests/functional/test_aarch64_aspeed_ast2700fc.py b/tests/functional/test_aarch64_aspeed_ast2700fc.py deleted file mode 100755 index b85370e..0000000 --- a/tests/functional/test_aarch64_aspeed_ast2700fc.py +++ /dev/null @@ -1,135 +0,0 @@ -#!/usr/bin/env python3 -# -# Functional test that boots the ASPEED SoCs with firmware -# -# Copyright (C) 2022 ASPEED Technology Inc -# -# SPDX-License-Identifier: GPL-2.0-or-later - -import os - -from qemu_test import QemuSystemTest, Asset -from qemu_test import wait_for_console_pattern -from qemu_test import exec_command_and_wait_for_pattern - - -class AST2x00MachineSDK(QemuSystemTest): - - def do_test_aarch64_aspeed_sdk_start(self, image): - self.require_netdev('user') - self.vm.set_console() - self.vm.add_args('-device', - 'tmp105,bus=aspeed.i2c.bus.1,address=0x4d,id=tmp-test') - self.vm.add_args('-drive', 'file=' + image + ',if=mtd,format=raw', - '-net', 'nic', '-net', 'user', '-snapshot') - - self.vm.launch() - - def verify_openbmc_boot_and_login(self, name): - wait_for_console_pattern(self, 'U-Boot 2023.10') - wait_for_console_pattern(self, '## Loading kernel from FIT Image') - wait_for_console_pattern(self, 'Starting kernel ...') - - wait_for_console_pattern(self, f'{name} login:') - exec_command_and_wait_for_pattern(self, 'root', 'Password:') - exec_command_and_wait_for_pattern(self, '0penBmc', f'root@{name}:~#') - - ASSET_SDK_V906_AST2700 = Asset( - 'https://github.com/AspeedTech-BMC/openbmc/releases/download/v09.06/ast2700-default-obmc.tar.gz', - 'f1d53e0be8a404ecce3e105f72bc50fa4e090ad13160ffa91b10a6e0233a9dc6') - - def do_ast2700_i2c_test(self): - exec_command_and_wait_for_pattern(self, - 'echo lm75 0x4d > /sys/class/i2c-dev/i2c-1/device/new_device ', - 'i2c i2c-1: new_device: Instantiated device lm75 at 0x4d') - exec_command_and_wait_for_pattern(self, - 'cat /sys/bus/i2c/devices/1-004d/hwmon/hwmon*/temp1_input', '0') - self.vm.cmd('qom-set', path='/machine/peripheral/tmp-test', - property='temperature', value=18000) - exec_command_and_wait_for_pattern(self, - 'cat /sys/bus/i2c/devices/1-004d/hwmon/hwmon*/temp1_input', '18000') - - def do_ast2700fc_ssp_test(self): - self.vm.shutdown() - self.vm.set_console(console_index=1) - self.vm.launch() - - exec_command_and_wait_for_pattern(self, '\012', 'ssp:~$') - exec_command_and_wait_for_pattern(self, 'version', - 'Zephyr version 3.7.1') - exec_command_and_wait_for_pattern(self, 'md 72c02000 1', - '[72c02000] 06010103') - - def do_ast2700fc_tsp_test(self): - self.vm.shutdown() - self.vm.set_console(console_index=2) - self.vm.launch() - - exec_command_and_wait_for_pattern(self, '\012', 'tsp:~$') - exec_command_and_wait_for_pattern(self, 'version', - 'Zephyr version 3.7.1') - exec_command_and_wait_for_pattern(self, 'md 72c02000 1', - '[72c02000] 06010103') - - def start_ast2700fc_test(self, name): - ca35_core = 4 - uboot_size = os.path.getsize(self.scratch_file(name, - 'u-boot-nodtb.bin')) - uboot_dtb_load_addr = hex(0x400000000 + uboot_size) - - load_images_list = [ - { - 'addr': '0x400000000', - 'file': self.scratch_file(name, - 'u-boot-nodtb.bin') - }, - { - 'addr': str(uboot_dtb_load_addr), - 'file': self.scratch_file(name, 'u-boot.dtb') - }, - { - 'addr': '0x430000000', - 'file': self.scratch_file(name, 'bl31.bin') - }, - { - 'addr': '0x430080000', - 'file': self.scratch_file(name, 'optee', - 'tee-raw.bin') - } - ] - - for load_image in load_images_list: - addr = load_image['addr'] - file = load_image['file'] - self.vm.add_args('-device', - f'loader,force-raw=on,addr={addr},file={file}') - - for i in range(ca35_core): - self.vm.add_args('-device', - f'loader,addr=0x430000000,cpu-num={i}') - - load_elf_list = { - 'ssp': self.scratch_file(name, 'zephyr-aspeed-ssp.elf'), - 'tsp': self.scratch_file(name, 'zephyr-aspeed-tsp.elf') - } - - for cpu_num, key in enumerate(load_elf_list, start=4): - file = load_elf_list[key] - self.vm.add_args('-device', - f'loader,file={file},cpu-num={cpu_num}') - - self.do_test_aarch64_aspeed_sdk_start( - self.scratch_file(name, 'image-bmc')) - - def test_aarch64_ast2700fc_sdk_v09_06(self): - self.set_machine('ast2700fc') - - self.archive_extract(self.ASSET_SDK_V906_AST2700) - self.start_ast2700fc_test('ast2700-default') - self.verify_openbmc_boot_and_login('ast2700-default') - self.do_ast2700_i2c_test() - self.do_ast2700fc_ssp_test() - self.do_ast2700fc_tsp_test() - -if __name__ == '__main__': - QemuSystemTest.main() diff --git a/tests/functional/test_aarch64_device_passthrough.py b/tests/functional/test_aarch64_device_passthrough.py deleted file mode 100755 index 1f3f158..0000000 --- a/tests/functional/test_aarch64_device_passthrough.py +++ /dev/null @@ -1,142 +0,0 @@ -#!/usr/bin/env python3 -# -# Boots a nested guest and compare content of a device (passthrough) to a -# reference image. Both vfio group and iommufd passthrough methods are tested. -# -# Copyright (c) 2025 Linaro Ltd. -# -# Author: Pierrick Bouvier -# -# SPDX-License-Identifier: GPL-2.0-or-later - -import os - -from qemu_test import QemuSystemTest, Asset -from qemu_test import exec_command, wait_for_console_pattern -from qemu_test import exec_command_and_wait_for_pattern -from random import randbytes - -guest_script = ''' -#!/usr/bin/env bash - -set -euo pipefail -set -x - -# find disks from nvme serial -dev_vfio=$(lsblk --nvme | grep vfio | cut -f 1 -d ' ') -dev_iommufd=$(lsblk --nvme | grep iommufd | cut -f 1 -d ' ') -pci_vfio=$(basename $(readlink -f /sys/block/$dev_vfio/../../../)) -pci_iommufd=$(basename $(readlink -f /sys/block/$dev_iommufd/../../../)) - -# bind disks to vfio -for p in "$pci_vfio" "$pci_iommufd"; do - if [ "$(cat /sys/bus/pci/devices/$p/driver_override)" == vfio-pci ]; then - continue - fi - echo $p > /sys/bus/pci/drivers/nvme/unbind - echo vfio-pci > /sys/bus/pci/devices/$p/driver_override - echo $p > /sys/bus/pci/drivers/vfio-pci/bind -done - -# boot nested guest and execute /host/nested_guest.sh -# one disk is passed through vfio group, the other, through iommufd -qemu-system-aarch64 \ --M virt \ --display none \ --serial stdio \ --cpu host \ --enable-kvm \ --m 1G \ --kernel /host/Image.gz \ --drive format=raw,file=/host/guest.ext4,if=virtio \ --append "root=/dev/vda init=/init -- bash /host/nested_guest.sh" \ --virtfs local,path=/host,mount_tag=host,security_model=mapped,readonly=off \ --device vfio-pci,host=$pci_vfio \ --object iommufd,id=iommufd0 \ --device vfio-pci,host=$pci_iommufd,iommufd=iommufd0 -''' - -nested_guest_script = ''' -#!/usr/bin/env bash - -set -euo pipefail -set -x - -image_vfio=/host/disk_vfio -image_iommufd=/host/disk_iommufd - -dev_vfio=$(lsblk --nvme | grep vfio | cut -f 1 -d ' ') -dev_iommufd=$(lsblk --nvme | grep iommufd | cut -f 1 -d ' ') - -# compare if devices are identical to original images -diff $image_vfio /dev/$dev_vfio -diff $image_iommufd /dev/$dev_iommufd - -echo device_passthrough_test_ok -''' - -class Aarch64DevicePassthrough(QemuSystemTest): - - # https://github.com/pbo-linaro/qemu-linux-stack - # - # Linux kernel is compiled with defconfig + - # IOMMUFD + VFIO_DEVICE_CDEV + ARM_SMMU_V3_IOMMUFD - # https://docs.kernel.org/driver-api/vfio.html#vfio-device-cde - ASSET_DEVICE_PASSTHROUGH_STACK = Asset( - ('https://fileserver.linaro.org/s/fx5DXxBYme8dw2G/' - 'download/device_passthrough.tar.xz'), - '812750b664d61c2986f2b149939ae28cafbd60d53e9c7e4b16e97143845e196d') - - # This tests the device passthrough implementation, by booting a VM - # supporting it with two nvme disks attached, and launching a nested VM - # reading their content. - def test_aarch64_device_passthrough(self): - self.set_machine('virt') - self.require_accelerator('tcg') - - self.vm.set_console() - - stack_path_tar_gz = self.ASSET_DEVICE_PASSTHROUGH_STACK.fetch() - self.archive_extract(stack_path_tar_gz, format="tar") - - stack = self.scratch_file('out') - kernel = os.path.join(stack, 'Image.gz') - rootfs_host = os.path.join(stack, 'host.ext4') - disk_vfio = os.path.join(stack, 'disk_vfio') - disk_iommufd = os.path.join(stack, 'disk_iommufd') - guest_cmd = os.path.join(stack, 'guest.sh') - nested_guest_cmd = os.path.join(stack, 'nested_guest.sh') - # we generate two random disks - with open(disk_vfio, "wb") as d: d.write(randbytes(512)) - with open(disk_iommufd, "wb") as d: d.write(randbytes(1024)) - with open(guest_cmd, 'w') as s: s.write(guest_script) - with open(nested_guest_cmd, 'w') as s: s.write(nested_guest_script) - - self.vm.add_args('-cpu', 'max') - self.vm.add_args('-m', '2G') - self.vm.add_args('-M', 'virt,' - 'virtualization=on,' - 'gic-version=max,' - 'iommu=smmuv3') - self.vm.add_args('-kernel', kernel) - self.vm.add_args('-drive', f'format=raw,file={rootfs_host}') - self.vm.add_args('-drive', - f'file={disk_vfio},if=none,id=vfio,format=raw') - self.vm.add_args('-device', 'nvme,serial=vfio,drive=vfio') - self.vm.add_args('-drive', - f'file={disk_iommufd},if=none,id=iommufd,format=raw') - self.vm.add_args('-device', 'nvme,serial=iommufd,drive=iommufd') - self.vm.add_args('-virtfs', - f'local,path={stack}/,mount_tag=host,' - 'security_model=mapped,readonly=off') - # boot and execute guest script - # init will trigger a kernel panic if script fails - self.vm.add_args('-append', - 'root=/dev/vda init=/init -- bash /host/guest.sh') - - self.vm.launch() - wait_for_console_pattern(self, 'device_passthrough_test_ok', - failure_message='Kernel panic') - -if __name__ == '__main__': - QemuSystemTest.main() diff --git a/tests/functional/test_aarch64_hotplug_pci.py b/tests/functional/test_aarch64_hotplug_pci.py deleted file mode 100755 index 0c67991..0000000 --- a/tests/functional/test_aarch64_hotplug_pci.py +++ /dev/null @@ -1,72 +0,0 @@ -#!/usr/bin/env python3 -# -# The test hotplugs a PCI device and checks it on a Linux guest. -# -# Copyright (c) 2025 Linaro Ltd. -# -# Author: -# Gustavo Romero -# -# SPDX-License-Identifier: GPL-2.0-or-later - -from qemu_test import LinuxKernelTest, Asset, exec_command_and_wait_for_pattern -from qemu_test import BUILD_DIR - -class HotplugPCI(LinuxKernelTest): - - ASSET_KERNEL = Asset( - ('https://ftp.debian.org/debian/dists/bookworm/main/installer-arm64/' - '20230607+deb12u11/images/netboot/debian-installer/arm64/linux'), - 'd92a60392ce1e379ca198a1a820899f8f0d39a62d047c41ab79492f81541a9d9') - - ASSET_INITRD = Asset( - ('https://ftp.debian.org/debian/dists/bookworm/main/installer-arm64/' - '20230607+deb12u11/images/netboot/debian-installer/arm64/initrd.gz'), - '9f817f76951f3237bca8216bee35267bfb826815687f4b2fcdd5e6c2a917790c') - - def test_hotplug_pci(self): - - self.set_machine('virt') - - self.vm.add_args('-m', '512M', - '-cpu', 'cortex-a57', - '-append', - 'console=ttyAMA0,115200 init=/bin/sh', - '-device', - 'pcie-root-port,bus=pcie.0,chassis=1,slot=1,id=pcie.1', - '-bios', - self.build_file('pc-bios', 'edk2-aarch64-code.fd')) - - # BusyBox prompt - prompt = "~ #" - self.launch_kernel(self.ASSET_KERNEL.fetch(), - self.ASSET_INITRD.fetch(), - wait_for=prompt) - - # Check for initial state: 2 network adapters, lo and enp0s1. - exec_command_and_wait_for_pattern(self, - 'ls /sys/class/net | wc -l', - '2') - - # Hotplug one network adapter to the root port, i.e. pcie.1 bus. - self.vm.cmd('device_add', - driver='virtio-net-pci', - bus='pcie.1', - addr=0, - id='na') - # Wait for the kernel to recognize the new device. - self.wait_for_console_pattern('virtio-pci') - self.wait_for_console_pattern('virtio_net') - - # Check if there is a new network adapter. - exec_command_and_wait_for_pattern(self, - 'ls /sys/class/net | wc -l', - '3') - - self.vm.cmd('device_del', id='na') - exec_command_and_wait_for_pattern(self, - 'ls /sys/class/net | wc -l', - '2') - -if __name__ == '__main__': - LinuxKernelTest.main() diff --git a/tests/functional/test_aarch64_imx8mp_evk.py b/tests/functional/test_aarch64_imx8mp_evk.py deleted file mode 100755 index 99ddcde..0000000 --- a/tests/functional/test_aarch64_imx8mp_evk.py +++ /dev/null @@ -1,68 +0,0 @@ -#!/usr/bin/env python3 -# -# Functional test that boots a Linux kernel and checks the console -# -# SPDX-License-Identifier: GPL-2.0-or-later - -from qemu_test import LinuxKernelTest, Asset - - -class Imx8mpEvkMachine(LinuxKernelTest): - - ASSET_IMAGE = Asset( - ('https://cloud.debian.org/images/cloud/bookworm/20231210-1590/' - 'debian-12-generic-arm64-20231210-1590.tar.xz'), - '7ebf1577b32d5af6204df74b54ca2e4675de9b5a9fa14f3ff70b88eeb7b3b359') - - KERNEL_OFFSET = 0x51000000 - KERNEL_SIZE = 32622528 - INITRD_OFFSET = 0x76000000 - INITRD_SIZE = 30987766 - DTB_OFFSET = 0x64F51000 - DTB_SIZE = 45 * 1024 - - def extract(self, in_path, out_path, offset, size): - try: - with open(in_path, "rb") as source: - source.seek(offset) - data = source.read(size) - with open(out_path, "wb") as target: - target.write(data) - except (IOError, ValueError) as e: - self.log.error(f"Failed to extract {out_path}: {e}") - raise - - def setUp(self): - super().setUp() - - self.image_path = self.scratch_file("disk.raw") - self.kernel_path = self.scratch_file("linux") - self.initrd_path = self.scratch_file("initrd.zstd") - self.dtb_path = self.scratch_file("imx8mp-evk.dtb") - - self.archive_extract(self.ASSET_IMAGE) - self.extract(self.image_path, self.kernel_path, - self.KERNEL_OFFSET, self.KERNEL_SIZE) - self.extract(self.image_path, self.initrd_path, - self.INITRD_OFFSET, self.INITRD_SIZE) - self.extract(self.image_path, self.dtb_path, - self.DTB_OFFSET, self.DTB_SIZE) - - def test_aarch64_imx8mp_evk_usdhc(self): - self.require_accelerator("tcg") - self.set_machine('imx8mp-evk') - self.vm.set_console(console_index=1) - self.vm.add_args('-m', '2G', - '-smp', '4', - '-kernel', self.kernel_path, - '-initrd', self.initrd_path, - '-dtb', self.dtb_path, - '-append', 'root=/dev/mmcblk2p1', - '-drive', f'file={self.image_path},if=sd,bus=2,' - 'format=raw,id=mmcblk2,snapshot=on') - - self.vm.launch() - self.wait_for_console_pattern('Welcome to ') - -if __name__ == '__main__': - LinuxKernelTest.main() diff --git a/tests/functional/test_aarch64_kvm.py b/tests/functional/test_aarch64_kvm.py deleted file mode 100755 index 9fb9286..0000000 --- a/tests/functional/test_aarch64_kvm.py +++ /dev/null @@ -1,71 +0,0 @@ -#!/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 -# -# SPDX-License-Identifier: GPL-2.0-or-later - -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") - - self.vm.launch() - - self.wait_for_console_pattern('buildroot login:') - ec_and_wait(self, 'root', '#') - ec_and_wait(self, f"export PS1='{self.PS1}'", self.OK_CMD) - - # this is just a smoketest, we don't run all the tests in the image - def _smoketest_kvm(self): - 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_nvhe_selftest(self): - self._launch_guest("nvhe") - self._smoketest_kvm() - - def test_aarch64_vhe_selftest(self): - self._launch_guest("vhe") - self._smoketest_kvm() - -if __name__ == '__main__': - LinuxKernelTest.main() diff --git a/tests/functional/test_aarch64_migration.py b/tests/functional/test_aarch64_migration.py deleted file mode 100755 index 70267e7..0000000 --- a/tests/functional/test_aarch64_migration.py +++ /dev/null @@ -1,26 +0,0 @@ -#!/usr/bin/env python3 -# -# SPDX-License-Identifier: GPL-2.0-or-later -# -# aarch64 migration test - -from migration import MigrationTest - - -class Aarch64MigrationTest(MigrationTest): - - def test_migration_with_tcp_localhost(self): - self.set_machine('quanta-gsj') - self.migration_with_tcp_localhost() - - def test_migration_with_unix(self): - self.set_machine('quanta-gsj') - self.migration_with_unix() - - def test_migration_with_exec(self): - self.set_machine('quanta-gsj') - self.migration_with_exec() - - -if __name__ == '__main__': - MigrationTest.main() diff --git a/tests/functional/test_aarch64_multiprocess.py b/tests/functional/test_aarch64_multiprocess.py deleted file mode 100755 index 1c6e45e..0000000 --- a/tests/functional/test_aarch64_multiprocess.py +++ /dev/null @@ -1,31 +0,0 @@ -#!/usr/bin/env python3 -# -# SPDX-License-Identifier: GPL-2.0-or-later -# -# Test for multiprocess qemu on aarch64 - -from multiprocess import Multiprocess -from qemu_test import Asset - - -class Aarch64Multiprocess(Multiprocess): - - ASSET_KERNEL_AARCH64 = Asset( - ('https://archives.fedoraproject.org/pub/archive/fedora/linux' - '/releases/31/Everything/aarch64/os/images/pxeboot/vmlinuz'), - '3ae07fcafbfc8e4abeb693035a74fe10698faae15e9ccd48882a9167800c1527') - - ASSET_INITRD_AARCH64 = Asset( - ('https://archives.fedoraproject.org/pub/archive/fedora/linux' - '/releases/31/Everything/aarch64/os/images/pxeboot/initrd.img'), - '9fd230cab10b1dafea41cf00150e6669d37051fad133bd618d2130284e16d526') - - def test_multiprocess(self): - kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE + - 'rdinit=/bin/bash console=ttyAMA0') - self.do_test(self.ASSET_KERNEL_AARCH64, self.ASSET_INITRD_AARCH64, - kernel_command_line, 'virt,gic-version=3') - - -if __name__ == '__main__': - Multiprocess.main() diff --git a/tests/functional/test_aarch64_raspi3.py b/tests/functional/test_aarch64_raspi3.py deleted file mode 100755 index 74f6630..0000000 --- a/tests/functional/test_aarch64_raspi3.py +++ /dev/null @@ -1,34 +0,0 @@ -#!/usr/bin/env python3 -# -# Functional test that boots a Linux kernel on a Raspberry Pi machine -# and checks the console -# -# Copyright (c) 2020 Philippe Mathieu-Daudé -# -# SPDX-License-Identifier: GPL-2.0-or-later - -from qemu_test import LinuxKernelTest, Asset - - -class Aarch64Raspi3Machine(LinuxKernelTest): - - ASSET_RPI3_UEFI = Asset( - ('https://github.com/pbatard/RPi3/releases/download/' - 'v1.15/RPi3_UEFI_Firmware_v1.15.zip'), - '8cff2e979560048b4c84921f41a91893240b9fb71a88f0b5c5d6c8edd994bd5b') - - def test_aarch64_raspi3_atf(self): - efi_name = 'RPI_EFI.fd' - efi_fd = self.archive_extract(self.ASSET_RPI3_UEFI, member=efi_name) - - self.set_machine('raspi3b') - self.vm.set_console(console_index=1) - self.vm.add_args('-cpu', 'cortex-a53', - '-nodefaults', - '-device', f'loader,file={efi_fd},force-raw=true') - self.vm.launch() - self.wait_for_console_pattern('version UEFI Firmware v1.15') - - -if __name__ == '__main__': - LinuxKernelTest.main() diff --git a/tests/functional/test_aarch64_raspi4.py b/tests/functional/test_aarch64_raspi4.py deleted file mode 100755 index 7a4302b..0000000 --- a/tests/functional/test_aarch64_raspi4.py +++ /dev/null @@ -1,96 +0,0 @@ -#!/usr/bin/env python3 -# -# Functional test that boots a Linux kernel on a Raspberry Pi machine -# and checks the console -# -# SPDX-License-Identifier: GPL-2.0-or-later - -from qemu_test import LinuxKernelTest, Asset -from qemu_test import exec_command_and_wait_for_pattern - - -class Aarch64Raspi4Machine(LinuxKernelTest): - - """ - The kernel can be rebuilt using the kernel source referenced - and following the instructions on the on: - https://www.raspberrypi.org/documentation/linux/kernel/building.md - """ - ASSET_KERNEL_20190215 = Asset( - ('http://archive.raspberrypi.org/debian/' - 'pool/main/r/raspberrypi-firmware/' - 'raspberrypi-kernel_1.20230106-1_arm64.deb'), - '56d5713c8f6eee8a0d3f0e73600ec11391144fef318b08943e9abd94c0a9baf7') - - ASSET_INITRD = Asset( - ('https://github.com/groeck/linux-build-test/raw/' - '86b2be1384d41c8c388e63078a847f1e1c4cb1de/rootfs/' - 'arm64/rootfs.cpio.gz'), - '7c0b16d1853772f6f4c3ca63e789b3b9ff4936efac9c8a01fb0c98c05c7a7648') - - def test_arm_raspi4(self): - kernel_path = self.archive_extract(self.ASSET_KERNEL_20190215, - member='boot/kernel8.img') - dtb_path = self.archive_extract(self.ASSET_KERNEL_20190215, - member='boot/bcm2711-rpi-4-b.dtb') - - self.set_machine('raspi4b') - self.vm.set_console() - kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE + - 'earlycon=pl011,mmio32,0xfe201000 ' + - 'console=ttyAMA0,115200 ' + - 'root=/dev/mmcblk1p2 rootwait ' + - 'dwc_otg.fiq_fsm_enable=0') - self.vm.add_args('-kernel', kernel_path, - '-dtb', dtb_path, - '-append', kernel_command_line) - # When PCI is supported we can add a USB controller: - # '-device', 'qemu-xhci,bus=pcie.1,id=xhci', - # '-device', 'usb-kbd,bus=xhci.0', - self.vm.launch() - console_pattern = 'Kernel command line: %s' % kernel_command_line - self.wait_for_console_pattern(console_pattern) - # When USB is enabled we can look for this - # console_pattern = 'Product: QEMU USB Keyboard' - # self.wait_for_console_pattern(console_pattern) - console_pattern = 'Waiting for root device' - self.wait_for_console_pattern(console_pattern) - - - def test_arm_raspi4_initrd(self): - kernel_path = self.archive_extract(self.ASSET_KERNEL_20190215, - member='boot/kernel8.img') - dtb_path = self.archive_extract(self.ASSET_KERNEL_20190215, - member='boot/bcm2711-rpi-4-b.dtb') - initrd_path = self.uncompress(self.ASSET_INITRD) - - self.set_machine('raspi4b') - self.vm.set_console() - kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE + - 'earlycon=pl011,mmio32,0xfe201000 ' + - 'console=ttyAMA0,115200 ' + - 'panic=-1 noreboot ' + - 'dwc_otg.fiq_fsm_enable=0') - self.vm.add_args('-kernel', kernel_path, - '-dtb', dtb_path, - '-initrd', initrd_path, - '-append', kernel_command_line, - '-no-reboot') - # When PCI is supported we can add a USB controller: - # '-device', 'qemu-xhci,bus=pcie.1,id=xhci', - # '-device', 'usb-kbd,bus=xhci.0', - self.vm.launch() - self.wait_for_console_pattern('Boot successful.') - - exec_command_and_wait_for_pattern(self, 'cat /proc/cpuinfo', - 'BCM2835') - exec_command_and_wait_for_pattern(self, 'cat /proc/iomem', - 'cprman@7e101000') - exec_command_and_wait_for_pattern(self, 'halt', 'reboot: System halted') - # TODO: Raspberry Pi4 doesn't shut down properly with recent kernels - # Wait for VM to shut down gracefully - #self.vm.wait() - - -if __name__ == '__main__': - LinuxKernelTest.main() diff --git a/tests/functional/test_aarch64_replay.py b/tests/functional/test_aarch64_replay.py deleted file mode 100755 index db12e76..0000000 --- a/tests/functional/test_aarch64_replay.py +++ /dev/null @@ -1,51 +0,0 @@ -#!/usr/bin/env python3 -# -# Replay test that boots a Linux kernel on an aarch64 machine -# and checks the console -# -# SPDX-License-Identifier: GPL-2.0-or-later - -from subprocess import check_call, DEVNULL - -from qemu_test import Asset, skipIfOperatingSystem, get_qemu_img -from replay_kernel import ReplayKernelBase - - -class Aarch64Replay(ReplayKernelBase): - - ASSET_KERNEL = Asset( - 'https://storage.tuxboot.com/buildroot/20241119/arm64/Image', - 'b74743c5e89e1cea0f73368d24ae0ae85c5204ff84be3b5e9610417417d2f235') - - ASSET_ROOTFS = Asset( - 'https://storage.tuxboot.com/buildroot/20241119/arm64/rootfs.ext4.zst', - 'a1acaaae2068df4648d04ff75f532aaa8c5edcd6b936122b6f0db4848a07b465') - - def test_aarch64_virt(self): - self.require_netdev('user') - self.set_machine('virt') - self.cpu = 'cortex-a57' - kernel_path = self.ASSET_KERNEL.fetch() - - raw_disk = self.uncompress(self.ASSET_ROOTFS) - disk = self.scratch_file('scratch.qcow2') - qemu_img = get_qemu_img(self) - check_call([qemu_img, 'create', '-f', 'qcow2', '-b', raw_disk, - '-F', 'raw', disk], stdout=DEVNULL, stderr=DEVNULL) - - args = ('-drive', 'file=%s,snapshot=on,id=hd0,if=none' % disk, - '-drive', 'driver=blkreplay,id=hd0-rr,if=none,image=hd0', - '-device', 'virtio-blk-device,drive=hd0-rr', - '-netdev', 'user,id=vnet,hostfwd=:127.0.0.1:0-:22', - '-device', 'virtio-net,netdev=vnet', - '-object', 'filter-replay,id=replay,netdev=vnet') - - kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE + - 'console=ttyAMA0 root=/dev/vda') - console_pattern = 'Welcome to TuxTest' - self.run_rr(kernel_path, kernel_command_line, console_pattern, - args=args) - - -if __name__ == '__main__': - ReplayKernelBase.main() diff --git a/tests/functional/test_aarch64_reverse_debug.py b/tests/functional/test_aarch64_reverse_debug.py deleted file mode 100755 index 8bc91cc..0000000 --- a/tests/functional/test_aarch64_reverse_debug.py +++ /dev/null @@ -1,38 +0,0 @@ -#!/usr/bin/env python3 -# -# SPDX-License-Identifier: GPL-2.0-or-later -# -# Reverse debugging test -# -# Copyright (c) 2020 ISP RAS -# -# Author: -# Pavel Dovgalyuk -# -# This work is licensed under the terms of the GNU GPL, version 2 or -# later. See the COPYING file in the top-level directory. - -from qemu_test import Asset, skipIfMissingImports, skipFlakyTest -from reverse_debugging import ReverseDebugging - - -@skipIfMissingImports('avocado.utils') -class ReverseDebugging_AArch64(ReverseDebugging): - - REG_PC = 32 - - ASSET_KERNEL = Asset( - ('https://archives.fedoraproject.org/pub/archive/fedora/linux/' - 'releases/29/Everything/aarch64/os/images/pxeboot/vmlinuz'), - '7e1430b81c26bdd0da025eeb8fbd77b5dc961da4364af26e771bd39f379cbbf7') - - @skipFlakyTest("https://gitlab.com/qemu-project/qemu/-/issues/2921") - def test_aarch64_virt(self): - self.set_machine('virt') - self.cpu = 'cortex-a53' - kernel_path = self.ASSET_KERNEL.fetch() - self.reverse_debugging(args=('-kernel', kernel_path)) - - -if __name__ == '__main__': - ReverseDebugging.main() diff --git a/tests/functional/test_aarch64_rme_sbsaref.py b/tests/functional/test_aarch64_rme_sbsaref.py deleted file mode 100755 index 746770e..0000000 --- a/tests/functional/test_aarch64_rme_sbsaref.py +++ /dev/null @@ -1,69 +0,0 @@ -#!/usr/bin/env python3 -# -# Functional test that boots a Realms environment on sbsa-ref machine and a -# nested guest VM using it. -# -# Copyright (c) 2024 Linaro Ltd. -# -# Author: Pierrick Bouvier -# -# SPDX-License-Identifier: GPL-2.0-or-later - -import os - -from qemu_test import QemuSystemTest, Asset, wait_for_console_pattern -from qemu_test import exec_command_and_wait_for_pattern -from test_aarch64_rme_virt import test_realms_guest - - -class Aarch64RMESbsaRefMachine(QemuSystemTest): - - # Stack is built with OP-TEE build environment from those instructions: - # https://linaro.atlassian.net/wiki/spaces/QEMU/pages/29051027459/ - # https://github.com/pbo-linaro/qemu-rme-stack - ASSET_RME_STACK_SBSA = Asset( - ('https://fileserver.linaro.org/s/KJyeBxL82mz2r7F/' - 'download/rme-stack-op-tee-4.2.0-cca-v4-sbsa.tar.gz'), - 'dd9ab28ec869bdf3b5376116cb3689103b43433fd5c4bca0f4a8d8b3c104999e') - - # This tests the FEAT_RME cpu implementation, by booting a VM supporting it, - # and launching a nested VM using it. - def test_aarch64_rme_sbsaref(self): - self.set_machine('sbsa-ref') - self.require_accelerator('tcg') - self.require_netdev('user') - - self.vm.set_console() - - stack_path_tar_gz = self.ASSET_RME_STACK_SBSA.fetch() - self.archive_extract(stack_path_tar_gz, format="tar") - - rme_stack = self.scratch_file('rme-stack-op-tee-4.2.0-cca-v4-sbsa') - pflash0 = os.path.join(rme_stack, 'images', 'SBSA_FLASH0.fd') - pflash1 = os.path.join(rme_stack, 'images', 'SBSA_FLASH1.fd') - virtual = os.path.join(rme_stack, 'images', 'disks', 'virtual') - drive = os.path.join(rme_stack, 'out-br', 'images', 'rootfs.ext4') - - self.vm.add_args('-cpu', 'max,x-rme=on,pauth-impdef=on') - self.vm.add_args('-m', '2G') - self.vm.add_args('-M', 'sbsa-ref') - self.vm.add_args('-drive', f'file={pflash0},format=raw,if=pflash') - self.vm.add_args('-drive', f'file={pflash1},format=raw,if=pflash') - self.vm.add_args('-drive', f'file=fat:rw:{virtual},format=raw') - self.vm.add_args('-drive', f'format=raw,if=none,file={drive},id=hd0') - self.vm.add_args('-device', 'virtio-blk-pci,drive=hd0') - self.vm.add_args('-device', 'virtio-9p-pci,fsdev=shr0,mount_tag=shr0') - self.vm.add_args('-fsdev', f'local,security_model=none,path={rme_stack},id=shr0') - self.vm.add_args('-device', 'virtio-net-pci,netdev=net0') - self.vm.add_args('-netdev', 'user,id=net0') - - self.vm.launch() - # Wait for host VM boot to complete. - wait_for_console_pattern(self, 'Welcome to Buildroot', - failure_message='Synchronous Exception at') - exec_command_and_wait_for_pattern(self, 'root', '#') - - test_realms_guest(self) - -if __name__ == '__main__': - QemuSystemTest.main() diff --git a/tests/functional/test_aarch64_rme_virt.py b/tests/functional/test_aarch64_rme_virt.py deleted file mode 100755 index 8452d27..0000000 --- a/tests/functional/test_aarch64_rme_virt.py +++ /dev/null @@ -1,101 +0,0 @@ -#!/usr/bin/env python3 -# -# Functional test that boots a Realms environment on virt machine and a nested -# guest VM using it. -# -# Copyright (c) 2024 Linaro Ltd. -# -# Author: Pierrick Bouvier -# -# SPDX-License-Identifier: GPL-2.0-or-later - -import os - -from qemu_test import QemuSystemTest, Asset -from qemu_test import exec_command, wait_for_console_pattern -from qemu_test import exec_command_and_wait_for_pattern - -def test_realms_guest(test_rme_instance): - - # Boot the (nested) guest VM - exec_command(test_rme_instance, - 'qemu-system-aarch64 -M virt,gic-version=3 ' - '-cpu host -enable-kvm -m 512M ' - '-M confidential-guest-support=rme0 ' - '-object rme-guest,id=rme0 ' - '-device virtio-net-pci,netdev=net0,romfile= ' - '-netdev user,id=net0 ' - '-kernel /mnt/out/bin/Image ' - '-initrd /mnt/out-br/images/rootfs.cpio ' - '-serial stdio') - # Detect Realm activation during (nested) guest boot. - wait_for_console_pattern(test_rme_instance, - 'SMC_RMI_REALM_ACTIVATE') - # Wait for (nested) guest boot to complete. - wait_for_console_pattern(test_rme_instance, - 'Welcome to Buildroot') - exec_command_and_wait_for_pattern(test_rme_instance, 'root', '#') - # query (nested) guest cca report - exec_command(test_rme_instance, 'cca-workload-attestation report') - wait_for_console_pattern(test_rme_instance, - '"cca-platform-hash-algo-id": "sha-256"') - wait_for_console_pattern(test_rme_instance, - '"cca-realm-hash-algo-id": "sha-512"') - wait_for_console_pattern(test_rme_instance, - '"cca-realm-public-key-hash-algo-id": "sha-256"') - -class Aarch64RMEVirtMachine(QemuSystemTest): - - # Stack is built with OP-TEE build environment from those instructions: - # https://linaro.atlassian.net/wiki/spaces/QEMU/pages/29051027459/ - # https://github.com/pbo-linaro/qemu-rme-stack - ASSET_RME_STACK_VIRT = Asset( - ('https://fileserver.linaro.org/s/iaRsNDJp2CXHMSJ/' - 'download/rme-stack-op-tee-4.2.0-cca-v4-qemu_v8.tar.gz'), - '1851adc232b094384d8b879b9a2cfff07ef3d6205032b85e9b3a4a9ae6b0b7ad') - - # This tests the FEAT_RME cpu implementation, by booting a VM supporting it, - # and launching a nested VM using it. - def test_aarch64_rme_virt(self): - self.set_machine('virt') - self.require_accelerator('tcg') - self.require_netdev('user') - - self.vm.set_console() - - stack_path_tar_gz = self.ASSET_RME_STACK_VIRT.fetch() - self.archive_extract(stack_path_tar_gz, format="tar") - - rme_stack = self.scratch_file('rme-stack-op-tee-4.2.0-cca-v4-qemu_v8') - kernel = os.path.join(rme_stack, 'out', 'bin', 'Image') - bios = os.path.join(rme_stack, 'out', 'bin', 'flash.bin') - drive = os.path.join(rme_stack, 'out-br', 'images', 'rootfs.ext4') - - self.vm.add_args('-cpu', 'max,x-rme=on,pauth-impdef=on') - self.vm.add_args('-m', '2G') - self.vm.add_args('-M', 'virt,acpi=off,' - 'virtualization=on,' - 'secure=on,' - 'gic-version=3') - self.vm.add_args('-bios', bios) - self.vm.add_args('-kernel', kernel) - self.vm.add_args('-drive', f'format=raw,if=none,file={drive},id=hd0') - self.vm.add_args('-device', 'virtio-blk-pci,drive=hd0') - self.vm.add_args('-device', 'virtio-9p-device,fsdev=shr0,mount_tag=shr0') - self.vm.add_args('-fsdev', f'local,security_model=none,path={rme_stack},id=shr0') - self.vm.add_args('-device', 'virtio-net-pci,netdev=net0') - self.vm.add_args('-netdev', 'user,id=net0') - # We need to add nokaslr to avoid triggering this sporadic bug: - # https://gitlab.com/qemu-project/qemu/-/issues/2823 - self.vm.add_args('-append', 'root=/dev/vda nokaslr') - - self.vm.launch() - # Wait for host VM boot to complete. - wait_for_console_pattern(self, 'Welcome to Buildroot', - failure_message='Synchronous Exception at') - exec_command_and_wait_for_pattern(self, 'root', '#') - - test_realms_guest(self) - -if __name__ == '__main__': - QemuSystemTest.main() diff --git a/tests/functional/test_aarch64_sbsaref.py b/tests/functional/test_aarch64_sbsaref.py deleted file mode 100755 index d3402f5..0000000 --- a/tests/functional/test_aarch64_sbsaref.py +++ /dev/null @@ -1,101 +0,0 @@ -#!/usr/bin/env python3 -# -# Functional test that boots a kernel and checks the console -# -# Copyright (c) 2023-2024 Linaro Ltd. -# -# Authors: -# Philippe Mathieu-Daudé -# Marcin Juszkiewicz -# -# SPDX-License-Identifier: GPL-2.0-or-later - -from qemu_test import QemuSystemTest, Asset -from qemu_test import wait_for_console_pattern -from qemu_test import interrupt_interactive_console_until_pattern - - -def fetch_firmware(test): - """ - Flash volumes generated using: - - Toolchain from Debian: - aarch64-linux-gnu-gcc (Debian 12.2.0-14) 12.2.0 - - Used components: - - - Trusted Firmware v2.12.0 - - Tianocore EDK2 edk2-stable202411 - - Tianocore EDK2-platforms 4b3530d - - """ - - # Secure BootRom (TF-A code) - fs0_path = test.uncompress(Aarch64SbsarefMachine.ASSET_FLASH0) - - # Non-secure rom (UEFI and EFI variables) - fs1_path = test.uncompress(Aarch64SbsarefMachine.ASSET_FLASH1) - - for path in [fs0_path, fs1_path]: - with open(path, "ab+") as fd: - fd.truncate(256 << 20) # Expand volumes to 256MiB - - test.vm.add_args( - "-drive", f"if=pflash,file={fs0_path},format=raw", - "-drive", f"if=pflash,file={fs1_path},format=raw", - ) - - -class Aarch64SbsarefMachine(QemuSystemTest): - """ - As firmware runs at a higher privilege level than the hypervisor we - can only run these tests under TCG emulation. - """ - - timeout = 180 - - ASSET_FLASH0 = Asset( - ('https://artifacts.codelinaro.org/artifactory/linaro-419-sbsa-ref/' - '20241122-189881/edk2/SBSA_FLASH0.fd.xz'), - '76eb89d42eebe324e4395329f47447cda9ac920aabcf99aca85424609c3384a5') - - ASSET_FLASH1 = Asset( - ('https://artifacts.codelinaro.org/artifactory/linaro-419-sbsa-ref/' - '20241122-189881/edk2/SBSA_FLASH1.fd.xz'), - 'f850f243bd8dbd49c51e061e0f79f1697546938f454aeb59ab7d93e5f0d412fc') - - def test_sbsaref_edk2_firmware(self): - - self.set_machine('sbsa-ref') - - fetch_firmware(self) - - self.vm.set_console() - self.vm.add_args('-cpu', 'cortex-a57') - self.vm.launch() - - # TF-A boot sequence: - # - # https://github.com/ARM-software/arm-trusted-firmware/blob/v2.8.0/\ - # docs/design/trusted-board-boot.rst#trusted-board-boot-sequence - # https://trustedfirmware-a.readthedocs.io/en/v2.8/\ - # design/firmware-design.html#cold-boot - - # AP Trusted ROM - wait_for_console_pattern(self, "Booting Trusted Firmware") - wait_for_console_pattern(self, "BL1: v2.12.0(release):") - wait_for_console_pattern(self, "BL1: Booting BL2") - - # Trusted Boot Firmware - wait_for_console_pattern(self, "BL2: v2.12.0(release)") - wait_for_console_pattern(self, "Booting BL31") - - # EL3 Runtime Software - wait_for_console_pattern(self, "BL31: v2.12.0(release)") - - # Non-trusted Firmware - wait_for_console_pattern(self, "UEFI firmware (version 1.0") - interrupt_interactive_console_until_pattern(self, "QEMU SBSA-REF Machine") - -if __name__ == '__main__': - QemuSystemTest.main() diff --git a/tests/functional/test_aarch64_sbsaref_alpine.py b/tests/functional/test_aarch64_sbsaref_alpine.py deleted file mode 100755 index 8776999..0000000 --- a/tests/functional/test_aarch64_sbsaref_alpine.py +++ /dev/null @@ -1,62 +0,0 @@ -#!/usr/bin/env python3 -# -# Functional test that boots a kernel and checks the console -# -# Copyright (c) 2023-2024 Linaro Ltd. -# -# Authors: -# Philippe Mathieu-Daudé -# Marcin Juszkiewicz -# -# SPDX-License-Identifier: GPL-2.0-or-later - -from qemu_test import QemuSystemTest, Asset, skipSlowTest -from qemu_test import wait_for_console_pattern -from test_aarch64_sbsaref import fetch_firmware - - -class Aarch64SbsarefAlpine(QemuSystemTest): - - ASSET_ALPINE_ISO = Asset( - ('https://dl-cdn.alpinelinux.org/' - 'alpine/v3.17/releases/aarch64/alpine-standard-3.17.2-aarch64.iso'), - '5a36304ecf039292082d92b48152a9ec21009d3a62f459de623e19c4bd9dc027') - - # This tests the whole boot chain from EFI to Userspace - # We only boot a whole OS for the current top level CPU and GIC - # Other test profiles should use more minimal boots - def boot_alpine_linux(self, cpu=None): - self.set_machine('sbsa-ref') - - fetch_firmware(self) - iso_path = self.ASSET_ALPINE_ISO.fetch() - - self.vm.set_console() - self.vm.add_args( - "-drive", f"file={iso_path},media=cdrom,format=raw", - ) - if cpu: - self.vm.add_args("-cpu", cpu) - - self.vm.launch() - wait_for_console_pattern(self, "Welcome to Alpine Linux 3.17") - - def test_sbsaref_alpine_linux_cortex_a57(self): - self.boot_alpine_linux("cortex-a57") - - def test_sbsaref_alpine_linux_default_cpu(self): - self.boot_alpine_linux() - - def test_sbsaref_alpine_linux_max_pauth_off(self): - self.boot_alpine_linux("max,pauth=off") - - def test_sbsaref_alpine_linux_max_pauth_impdef(self): - self.boot_alpine_linux("max,pauth-impdef=on") - - @skipSlowTest() # Test might timeout due to PAuth emulation - def test_sbsaref_alpine_linux_max(self): - self.boot_alpine_linux("max") - - -if __name__ == '__main__': - QemuSystemTest.main() diff --git a/tests/functional/test_aarch64_sbsaref_freebsd.py b/tests/functional/test_aarch64_sbsaref_freebsd.py deleted file mode 100755 index 7ef016f..0000000 --- a/tests/functional/test_aarch64_sbsaref_freebsd.py +++ /dev/null @@ -1,63 +0,0 @@ -#!/usr/bin/env python3 -# -# Functional test that boots a kernel and checks the console -# -# Copyright (c) 2023-2024 Linaro Ltd. -# -# Authors: -# Philippe Mathieu-Daudé -# Marcin Juszkiewicz -# -# SPDX-License-Identifier: GPL-2.0-or-later - -from qemu_test import QemuSystemTest, Asset, skipSlowTest -from qemu_test import wait_for_console_pattern -from test_aarch64_sbsaref import fetch_firmware - - -class Aarch64SbsarefFreeBSD(QemuSystemTest): - - ASSET_FREEBSD_ISO = Asset( - ('http://ftp-archive.freebsd.org/pub/FreeBSD-Archive/old-releases/arm64' - '/aarch64/ISO-IMAGES/14.1/FreeBSD-14.1-RELEASE-arm64-aarch64-bootonly.iso.xz'), - '7313a4495ffd71ab77b49b1e83f571521c32756e1d75bf48bd890e0ab0f75827') - - # This tests the whole boot chain from EFI to Userspace - # We only boot a whole OS for the current top level CPU and GIC - # Other test profiles should use more minimal boots - def boot_freebsd14(self, cpu=None): - self.set_machine('sbsa-ref') - - fetch_firmware(self) - img_path = self.uncompress(self.ASSET_FREEBSD_ISO) - - self.vm.set_console() - self.vm.add_args( - "-drive", f"file={img_path},format=raw,snapshot=on", - ) - if cpu: - self.vm.add_args("-cpu", cpu) - - self.vm.launch() - wait_for_console_pattern(self, 'Welcome to FreeBSD!') - - def test_sbsaref_freebsd14_cortex_a57(self): - self.boot_freebsd14("cortex-a57") - - def test_sbsaref_freebsd14_default_cpu(self): - self.boot_freebsd14() - - def test_sbsaref_freebsd14_max_pauth_off(self): - self.boot_freebsd14("max,pauth=off") - - @skipSlowTest() # Test might timeout due to PAuth emulation - def test_sbsaref_freebsd14_max_pauth_impdef(self): - self.boot_freebsd14("max,pauth-impdef=on") - - @skipSlowTest() # Test might timeout due to PAuth emulation - def test_sbsaref_freebsd14_max(self): - self.boot_freebsd14("max") - - -if __name__ == '__main__': - QemuSystemTest.main() diff --git a/tests/functional/test_aarch64_smmu.py b/tests/functional/test_aarch64_smmu.py deleted file mode 100755 index e0f4a92..0000000 --- a/tests/functional/test_aarch64_smmu.py +++ /dev/null @@ -1,211 +0,0 @@ -#!/usr/bin/env python3 -# -# SPDX-License-Identifier: GPL-2.0-or-later -# -# SMMUv3 Functional tests -# -# Copyright (c) 2021 Red Hat, Inc. -# -# Author: -# Eric Auger -# -# This work is licensed under the terms of the GNU GPL, version 2 or -# later. See the COPYING file in the top-level directory. - -import os -import time - -from qemu_test import LinuxKernelTest, Asset, exec_command_and_wait_for_pattern -from qemu_test import BUILD_DIR -from qemu.utils import kvm_available, hvf_available - - -class SMMU(LinuxKernelTest): - - default_kernel_params = ('earlyprintk=pl011,0x9000000 no_timer_check ' - 'printk.time=1 rd_NO_PLYMOUTH net.ifnames=0 ' - 'console=ttyAMA0 rd.rescue') - IOMMU_ADDON = ',iommu_platform=on,disable-modern=off,disable-legacy=on' - kernel_path = None - initrd_path = None - kernel_params = None - - GUEST_PORT = 8080 - - def set_up_boot(self, path): - self.vm.add_args('-device', 'virtio-blk-pci,bus=pcie.0,' + - 'drive=drv0,id=virtio-disk0,bootindex=1,' - 'werror=stop,rerror=stop' + self.IOMMU_ADDON) - self.vm.add_args('-drive', - f'file={path},if=none,cache=writethrough,id=drv0,snapshot=on') - - self.vm.add_args('-netdev', - 'user,id=n1,hostfwd=tcp:127.0.0.1:0-:%d' % - self.GUEST_PORT) - self.vm.add_args('-device', 'virtio-net,netdev=n1' + self.IOMMU_ADDON) - - def common_vm_setup(self, kernel, initrd, disk): - if hvf_available(self.qemu_bin): - accel = "hvf" - elif kvm_available(self.qemu_bin): - accel = "kvm" - else: - self.skipTest("Neither HVF nor KVM accelerator is available") - self.require_accelerator(accel) - self.require_netdev('user') - self.set_machine("virt") - self.vm.add_args('-m', '1G') - self.vm.add_args("-accel", accel) - self.vm.add_args("-cpu", "host") - self.vm.add_args("-machine", "iommu=smmuv3") - self.vm.add_args("-d", "guest_errors") - self.vm.add_args('-bios', os.path.join(BUILD_DIR, 'pc-bios', - 'edk2-aarch64-code.fd')) - self.vm.add_args('-device', 'virtio-rng-pci,rng=rng0') - self.vm.add_args('-object', - 'rng-random,id=rng0,filename=/dev/urandom') - - self.kernel_path = kernel.fetch() - self.initrd_path = initrd.fetch() - self.set_up_boot(disk.fetch()) - - def run_and_check(self, filename, hashsum): - self.vm.add_args('-initrd', self.initrd_path) - self.vm.add_args('-append', self.kernel_params) - self.launch_kernel(self.kernel_path, initrd=self.initrd_path, - wait_for='attach it to a bug report.') - prompt = '# ' - # Fedora 33 requires 'return' to be pressed to enter the shell. - # There seems to be a small race between detecting the previous ':' - # and sending the newline, so we need to add a small delay here. - self.wait_for_console_pattern(':') - time.sleep(0.2) - exec_command_and_wait_for_pattern(self, '\n', prompt) - exec_command_and_wait_for_pattern(self, 'cat /proc/cmdline', - self.kernel_params) - - # Checking for SMMU enablement: - self.log.info("Checking whether SMMU has been enabled...") - exec_command_and_wait_for_pattern(self, 'dmesg | grep smmu', - 'arm-smmu-v3') - self.wait_for_console_pattern(prompt) - exec_command_and_wait_for_pattern(self, - 'find /sys/kernel/iommu_groups/ -type l', - 'devices/0000:00:') - self.wait_for_console_pattern(prompt) - - # Copy a file (checked later), umount afterwards to drop disk cache: - self.log.info("Checking hard disk...") - exec_command_and_wait_for_pattern(self, - "while ! (dmesg -c | grep vda:) ; do sleep 1 ; done", - "vda2") - exec_command_and_wait_for_pattern(self, 'mount /dev/vda2 /sysroot', - 'mounted filesystem') - exec_command_and_wait_for_pattern(self, 'cp /bin/vi /sysroot/root/vi', - prompt) - exec_command_and_wait_for_pattern(self, 'umount /sysroot', prompt) - # Switch from initrd to the cloud image filesystem: - exec_command_and_wait_for_pattern(self, 'mount /dev/vda2 /sysroot', - prompt) - exec_command_and_wait_for_pattern(self, - ('for d in dev proc sys run ; do ' - 'mount -o bind /$d /sysroot/$d ; done'), prompt) - exec_command_and_wait_for_pattern(self, 'chroot /sysroot', prompt) - # Check files on the hard disk: - exec_command_and_wait_for_pattern(self, - ('if diff -q /root/vi /usr/bin/vi ; then echo "file" "ok" ; ' - 'else echo "files differ"; fi'), 'file ok') - self.wait_for_console_pattern(prompt) - exec_command_and_wait_for_pattern(self, f'sha256sum {filename}', - hashsum) - - # Check virtio-net via HTTP: - exec_command_and_wait_for_pattern(self, 'dhclient eth0', prompt) - self.check_http_download(filename, hashsum, self.GUEST_PORT) - - - # 5.3 kernel without RIL # - - ASSET_KERNEL_F31 = Asset( - ('https://archives.fedoraproject.org/pub/archive/fedora/linux/' - 'releases/31/Server/aarch64/os/images/pxeboot/vmlinuz'), - '3ae07fcafbfc8e4abeb693035a74fe10698faae15e9ccd48882a9167800c1527') - - ASSET_INITRD_F31 = Asset( - ('https://archives.fedoraproject.org/pub/archive/fedora/linux/' - 'releases/31/Server/aarch64/os/images/pxeboot/initrd.img'), - '9f3146b28bc531c689f3c5f114cb74e4bd7bd548e0ba19fa77921d8bd256755a') - - ASSET_DISK_F31 = Asset( - ('https://archives.fedoraproject.org/pub/archive/fedora/linux/releases' - '/31/Cloud/aarch64/images/Fedora-Cloud-Base-31-1.9.aarch64.qcow2'), - '1e18d9c0cf734940c4b5d5ec592facaed2af0ad0329383d5639c997fdf16fe49') - - F31_FILENAME = '/boot/initramfs-5.3.7-301.fc31.aarch64.img' - F31_HSUM = '1a4beec6607d94df73d9dd1b4985c9c23dd0fdcf4e6ca1351d477f190df7bef9' - - def test_smmu_noril(self): - self.common_vm_setup(self.ASSET_KERNEL_F31, self.ASSET_INITRD_F31, - self.ASSET_DISK_F31) - self.kernel_params = self.default_kernel_params - self.run_and_check(self.F31_FILENAME, self.F31_HSUM) - - def test_smmu_noril_passthrough(self): - self.common_vm_setup(self.ASSET_KERNEL_F31, self.ASSET_INITRD_F31, - self.ASSET_DISK_F31) - self.kernel_params = (self.default_kernel_params + - ' iommu.passthrough=on') - self.run_and_check(self.F31_FILENAME, self.F31_HSUM) - - def test_smmu_noril_nostrict(self): - self.common_vm_setup(self.ASSET_KERNEL_F31, self.ASSET_INITRD_F31, - self.ASSET_DISK_F31) - self.kernel_params = (self.default_kernel_params + - ' iommu.strict=0') - self.run_and_check(self.F31_FILENAME, self.F31_HSUM) - - - # 5.8 kernel featuring range invalidation - # >= v5.7 kernel - - ASSET_KERNEL_F33 = Asset( - ('https://archives.fedoraproject.org/pub/archive/fedora/linux/' - 'releases/33/Server/aarch64/os/images/pxeboot/vmlinuz'), - 'd8b1e6f7241f339d8e7609c456cf0461ffa4583ed07e0b55c7d1d8a0c154aa89') - - ASSET_INITRD_F33 = Asset( - ('https://archives.fedoraproject.org/pub/archive/fedora/linux/' - 'releases/33/Server/aarch64/os/images/pxeboot/initrd.img'), - '92513f55295c2c16a777f7b6c35ccd70a438e9e1e40b6ba39e0e60900615b3df') - - ASSET_DISK_F33 = Asset( - ('https://archives.fedoraproject.org/pub/archive/fedora/linux/releases' - '/33/Cloud/aarch64/images/Fedora-Cloud-Base-33-1.2.aarch64.qcow2'), - 'e7f75cdfd523fe5ac2ca9eeece68edc1a81f386a17f969c1d1c7c87031008a6b') - - F33_FILENAME = '/boot/initramfs-5.8.15-301.fc33.aarch64.img' - F33_HSUM = '079cfad0caa82e84c8ca1fb0897a4999dd769f262216099f518619e807a550d9' - - def test_smmu_ril(self): - self.common_vm_setup(self.ASSET_KERNEL_F33, self.ASSET_INITRD_F33, - self.ASSET_DISK_F33) - self.kernel_params = self.default_kernel_params - self.run_and_check(self.F33_FILENAME, self.F33_HSUM) - - def test_smmu_ril_passthrough(self): - self.common_vm_setup(self.ASSET_KERNEL_F33, self.ASSET_INITRD_F33, - self.ASSET_DISK_F33) - self.kernel_params = (self.default_kernel_params + - ' iommu.passthrough=on') - self.run_and_check(self.F33_FILENAME, self.F33_HSUM) - - def test_smmu_ril_nostrict(self): - self.common_vm_setup(self.ASSET_KERNEL_F33, self.ASSET_INITRD_F33, - self.ASSET_DISK_F33) - self.kernel_params = (self.default_kernel_params + - ' iommu.strict=0') - self.run_and_check(self.F33_FILENAME, self.F33_HSUM) - - -if __name__ == '__main__': - LinuxKernelTest.main() diff --git a/tests/functional/test_aarch64_tcg_plugins.py b/tests/functional/test_aarch64_tcg_plugins.py deleted file mode 100755 index cb7e929..0000000 --- a/tests/functional/test_aarch64_tcg_plugins.py +++ /dev/null @@ -1,118 +0,0 @@ -#!/usr/bin/env python3 -# -# TCG Plugins tests -# -# These are a little more involved than the basic tests run by check-tcg. -# -# Copyright (c) 2021 Linaro -# -# Author: -# Alex Bennée -# -# SPDX-License-Identifier: GPL-2.0-or-later - -import tempfile -import mmap -import re - -from qemu.machine.machine import VMLaunchFailure -from qemu_test import LinuxKernelTest, Asset - - -class PluginKernelBase(LinuxKernelTest): - """ - Boots a Linux kernel with a TCG plugin enabled. - """ - - timeout = 120 - KERNEL_COMMON_COMMAND_LINE = 'printk.time=1 panic=-1 ' - - def run_vm(self, kernel_path, kernel_command_line, - plugin, plugin_log, console_pattern, args=None): - - vm = self.get_vm() - vm.set_console() - vm.add_args('-kernel', kernel_path, - '-append', kernel_command_line, - '-plugin', plugin, - '-d', 'plugin', - '-D', plugin_log, - '-net', 'none', - '-no-reboot') - if args: - vm.add_args(*args) - - try: - vm.launch() - except VMLaunchFailure as excp: - if "plugin interface not enabled in this build" in excp.output: - self.skipTest("TCG plugins not enabled") - else: - self.log.info(f"unhandled launch failure: {excp.output}") - raise excp - - self.wait_for_console_pattern(console_pattern, vm) - # ensure logs are flushed - vm.shutdown() - - -class PluginKernelNormal(PluginKernelBase): - - ASSET_KERNEL = Asset( - ('https://storage.tuxboot.com/20230331/arm64/Image'), - 'ce95a7101a5fecebe0fe630deee6bd97b32ba41bc8754090e9ad8961ea8674c7') - - def test_aarch64_virt_insn(self): - self.set_machine('virt') - self.cpu='cortex-a53' - kernel_path = self.ASSET_KERNEL.fetch() - kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE + - 'console=ttyAMA0') - console_pattern = 'Please append a correct "root=" boot option' - - plugin_log = tempfile.NamedTemporaryFile(mode="r+t", prefix="plugin", - suffix=".log") - - self.run_vm(kernel_path, kernel_command_line, - self.plugin_file('libinsn'), plugin_log.name, - console_pattern) - - with plugin_log as lf, \ - mmap.mmap(lf.fileno(), 0, access=mmap.ACCESS_READ) as s: - - m = re.search(br"insns: (?P\d+)", s) - if "count" not in m.groupdict(): - self.fail("Failed to find instruction count") - else: - count = int(m.group("count")) - self.log.info(f"Counted: {count} instructions") - - - def test_aarch64_virt_insn_icount(self): - self.set_machine('virt') - self.cpu='cortex-a53' - kernel_path = self.ASSET_KERNEL.fetch() - kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE + - 'console=ttyAMA0') - console_pattern = 'Please append a correct "root=" boot option' - - plugin_log = tempfile.NamedTemporaryFile(mode="r+t", prefix="plugin", - suffix=".log") - - self.run_vm(kernel_path, kernel_command_line, - self.plugin_file('libinsn'), plugin_log.name, - console_pattern, - args=('-icount', 'shift=1')) - - with plugin_log as lf, \ - mmap.mmap(lf.fileno(), 0, access=mmap.ACCESS_READ) as s: - - m = re.search(br"insns: (?P\d+)", s) - if "count" not in m.groupdict(): - self.fail("Failed to find instruction count") - else: - count = int(m.group("count")) - self.log.info(f"Counted: {count} instructions") - -if __name__ == '__main__': - LinuxKernelTest.main() diff --git a/tests/functional/test_aarch64_tuxrun.py b/tests/functional/test_aarch64_tuxrun.py deleted file mode 100755 index 75adc8a..0000000 --- a/tests/functional/test_aarch64_tuxrun.py +++ /dev/null @@ -1,50 +0,0 @@ -#!/usr/bin/env python3 -# -# Functional test that boots known good tuxboot images the same way -# that tuxrun (www.tuxrun.org) does. This tool is used by things like -# the LKFT project to run regression tests on kernels. -# -# Copyright (c) 2023 Linaro Ltd. -# -# Author: -# Alex Bennée -# -# SPDX-License-Identifier: GPL-2.0-or-later - -from qemu_test import Asset -from qemu_test.tuxruntest import TuxRunBaselineTest - -class TuxRunAarch64Test(TuxRunBaselineTest): - - ASSET_ARM64_KERNEL = Asset( - 'https://storage.tuxboot.com/buildroot/20241119/arm64/Image', - 'b74743c5e89e1cea0f73368d24ae0ae85c5204ff84be3b5e9610417417d2f235') - ASSET_ARM64_ROOTFS = Asset( - 'https://storage.tuxboot.com/buildroot/20241119/arm64/rootfs.ext4.zst', - 'a1acaaae2068df4648d04ff75f532aaa8c5edcd6b936122b6f0db4848a07b465') - - def test_arm64(self): - self.set_machine('virt') - self.cpu='cortex-a57' - self.console='ttyAMA0' - self.wait_for_shutdown=False - self.common_tuxrun(kernel_asset=self.ASSET_ARM64_KERNEL, - rootfs_asset=self.ASSET_ARM64_ROOTFS) - - ASSET_ARM64BE_KERNEL = Asset( - 'https://storage.tuxboot.com/buildroot/20241119/arm64be/Image', - 'fd6af4f16689d17a2c24fe0053cc212edcdf77abdcaf301800b8d38fa9f6e109') - ASSET_ARM64BE_ROOTFS = Asset( - 'https://storage.tuxboot.com/buildroot/20241119/arm64be/rootfs.ext4.zst', - 'f5e9371b62701aab8dead52592ca7488c8a9e255c9be8d7635c7f30f477c2c21') - - def test_arm64be(self): - self.set_machine('virt') - self.cpu='cortex-a57' - self.console='ttyAMA0' - self.wait_for_shutdown=False - self.common_tuxrun(kernel_asset=self.ASSET_ARM64BE_KERNEL, - rootfs_asset=self.ASSET_ARM64BE_ROOTFS) - -if __name__ == '__main__': - TuxRunBaselineTest.main() diff --git a/tests/functional/test_aarch64_virt.py b/tests/functional/test_aarch64_virt.py deleted file mode 100755 index 4d0ad90..0000000 --- a/tests/functional/test_aarch64_virt.py +++ /dev/null @@ -1,135 +0,0 @@ -#!/usr/bin/env python3 -# -# Functional test that boots a various Linux systems and checks the -# console output. -# -# Copyright (c) 2022 Linaro Ltd. -# -# Author: -# Alex Bennée -# -# SPDX-License-Identifier: GPL-2.0-or-later - -import logging -from subprocess import check_call, DEVNULL - -from qemu_test import QemuSystemTest, Asset, exec_command_and_wait_for_pattern -from qemu_test import wait_for_console_pattern, get_qemu_img - - -class Aarch64VirtMachine(QemuSystemTest): - KERNEL_COMMON_COMMAND_LINE = 'printk.time=0 ' - timeout = 360 - - def wait_for_console_pattern(self, success_message, vm=None): - wait_for_console_pattern(self, success_message, - failure_message='Kernel panic - not syncing', - vm=vm) - - ASSET_ALPINE_ISO = Asset( - ('https://dl-cdn.alpinelinux.org/' - 'alpine/v3.17/releases/aarch64/alpine-standard-3.17.2-aarch64.iso'), - '5a36304ecf039292082d92b48152a9ec21009d3a62f459de623e19c4bd9dc027') - - # This tests the whole boot chain from EFI to Userspace - # We only boot a whole OS for the current top level CPU and GIC - # Other test profiles should use more minimal boots - def test_alpine_virt_tcg_gic_max(self): - iso_path = self.ASSET_ALPINE_ISO.fetch() - - self.set_machine('virt') - self.require_accelerator("tcg") - - self.vm.set_console() - self.vm.add_args("-accel", "tcg") - self.vm.add_args("-cpu", "max,pauth-impdef=on") - self.vm.add_args("-machine", - "virt,acpi=on," - "virtualization=on," - "mte=on," - "gic-version=max,iommu=smmuv3") - self.vm.add_args("-smp", "2", "-m", "1024") - self.vm.add_args('-bios', self.build_file('pc-bios', - 'edk2-aarch64-code.fd')) - self.vm.add_args("-drive", f"file={iso_path},media=cdrom,format=raw") - self.vm.add_args('-device', 'virtio-rng-pci,rng=rng0') - self.vm.add_args('-object', 'rng-random,id=rng0,filename=/dev/urandom') - - self.vm.launch() - self.wait_for_console_pattern('Welcome to Alpine Linux 3.17') - - - ASSET_KERNEL = Asset( - ('https://fileserver.linaro.org/s/' - 'z6B2ARM7DQT3HWN/download'), - '12a54d4805cda6ab647cb7c7bbdb16fafb3df400e0d6f16445c1a0436100ef8d') - - def common_aarch64_virt(self, machine): - """ - Common code to launch basic virt machine with kernel+initrd - and a scratch disk. - """ - self.set_machine('virt') - self.require_accelerator("tcg") - - logger = logging.getLogger('aarch64_virt') - - kernel_path = self.ASSET_KERNEL.fetch() - - self.vm.set_console() - kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE + - 'console=ttyAMA0') - self.vm.add_args('-cpu', 'max,pauth-impdef=on', - '-machine', machine, - '-accel', 'tcg', - '-kernel', kernel_path, - '-append', kernel_command_line) - - # A RNG offers an easy way to generate a few IRQs - self.vm.add_args('-device', 'virtio-rng-pci,rng=rng0') - self.vm.add_args('-object', - 'rng-random,id=rng0,filename=/dev/urandom') - - # Also add a scratch block device - logger.info('creating scratch qcow2 image') - image_path = self.scratch_file('scratch.qcow2') - qemu_img = get_qemu_img(self) - check_call([qemu_img, 'create', '-f', 'qcow2', image_path, '8M'], - stdout=DEVNULL, stderr=DEVNULL) - - # Add the device - self.vm.add_args('-blockdev', - "driver=qcow2," - "file.driver=file," - f"file.filename={image_path},node-name=scratch") - self.vm.add_args('-device', - 'virtio-blk-device,drive=scratch') - - self.vm.launch() - - ps1='#' - self.wait_for_console_pattern('login:') - - commands = [ - ('root', ps1), - ('cat /proc/interrupts', ps1), - ('cat /proc/self/maps', ps1), - ('uname -a', ps1), - ('dd if=/dev/hwrng of=/dev/vda bs=512 count=4', ps1), - ('md5sum /dev/vda', ps1), - ('halt -n', 'reboot: System halted') - ] - - for cmd, pattern in commands: - exec_command_and_wait_for_pattern(self, cmd, pattern) - - def test_aarch64_virt_gicv3(self): - self.common_aarch64_virt("virt,gic_version=3") - - def test_aarch64_virt_gicv2(self): - self.common_aarch64_virt("virt,gic-version=2") - - - -if __name__ == '__main__': - QemuSystemTest.main() diff --git a/tests/functional/test_aarch64_virt_gpu.py b/tests/functional/test_aarch64_virt_gpu.py deleted file mode 100755 index 4e50887..0000000 --- a/tests/functional/test_aarch64_virt_gpu.py +++ /dev/null @@ -1,142 +0,0 @@ -#!/usr/bin/env python3 -# -# Functional tests for the various graphics modes we can support. -# -# Copyright (c) 2024, 2025 Linaro Ltd. -# -# Author: -# Alex Bennée -# -# 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 import skipIfMissingCommands - -from qemu_test.linuxkernel import LinuxKernelTest - -from re import search -from subprocess import check_output, CalledProcessError - -class Aarch64VirtGPUMachine(LinuxKernelTest): - - ASSET_VIRT_GPU_KERNEL = Asset( - 'https://fileserver.linaro.org/s/ce5jXBFinPxtEdx/' - 'download?path=%2F&files=' - 'Image.6.12.16.aarch64', - '7888c51c55d37e86bbbdeb5acea9f08c34e6b0f03c1f5b2463285f6a6f6eec8b') - - ASSET_VIRT_GPU_ROOTFS = Asset( - 'https://fileserver.linaro.org/s/ce5jXBFinPxtEdx/' - 'download?path=%2F&files=' - 'rootfs.aarch64.ext2.zstd', - 'd45118c899420b7e673f1539a37a35480134b3e36e3a59e2cb69b1781cbb14ef') - - def _launch_virt_gpu(self, gpu_device): - - self.set_machine('virt') - self.require_accelerator("tcg") - - kernel_path = self.ASSET_VIRT_GPU_KERNEL.fetch() - image_path = self.uncompress(self.ASSET_VIRT_GPU_ROOTFS, format="zstd") - - self.vm.set_console() - kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE + - 'console=ttyAMA0 root=/dev/vda') - - self.vm.add_args("-accel", "tcg") - self.vm.add_args("-cpu", "cortex-a72") - self.vm.add_args("-machine", "virt,gic-version=max", - '-kernel', kernel_path, - '-append', kernel_command_line) - self.vm.add_args("-smp", "2", "-m", "2048") - self.vm.add_args("-device", gpu_device) - self.vm.add_args("-display", "egl-headless") - self.vm.add_args("-display", "dbus,gl=on") - - self.vm.add_args("-device", "virtio-blk-device,drive=hd0") - self.vm.add_args("-blockdev", - "driver=raw,file.driver=file," - "node-name=hd0,read-only=on," - f"file.filename={image_path}") - self.vm.add_args("-snapshot") - - try: - self.vm.launch() - except VMLaunchFailure as excp: - if "old virglrenderer, blob resources unsupported" in excp.output: - self.skipTest("No blob support for virtio-gpu") - elif "old virglrenderer, venus unsupported" in excp.output: - self.skipTest("No venus support for virtio-gpu") - elif "egl: no drm render node available" in excp.output: - self.skipTest("Can't access host DRM render node") - elif "'type' does not accept value 'egl-headless'" in excp.output: - self.skipTest("egl-headless support is not available") - elif "'type' does not accept value 'dbus'" in excp.output: - self.skipTest("dbus display support is not available") - elif "eglInitialize failed: EGL_NOT_INITIALIZED" in excp.output: - self.skipTest("EGL failed to initialize on this host") - else: - self.log.info("unhandled launch failure: %s", excp.output) - raise excp - - self.wait_for_console_pattern('buildroot login:') - ec_and_wait(self, 'root', '#') - - def _run_virt_weston_test(self, cmd, fail = None): - - # make it easier to detect successful return to shell - PS1 = 'RES=[$?] # ' - OK_CMD = 'RES=[0] # ' - - ec_and_wait(self, 'export XDG_RUNTIME_DIR=/tmp', '#') - ec_and_wait(self, f"export PS1='{PS1}'", OK_CMD) - full_cmd = f"weston -B headless --renderer gl --shell kiosk -- {cmd}" - ec_and_wait(self, full_cmd, OK_CMD, fail) - - @skipIfMissingCommands('zstd') - def test_aarch64_virt_with_virgl_gpu(self): - - self.require_device('virtio-gpu-gl-pci') - - self._launch_virt_gpu("virtio-gpu-gl-pci") - - # subset of the glmark tests - tests = " ".join([f"-b {test}" for test in - ["build", "texture", "shading", - "bump", "desktop", "buffer"]]) - - self._run_virt_weston_test("glmark2-wayland --validate " + tests) - - @skipIfMissingCommands('zstd') - def test_aarch64_virt_with_virgl_blobs_gpu(self): - - self.require_device('virtio-gpu-gl-pci') - - self._launch_virt_gpu("virtio-gpu-gl-pci,hostmem=4G,blob=on") - self._run_virt_weston_test("glmark2-wayland -b:duration=1.0") - - @skipIfMissingCommands('zstd') - @skipIfMissingCommands('vulkaninfo') - def test_aarch64_virt_with_vulkan_gpu(self): - - self.require_device('virtio-gpu-gl-pci') - - try: - vk_info = check_output(["vulkaninfo", "--summary"], - encoding="utf-8") - except CalledProcessError as excp: - self.skipTest(f"Miss-configured host Vulkan: {excp.output}") - - if search(r"driverID\s+=\s+DRIVER_ID_NVIDIA_PROPRIETARY", vk_info): - self.skipTest("Test skipped on NVIDIA proprietary driver") - - self._launch_virt_gpu("virtio-gpu-gl-pci,hostmem=4G,blob=on,venus=on") - self._run_virt_weston_test("vkmark -b:duration=1.0", - "debug: stuck in fence wait with iter at") - - -if __name__ == '__main__': - LinuxKernelTest.main() diff --git a/tests/functional/test_aarch64_xen.py b/tests/functional/test_aarch64_xen.py deleted file mode 100755 index 261d796..0000000 --- a/tests/functional/test_aarch64_xen.py +++ /dev/null @@ -1,91 +0,0 @@ -#!/usr/bin/env python3 -# -# Functional test that boots a Xen hypervisor with a domU kernel and -# checks the console output is vaguely sane . -# -# Copyright (c) 2020 Linaro -# -# Author: -# Alex Bennée -# -# SPDX-License-Identifier: GPL-2.0-or-later -# -# This work is licensed under the terms of the GNU GPL, version 2 or -# later. See the COPYING file in the top-level directory. - -from qemu_test import Asset, LinuxKernelTest, wait_for_console_pattern - - -class BootXen(LinuxKernelTest): - """ - Boots a Xen hypervisor with a Linux DomU kernel. - """ - - timeout = 90 - XEN_COMMON_COMMAND_LINE = 'dom0_mem=128M loglvl=all guest_loglvl=all' - - ASSET_KERNEL = Asset( - ('https://fileserver.linaro.org/s/JSsewXGZ6mqxPr5/' - 'download?path=%2F&files=linux-5.9.9-arm64-ajb'), - '00366fa51ea957c19462d2e2aefd480bef80ce727120e714ae48e0c88f261edb') - - def launch_xen(self, xen_path): - """ - Launch Xen with a dom0 guest kernel - """ - self.require_accelerator("tcg") # virtualization=on - self.set_machine('virt') - self.cpu = "cortex-a57" - self.kernel_path = self.ASSET_KERNEL.fetch() - self.log.info("launch with xen_path: %s", xen_path) - - self.vm.set_console() - - self.vm.add_args('-machine', 'virtualization=on', - '-m', '768', - '-kernel', xen_path, - '-append', self.XEN_COMMON_COMMAND_LINE, - '-device', - 'guest-loader,addr=0x47000000,kernel=%s,bootargs=console=hvc0' - % (self.kernel_path)) - - self.vm.launch() - - console_pattern = 'VFS: Cannot open root device' - wait_for_console_pattern(self, console_pattern, "Panic on CPU 0:") - - ASSET_XEN_4_11 = Asset( - ('https://fileserver.linaro.org/s/JSsewXGZ6mqxPr5/download?path=%2F&' - 'files=xen-hypervisor-4.11-arm64_4.11.4%2B37-g3263f257ca-1_arm64.deb'), - 'b745c2631342f9fcc0147ddc364edb62c20ecfebd430e5a3546e7d7c6891c0bc') - - def test_arm64_xen_411_and_dom0(self): - # archive of file from https://deb.debian.org/debian/pool/main/x/xen/ - xen_path = self.archive_extract(self.ASSET_XEN_4_11, format='deb', - member="boot/xen-4.11-arm64") - self.launch_xen(xen_path) - - ASSET_XEN_4_14 = Asset( - ('https://fileserver.linaro.org/s/JSsewXGZ6mqxPr5/download?path=%2F&' - 'files=xen-hypervisor-4.14-arm64_4.14.0%2B80-gd101b417b7-1_arm64.deb'), - 'e930a3293248edabd367d5b4b3b6448b9c99c057096ea8b47228a7870661d5cb') - - def test_arm64_xen_414_and_dom0(self): - # archive of file from https://deb.debian.org/debian/pool/main/x/xen/ - xen_path = self.archive_extract(self.ASSET_XEN_4_14, format='deb', - member="boot/xen-4.14-arm64") - self.launch_xen(xen_path) - - ASSET_XEN_4_15 = Asset( - ('https://fileserver.linaro.org/s/JSsewXGZ6mqxPr5/download?path=%2F&' - 'files=xen-upstream-4.15-unstable.deb'), - '2a9a8af8acf0231844657cc28baab95bd918b0ee2d493ee4ee6f8846e1358bc9') - - def test_arm64_xen_415_and_dom0(self): - xen_path = self.archive_extract(self.ASSET_XEN_4_15, format='deb', - member="boot/xen-4.15-unstable") - self.launch_xen(xen_path) - - -if __name__ == '__main__': - LinuxKernelTest.main() diff --git a/tests/functional/test_aarch64_xlnx_versal.py b/tests/functional/test_aarch64_xlnx_versal.py deleted file mode 100755 index 4b9c49e..0000000 --- a/tests/functional/test_aarch64_xlnx_versal.py +++ /dev/null @@ -1,37 +0,0 @@ -#!/usr/bin/env python3 -# -# Functional test that boots a Linux kernel and checks the console -# -# SPDX-License-Identifier: GPL-2.0-or-later - -from qemu_test import LinuxKernelTest, Asset - -class XlnxVersalVirtMachine(LinuxKernelTest): - - ASSET_KERNEL = Asset( - ('http://ports.ubuntu.com/ubuntu-ports/dists/bionic-updates/main/' - 'installer-arm64/20101020ubuntu543.19/images/netboot/' - 'ubuntu-installer/arm64/linux'), - 'ce54f74ab0b15cfd13d1a293f2d27ffd79d8a85b7bb9bf21093ae9513864ac79') - - ASSET_INITRD = Asset( - ('http://ports.ubuntu.com/ubuntu-ports/dists/bionic-updates/main/' - 'installer-arm64/20101020ubuntu543.19/images/netboot/' - '/ubuntu-installer/arm64/initrd.gz'), - 'e7a5e716b6f516d8be315c06e7331aaf16994fe4222e0e7cfb34bc015698929e') - - def test_aarch64_xlnx_versal_virt(self): - self.set_machine('xlnx-versal-virt') - kernel_path = self.ASSET_KERNEL.fetch() - initrd_path = self.ASSET_INITRD.fetch() - - self.vm.set_console() - self.vm.add_args('-m', '2G', - '-accel', 'tcg', - '-kernel', kernel_path, - '-initrd', initrd_path) - self.vm.launch() - self.wait_for_console_pattern('Checked W+X mappings: passed') - -if __name__ == '__main__': - LinuxKernelTest.main() -- cgit v1.1 From e534eee5ba6aefd905c16bcb714d1ff8156a0c45 Mon Sep 17 00:00:00 2001 From: Thomas Huth Date: Tue, 19 Aug 2025 13:23:43 +0200 Subject: tests/functional: Move alpha tests into architecture specific folder MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The tests/functional folder has become quite crowded already, some restructuring would be helpful here. Thus move the alpha tests into a target-specific subfolder. Reviewed-by: Pierrick Bouvier Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Thomas Huth Message-ID: <20250819112403.432587-7-thuth@redhat.com> --- tests/functional/alpha/meson.build | 10 ++++++++++ tests/functional/alpha/test_clipper.py | 34 ++++++++++++++++++++++++++++++++ tests/functional/alpha/test_migration.py | 26 ++++++++++++++++++++++++ tests/functional/alpha/test_replay.py | 29 +++++++++++++++++++++++++++ tests/functional/meson.build | 10 +--------- tests/functional/test_alpha_clipper.py | 34 -------------------------------- tests/functional/test_alpha_migration.py | 26 ------------------------ tests/functional/test_alpha_replay.py | 29 --------------------------- 8 files changed, 100 insertions(+), 98 deletions(-) create mode 100644 tests/functional/alpha/meson.build create mode 100755 tests/functional/alpha/test_clipper.py create mode 100755 tests/functional/alpha/test_migration.py create mode 100755 tests/functional/alpha/test_replay.py delete mode 100755 tests/functional/test_alpha_clipper.py delete mode 100755 tests/functional/test_alpha_migration.py delete mode 100755 tests/functional/test_alpha_replay.py (limited to 'tests') diff --git a/tests/functional/alpha/meson.build b/tests/functional/alpha/meson.build new file mode 100644 index 0000000..26a5b3f --- /dev/null +++ b/tests/functional/alpha/meson.build @@ -0,0 +1,10 @@ +# SPDX-License-Identifier: GPL-2.0-or-later + +tests_alpha_system_quick = [ + 'migration', +] + +tests_alpha_system_thorough = [ + 'clipper', + 'replay', +] diff --git a/tests/functional/alpha/test_clipper.py b/tests/functional/alpha/test_clipper.py new file mode 100755 index 0000000..c5d7181 --- /dev/null +++ b/tests/functional/alpha/test_clipper.py @@ -0,0 +1,34 @@ +#!/usr/bin/env python3 +# +# Functional test that boots a Linux kernel on an Alpha Clipper machine +# and checks the console +# +# SPDX-License-Identifier: GPL-2.0-or-later + +from qemu_test import LinuxKernelTest, Asset + + +class AlphaClipperTest(LinuxKernelTest): + + ASSET_KERNEL = Asset( + ('http://archive.debian.org/debian/dists/lenny/main/' + 'installer-alpha/20090123lenny10/images/cdrom/vmlinuz'), + '34f53da3fa32212e4f00b03cb944b2ad81c06bc8faaf9b7193b2e544ceeca576') + + def test_alpha_clipper(self): + self.set_machine('clipper') + kernel_path = self.ASSET_KERNEL.fetch() + + uncompressed_kernel = self.uncompress(self.ASSET_KERNEL, format="gz") + + self.vm.set_console() + kernel_command_line = self.KERNEL_COMMON_COMMAND_LINE + 'console=ttyS0' + self.vm.add_args('-nodefaults', + '-kernel', uncompressed_kernel, + '-append', kernel_command_line) + self.vm.launch() + console_pattern = 'Kernel command line: %s' % kernel_command_line + self.wait_for_console_pattern(console_pattern) + +if __name__ == '__main__': + LinuxKernelTest.main() diff --git a/tests/functional/alpha/test_migration.py b/tests/functional/alpha/test_migration.py new file mode 100755 index 0000000..f11b523 --- /dev/null +++ b/tests/functional/alpha/test_migration.py @@ -0,0 +1,26 @@ +#!/usr/bin/env python3 +# +# SPDX-License-Identifier: GPL-2.0-or-later +# +# Alpha migration test + +from migration import MigrationTest + + +class AlphaMigrationTest(MigrationTest): + + def test_migration_with_tcp_localhost(self): + self.set_machine('clipper') + self.migration_with_tcp_localhost() + + def test_migration_with_unix(self): + self.set_machine('clipper') + self.migration_with_unix() + + def test_migration_with_exec(self): + self.set_machine('clipper') + self.migration_with_exec() + + +if __name__ == '__main__': + MigrationTest.main() diff --git a/tests/functional/alpha/test_replay.py b/tests/functional/alpha/test_replay.py new file mode 100755 index 0000000..24a17ef --- /dev/null +++ b/tests/functional/alpha/test_replay.py @@ -0,0 +1,29 @@ +#!/usr/bin/env python3 +# +# Replay test that boots a Linux kernel on an Alpha machine +# and checks the console +# +# SPDX-License-Identifier: GPL-2.0-or-later + +from qemu_test import Asset +from replay_kernel import ReplayKernelBase + + +class AlphaReplay(ReplayKernelBase): + + ASSET_KERNEL = Asset( + ('http://archive.debian.org/debian/dists/lenny/main/installer-alpha/' + '20090123lenny10/images/cdrom/vmlinuz'), + '34f53da3fa32212e4f00b03cb944b2ad81c06bc8faaf9b7193b2e544ceeca576') + + def test_clipper(self): + self.set_machine('clipper') + kernel_path = self.uncompress(self.ASSET_KERNEL, format='gz') + kernel_command_line = self.KERNEL_COMMON_COMMAND_LINE + 'console=ttyS0' + console_pattern = 'Kernel command line: %s' % kernel_command_line + self.run_rr(kernel_path, kernel_command_line, console_pattern, shift=9, + args=('-nodefaults', )) + + +if __name__ == '__main__': + ReplayKernelBase.main() diff --git a/tests/functional/meson.build b/tests/functional/meson.build index 9cb6325..a7f8c88 100644 --- a/tests/functional/meson.build +++ b/tests/functional/meson.build @@ -10,6 +10,7 @@ if get_option('tcg_interpreter') endif subdir('aarch64') +subdir('alpha') test_arm_timeouts = { 'arm_aspeed_palmetto' : 120, @@ -96,15 +97,6 @@ tests_generic_linuxuser = [ tests_generic_bsduser = [ ] -tests_alpha_system_quick = [ - 'alpha_migration', -] - -tests_alpha_system_thorough = [ - 'alpha_clipper', - 'alpha_replay', -] - tests_arm_system_quick = [ 'arm_migration', ] diff --git a/tests/functional/test_alpha_clipper.py b/tests/functional/test_alpha_clipper.py deleted file mode 100755 index c5d7181..0000000 --- a/tests/functional/test_alpha_clipper.py +++ /dev/null @@ -1,34 +0,0 @@ -#!/usr/bin/env python3 -# -# Functional test that boots a Linux kernel on an Alpha Clipper machine -# and checks the console -# -# SPDX-License-Identifier: GPL-2.0-or-later - -from qemu_test import LinuxKernelTest, Asset - - -class AlphaClipperTest(LinuxKernelTest): - - ASSET_KERNEL = Asset( - ('http://archive.debian.org/debian/dists/lenny/main/' - 'installer-alpha/20090123lenny10/images/cdrom/vmlinuz'), - '34f53da3fa32212e4f00b03cb944b2ad81c06bc8faaf9b7193b2e544ceeca576') - - def test_alpha_clipper(self): - self.set_machine('clipper') - kernel_path = self.ASSET_KERNEL.fetch() - - uncompressed_kernel = self.uncompress(self.ASSET_KERNEL, format="gz") - - self.vm.set_console() - kernel_command_line = self.KERNEL_COMMON_COMMAND_LINE + 'console=ttyS0' - self.vm.add_args('-nodefaults', - '-kernel', uncompressed_kernel, - '-append', kernel_command_line) - self.vm.launch() - console_pattern = 'Kernel command line: %s' % kernel_command_line - self.wait_for_console_pattern(console_pattern) - -if __name__ == '__main__': - LinuxKernelTest.main() diff --git a/tests/functional/test_alpha_migration.py b/tests/functional/test_alpha_migration.py deleted file mode 100755 index f11b523..0000000 --- a/tests/functional/test_alpha_migration.py +++ /dev/null @@ -1,26 +0,0 @@ -#!/usr/bin/env python3 -# -# SPDX-License-Identifier: GPL-2.0-or-later -# -# Alpha migration test - -from migration import MigrationTest - - -class AlphaMigrationTest(MigrationTest): - - def test_migration_with_tcp_localhost(self): - self.set_machine('clipper') - self.migration_with_tcp_localhost() - - def test_migration_with_unix(self): - self.set_machine('clipper') - self.migration_with_unix() - - def test_migration_with_exec(self): - self.set_machine('clipper') - self.migration_with_exec() - - -if __name__ == '__main__': - MigrationTest.main() diff --git a/tests/functional/test_alpha_replay.py b/tests/functional/test_alpha_replay.py deleted file mode 100755 index 24a17ef..0000000 --- a/tests/functional/test_alpha_replay.py +++ /dev/null @@ -1,29 +0,0 @@ -#!/usr/bin/env python3 -# -# Replay test that boots a Linux kernel on an Alpha machine -# and checks the console -# -# SPDX-License-Identifier: GPL-2.0-or-later - -from qemu_test import Asset -from replay_kernel import ReplayKernelBase - - -class AlphaReplay(ReplayKernelBase): - - ASSET_KERNEL = Asset( - ('http://archive.debian.org/debian/dists/lenny/main/installer-alpha/' - '20090123lenny10/images/cdrom/vmlinuz'), - '34f53da3fa32212e4f00b03cb944b2ad81c06bc8faaf9b7193b2e544ceeca576') - - def test_clipper(self): - self.set_machine('clipper') - kernel_path = self.uncompress(self.ASSET_KERNEL, format='gz') - kernel_command_line = self.KERNEL_COMMON_COMMAND_LINE + 'console=ttyS0' - console_pattern = 'Kernel command line: %s' % kernel_command_line - self.run_rr(kernel_path, kernel_command_line, console_pattern, shift=9, - args=('-nodefaults', )) - - -if __name__ == '__main__': - ReplayKernelBase.main() -- cgit v1.1 From 8de42cb748287d8dcc521d057b107f32d98e5edd Mon Sep 17 00:00:00 2001 From: Thomas Huth Date: Tue, 19 Aug 2025 13:23:44 +0200 Subject: tests/functional: Move arm tests into architecture specific folder The tests/functional folder has become quite crowded, thus move the arm tests into a target-specific subfolder. Reviewed-by: Pierrick Bouvier Signed-off-by: Thomas Huth Message-ID: <20250819112403.432587-8-thuth@redhat.com> --- tests/functional/arm/meson.build | 62 ++++++ tests/functional/arm/test_aspeed_ast1030.py | 73 +++++++ tests/functional/arm/test_aspeed_ast2500.py | 56 ++++++ tests/functional/arm/test_aspeed_ast2600.py | 140 +++++++++++++ tests/functional/arm/test_aspeed_bletchley.py | 25 +++ tests/functional/arm/test_aspeed_catalina.py | 25 +++ tests/functional/arm/test_aspeed_gb200nvl_bmc.py | 26 +++ tests/functional/arm/test_aspeed_palmetto.py | 25 +++ tests/functional/arm/test_aspeed_rainier.py | 65 +++++++ tests/functional/arm/test_aspeed_romulus.py | 25 +++ tests/functional/arm/test_aspeed_witherspoon.py | 25 +++ tests/functional/arm/test_bflt.py | 41 ++++ tests/functional/arm/test_bpim2u.py | 180 +++++++++++++++++ tests/functional/arm/test_canona1100.py | 37 ++++ tests/functional/arm/test_collie.py | 31 +++ tests/functional/arm/test_cubieboard.py | 144 ++++++++++++++ tests/functional/arm/test_emcraft_sf2.py | 52 +++++ tests/functional/arm/test_integratorcp.py | 95 +++++++++ tests/functional/arm/test_max78000fthr.py | 48 +++++ tests/functional/arm/test_microbit.py | 31 +++ tests/functional/arm/test_migration.py | 26 +++ tests/functional/arm/test_orangepi.py | 237 +++++++++++++++++++++++ tests/functional/arm/test_quanta_gsj.py | 92 +++++++++ tests/functional/arm/test_raspi2.py | 92 +++++++++ tests/functional/arm/test_realview.py | 47 +++++ tests/functional/arm/test_replay.py | 69 +++++++ tests/functional/arm/test_smdkc210.py | 51 +++++ tests/functional/arm/test_stellaris.py | 48 +++++ tests/functional/arm/test_sx1.py | 73 +++++++ tests/functional/arm/test_tuxrun.py | 70 +++++++ tests/functional/arm/test_vexpress.py | 26 +++ tests/functional/arm/test_virt.py | 30 +++ tests/functional/meson.build | 62 +----- tests/functional/test_arm_aspeed_ast1030.py | 73 ------- tests/functional/test_arm_aspeed_ast2500.py | 56 ------ tests/functional/test_arm_aspeed_ast2600.py | 140 ------------- tests/functional/test_arm_aspeed_bletchley.py | 25 --- tests/functional/test_arm_aspeed_catalina.py | 25 --- tests/functional/test_arm_aspeed_gb200nvl_bmc.py | 26 --- tests/functional/test_arm_aspeed_palmetto.py | 25 --- tests/functional/test_arm_aspeed_rainier.py | 65 ------- tests/functional/test_arm_aspeed_romulus.py | 25 --- tests/functional/test_arm_aspeed_witherspoon.py | 25 --- tests/functional/test_arm_bflt.py | 41 ---- tests/functional/test_arm_bpim2u.py | 180 ----------------- tests/functional/test_arm_canona1100.py | 37 ---- tests/functional/test_arm_collie.py | 31 --- tests/functional/test_arm_cubieboard.py | 144 -------------- tests/functional/test_arm_emcraft_sf2.py | 52 ----- tests/functional/test_arm_integratorcp.py | 95 --------- tests/functional/test_arm_max78000fthr.py | 48 ----- tests/functional/test_arm_microbit.py | 31 --- tests/functional/test_arm_migration.py | 26 --- tests/functional/test_arm_orangepi.py | 237 ----------------------- tests/functional/test_arm_quanta_gsj.py | 92 --------- tests/functional/test_arm_raspi2.py | 92 --------- tests/functional/test_arm_realview.py | 47 ----- tests/functional/test_arm_replay.py | 69 ------- tests/functional/test_arm_smdkc210.py | 51 ----- tests/functional/test_arm_stellaris.py | 48 ----- tests/functional/test_arm_sx1.py | 73 ------- tests/functional/test_arm_tuxrun.py | 70 ------- tests/functional/test_arm_vexpress.py | 26 --- tests/functional/test_arm_virt.py | 30 --- 64 files changed, 2068 insertions(+), 2066 deletions(-) create mode 100644 tests/functional/arm/meson.build create mode 100755 tests/functional/arm/test_aspeed_ast1030.py create mode 100755 tests/functional/arm/test_aspeed_ast2500.py create mode 100755 tests/functional/arm/test_aspeed_ast2600.py create mode 100755 tests/functional/arm/test_aspeed_bletchley.py create mode 100755 tests/functional/arm/test_aspeed_catalina.py create mode 100755 tests/functional/arm/test_aspeed_gb200nvl_bmc.py create mode 100755 tests/functional/arm/test_aspeed_palmetto.py create mode 100755 tests/functional/arm/test_aspeed_rainier.py create mode 100755 tests/functional/arm/test_aspeed_romulus.py create mode 100755 tests/functional/arm/test_aspeed_witherspoon.py create mode 100755 tests/functional/arm/test_bflt.py create mode 100755 tests/functional/arm/test_bpim2u.py create mode 100755 tests/functional/arm/test_canona1100.py create mode 100755 tests/functional/arm/test_collie.py create mode 100755 tests/functional/arm/test_cubieboard.py create mode 100755 tests/functional/arm/test_emcraft_sf2.py create mode 100755 tests/functional/arm/test_integratorcp.py create mode 100755 tests/functional/arm/test_max78000fthr.py create mode 100755 tests/functional/arm/test_microbit.py create mode 100755 tests/functional/arm/test_migration.py create mode 100755 tests/functional/arm/test_orangepi.py create mode 100755 tests/functional/arm/test_quanta_gsj.py create mode 100755 tests/functional/arm/test_raspi2.py create mode 100755 tests/functional/arm/test_realview.py create mode 100755 tests/functional/arm/test_replay.py create mode 100755 tests/functional/arm/test_smdkc210.py create mode 100755 tests/functional/arm/test_stellaris.py create mode 100755 tests/functional/arm/test_sx1.py create mode 100755 tests/functional/arm/test_tuxrun.py create mode 100755 tests/functional/arm/test_vexpress.py create mode 100755 tests/functional/arm/test_virt.py delete mode 100755 tests/functional/test_arm_aspeed_ast1030.py delete mode 100755 tests/functional/test_arm_aspeed_ast2500.py delete mode 100755 tests/functional/test_arm_aspeed_ast2600.py delete mode 100644 tests/functional/test_arm_aspeed_bletchley.py delete mode 100755 tests/functional/test_arm_aspeed_catalina.py delete mode 100644 tests/functional/test_arm_aspeed_gb200nvl_bmc.py delete mode 100755 tests/functional/test_arm_aspeed_palmetto.py delete mode 100755 tests/functional/test_arm_aspeed_rainier.py delete mode 100755 tests/functional/test_arm_aspeed_romulus.py delete mode 100644 tests/functional/test_arm_aspeed_witherspoon.py delete mode 100755 tests/functional/test_arm_bflt.py delete mode 100755 tests/functional/test_arm_bpim2u.py delete mode 100755 tests/functional/test_arm_canona1100.py delete mode 100755 tests/functional/test_arm_collie.py delete mode 100755 tests/functional/test_arm_cubieboard.py delete mode 100755 tests/functional/test_arm_emcraft_sf2.py delete mode 100755 tests/functional/test_arm_integratorcp.py delete mode 100755 tests/functional/test_arm_max78000fthr.py delete mode 100755 tests/functional/test_arm_microbit.py delete mode 100755 tests/functional/test_arm_migration.py delete mode 100755 tests/functional/test_arm_orangepi.py delete mode 100755 tests/functional/test_arm_quanta_gsj.py delete mode 100755 tests/functional/test_arm_raspi2.py delete mode 100755 tests/functional/test_arm_realview.py delete mode 100755 tests/functional/test_arm_replay.py delete mode 100755 tests/functional/test_arm_smdkc210.py delete mode 100755 tests/functional/test_arm_stellaris.py delete mode 100755 tests/functional/test_arm_sx1.py delete mode 100755 tests/functional/test_arm_tuxrun.py delete mode 100755 tests/functional/test_arm_vexpress.py delete mode 100755 tests/functional/test_arm_virt.py (limited to 'tests') diff --git a/tests/functional/arm/meson.build b/tests/functional/arm/meson.build new file mode 100644 index 0000000..e4e7dba --- /dev/null +++ b/tests/functional/arm/meson.build @@ -0,0 +1,62 @@ +# SPDX-License-Identifier: GPL-2.0-or-later + +test_arm_timeouts = { + 'aspeed_palmetto' : 120, + 'aspeed_romulus' : 120, + 'aspeed_witherspoon' : 120, + 'aspeed_ast2500' : 720, + 'aspeed_ast2600' : 1200, + 'aspeed_bletchley' : 480, + 'aspeed_catalina' : 480, + 'aspeed_gb200nvl_bmc' : 480, + 'aspeed_rainier' : 480, + 'bpim2u' : 500, + 'collie' : 180, + 'cubieboard' : 360, + 'orangepi' : 540, + 'quanta_gsj' : 240, + 'raspi2' : 120, + 'replay' : 240, + 'tuxrun' : 240, + 'sx1' : 360, +} + +tests_arm_system_quick = [ + 'migration', +] + +tests_arm_system_thorough = [ + 'aspeed_ast1030', + 'aspeed_palmetto', + 'aspeed_romulus', + 'aspeed_witherspoon', + 'aspeed_ast2500', + 'aspeed_ast2600', + 'aspeed_bletchley', + 'aspeed_catalina', + 'aspeed_gb200nvl_bmc', + 'aspeed_rainier', + 'bpim2u', + 'canona1100', + 'collie', + 'cubieboard', + 'emcraft_sf2', + 'integratorcp', + 'max78000fthr', + 'microbit', + 'orangepi', + 'quanta_gsj', + 'raspi2', + 'realview', + 'replay', + 'smdkc210', + 'stellaris', + 'sx1', + 'vexpress', + 'virt', + 'tuxrun', +] + +tests_arm_linuxuser_thorough = [ + 'bflt', +] diff --git a/tests/functional/arm/test_aspeed_ast1030.py b/tests/functional/arm/test_aspeed_ast1030.py new file mode 100755 index 0000000..77037f0 --- /dev/null +++ b/tests/functional/arm/test_aspeed_ast1030.py @@ -0,0 +1,73 @@ +#!/usr/bin/env python3 +# +# Functional test that boots the ASPEED SoCs with firmware +# +# Copyright (C) 2022 ASPEED Technology Inc +# +# SPDX-License-Identifier: GPL-2.0-or-later + +from qemu_test import LinuxKernelTest, Asset +from qemu_test import exec_command_and_wait_for_pattern + + +class AST1030Machine(LinuxKernelTest): + + ASSET_ZEPHYR_3_00 = Asset( + ('https://github.com/AspeedTech-BMC' + '/zephyr/releases/download/v00.03.00/ast1030-evb-demo.zip'), + '37fe3ecd4a1b9d620971a15b96492a81093435396eeac69b6f3e384262ff555f') + + def test_ast1030_zephyros_3_00(self): + self.set_machine('ast1030-evb') + + kernel_name = "ast1030-evb-demo/zephyr.elf" + kernel_file = self.archive_extract( + self.ASSET_ZEPHYR_3_00, member=kernel_name) + + self.vm.set_console() + self.vm.add_args('-kernel', kernel_file, '-nographic') + self.vm.launch() + self.wait_for_console_pattern("Booting Zephyr OS") + exec_command_and_wait_for_pattern(self, "help", + "Available commands") + + ASSET_ZEPHYR_1_07 = Asset( + ('https://github.com/AspeedTech-BMC' + '/zephyr/releases/download/v00.01.07/ast1030-evb-demo.zip'), + 'ad52e27959746988afaed8429bf4e12ab988c05c4d07c9d90e13ec6f7be4574c') + + def test_ast1030_zephyros_1_07(self): + self.set_machine('ast1030-evb') + + kernel_name = "ast1030-evb-demo/zephyr.bin" + kernel_file = self.archive_extract( + self.ASSET_ZEPHYR_1_07, member=kernel_name) + + self.vm.set_console() + self.vm.add_args('-kernel', kernel_file, '-nographic') + self.vm.launch() + self.wait_for_console_pattern("Booting Zephyr OS") + for shell_cmd in [ + 'kernel stacks', + 'otp info conf', + 'otp info scu', + 'hwinfo devid', + 'crypto aes256_cbc_vault', + 'random get', + 'jtag JTAG1 sw_xfer high TMS', + 'adc ADC0 resolution 12', + 'adc ADC0 read 42', + 'adc ADC1 read 69', + 'i2c scan I2C_0', + 'i3c attach I3C_0', + 'hash test', + 'kernel uptime', + 'kernel reboot warm', + 'kernel uptime', + 'kernel reboot cold', + 'kernel uptime', + ]: exec_command_and_wait_for_pattern(self, shell_cmd, "uart:~$") + + +if __name__ == '__main__': + LinuxKernelTest.main() diff --git a/tests/functional/arm/test_aspeed_ast2500.py b/tests/functional/arm/test_aspeed_ast2500.py new file mode 100755 index 0000000..6923fe8 --- /dev/null +++ b/tests/functional/arm/test_aspeed_ast2500.py @@ -0,0 +1,56 @@ +#!/usr/bin/env python3 +# +# Functional test that boots the ASPEED machines +# +# SPDX-License-Identifier: GPL-2.0-or-later + +from qemu_test import Asset, exec_command_and_wait_for_pattern +from aspeed import AspeedTest + + +class AST2500Machine(AspeedTest): + + ASSET_BR2_202411_AST2500_FLASH = Asset( + ('https://github.com/legoater/qemu-aspeed-boot/raw/master/' + 'images/ast2500-evb/buildroot-2024.11/flash.img'), + '641e6906c18c0f19a2aeb48099d66d4771929c361001d554d0d45c667413e13a') + + def test_arm_ast2500_evb_buildroot(self): + self.set_machine('ast2500-evb') + + image_path = self.ASSET_BR2_202411_AST2500_FLASH.fetch() + + self.vm.add_args('-device', + 'tmp105,bus=aspeed.i2c.bus.3,address=0x4d,id=tmp-test') + self.do_test_arm_aspeed_buildroot_start(image_path, '0x0', + 'ast2500-evb login:') + + exec_command_and_wait_for_pattern(self, + 'echo lm75 0x4d > /sys/class/i2c-dev/i2c-3/device/new_device', + 'i2c i2c-3: new_device: Instantiated device lm75 at 0x4d') + exec_command_and_wait_for_pattern(self, + 'cat /sys/class/hwmon/hwmon1/temp1_input', '0') + self.vm.cmd('qom-set', path='/machine/peripheral/tmp-test', + property='temperature', value=18000) + exec_command_and_wait_for_pattern(self, + 'cat /sys/class/hwmon/hwmon1/temp1_input', '18000') + + self.do_test_arm_aspeed_buildroot_poweroff() + + ASSET_SDK_V906_AST2500 = Asset( + 'https://github.com/AspeedTech-BMC/openbmc/releases/download/v09.06/ast2500-default-obmc.tar.gz', + '542db84645b4efd8aed50385d7f4dd1caff379a987032311cfa7b563a3addb2a') + + def test_arm_ast2500_evb_sdk(self): + self.set_machine('ast2500-evb') + + self.archive_extract(self.ASSET_SDK_V906_AST2500) + + self.do_test_arm_aspeed_sdk_start( + self.scratch_file("ast2500-default", "image-bmc")) + + self.wait_for_console_pattern('ast2500-default login:') + + +if __name__ == '__main__': + AspeedTest.main() diff --git a/tests/functional/arm/test_aspeed_ast2600.py b/tests/functional/arm/test_aspeed_ast2600.py new file mode 100755 index 0000000..fdae4c9 --- /dev/null +++ b/tests/functional/arm/test_aspeed_ast2600.py @@ -0,0 +1,140 @@ +#!/usr/bin/env python3 +# +# Functional test that boots the ASPEED machines +# +# SPDX-License-Identifier: GPL-2.0-or-later + +import os +import time +import tempfile +import subprocess + +from qemu_test import Asset +from aspeed import AspeedTest +from qemu_test import exec_command_and_wait_for_pattern, skipIfMissingCommands + + +class AST2600Machine(AspeedTest): + + ASSET_BR2_202411_AST2600_FLASH = Asset( + ('https://github.com/legoater/qemu-aspeed-boot/raw/master/' + 'images/ast2600-evb/buildroot-2024.11/flash.img'), + '4bb2f3dfdea31199b51d66b42f686dc5374c144a7346fdc650194a5578b73609') + + def test_arm_ast2600_evb_buildroot(self): + self.set_machine('ast2600-evb') + + image_path = self.ASSET_BR2_202411_AST2600_FLASH.fetch() + + self.vm.add_args('-device', + 'tmp105,bus=aspeed.i2c.bus.3,address=0x4d,id=tmp-test') + self.vm.add_args('-device', + 'ds1338,bus=aspeed.i2c.bus.3,address=0x32') + self.vm.add_args('-device', + 'i2c-echo,bus=aspeed.i2c.bus.3,address=0x42') + self.do_test_arm_aspeed_buildroot_start(image_path, '0xf00', + 'ast2600-evb login:') + + exec_command_and_wait_for_pattern(self, + 'echo lm75 0x4d > /sys/class/i2c-dev/i2c-3/device/new_device', + 'i2c i2c-3: new_device: Instantiated device lm75 at 0x4d') + exec_command_and_wait_for_pattern(self, + 'cat /sys/class/hwmon/hwmon1/temp1_input', '0') + self.vm.cmd('qom-set', path='/machine/peripheral/tmp-test', + property='temperature', value=18000) + exec_command_and_wait_for_pattern(self, + 'cat /sys/class/hwmon/hwmon1/temp1_input', '18000') + + exec_command_and_wait_for_pattern(self, + 'echo ds1307 0x32 > /sys/class/i2c-dev/i2c-3/device/new_device', + 'i2c i2c-3: new_device: Instantiated device ds1307 at 0x32') + year = time.strftime("%Y") + exec_command_and_wait_for_pattern(self, 'hwclock -f /dev/rtc1', year) + + exec_command_and_wait_for_pattern(self, + 'echo slave-24c02 0x1064 > /sys/bus/i2c/devices/i2c-3/new_device', + 'i2c i2c-3: new_device: Instantiated device slave-24c02 at 0x64') + exec_command_and_wait_for_pattern(self, + 'i2cset -y 3 0x42 0x64 0x00 0xaa i', '#') + exec_command_and_wait_for_pattern(self, + 'hexdump /sys/bus/i2c/devices/3-1064/slave-eeprom', + '0000000 ffaa ffff ffff ffff ffff ffff ffff ffff') + self.do_test_arm_aspeed_buildroot_poweroff() + + ASSET_BR2_202302_AST2600_TPM_FLASH = Asset( + ('https://github.com/legoater/qemu-aspeed-boot/raw/master/' + 'images/ast2600-evb/buildroot-2023.02-tpm/flash.img'), + 'a46009ae8a5403a0826d607215e731a8c68d27c14c41e55331706b8f9c7bd997') + + @skipIfMissingCommands('swtpm') + def test_arm_ast2600_evb_buildroot_tpm(self): + self.set_machine('ast2600-evb') + + image_path = self.ASSET_BR2_202302_AST2600_TPM_FLASH.fetch() + + tpmstate_dir = tempfile.TemporaryDirectory(prefix="qemu_") + socket = os.path.join(tpmstate_dir.name, 'swtpm-socket') + + # We must put the TPM state dir in /tmp/, not the build dir, + # because some distros use AppArmor to lock down swtpm and + # restrict the set of locations it can access files in. + subprocess.run(['swtpm', 'socket', '-d', '--tpm2', + '--tpmstate', f'dir={tpmstate_dir.name}', + '--ctrl', f'type=unixio,path={socket}']) + + self.vm.add_args('-chardev', f'socket,id=chrtpm,path={socket}') + self.vm.add_args('-tpmdev', 'emulator,id=tpm0,chardev=chrtpm') + self.vm.add_args('-device', + 'tpm-tis-i2c,tpmdev=tpm0,bus=aspeed.i2c.bus.12,address=0x2e') + self.do_test_arm_aspeed_buildroot_start(image_path, '0xf00', 'Aspeed AST2600 EVB') + + exec_command_and_wait_for_pattern(self, + 'echo tpm_tis_i2c 0x2e > /sys/bus/i2c/devices/i2c-12/new_device', + 'tpm_tis_i2c 12-002e: 2.0 TPM (device-id 0x1, rev-id 1)') + exec_command_and_wait_for_pattern(self, + 'cat /sys/class/tpm/tpm0/pcr-sha256/0', + 'B804724EA13F52A9072BA87FE8FDCC497DFC9DF9AA15B9088694639C431688E0') + + self.do_test_arm_aspeed_buildroot_poweroff() + + ASSET_SDK_V906_AST2600 = Asset( + 'https://github.com/AspeedTech-BMC/openbmc/releases/download/v09.06/ast2600-default-obmc.tar.gz', + '768d76e247896ad78c154b9cff4f766da2ce65f217d620b286a4a03a8a4f68f5') + + def test_arm_ast2600_evb_sdk(self): + self.set_machine('ast2600-evb') + + self.archive_extract(self.ASSET_SDK_V906_AST2600) + + self.vm.add_args('-device', + 'tmp105,bus=aspeed.i2c.bus.5,address=0x4d,id=tmp-test') + self.vm.add_args('-device', + 'ds1338,bus=aspeed.i2c.bus.5,address=0x32') + self.do_test_arm_aspeed_sdk_start( + self.scratch_file("ast2600-default", "image-bmc")) + + self.wait_for_console_pattern('ast2600-default login:') + + exec_command_and_wait_for_pattern(self, 'root', 'Password:') + exec_command_and_wait_for_pattern(self, '0penBmc', + 'root@ast2600-default:~#') + + exec_command_and_wait_for_pattern(self, + 'echo lm75 0x4d > /sys/class/i2c-dev/i2c-5/device/new_device', + 'i2c i2c-5: new_device: Instantiated device lm75 at 0x4d') + exec_command_and_wait_for_pattern(self, + 'cat /sys/class/hwmon/hwmon19/temp1_input', '0') + self.vm.cmd('qom-set', path='/machine/peripheral/tmp-test', + property='temperature', value=18000) + exec_command_and_wait_for_pattern(self, + 'cat /sys/class/hwmon/hwmon19/temp1_input', '18000') + + exec_command_and_wait_for_pattern(self, + 'echo ds1307 0x32 > /sys/class/i2c-dev/i2c-5/device/new_device', + 'i2c i2c-5: new_device: Instantiated device ds1307 at 0x32') + year = time.strftime("%Y") + exec_command_and_wait_for_pattern(self, + '/sbin/hwclock -f /dev/rtc1', year) + +if __name__ == '__main__': + AspeedTest.main() diff --git a/tests/functional/arm/test_aspeed_bletchley.py b/tests/functional/arm/test_aspeed_bletchley.py new file mode 100755 index 0000000..5a60b24 --- /dev/null +++ b/tests/functional/arm/test_aspeed_bletchley.py @@ -0,0 +1,25 @@ +#!/usr/bin/env python3 +# +# Functional test that boots the ASPEED machines +# +# SPDX-License-Identifier: GPL-2.0-or-later + +from qemu_test import Asset +from aspeed import AspeedTest + + +class BletchleyMachine(AspeedTest): + + ASSET_BLETCHLEY_FLASH = Asset( + 'https://github.com/legoater/qemu-aspeed-boot/raw/master/images/bletchley-bmc/openbmc-20250128071329/obmc-phosphor-image-bletchley-20250128071329.static.mtd.xz', + 'db21d04d47d7bb2a276f59d308614b4dfb70b9c7c81facbbca40a3977a2d8844') + + def test_arm_ast2600_bletchley_openbmc(self): + image_path = self.uncompress(self.ASSET_BLETCHLEY_FLASH) + + self.do_test_arm_aspeed_openbmc('bletchley-bmc', image=image_path, + uboot='2019.04', cpu_id='0xf00', + soc='AST2600 rev A3') + +if __name__ == '__main__': + AspeedTest.main() diff --git a/tests/functional/arm/test_aspeed_catalina.py b/tests/functional/arm/test_aspeed_catalina.py new file mode 100755 index 0000000..dc2f24e --- /dev/null +++ b/tests/functional/arm/test_aspeed_catalina.py @@ -0,0 +1,25 @@ +#!/usr/bin/env python3 +# +# Functional test that boots the ASPEED machines +# +# SPDX-License-Identifier: GPL-2.0-or-later + +from qemu_test import Asset +from aspeed import AspeedTest + + +class CatalinaMachine(AspeedTest): + + ASSET_CATALINA_FLASH = Asset( + 'https://github.com/legoater/qemu-aspeed-boot/raw/a866feb5ef81245b4827a214584bf6bcc72939f6/images/catalina-bmc/obmc-phosphor-image-catalina-20250619123021.static.mtd.xz', + '287402e1ba021991e06be1d098f509444a02a3d81a73a932f66528b159e864f9') + + def test_arm_ast2600_catalina_openbmc(self): + image_path = self.uncompress(self.ASSET_CATALINA_FLASH) + + self.do_test_arm_aspeed_openbmc('catalina-bmc', image=image_path, + uboot='2019.04', cpu_id='0xf00', + soc='AST2600 rev A3') + +if __name__ == '__main__': + AspeedTest.main() diff --git a/tests/functional/arm/test_aspeed_gb200nvl_bmc.py b/tests/functional/arm/test_aspeed_gb200nvl_bmc.py new file mode 100755 index 0000000..8e8e3f0 --- /dev/null +++ b/tests/functional/arm/test_aspeed_gb200nvl_bmc.py @@ -0,0 +1,26 @@ +#!/usr/bin/env python3 +# +# Functional test that boots the ASPEED machines +# +# SPDX-License-Identifier: GPL-2.0-or-later + +from qemu_test import Asset +from aspeed import AspeedTest + + +class GB200Machine(AspeedTest): + + ASSET_GB200_FLASH = Asset( + 'https://github.com/legoater/qemu-aspeed-boot/raw/refs/heads/master/images/gb200nvl-obmc/obmc-phosphor-image-gb200nvl-obmc-20250702182348.static.mtd.xz', + 'b84819317cb3dc762895ad507705978ef000bfc77c50c33a63bdd37921db0dbc') + + def test_arm_aspeed_gb200_openbmc(self): + image_path = self.uncompress(self.ASSET_GB200_FLASH) + + self.do_test_arm_aspeed_openbmc('gb200nvl-bmc', image=image_path, + uboot='2019.04', cpu_id='0xf00', + soc='AST2600 rev A3', + image_hostname='gb200nvl-obmc') + +if __name__ == '__main__': + AspeedTest.main() diff --git a/tests/functional/arm/test_aspeed_palmetto.py b/tests/functional/arm/test_aspeed_palmetto.py new file mode 100755 index 0000000..ff0b821 --- /dev/null +++ b/tests/functional/arm/test_aspeed_palmetto.py @@ -0,0 +1,25 @@ +#!/usr/bin/env python3 +# +# Functional test that boots the ASPEED machines +# +# SPDX-License-Identifier: GPL-2.0-or-later + +from qemu_test import Asset +from aspeed import AspeedTest + + +class PalmettoMachine(AspeedTest): + + ASSET_PALMETTO_FLASH = Asset( + 'https://github.com/legoater/qemu-aspeed-boot/raw/master/images/palmetto-bmc/openbmc-20250128071432/obmc-phosphor-image-palmetto-20250128071432.static.mtd', + 'bce7c392eec75c707a91cfc8fad7ca9a69d7e4f10df936930d65c1cb9897ac81') + + def test_arm_ast2400_palmetto_openbmc(self): + image_path = self.ASSET_PALMETTO_FLASH.fetch() + + self.do_test_arm_aspeed_openbmc('palmetto-bmc', image=image_path, + uboot='2019.04', cpu_id='0x0', + soc='AST2400 rev A1') + +if __name__ == '__main__': + AspeedTest.main() diff --git a/tests/functional/arm/test_aspeed_rainier.py b/tests/functional/arm/test_aspeed_rainier.py new file mode 100755 index 0000000..602d619 --- /dev/null +++ b/tests/functional/arm/test_aspeed_rainier.py @@ -0,0 +1,65 @@ +#!/usr/bin/env python3 +# +# Functional test that boots the ASPEED machines +# +# SPDX-License-Identifier: GPL-2.0-or-later + +from qemu_test import Asset +from aspeed import AspeedTest + +class RainierMachine(AspeedTest): + + ASSET_RAINIER_EMMC = Asset( + ('https://fileserver.linaro.org/s/B6pJTwWEkzSDi36/download/' + 'mmc-p10bmc-20240617.qcow2'), + 'd523fb478d2b84d5adc5658d08502bc64b1486955683814f89c6137518acd90b') + + def test_arm_aspeed_emmc_boot(self): + self.set_machine('rainier-bmc') + self.require_netdev('user') + + image_path = self.ASSET_RAINIER_EMMC.fetch() + + self.vm.set_console() + self.vm.add_args('-drive', + 'file=' + image_path + ',if=sd,id=sd2,index=2', + '-net', 'nic', '-net', 'user', '-snapshot') + self.vm.launch() + + self.wait_for_console_pattern('U-Boot SPL 2019.04') + self.wait_for_console_pattern('Trying to boot from MMC1') + self.wait_for_console_pattern('U-Boot 2019.04') + self.wait_for_console_pattern('eMMC 2nd Boot') + self.wait_for_console_pattern('## Loading kernel from FIT Image') + self.wait_for_console_pattern('Starting kernel ...') + self.wait_for_console_pattern('Booting Linux on physical CPU 0xf00') + self.wait_for_console_pattern('mmcblk0: p1 p2 p3 p4 p5 p6 p7') + self.wait_for_console_pattern('IBM eBMC (OpenBMC for IBM Enterprise') + + ASSET_DEBIAN_LINUX_ARMHF_DEB = Asset( + ('http://snapshot.debian.org/archive/debian/20220606T211338Z/pool/main/l/linux/linux-image-5.17.0-2-armmp_5.17.6-1%2Bb1_armhf.deb'), + '8acb2b4439faedc2f3ed4bdb2847ad4f6e0491f73debaeb7f660c8abe4dcdc0e') + + def test_arm_debian_kernel_boot(self): + self.set_machine('rainier-bmc') + + kernel_path = self.archive_extract( + self.ASSET_DEBIAN_LINUX_ARMHF_DEB, + member='boot/vmlinuz-5.17.0-2-armmp') + dtb_path = self.archive_extract( + self.ASSET_DEBIAN_LINUX_ARMHF_DEB, + member='usr/lib/linux-image-5.17.0-2-armmp/aspeed-bmc-ibm-rainier.dtb') + + self.vm.set_console() + self.vm.add_args('-kernel', kernel_path, + '-dtb', dtb_path, + '-net', 'nic') + self.vm.launch() + + self.wait_for_console_pattern("Booting Linux on physical CPU 0xf00") + self.wait_for_console_pattern("SMP: Total of 2 processors activated") + self.wait_for_console_pattern("No filesystem could mount root") + + +if __name__ == '__main__': + AspeedTest.main() diff --git a/tests/functional/arm/test_aspeed_romulus.py b/tests/functional/arm/test_aspeed_romulus.py new file mode 100755 index 0000000..0447212 --- /dev/null +++ b/tests/functional/arm/test_aspeed_romulus.py @@ -0,0 +1,25 @@ +#!/usr/bin/env python3 +# +# Functional test that boots the ASPEED machines +# +# SPDX-License-Identifier: GPL-2.0-or-later + +from qemu_test import Asset +from aspeed import AspeedTest + + +class RomulusMachine(AspeedTest): + + ASSET_ROMULUS_FLASH = Asset( + 'https://github.com/legoater/qemu-aspeed-boot/raw/master/images/romulus-bmc/openbmc-20250128071340/obmc-phosphor-image-romulus-20250128071340.static.mtd', + '6d031376440c82ed9d087d25e9fa76aea75b42f80daa252ec402c0bc3cf6cf5b') + + def test_arm_ast2500_romulus_openbmc(self): + image_path = self.ASSET_ROMULUS_FLASH.fetch() + + self.do_test_arm_aspeed_openbmc('romulus-bmc', image=image_path, + uboot='2019.04', cpu_id='0x0', + soc='AST2500 rev A1') + +if __name__ == '__main__': + AspeedTest.main() diff --git a/tests/functional/arm/test_aspeed_witherspoon.py b/tests/functional/arm/test_aspeed_witherspoon.py new file mode 100755 index 0000000..51a2d47 --- /dev/null +++ b/tests/functional/arm/test_aspeed_witherspoon.py @@ -0,0 +1,25 @@ +#!/usr/bin/env python3 +# +# Functional test that boots the ASPEED machines +# +# SPDX-License-Identifier: GPL-2.0-or-later + +from qemu_test import Asset +from aspeed import AspeedTest + + +class WitherspoonMachine(AspeedTest): + + ASSET_WITHERSPOON_FLASH = Asset( + 'https://github.com/legoater/qemu-aspeed-boot/raw/master/images/witherspoon-bmc/openbmc-20240618035022/obmc-phosphor-image-witherspoon-20240618035022.ubi.mtd', + '937d9ed449ea6c6cbed983519088a42d0cafe276bcfe4fce07772ca6673f9213') + + def test_arm_ast2500_witherspoon_openbmc(self): + image_path = self.ASSET_WITHERSPOON_FLASH.fetch() + + self.do_test_arm_aspeed_openbmc('witherspoon-bmc', image=image_path, + uboot='2016.07', cpu_id='0x0', + soc='AST2500 rev A1') + +if __name__ == '__main__': + AspeedTest.main() diff --git a/tests/functional/arm/test_bflt.py b/tests/functional/arm/test_bflt.py new file mode 100755 index 0000000..f273fc8 --- /dev/null +++ b/tests/functional/arm/test_bflt.py @@ -0,0 +1,41 @@ +#!/usr/bin/env python3 +# +# Test the bFLT loader format +# +# Copyright (C) 2019 Philippe Mathieu-Daudé +# +# SPDX-License-Identifier: GPL-2.0-or-later + +import bz2 + +from qemu_test import QemuUserTest, Asset +from qemu_test import skipIfMissingCommands, skipUntrustedTest + + +class LoadBFLT(QemuUserTest): + + ASSET_ROOTFS = Asset( + ('https://elinux.org/images/5/51/Stm32_mini_rootfs.cpio.bz2'), + 'eefb788e4980c9e8d6c9d60ce7d15d4da6bf4fbc6a80f487673824600d5ba9cc') + + @skipIfMissingCommands('cpio') + @skipUntrustedTest() + def test_stm32(self): + # See https://elinux.org/STM32#User_Space + rootfs_path_bz2 = self.ASSET_ROOTFS.fetch() + busybox_path = self.scratch_file("bin", "busybox") + + with bz2.open(rootfs_path_bz2, 'rb') as cpio_handle: + self.archive_extract(cpio_handle, format="cpio") + + res = self.run_cmd(busybox_path) + ver = 'BusyBox v1.24.0.git (2015-02-03 22:17:13 CET) multi-call binary.' + self.assertIn(ver, res.stdout) + + res = self.run_cmd(busybox_path, ['uname', '-a']) + unm = 'armv7l GNU/Linux' + self.assertIn(unm, res.stdout) + + +if __name__ == '__main__': + QemuUserTest.main() diff --git a/tests/functional/arm/test_bpim2u.py b/tests/functional/arm/test_bpim2u.py new file mode 100755 index 0000000..8bed64b --- /dev/null +++ b/tests/functional/arm/test_bpim2u.py @@ -0,0 +1,180 @@ +#!/usr/bin/env python3 +# +# Functional test that boots a Linux kernel on a Banana Pi machine +# and checks the console +# +# SPDX-License-Identifier: GPL-2.0-or-later + +import os + +from qemu_test import LinuxKernelTest, exec_command_and_wait_for_pattern +from qemu_test import Asset, interrupt_interactive_console_until_pattern +from qemu_test import skipBigDataTest +from qemu_test.utils import image_pow2ceil_expand + + +class BananaPiMachine(LinuxKernelTest): + + ASSET_DEB = Asset( + ('https://apt.armbian.com/pool/main/l/linux-6.6.16/' + 'linux-image-current-sunxi_24.2.1_armhf__6.6.16-Seb3e-D6b4a-P2359-Ce96bHfe66-HK01ba-V014b-B067e-R448a.deb'), + '3d968c15b121ede871dce49d13ee7644d6f74b6b121b84c9a40f51b0c80d6d22') + + ASSET_INITRD = Asset( + ('https://github.com/groeck/linux-build-test/raw/' + '2eb0a73b5d5a28df3170c546ddaaa9757e1e0848/rootfs/' + 'arm/rootfs-armv7a.cpio.gz'), + '2c8dbdb16ea7af2dfbcbea96044dde639fb07d09fd3c4fb31f2027ef71e55ddd') + + ASSET_ROOTFS = Asset( + ('http://storage.kernelci.org/images/rootfs/buildroot/' + 'buildroot-baseline/20230703.0/armel/rootfs.ext2.xz'), + '42b44a12965ac0afe9a88378527fb698a7dc76af50495efc2361ee1595b4e5c6') + + ASSET_SD_IMAGE = Asset( + ('https://downloads.openwrt.org/releases/22.03.3/targets/sunxi/cortexa7/' + 'openwrt-22.03.3-sunxi-cortexa7-sinovoip_bananapi-m2-ultra-ext4-sdcard.img.gz'), + '5b41b4e11423e562c6011640f9a7cd3bdd0a3d42b83430f7caa70a432e6cd82c') + + def test_arm_bpim2u(self): + self.set_machine('bpim2u') + kernel_path = self.archive_extract( + self.ASSET_DEB, member='boot/vmlinuz-6.6.16-current-sunxi') + dtb_path = ('usr/lib/linux-image-6.6.16-current-sunxi/' + 'sun8i-r40-bananapi-m2-ultra.dtb') + dtb_path = self.archive_extract(self.ASSET_DEB, member=dtb_path) + + self.vm.set_console() + kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE + + 'console=ttyS0,115200n8 ' + 'earlycon=uart,mmio32,0x1c28000') + self.vm.add_args('-kernel', kernel_path, + '-dtb', dtb_path, + '-append', kernel_command_line) + self.vm.launch() + console_pattern = 'Kernel command line: %s' % kernel_command_line + self.wait_for_console_pattern(console_pattern) + os.remove(kernel_path) + os.remove(dtb_path) + + def test_arm_bpim2u_initrd(self): + self.set_machine('bpim2u') + kernel_path = self.archive_extract( + self.ASSET_DEB, member='boot/vmlinuz-6.6.16-current-sunxi') + dtb_path = ('usr/lib/linux-image-6.6.16-current-sunxi/' + 'sun8i-r40-bananapi-m2-ultra.dtb') + dtb_path = self.archive_extract(self.ASSET_DEB, member=dtb_path) + initrd_path = self.uncompress(self.ASSET_INITRD) + + self.vm.set_console() + kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE + + 'console=ttyS0,115200 ' + 'panic=-1 noreboot') + self.vm.add_args('-kernel', kernel_path, + '-dtb', dtb_path, + '-initrd', initrd_path, + '-append', kernel_command_line, + '-no-reboot') + self.vm.launch() + self.wait_for_console_pattern('Boot successful.') + + exec_command_and_wait_for_pattern(self, 'cat /proc/cpuinfo', + 'Allwinner sun8i Family') + exec_command_and_wait_for_pattern(self, 'cat /proc/iomem', + 'system-control@1c00000') + exec_command_and_wait_for_pattern(self, 'reboot', + 'reboot: Restarting system') + # Wait for VM to shut down gracefully + self.vm.wait() + os.remove(kernel_path) + os.remove(dtb_path) + os.remove(initrd_path) + + def test_arm_bpim2u_gmac(self): + self.set_machine('bpim2u') + self.require_netdev('user') + + deb_path = self.ASSET_DEB.fetch() + kernel_path = self.archive_extract( + self.ASSET_DEB, member='boot/vmlinuz-6.6.16-current-sunxi') + dtb_path = ('usr/lib/linux-image-6.6.16-current-sunxi/' + 'sun8i-r40-bananapi-m2-ultra.dtb') + dtb_path = self.archive_extract(self.ASSET_DEB, member=dtb_path) + rootfs_path = self.uncompress(self.ASSET_ROOTFS) + image_pow2ceil_expand(rootfs_path) + + self.vm.set_console() + kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE + + 'console=ttyS0,115200 ' + 'root=b300 rootwait rw ' + 'panic=-1 noreboot') + self.vm.add_args('-kernel', kernel_path, + '-dtb', dtb_path, + '-drive', 'file=' + rootfs_path + ',if=sd,format=raw', + '-net', 'nic,model=gmac,netdev=host_gmac', + '-netdev', 'user,id=host_gmac', + '-append', kernel_command_line, + '-no-reboot') + self.vm.launch() + shell_ready = "/bin/sh: can't access tty; job control turned off" + self.wait_for_console_pattern(shell_ready) + + exec_command_and_wait_for_pattern(self, 'cat /proc/cpuinfo', + 'Allwinner sun8i Family') + exec_command_and_wait_for_pattern(self, 'cat /proc/partitions', + 'mmcblk') + exec_command_and_wait_for_pattern(self, 'ifconfig eth0 up', + 'eth0: Link is Up') + exec_command_and_wait_for_pattern(self, 'udhcpc eth0', + 'udhcpc: lease of 10.0.2.15 obtained') + exec_command_and_wait_for_pattern(self, 'ping -c 3 10.0.2.2', + '3 packets transmitted, 3 packets received, 0% packet loss') + exec_command_and_wait_for_pattern(self, 'reboot', + 'reboot: Restarting system') + # Wait for VM to shut down gracefully + self.vm.wait() + os.remove(kernel_path) + os.remove(dtb_path) + os.remove(rootfs_path) + + @skipBigDataTest() + def test_arm_bpim2u_openwrt_22_03_3(self): + self.set_machine('bpim2u') + self.require_netdev('user') + + # This test download a 8.9 MiB compressed image and expand it + # to 127 MiB. + image_path = self.uncompress(self.ASSET_SD_IMAGE) + image_pow2ceil_expand(image_path) + + self.vm.set_console() + self.vm.add_args('-drive', 'file=' + image_path + ',if=sd,format=raw', + '-nic', 'user', + '-no-reboot') + self.vm.launch() + + kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE + + 'usbcore.nousb ' + 'noreboot') + + self.wait_for_console_pattern('U-Boot SPL') + + interrupt_interactive_console_until_pattern( + self, 'Hit any key to stop autoboot:', '=>') + exec_command_and_wait_for_pattern(self, "setenv extraargs '" + + kernel_command_line + "'", '=>') + exec_command_and_wait_for_pattern(self, 'boot', 'Starting kernel ...') + + self.wait_for_console_pattern( + 'Please press Enter to activate this console.') + + exec_command_and_wait_for_pattern(self, ' ', 'root@') + + exec_command_and_wait_for_pattern(self, 'cat /proc/cpuinfo', + 'Allwinner sun8i Family') + exec_command_and_wait_for_pattern(self, 'cat /proc/iomem', + 'system-control@1c00000') + os.remove(image_path) + +if __name__ == '__main__': + LinuxKernelTest.main() diff --git a/tests/functional/arm/test_canona1100.py b/tests/functional/arm/test_canona1100.py new file mode 100755 index 0000000..21a1a59 --- /dev/null +++ b/tests/functional/arm/test_canona1100.py @@ -0,0 +1,37 @@ +#!/usr/bin/env python3 +# +# Functional test that boots the canon-a1100 machine with firmware +# +# Copyright (c) 2020 Red Hat, Inc. +# +# Author: +# Thomas Huth +# +# This work is licensed under the terms of the GNU GPL, version 2 or +# later. See the COPYING file in the top-level directory. + +from qemu_test import QemuSystemTest, Asset +from qemu_test import wait_for_console_pattern + + +class CanonA1100Machine(QemuSystemTest): + """Boots the barebox firmware and checks that the console is operational""" + + timeout = 90 + + ASSET_BIOS = Asset(('https://qemu-advcal.gitlab.io' + '/qac-best-of-multiarch/download/day18.tar.xz'), + '28e71874ce985be66b7fd1345ed88cb2523b982f899c8d2900d6353054a1be49') + + def test_arm_canona1100(self): + self.set_machine('canon-a1100') + + bios = self.archive_extract(self.ASSET_BIOS, + member="day18/barebox.canon-a1100.bin") + self.vm.set_console() + self.vm.add_args('-bios', bios) + self.vm.launch() + wait_for_console_pattern(self, 'running /env/bin/init') + +if __name__ == '__main__': + QemuSystemTest.main() diff --git a/tests/functional/arm/test_collie.py b/tests/functional/arm/test_collie.py new file mode 100755 index 0000000..fe1be3d --- /dev/null +++ b/tests/functional/arm/test_collie.py @@ -0,0 +1,31 @@ +#!/usr/bin/env python3 +# +# Functional test that boots a Linux kernel on a collie machine +# and checks the console +# +# SPDX-License-Identifier: GPL-2.0-or-later + +from qemu_test import LinuxKernelTest, Asset + + +class CollieTest(LinuxKernelTest): + + ASSET_ZIMAGE = Asset( + 'https://github.com/groeck/linux-test-downloads/raw/225223f2ad7d637b34426810bf6c3b727b76a718/collie/zImage', + '10ace8abf9e0875ef8a83b8829cc3b5b50bc6d7bc3ca29f19f49f5673a43c13b') + + ASSET_ROOTFS = Asset( + 'https://github.com/groeck/linux-test-downloads/raw/225223f2ad7d637b34426810bf6c3b727b76a718/collie/rootfs-sa110.cpio', + '89ccaaa5c6b33331887047e1618ffe81b0f55909173944347d5d2426f3bcc1f2') + + def test_arm_collie(self): + self.set_machine('collie') + zimage_path = self.ASSET_ZIMAGE.fetch() + rootfs_path = self.ASSET_ROOTFS.fetch() + self.vm.add_args('-append', 'rdinit=/sbin/init console=ttySA1') + self.launch_kernel(zimage_path, + initrd=rootfs_path, + wait_for='reboot: Restarting system') + +if __name__ == '__main__': + LinuxKernelTest.main() diff --git a/tests/functional/arm/test_cubieboard.py b/tests/functional/arm/test_cubieboard.py new file mode 100755 index 0000000..b536c2f --- /dev/null +++ b/tests/functional/arm/test_cubieboard.py @@ -0,0 +1,144 @@ +#!/usr/bin/env python3 +# +# Functional test that boots a Linux kernel and checks the console +# +# SPDX-License-Identifier: GPL-2.0-or-later + +from qemu_test import LinuxKernelTest, Asset, exec_command_and_wait_for_pattern +from qemu_test import interrupt_interactive_console_until_pattern +from qemu_test import skipBigDataTest +from qemu_test.utils import image_pow2ceil_expand + + +class CubieboardMachine(LinuxKernelTest): + + ASSET_DEB = Asset( + ('https://apt.armbian.com/pool/main/l/linux-6.6.16/' + 'linux-image-current-sunxi_24.2.1_armhf__6.6.16-Seb3e-D6b4a-P2359-Ce96bHfe66-HK01ba-V014b-B067e-R448a.deb'), + '3d968c15b121ede871dce49d13ee7644d6f74b6b121b84c9a40f51b0c80d6d22') + + ASSET_INITRD = Asset( + ('https://github.com/groeck/linux-build-test/raw/' + '2eb0a73b5d5a28df3170c546ddaaa9757e1e0848/rootfs/' + 'arm/rootfs-armv5.cpio.gz'), + '334b8d256db67a3f2b3ad070aa08b5ade39624e0e7e35b02f4359a577bc8f39b') + + ASSET_SATA_ROOTFS = Asset( + ('https://github.com/groeck/linux-build-test/raw/' + '2eb0a73b5d5a28df3170c546ddaaa9757e1e0848/rootfs/' + 'arm/rootfs-armv5.ext2.gz'), + '17fc750da568580b39372133051ef2f0a963c0c0b369b845614442d025701745') + + ASSET_OPENWRT = Asset( + ('https://downloads.openwrt.org/releases/22.03.2/targets/sunxi/cortexa8/' + 'openwrt-22.03.2-sunxi-cortexa8-cubietech_a10-cubieboard-ext4-sdcard.img.gz'), + '94b5ecbfbc0b3b56276e5146b899eafa2ac5dc2d08733d6705af9f144f39f554') + + def test_arm_cubieboard_initrd(self): + self.set_machine('cubieboard') + kernel_path = self.archive_extract( + self.ASSET_DEB, member='boot/vmlinuz-6.6.16-current-sunxi') + dtb_path = ('usr/lib/linux-image-6.6.16-current-sunxi/' + + 'sun4i-a10-cubieboard.dtb') + dtb_path = self.archive_extract(self.ASSET_DEB, member=dtb_path) + initrd_path = self.uncompress(self.ASSET_INITRD) + + self.vm.set_console() + kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE + + 'console=ttyS0,115200 ' + 'usbcore.nousb ' + 'panic=-1 noreboot') + self.vm.add_args('-kernel', kernel_path, + '-dtb', dtb_path, + '-initrd', initrd_path, + '-append', kernel_command_line, + '-no-reboot') + self.vm.launch() + self.wait_for_console_pattern('Boot successful.') + + exec_command_and_wait_for_pattern(self, 'cat /proc/cpuinfo', + 'Allwinner sun4i/sun5i') + exec_command_and_wait_for_pattern(self, 'cat /proc/iomem', + 'system-control@1c00000') + exec_command_and_wait_for_pattern(self, 'reboot', + 'reboot: Restarting system') + # Wait for VM to shut down gracefully + self.vm.wait() + + def test_arm_cubieboard_sata(self): + self.set_machine('cubieboard') + kernel_path = self.archive_extract( + self.ASSET_DEB, member='boot/vmlinuz-6.6.16-current-sunxi') + dtb_path = ('usr/lib/linux-image-6.6.16-current-sunxi/' + + 'sun4i-a10-cubieboard.dtb') + dtb_path = self.archive_extract(self.ASSET_DEB, member=dtb_path) + + rootfs_path = self.uncompress(self.ASSET_SATA_ROOTFS) + + self.vm.set_console() + kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE + + 'console=ttyS0,115200 ' + 'usbcore.nousb ' + 'root=/dev/sda ro ' + 'panic=-1 noreboot') + self.vm.add_args('-kernel', kernel_path, + '-dtb', dtb_path, + '-drive', 'if=none,format=raw,id=disk0,file=' + + rootfs_path, + '-device', 'ide-hd,bus=ide.0,drive=disk0', + '-append', kernel_command_line, + '-no-reboot') + self.vm.launch() + self.wait_for_console_pattern('Boot successful.') + + exec_command_and_wait_for_pattern(self, 'cat /proc/cpuinfo', + 'Allwinner sun4i/sun5i') + exec_command_and_wait_for_pattern(self, 'cat /proc/partitions', + 'sda') + exec_command_and_wait_for_pattern(self, 'reboot', + 'reboot: Restarting system') + # Wait for VM to shut down gracefully + self.vm.wait() + + @skipBigDataTest() + def test_arm_cubieboard_openwrt_22_03_2(self): + # This test download a 7.5 MiB compressed image and expand it + # to 126 MiB. + self.set_machine('cubieboard') + self.require_netdev('user') + + image_path = self.uncompress(self.ASSET_OPENWRT) + image_pow2ceil_expand(image_path) + + self.vm.set_console() + self.vm.add_args('-drive', 'file=' + image_path + ',if=sd,format=raw', + '-nic', 'user', + '-no-reboot') + self.vm.launch() + + kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE + + 'usbcore.nousb ' + 'noreboot') + + self.wait_for_console_pattern('U-Boot SPL') + + interrupt_interactive_console_until_pattern( + self, 'Hit any key to stop autoboot:', '=>') + exec_command_and_wait_for_pattern(self, "setenv extraargs '" + + kernel_command_line + "'", '=>') + exec_command_and_wait_for_pattern(self, 'boot', 'Starting kernel ...') + + self.wait_for_console_pattern( + 'Please press Enter to activate this console.') + + exec_command_and_wait_for_pattern(self, ' ', 'root@') + + exec_command_and_wait_for_pattern(self, 'cat /proc/cpuinfo', + 'Allwinner sun4i/sun5i') + exec_command_and_wait_for_pattern(self, 'reboot', + 'reboot: Restarting system') + # Wait for VM to shut down gracefully + self.vm.wait() + +if __name__ == '__main__': + LinuxKernelTest.main() diff --git a/tests/functional/arm/test_emcraft_sf2.py b/tests/functional/arm/test_emcraft_sf2.py new file mode 100755 index 0000000..f9f3f06 --- /dev/null +++ b/tests/functional/arm/test_emcraft_sf2.py @@ -0,0 +1,52 @@ +#!/usr/bin/env python3 +# +# Functional test that boots a Linux kernel and checks the console +# +# SPDX-License-Identifier: GPL-2.0-or-later + +import os +import shutil + +from qemu_test import LinuxKernelTest, Asset, exec_command_and_wait_for_pattern +from qemu_test.utils import file_truncate + +class EmcraftSf2Machine(LinuxKernelTest): + + ASSET_UBOOT = Asset( + ('https://raw.githubusercontent.com/Subbaraya-Sundeep/qemu-test-binaries/' + 'fe371d32e50ca682391e1e70ab98c2942aeffb01/u-boot'), + '5c6a15103375db11b21f2236473679a9dbbed6d89652bfcdd501c263d68ab725') + + ASSET_SPI = Asset( + ('https://raw.githubusercontent.com/Subbaraya-Sundeep/qemu-test-binaries/' + 'fe371d32e50ca682391e1e70ab98c2942aeffb01/spi.bin'), + 'cd9bdd2c4cb55a59c3adb6bcf74881667c4500dde0570a43aa3be2b17eecfdb6') + + def test_arm_emcraft_sf2(self): + self.set_machine('emcraft-sf2') + self.require_netdev('user') + + uboot_path = self.ASSET_UBOOT.fetch() + spi_path = self.ASSET_SPI.fetch() + spi_path_rw = self.scratch_file('spi.bin') + shutil.copy(spi_path, spi_path_rw) + os.chmod(spi_path_rw, 0o600) + + file_truncate(spi_path_rw, 16 << 20) # Spansion S25FL128SDPBHICO is 16 MiB + + self.vm.set_console() + kernel_command_line = self.KERNEL_COMMON_COMMAND_LINE + self.vm.add_args('-kernel', uboot_path, + '-append', kernel_command_line, + '-drive', 'file=' + spi_path_rw + ',if=mtd,format=raw', + '-no-reboot') + self.vm.launch() + self.wait_for_console_pattern('Enter \'help\' for a list') + + exec_command_and_wait_for_pattern(self, 'ifconfig eth0 10.0.2.15', + 'eth0: link becomes ready') + exec_command_and_wait_for_pattern(self, 'ping -c 3 10.0.2.2', + '3 packets transmitted, 3 packets received, 0% packet loss') + +if __name__ == '__main__': + LinuxKernelTest.main() diff --git a/tests/functional/arm/test_integratorcp.py b/tests/functional/arm/test_integratorcp.py new file mode 100755 index 0000000..4f00924 --- /dev/null +++ b/tests/functional/arm/test_integratorcp.py @@ -0,0 +1,95 @@ +#!/usr/bin/env python3 +# +# Functional test that boots a Linux kernel and checks the console +# +# Copyright (c) 2020 Red Hat, Inc. +# +# Author: +# Thomas Huth +# +# This work is licensed under the terms of the GNU GPL, version 2 or +# later. See the COPYING file in the top-level directory. +# +# SPDX-License-Identifier: GPL-2.0-or-later + +import logging + +from qemu_test import QemuSystemTest, Asset +from qemu_test import wait_for_console_pattern +from qemu_test import skipIfMissingImports, skipUntrustedTest + + +class IntegratorMachine(QemuSystemTest): + + timeout = 90 + + ASSET_KERNEL = Asset( + ('https://github.com/zayac/qemu-arm/raw/master/' + 'arm-test/kernel/zImage.integrator'), + '26e7c7e8f943de785d95bd3c74d66451604a9b6a7a3d25dceb279e7548fd8e78') + + ASSET_INITRD = Asset( + ('https://github.com/zayac/qemu-arm/raw/master/' + 'arm-test/kernel/arm_root.img'), + 'e187c27fb342ad148c7f33475fbed124933e0b3f4be8c74bc4f3426a4793373a') + + ASSET_TUXLOGO = Asset( + ('https://github.com/torvalds/linux/raw/v2.6.12/' + 'drivers/video/logo/logo_linux_vga16.ppm'), + 'b762f0d91ec018887ad1b334543c2fdf9be9fdfc87672b409211efaa3ea0ef79') + + def boot_integratorcp(self): + kernel_path = self.ASSET_KERNEL.fetch() + initrd_path = self.ASSET_INITRD.fetch() + + self.set_machine('integratorcp') + self.vm.set_console() + self.vm.add_args('-kernel', kernel_path, + '-initrd', initrd_path, + '-append', 'printk.time=0 console=ttyAMA0') + self.vm.launch() + + @skipUntrustedTest() + def test_integratorcp_console(self): + """ + Boots the Linux kernel and checks that the console is operational + """ + self.boot_integratorcp() + wait_for_console_pattern(self, 'Log in as root') + + @skipIfMissingImports("numpy", "cv2") + @skipUntrustedTest() + def test_framebuffer_tux_logo(self): + """ + Boot Linux and verify the Tux logo is displayed on the framebuffer. + """ + import numpy as np + import cv2 + + screendump_path = self.scratch_file("screendump.pbm") + tuxlogo_path = self.ASSET_TUXLOGO.fetch() + + self.boot_integratorcp() + framebuffer_ready = 'Console: switching to colour frame buffer device' + wait_for_console_pattern(self, framebuffer_ready) + self.vm.cmd('human-monitor-command', command_line='stop') + res = self.vm.cmd('human-monitor-command', + command_line='screendump %s' % screendump_path) + if 'unknown command' in res: + self.skipTest('screendump not available') + logger = logging.getLogger('framebuffer') + + cpu_count = 1 + match_threshold = 0.92 + screendump_bgr = cv2.imread(screendump_path) + screendump_gray = cv2.cvtColor(screendump_bgr, cv2.COLOR_BGR2GRAY) + result = cv2.matchTemplate(screendump_gray, cv2.imread(tuxlogo_path, 0), + cv2.TM_CCOEFF_NORMED) + loc = np.where(result >= match_threshold) + tux_count = 0 + for tux_count, pt in enumerate(zip(*loc[::-1]), start=1): + logger.debug('found Tux at position [x, y] = %s', pt) + self.assertGreaterEqual(tux_count, cpu_count) + +if __name__ == '__main__': + QemuSystemTest.main() diff --git a/tests/functional/arm/test_max78000fthr.py b/tests/functional/arm/test_max78000fthr.py new file mode 100755 index 0000000..a82980b --- /dev/null +++ b/tests/functional/arm/test_max78000fthr.py @@ -0,0 +1,48 @@ +#!/usr/bin/env python3 +# +# Functional test that checks the max78000fthr machine. +# Tests ICC, GCR, TRNG, AES, and UART +# +# SPDX-License-Identifier: GPL-2.0-or-later + +from qemu_test import QemuSystemTest, Asset, exec_command_and_wait_for_pattern +from qemu_test import wait_for_console_pattern + + +class Max78000Machine(QemuSystemTest): + + ASSET_FW = Asset( + 'https://github.com/JacksonDonaldson/max78000Test/raw/main/build/max78000.bin', + '86940b4bf60931bc6a8aa5db4b9f7f3cf8f64dbbd7ac534647980e536cf3adf7') + + def test_fthr(self): + self.set_machine('max78000fthr') + fw_path = self.ASSET_FW.fetch() + self.vm.set_console() + self.vm.add_args('-kernel', fw_path) + self.vm.add_args('-device', "loader,file=" + fw_path + ",addr=0x10000000") + self.vm.launch() + + wait_for_console_pattern(self, 'started') + + # i -> prints instruction cache values + exec_command_and_wait_for_pattern(self, 'i', 'CTRL: 00010001') + + # r -> gcr resets the machine + exec_command_and_wait_for_pattern(self, 'r', 'started') + + # z -> sets some memory, then has gcr zero it + exec_command_and_wait_for_pattern(self, 'z', 'initial value: 12345678') + wait_for_console_pattern(self, "after memz: 00000000") + + # t -> runs trng + exec_command_and_wait_for_pattern(self, 't', 'random data:') + + # a -> runs aes + exec_command_and_wait_for_pattern(self, 'a', + 'encrypted to : a47ca9dd e0df4c86 a070af6e 91710dec') + wait_for_console_pattern(self, + 'encrypted to : cab7a28e bf456751 9049fcea 8960494b') + +if __name__ == '__main__': + QemuSystemTest.main() diff --git a/tests/functional/arm/test_microbit.py b/tests/functional/arm/test_microbit.py new file mode 100755 index 0000000..68ea4e7 --- /dev/null +++ b/tests/functional/arm/test_microbit.py @@ -0,0 +1,31 @@ +#!/usr/bin/env python3 +# +# SPDX-License-Identifier: GPL-2.0-or-later +# +# Copyright 2025, The QEMU Project Developers. +# +# A functional test that runs MicroPython on the arm microbit machine. + +from qemu_test import QemuSystemTest, Asset, exec_command_and_wait_for_pattern +from qemu_test import wait_for_console_pattern + + +class MicrobitMachine(QemuSystemTest): + + ASSET_MICRO = Asset('https://ozlabs.org/~joel/microbit-micropython.hex', + '021641f93dfb11767d4978dbb3ca7f475d1b13c69e7f4aec3382f212636bffd6') + + def test_arm_microbit(self): + self.set_machine('microbit') + + micropython = self.ASSET_MICRO.fetch() + self.vm.set_console() + self.vm.add_args('-device', f'loader,file={micropython}') + self.vm.launch() + wait_for_console_pattern(self, 'Type "help()" for more information.') + exec_command_and_wait_for_pattern(self, 'import machine as mch', '>>>') + exec_command_and_wait_for_pattern(self, 'mch.reset()', 'MicroPython') + wait_for_console_pattern(self, '>>>') + +if __name__ == '__main__': + QemuSystemTest.main() diff --git a/tests/functional/arm/test_migration.py b/tests/functional/arm/test_migration.py new file mode 100755 index 0000000..0aa89f4 --- /dev/null +++ b/tests/functional/arm/test_migration.py @@ -0,0 +1,26 @@ +#!/usr/bin/env python3 +# +# SPDX-License-Identifier: GPL-2.0-or-later +# +# arm migration test + +from migration import MigrationTest + + +class ArmMigrationTest(MigrationTest): + + def test_migration_with_tcp_localhost(self): + self.set_machine('npcm750-evb') + self.migration_with_tcp_localhost() + + def test_migration_with_unix(self): + self.set_machine('npcm750-evb') + self.migration_with_unix() + + def test_migration_with_exec(self): + self.set_machine('npcm750-evb') + self.migration_with_exec() + + +if __name__ == '__main__': + MigrationTest.main() diff --git a/tests/functional/arm/test_orangepi.py b/tests/functional/arm/test_orangepi.py new file mode 100755 index 0000000..f9bfa8c --- /dev/null +++ b/tests/functional/arm/test_orangepi.py @@ -0,0 +1,237 @@ +#!/usr/bin/env python3 +# +# Functional test that boots a Linux kernel on an Orange Pi machine +# and checks the console +# +# SPDX-License-Identifier: GPL-2.0-or-later + +import os +import shutil + +from qemu_test import LinuxKernelTest, exec_command_and_wait_for_pattern +from qemu_test import Asset, interrupt_interactive_console_until_pattern +from qemu_test import wait_for_console_pattern, skipBigDataTest +from qemu_test.utils import image_pow2ceil_expand + + +class OrangePiMachine(LinuxKernelTest): + + ASSET_DEB = Asset( + ('https://apt.armbian.com/pool/main/l/linux-6.6.16/' + 'linux-image-current-sunxi_24.2.1_armhf__6.6.16-Seb3e-D6b4a-P2359-Ce96bHfe66-HK01ba-V014b-B067e-R448a.deb'), + '3d968c15b121ede871dce49d13ee7644d6f74b6b121b84c9a40f51b0c80d6d22') + + ASSET_INITRD = Asset( + ('https://github.com/groeck/linux-build-test/raw/' + '2eb0a73b5d5a28df3170c546ddaaa9757e1e0848/rootfs/' + 'arm/rootfs-armv7a.cpio.gz'), + '2c8dbdb16ea7af2dfbcbea96044dde639fb07d09fd3c4fb31f2027ef71e55ddd') + + ASSET_ROOTFS = Asset( + ('http://storage.kernelci.org/images/rootfs/buildroot/' + 'buildroot-baseline/20230703.0/armel/rootfs.ext2.xz'), + '42b44a12965ac0afe9a88378527fb698a7dc76af50495efc2361ee1595b4e5c6') + + ASSET_ARMBIAN = Asset( + ('https://k-space.ee.armbian.com/archive/orangepipc/archive/' + 'Armbian_23.8.1_Orangepipc_jammy_current_6.1.47.img.xz'), + 'b386dff6552513b5f164ea00f94814a6b0f1da9fb90b83725e949cf797e11afb') + + ASSET_UBOOT = Asset( + ('http://snapshot.debian.org/archive/debian/20200108T145233Z/pool/' + 'main/u/u-boot/u-boot-sunxi_2020.01%2Bdfsg-1_armhf.deb'), + '9223d94dc283ab54df41ce9d6f69025a5b47fece29fb67a714e23aa0cdf3bdfa') + + ASSET_NETBSD = Asset( + ('https://archive.netbsd.org/pub/NetBSD-archive/NetBSD-9.0/' + 'evbarm-earmv7hf/binary/gzimg/armv7.img.gz'), + '20d3e07dc057e15c12452620e90ecab2047f0f7940d9cba8182ebc795927177f') + + def test_arm_orangepi(self): + self.set_machine('orangepi-pc') + kernel_path = self.archive_extract( + self.ASSET_DEB, member='boot/vmlinuz-6.6.16-current-sunxi') + dtb_path = ('usr/lib/linux-image-6.6.16-current-sunxi/' + + 'sun8i-h3-orangepi-pc.dtb') + dtb_path = self.archive_extract(self.ASSET_DEB, member=dtb_path) + + self.vm.set_console() + kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE + + 'console=ttyS0,115200n8 ' + 'earlycon=uart,mmio32,0x1c28000') + self.vm.add_args('-kernel', kernel_path, + '-dtb', dtb_path, + '-append', kernel_command_line) + self.vm.launch() + console_pattern = 'Kernel command line: %s' % kernel_command_line + self.wait_for_console_pattern(console_pattern) + os.remove(kernel_path) + os.remove(dtb_path) + + def test_arm_orangepi_initrd(self): + self.set_machine('orangepi-pc') + kernel_path = self.archive_extract( + self.ASSET_DEB, member='boot/vmlinuz-6.6.16-current-sunxi') + dtb_path = ('usr/lib/linux-image-6.6.16-current-sunxi/' + + 'sun8i-h3-orangepi-pc.dtb') + dtb_path = self.archive_extract(self.ASSET_DEB, member=dtb_path) + initrd_path = self.uncompress(self.ASSET_INITRD) + + self.vm.set_console() + kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE + + 'console=ttyS0,115200 ' + 'panic=-1 noreboot') + self.vm.add_args('-kernel', kernel_path, + '-dtb', dtb_path, + '-initrd', initrd_path, + '-append', kernel_command_line, + '-no-reboot') + self.vm.launch() + self.wait_for_console_pattern('Boot successful.') + + exec_command_and_wait_for_pattern(self, 'cat /proc/cpuinfo', + 'Allwinner sun8i Family') + exec_command_and_wait_for_pattern(self, 'cat /proc/iomem', + 'system-control@1c00000') + exec_command_and_wait_for_pattern(self, 'reboot', + 'reboot: Restarting system') + # Wait for VM to shut down gracefully + self.vm.wait() + os.remove(kernel_path) + os.remove(dtb_path) + os.remove(initrd_path) + + def test_arm_orangepi_sd(self): + self.set_machine('orangepi-pc') + self.require_netdev('user') + kernel_path = self.archive_extract( + self.ASSET_DEB, member='boot/vmlinuz-6.6.16-current-sunxi') + dtb_path = ('usr/lib/linux-image-6.6.16-current-sunxi/' + + 'sun8i-h3-orangepi-pc.dtb') + dtb_path = self.archive_extract(self.ASSET_DEB, member=dtb_path) + rootfs_path = self.uncompress(self.ASSET_ROOTFS) + image_pow2ceil_expand(rootfs_path) + + self.vm.set_console() + kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE + + 'console=ttyS0,115200 ' + 'root=/dev/mmcblk0 rootwait rw ' + 'panic=-1 noreboot') + self.vm.add_args('-kernel', kernel_path, + '-dtb', dtb_path, + '-drive', 'file=' + rootfs_path + ',if=sd,format=raw', + '-append', kernel_command_line, + '-no-reboot') + self.vm.launch() + shell_ready = "/bin/sh: can't access tty; job control turned off" + self.wait_for_console_pattern(shell_ready) + + exec_command_and_wait_for_pattern(self, 'cat /proc/cpuinfo', + 'Allwinner sun8i Family') + exec_command_and_wait_for_pattern(self, 'cat /proc/partitions', + 'mmcblk0') + exec_command_and_wait_for_pattern(self, 'ifconfig eth0 up', + 'eth0: Link is Up') + exec_command_and_wait_for_pattern(self, 'udhcpc eth0', + 'udhcpc: lease of 10.0.2.15 obtained') + exec_command_and_wait_for_pattern(self, 'ping -c 3 10.0.2.2', + '3 packets transmitted, 3 packets received, 0% packet loss') + exec_command_and_wait_for_pattern(self, 'reboot', + 'reboot: Restarting system') + # Wait for VM to shut down gracefully + self.vm.wait() + os.remove(kernel_path) + os.remove(dtb_path) + os.remove(rootfs_path) + + @skipBigDataTest() + def test_arm_orangepi_armbian(self): + self.set_machine('orangepi-pc') + self.require_netdev('user') + + # This test download a 275 MiB compressed image and expand it + # to 1036 MiB, but the underlying filesystem is 1552 MiB... + # As we expand it to 2 GiB we are safe. + image_path = self.uncompress(self.ASSET_ARMBIAN) + image_pow2ceil_expand(image_path) + + self.vm.set_console() + self.vm.add_args('-drive', 'file=' + image_path + ',if=sd,format=raw', + '-nic', 'user', + '-no-reboot') + self.vm.launch() + + kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE + + 'console=ttyS0,115200 ' + 'loglevel=7 ' + 'nosmp ' + 'systemd.default_timeout_start_sec=9000 ' + 'systemd.mask=armbian-zram-config.service ' + 'systemd.mask=armbian-ramlog.service') + + self.wait_for_console_pattern('U-Boot SPL') + self.wait_for_console_pattern('Autoboot in ') + exec_command_and_wait_for_pattern(self, ' ', '=>') + exec_command_and_wait_for_pattern(self, "setenv extraargs '" + + kernel_command_line + "'", '=>') + exec_command_and_wait_for_pattern(self, 'boot', 'Starting kernel ...') + + self.wait_for_console_pattern('systemd[1]: Hostname set ' + + 'to ') + self.wait_for_console_pattern('Starting Load Kernel Modules...') + + @skipBigDataTest() + def test_arm_orangepi_uboot_netbsd9(self): + self.set_machine('orangepi-pc') + self.require_netdev('user') + + # This test download a 304MB compressed image and expand it to 2GB + # We use the common OrangePi PC 'plus' build of U-Boot for our secondary + # program loader (SPL). We will then set the path to the more specific + # OrangePi "PC" device tree blob with 'setenv fdtfile' in U-Boot prompt, + # before to boot NetBSD. + uboot_path = 'usr/lib/u-boot/orangepi_plus/u-boot-sunxi-with-spl.bin' + uboot_path = self.archive_extract(self.ASSET_UBOOT, member=uboot_path) + image_path = self.uncompress(self.ASSET_NETBSD) + image_pow2ceil_expand(image_path) + image_drive_args = 'if=sd,format=raw,snapshot=on,file=' + image_path + + # dd if=u-boot-sunxi-with-spl.bin of=armv7.img bs=1K seek=8 conv=notrunc + with open(uboot_path, 'rb') as f_in: + with open(image_path, 'r+b') as f_out: + f_out.seek(8 * 1024) + shutil.copyfileobj(f_in, f_out) + + self.vm.set_console() + self.vm.add_args('-nic', 'user', + '-drive', image_drive_args, + '-global', 'allwinner-rtc.base-year=2000', + '-no-reboot') + self.vm.launch() + wait_for_console_pattern(self, 'U-Boot 2020.01+dfsg-1') + interrupt_interactive_console_until_pattern(self, + 'Hit any key to stop autoboot:', + 'switch to partitions #0, OK') + + exec_command_and_wait_for_pattern(self, '', '=>') + cmd = 'setenv bootargs root=ld0a' + exec_command_and_wait_for_pattern(self, cmd, '=>') + cmd = 'setenv kernel netbsd-GENERIC.ub' + exec_command_and_wait_for_pattern(self, cmd, '=>') + cmd = 'setenv fdtfile dtb/sun8i-h3-orangepi-pc.dtb' + exec_command_and_wait_for_pattern(self, cmd, '=>') + cmd = ("setenv bootcmd 'fatload mmc 0:1 ${kernel_addr_r} ${kernel}; " + "fatload mmc 0:1 ${fdt_addr_r} ${fdtfile}; " + "fdt addr ${fdt_addr_r}; " + "bootm ${kernel_addr_r} - ${fdt_addr_r}'") + exec_command_and_wait_for_pattern(self, cmd, '=>') + + exec_command_and_wait_for_pattern(self, 'boot', + 'Booting kernel from Legacy Image') + wait_for_console_pattern(self, 'Starting kernel ...') + wait_for_console_pattern(self, 'NetBSD 9.0 (GENERIC)') + # Wait for user-space + wait_for_console_pattern(self, 'Starting root file system check') + +if __name__ == '__main__': + LinuxKernelTest.main() diff --git a/tests/functional/arm/test_quanta_gsj.py b/tests/functional/arm/test_quanta_gsj.py new file mode 100755 index 0000000..cb0545f --- /dev/null +++ b/tests/functional/arm/test_quanta_gsj.py @@ -0,0 +1,92 @@ +#!/usr/bin/env python3 +# +# Functional test that boots a Linux kernel and checks the console +# +# SPDX-License-Identifier: GPL-2.0-or-later + +from qemu_test import LinuxKernelTest, Asset, exec_command_and_wait_for_pattern +from qemu_test import interrupt_interactive_console_until_pattern, skipSlowTest + + +class EmcraftSf2Machine(LinuxKernelTest): + + ASSET_IMAGE = Asset( + ('https://github.com/hskinnemoen/openbmc/releases/download/' + '20200711-gsj-qemu-0/obmc-phosphor-image-gsj.static.mtd.gz'), + 'eccd4e375cde53034c84aece5c511932cacf838d9fd3f63da368a511757da72b') + + ASSET_INITRD = Asset( + ('https://github.com/hskinnemoen/openbmc/releases/download/' + '20200711-gsj-qemu-0/obmc-phosphor-initramfs-gsj.cpio.xz'), + '37b05009fc54db1434beac12bd7ff99a2e751a2f032ee18d9042f991dd0cdeaa') + + ASSET_KERNEL = Asset( + ('https://github.com/hskinnemoen/openbmc/releases/download/' + '20200711-gsj-qemu-0/uImage-gsj.bin'), + 'ce6d6b37bff46c74fc7b1e90da10a431cc37a62cdb35ec199fa73473d0790110') + + ASSET_DTB = Asset( + ('https://github.com/hskinnemoen/openbmc/releases/download/' + '20200711-gsj-qemu-0/nuvoton-npcm730-gsj.dtb'), + '3249b2da787d4b9ad4e61f315b160abfceb87b5e1895a7ce898ce7f40c8d4045') + + @skipSlowTest() + def test_arm_quanta_gsj(self): + self.set_machine('quanta-gsj') + image_path = self.uncompress(self.ASSET_IMAGE, format='gz') + + self.vm.set_console() + drive_args = 'file=' + image_path + ',if=mtd,bus=0,unit=0' + self.vm.add_args('-drive', drive_args) + self.vm.launch() + + # Disable drivers and services that stall for a long time during boot, + # to avoid running past the 90-second timeout. These may be removed + # as the corresponding device support is added. + kernel_command_line = self.KERNEL_COMMON_COMMAND_LINE + ( + 'console=${console} ' + 'mem=${mem} ' + 'initcall_blacklist=npcm_i2c_bus_driver_init ' + 'systemd.mask=systemd-random-seed.service ' + 'systemd.mask=dropbearkey.service ' + ) + + self.wait_for_console_pattern('> BootBlock by Nuvoton') + self.wait_for_console_pattern('>Device: Poleg BMC NPCM730') + self.wait_for_console_pattern('>Skip DDR init.') + self.wait_for_console_pattern('U-Boot ') + interrupt_interactive_console_until_pattern( + self, 'Hit any key to stop autoboot:', 'U-Boot>') + exec_command_and_wait_for_pattern( + self, "setenv bootargs ${bootargs} " + kernel_command_line, + 'U-Boot>') + exec_command_and_wait_for_pattern( + self, 'run romboot', 'Booting Kernel from flash') + self.wait_for_console_pattern('Booting Linux on physical CPU 0x0') + self.wait_for_console_pattern('CPU1: thread -1, cpu 1, socket 0') + self.wait_for_console_pattern('OpenBMC Project Reference Distro') + self.wait_for_console_pattern('gsj login:') + + def test_arm_quanta_gsj_initrd(self): + self.set_machine('quanta-gsj') + initrd_path = self.ASSET_INITRD.fetch() + kernel_path = self.ASSET_KERNEL.fetch() + dtb_path = self.ASSET_DTB.fetch() + + self.vm.set_console() + kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE + + 'console=ttyS0,115200n8 ' + 'earlycon=uart8250,mmio32,0xf0001000') + self.vm.add_args('-kernel', kernel_path, + '-initrd', initrd_path, + '-dtb', dtb_path, + '-append', kernel_command_line) + self.vm.launch() + + self.wait_for_console_pattern('Booting Linux on physical CPU 0x0') + self.wait_for_console_pattern('CPU1: thread -1, cpu 1, socket 0') + self.wait_for_console_pattern( + 'Give root password for system maintenance') + +if __name__ == '__main__': + LinuxKernelTest.main() diff --git a/tests/functional/arm/test_raspi2.py b/tests/functional/arm/test_raspi2.py new file mode 100755 index 0000000..d3c7aaa --- /dev/null +++ b/tests/functional/arm/test_raspi2.py @@ -0,0 +1,92 @@ +#!/usr/bin/env python3 +# +# Functional test that boots a Linux kernel on a Raspberry Pi machine +# and checks the console +# +# Copyright (c) 2019 Philippe Mathieu-Daudé +# +# SPDX-License-Identifier: GPL-2.0-or-later + +from qemu_test import LinuxKernelTest, Asset +from qemu_test import exec_command_and_wait_for_pattern + + +class ArmRaspi2Machine(LinuxKernelTest): + + ASSET_KERNEL_20190215 = Asset( + ('http://archive.raspberrypi.org/debian/' + 'pool/main/r/raspberrypi-firmware/' + 'raspberrypi-kernel_1.20190215-1_armhf.deb'), + '9f1759f7228113da24f5ee2aa6312946ec09a83e076aba9406c46ff776dfb291') + + ASSET_INITRD = Asset( + ('https://github.com/groeck/linux-build-test/raw/' + '2eb0a73b5d5a28df3170c546ddaaa9757e1e0848/rootfs/' + 'arm/rootfs-armv7a.cpio.gz'), + '2c8dbdb16ea7af2dfbcbea96044dde639fb07d09fd3c4fb31f2027ef71e55ddd') + + def do_test_arm_raspi2(self, uart_id): + """ + The kernel can be rebuilt using the kernel source referenced + and following the instructions on the on: + https://www.raspberrypi.org/documentation/linux/kernel/building.md + """ + serial_kernel_cmdline = { + 0: 'earlycon=pl011,0x3f201000 console=ttyAMA0', + } + kernel_path = self.archive_extract(self.ASSET_KERNEL_20190215, + member='boot/kernel7.img') + dtb_path = self.archive_extract(self.ASSET_KERNEL_20190215, + member='boot/bcm2709-rpi-2-b.dtb') + + self.set_machine('raspi2b') + self.vm.set_console() + kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE + + serial_kernel_cmdline[uart_id] + + ' root=/dev/mmcblk0p2 rootwait ' + + 'dwc_otg.fiq_fsm_enable=0') + self.vm.add_args('-kernel', kernel_path, + '-dtb', dtb_path, + '-append', kernel_command_line, + '-device', 'usb-kbd') + self.vm.launch() + + console_pattern = 'Kernel command line: %s' % kernel_command_line + self.wait_for_console_pattern(console_pattern) + self.wait_for_console_pattern('Product: QEMU USB Keyboard') + + def test_arm_raspi2_uart0(self): + self.do_test_arm_raspi2(0) + + def test_arm_raspi2_initrd(self): + kernel_path = self.archive_extract(self.ASSET_KERNEL_20190215, + member='boot/kernel7.img') + dtb_path = self.archive_extract(self.ASSET_KERNEL_20190215, + member='boot/bcm2709-rpi-2-b.dtb') + initrd_path = self.uncompress(self.ASSET_INITRD) + + self.set_machine('raspi2b') + self.vm.set_console() + kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE + + 'earlycon=pl011,0x3f201000 console=ttyAMA0 ' + 'panic=-1 noreboot ' + + 'dwc_otg.fiq_fsm_enable=0') + self.vm.add_args('-kernel', kernel_path, + '-dtb', dtb_path, + '-initrd', initrd_path, + '-append', kernel_command_line, + '-no-reboot') + self.vm.launch() + self.wait_for_console_pattern('Boot successful.') + + exec_command_and_wait_for_pattern(self, 'cat /proc/cpuinfo', + 'BCM2835') + exec_command_and_wait_for_pattern(self, 'cat /proc/iomem', + '/soc/cprman@7e101000') + exec_command_and_wait_for_pattern(self, 'halt', 'reboot: System halted') + # Wait for VM to shut down gracefully + self.vm.wait() + + +if __name__ == '__main__': + LinuxKernelTest.main() diff --git a/tests/functional/arm/test_realview.py b/tests/functional/arm/test_realview.py new file mode 100755 index 0000000..82cc964 --- /dev/null +++ b/tests/functional/arm/test_realview.py @@ -0,0 +1,47 @@ +#!/usr/bin/env python3 +# +# Functional test that boots a Linux kernel on a realview arm machine +# and checks the console +# +# SPDX-License-Identifier: GPL-2.0-or-later + +from qemu_test import LinuxKernelTest, exec_command_and_wait_for_pattern +from qemu_test import Asset + + +class RealviewMachine(LinuxKernelTest): + + ASSET_REALVIEW_MPCORE = Asset( + ('https://archive.openwrt.org/chaos_calmer/15.05.1/realview/generic/' + 'openwrt-15.05.1-realview-vmlinux-initramfs.elf'), + 'd3a01037f33e7512d46d50975588d5c3a0e0cbf25f37afab44775c2a2be523e6') + + def test_realview_ep_mpcore(self): + self.require_netdev('user') + self.set_machine('realview-eb-mpcore') + kernel_path = self.ASSET_REALVIEW_MPCORE.fetch() + self.vm.set_console() + kernel_param = 'console=ttyAMA0 mem=128M quiet' + self.vm.add_args('-kernel', kernel_path, + '-append', kernel_param) + self.vm.launch() + self.wait_for_console_pattern('Please press Enter to activate') + prompt = ':/#' + exec_command_and_wait_for_pattern(self, '', prompt) + exec_command_and_wait_for_pattern(self, 'dmesg', kernel_param) + self.wait_for_console_pattern(prompt) + exec_command_and_wait_for_pattern(self, + ('while ! dmesg | grep "br-lan: port 1(eth0) entered" ;' + ' do sleep 1 ; done'), + 'entered forwarding state') + self.wait_for_console_pattern(prompt) + exec_command_and_wait_for_pattern(self, + 'while ! ifconfig | grep "10.0.2.15" ; do sleep 1 ; done', + 'addr:10.0.2.15') + self.wait_for_console_pattern(prompt) + exec_command_and_wait_for_pattern(self, 'ping -c 1 10.0.2.2', + '1 packets received, 0% packet loss') + + +if __name__ == '__main__': + LinuxKernelTest.main() diff --git a/tests/functional/arm/test_replay.py b/tests/functional/arm/test_replay.py new file mode 100755 index 0000000..e002e6a --- /dev/null +++ b/tests/functional/arm/test_replay.py @@ -0,0 +1,69 @@ +#!/usr/bin/env python3 +# +# Replay test that boots a Linux kernel on arm machines and checks the console +# +# SPDX-License-Identifier: GPL-2.0-or-later + +from qemu_test import Asset +from replay_kernel import ReplayKernelBase + + +class ArmReplay(ReplayKernelBase): + + ASSET_VIRT = Asset( + ('https://archives.fedoraproject.org/pub/archive/fedora/linux/' + 'releases/29/Everything/armhfp/os/images/pxeboot/vmlinuz'), + '18dd5f1a9a28bd539f9d047f7c0677211bae528e8712b40ca5a229a4ad8e2591') + + def test_virt(self): + self.set_machine('virt') + kernel_path = self.ASSET_VIRT.fetch() + kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE + + 'console=ttyAMA0') + console_pattern = 'VFS: Cannot open root device' + self.run_rr(kernel_path, kernel_command_line, console_pattern, shift=1) + + ASSET_CUBIE_KERNEL = Asset( + ('https://apt.armbian.com/pool/main/l/linux-6.6.16/' + 'linux-image-current-sunxi_24.2.1_armhf_' + '_6.6.16-Seb3e-D6b4a-P2359-Ce96bHfe66-HK01ba-V014b-B067e-R448a.deb'), + '3d968c15b121ede871dce49d13ee7644d6f74b6b121b84c9a40f51b0c80d6d22') + + ASSET_CUBIE_INITRD = Asset( + ('https://github.com/groeck/linux-build-test/raw/' + '2eb0a73b5d5a28df3170c546ddaaa9757e1e0848/rootfs/arm/rootfs-armv5.cpio.gz'), + '334b8d256db67a3f2b3ad070aa08b5ade39624e0e7e35b02f4359a577bc8f39b') + + def test_cubieboard(self): + self.set_machine('cubieboard') + kernel_path = self.archive_extract(self.ASSET_CUBIE_KERNEL, + member='boot/vmlinuz-6.6.16-current-sunxi') + dtb_path = self.archive_extract(self.ASSET_CUBIE_KERNEL, + member='usr/lib/linux-image-6.6.16-current-sunxi/sun4i-a10-cubieboard.dtb') + initrd_path = self.uncompress(self.ASSET_CUBIE_INITRD) + + kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE + + 'console=ttyS0,115200 ' + 'usbcore.nousb ' + 'panic=-1 noreboot') + console_pattern = 'Boot successful.' + self.run_rr(kernel_path, kernel_command_line, console_pattern, shift=1, + args=('-dtb', dtb_path, + '-initrd', initrd_path, + '-no-reboot')) + + ASSET_DAY16 = Asset( + 'https://qemu-advcal.gitlab.io/qac-best-of-multiarch/download/day16.tar.xz', + '63311adb2d4c4e7a73214a86d29988add87266a909719c56acfadd026b4110a7') + + def test_vexpressa9(self): + self.set_machine('vexpress-a9') + self.archive_extract(self.ASSET_DAY16) + kernel_path = self.scratch_file('day16', 'winter.zImage') + dtb_path = self.scratch_file('day16', 'vexpress-v2p-ca9.dtb') + self.run_rr(kernel_path, self.REPLAY_KERNEL_COMMAND_LINE, + 'QEMU advent calendar', args=('-dtb', dtb_path)) + + +if __name__ == '__main__': + ReplayKernelBase.main() diff --git a/tests/functional/arm/test_smdkc210.py b/tests/functional/arm/test_smdkc210.py new file mode 100755 index 0000000..3154e7f --- /dev/null +++ b/tests/functional/arm/test_smdkc210.py @@ -0,0 +1,51 @@ +#!/usr/bin/env python3 +# +# Functional test that boots a Linux kernel and checks the console +# +# SPDX-License-Identifier: GPL-2.0-or-later + +from qemu_test import LinuxKernelTest, Asset + + +class Smdkc210Machine(LinuxKernelTest): + + ASSET_DEB = Asset( + ('https://snapshot.debian.org/archive/debian/20190928T224601Z/pool/' + 'main/l/linux/linux-image-4.19.0-6-armmp_4.19.67-2+deb10u1_armhf.deb'), + '421804e7579ef40d554c962850dbdf1bfc79f7fa7faec9d391397170dc806c3e') + + ASSET_ROOTFS = Asset( + ('https://github.com/groeck/linux-build-test/raw/' + '2eb0a73b5d5a28df3170c546ddaaa9757e1e0848/rootfs/arm/' + 'rootfs-armv5.cpio.gz'), + '334b8d256db67a3f2b3ad070aa08b5ade39624e0e7e35b02f4359a577bc8f39b') + + def test_arm_exynos4210_initrd(self): + self.set_machine('smdkc210') + + kernel_path = self.archive_extract(self.ASSET_DEB, + member='boot/vmlinuz-4.19.0-6-armmp') + dtb_path = 'usr/lib/linux-image-4.19.0-6-armmp/exynos4210-smdkv310.dtb' + dtb_path = self.archive_extract(self.ASSET_DEB, member=dtb_path) + + initrd_path = self.uncompress(self.ASSET_ROOTFS) + + self.vm.set_console() + kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE + + 'earlycon=exynos4210,0x13800000 earlyprintk ' + + 'console=ttySAC0,115200n8 ' + + 'random.trust_cpu=off cryptomgr.notests ' + + 'cpuidle.off=1 panic=-1 noreboot') + + self.vm.add_args('-kernel', kernel_path, + '-dtb', dtb_path, + '-initrd', initrd_path, + '-append', kernel_command_line, + '-no-reboot') + self.vm.launch() + + self.wait_for_console_pattern('Boot successful.') + # TODO user command, for now the uart is stuck + +if __name__ == '__main__': + LinuxKernelTest.main() diff --git a/tests/functional/arm/test_stellaris.py b/tests/functional/arm/test_stellaris.py new file mode 100755 index 0000000..cbd21cb --- /dev/null +++ b/tests/functional/arm/test_stellaris.py @@ -0,0 +1,48 @@ +#!/usr/bin/env python3 +# +# Functional test that checks the serial console of the stellaris machines +# +# SPDX-License-Identifier: GPL-2.0-or-later + +from qemu_test import QemuSystemTest, Asset, exec_command_and_wait_for_pattern +from qemu_test import wait_for_console_pattern + + +class StellarisMachine(QemuSystemTest): + + ASSET_DAY22 = Asset( + 'https://www.qemu-advent-calendar.org/2023/download/day22.tar.gz', + 'ae3a63ef4b7a22c21bfc7fc0d85e402fe95e223308ed23ac854405016431ff51') + + def test_lm3s6965evb(self): + self.set_machine('lm3s6965evb') + kernel_path = self.archive_extract(self.ASSET_DAY22, + member='day22/day22.bin') + self.vm.set_console() + self.vm.add_args('-kernel', kernel_path) + self.vm.launch() + + wait_for_console_pattern(self, 'In a one horse open') + + ASSET_NOTMAIN = Asset( + 'https://github.com/Ahelion/QemuArmM4FDemoSw/raw/master/build/notmain.bin', + '6ceda031aa081a420fca2fca9e137fa681d6e3820d820ad1917736cb265e611a') + + def test_lm3s811evb(self): + self.set_machine('lm3s811evb') + kernel_path = self.ASSET_NOTMAIN.fetch() + + self.vm.set_console() + self.vm.add_args('-cpu', 'cortex-m4') + self.vm.add_args('-kernel', kernel_path) + self.vm.launch() + + # The test kernel emits an initial '!' and then waits for input. + # For each character that we send it responds with a certain + # other ASCII character. + wait_for_console_pattern(self, '!') + exec_command_and_wait_for_pattern(self, '789', 'cdf') + + +if __name__ == '__main__': + QemuSystemTest.main() diff --git a/tests/functional/arm/test_sx1.py b/tests/functional/arm/test_sx1.py new file mode 100755 index 0000000..25800b3 --- /dev/null +++ b/tests/functional/arm/test_sx1.py @@ -0,0 +1,73 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Linaro Ltd. +# +# Functional test that boots a Linux kernel on an sx1 machine +# and checks the console. We have three variants: +# * just boot initrd +# * boot with filesystem on SD card +# * boot from flash +# In all cases these images have a userspace that is configured +# to immediately reboot the system on successful boot, so we +# only need to wait for QEMU to exit (via -no-reboot). +# +# SPDX-License-Identifier: GPL-2.0-or-later + +from qemu_test import LinuxKernelTest, Asset + + +class SX1Test(LinuxKernelTest): + + ASSET_ZIMAGE = Asset( + 'https://github.com/groeck/linux-test-downloads/raw/225223f2ad7d637b34426810bf6c3b727b76a718/sx1/zImage', + 'a0271899a8dc2165f9e0adb2d0a57fc839ae3a469722ffc56c77e108a8887615') + + ASSET_INITRD = Asset( + 'https://github.com/groeck/linux-test-downloads/raw/225223f2ad7d637b34426810bf6c3b727b76a718/sx1/rootfs-armv4.cpio', + '35b0721249821aa544cd85b85d3cb8901db4c6d128eed86ab261e5d9e37d58f8') + + ASSET_SD_FS = Asset( + 'https://github.com/groeck/linux-test-downloads/raw/225223f2ad7d637b34426810bf6c3b727b76a718/sx1/rootfs-armv4.ext2', + 'c1db7f43ef92469ebc8605013728c8950e7608439f01d13678994f0ce101c3a8') + + ASSET_FLASH = Asset( + 'https://github.com/groeck/linux-test-downloads/raw/225223f2ad7d637b34426810bf6c3b727b76a718/sx1/flash', + '17e6a2758fa38efd2666be0879d4751fd37d194f25168a8deede420df519b676') + + CONSOLE_ARGS = 'console=ttyS0,115200 earlycon=uart8250,mmio32,0xfffb0000,115200n8' + + def test_arm_sx1_initrd(self): + self.set_machine('sx1') + zimage_path = self.ASSET_ZIMAGE.fetch() + initrd_path = self.ASSET_INITRD.fetch() + self.vm.add_args('-append', f'kunit.enable=0 rdinit=/sbin/init {self.CONSOLE_ARGS}') + self.vm.add_args('-no-reboot') + self.launch_kernel(zimage_path, + initrd=initrd_path, + wait_for='Boot successful') + self.vm.wait(timeout=120) + + def test_arm_sx1_sd(self): + self.set_machine('sx1') + zimage_path = self.ASSET_ZIMAGE.fetch() + sd_fs_path = self.ASSET_SD_FS.fetch() + self.vm.add_args('-append', f'kunit.enable=0 root=/dev/mmcblk0 rootwait {self.CONSOLE_ARGS}') + self.vm.add_args('-no-reboot') + self.vm.add_args('-snapshot') + self.vm.add_args('-drive', f'format=raw,if=sd,file={sd_fs_path}') + self.launch_kernel(zimage_path, wait_for='Boot successful') + self.vm.wait(timeout=120) + + def test_arm_sx1_flash(self): + self.set_machine('sx1') + zimage_path = self.ASSET_ZIMAGE.fetch() + flash_path = self.ASSET_FLASH.fetch() + self.vm.add_args('-append', f'kunit.enable=0 root=/dev/mtdblock3 rootwait {self.CONSOLE_ARGS}') + self.vm.add_args('-no-reboot') + self.vm.add_args('-snapshot') + self.vm.add_args('-drive', f'format=raw,if=pflash,file={flash_path}') + self.launch_kernel(zimage_path, wait_for='Boot successful') + self.vm.wait(timeout=120) + +if __name__ == '__main__': + LinuxKernelTest.main() diff --git a/tests/functional/arm/test_tuxrun.py b/tests/functional/arm/test_tuxrun.py new file mode 100755 index 0000000..4ac85f4 --- /dev/null +++ b/tests/functional/arm/test_tuxrun.py @@ -0,0 +1,70 @@ +#!/usr/bin/env python3 +# +# Functional test that boots known good tuxboot images the same way +# that tuxrun (www.tuxrun.org) does. This tool is used by things like +# the LKFT project to run regression tests on kernels. +# +# Copyright (c) 2023 Linaro Ltd. +# +# Author: +# Alex Bennée +# +# SPDX-License-Identifier: GPL-2.0-or-later + +from qemu_test import Asset +from qemu_test.tuxruntest import TuxRunBaselineTest + +class TuxRunArmTest(TuxRunBaselineTest): + + ASSET_ARMV5_KERNEL = Asset( + 'https://storage.tuxboot.com/buildroot/20241119/armv5/zImage', + '3931a3908dbcf0ec0fe292d035ffc4dfed95f797dedd4a59ccfcf7a46e6f92d4') + ASSET_ARMV5_ROOTFS = Asset( + 'https://storage.tuxboot.com/buildroot/20241119/armv5/rootfs.ext4.zst', + '60ff78b68c7021df378e4fc2d66d3b016484d1acc7e07fb8920c1d8e30f4571f') + ASSET_ARMV5_DTB = Asset( + 'https://storage.tuxboot.com/buildroot/20241119/armv5/versatile-pb.dtb', + '50988e69ef3f3b08bfb9146e8fe414129990029e8dfbed444953b7e14809530a') + + def test_armv5(self): + self.set_machine('versatilepb') + self.cpu='arm926' + self.console='ttyAMA0' + self.wait_for_shutdown=False + self.common_tuxrun(kernel_asset=self.ASSET_ARMV5_KERNEL, + rootfs_asset=self.ASSET_ARMV5_ROOTFS, + dtb_asset=self.ASSET_ARMV5_DTB, + drive="virtio-blk-pci") + + ASSET_ARMV7_KERNEL = Asset( + 'https://storage.tuxboot.com/buildroot/20241119/armv7/zImage', + '1377bc3d90de5ce57ab17cd67429fe8b15c2e9964248c775c682b67e6299b991') + ASSET_ARMV7_ROOTFS = Asset( + 'https://storage.tuxboot.com/buildroot/20241119/armv7/rootfs.ext4.zst', + 'ed2cbc69bd6b3fbd5cafb5ee961393c7cfbe726446f14301c67d6b1f28bfdb51') + + def test_armv7(self): + self.set_machine('virt') + self.cpu='cortex-a15' + self.console='ttyAMA0' + self.wait_for_shutdown=False + self.common_tuxrun(kernel_asset=self.ASSET_ARMV7_KERNEL, + rootfs_asset=self.ASSET_ARMV7_ROOTFS) + + ASSET_ARMV7BE_KERNEL = Asset( + 'https://storage.tuxboot.com/buildroot/20241119/armv7be/zImage', + 'a244e6da99f1bbd254827ec7681bd4aac9eb1aa05aaebc6b15e5d289ebb683f3') + ASSET_ARMV7BE_ROOTFS = Asset( + 'https://storage.tuxboot.com/buildroot/20241119/armv7be/rootfs.ext4.zst', + 'd4f9c57860a512163f30ecc69b2174d1a1bdeb853a43dc49a09cfcfe84e428ea') + + def test_armv7be(self): + self.set_machine('virt') + self.cpu='cortex-a15' + self.console='ttyAMA0' + self.wait_for_shutdown=False + self.common_tuxrun(kernel_asset=self.ASSET_ARMV7BE_KERNEL, + rootfs_asset=self.ASSET_ARMV7BE_ROOTFS) + +if __name__ == '__main__': + TuxRunBaselineTest.main() diff --git a/tests/functional/arm/test_vexpress.py b/tests/functional/arm/test_vexpress.py new file mode 100755 index 0000000..6b11552 --- /dev/null +++ b/tests/functional/arm/test_vexpress.py @@ -0,0 +1,26 @@ +#!/usr/bin/env python3 +# +# Functional test that boots a Linux kernel on an versatile express machine +# and checks the console +# +# SPDX-License-Identifier: GPL-2.0-or-later + +from qemu_test import LinuxKernelTest, Asset + + +class VExpressTest(LinuxKernelTest): + + ASSET_DAY16 = Asset( + 'https://qemu-advcal.gitlab.io/qac-best-of-multiarch/download/day16.tar.xz', + '63311adb2d4c4e7a73214a86d29988add87266a909719c56acfadd026b4110a7') + + def test_arm_vexpressa9(self): + self.set_machine('vexpress-a9') + self.archive_extract(self.ASSET_DAY16) + self.launch_kernel(self.scratch_file('day16', 'winter.zImage'), + dtb=self.scratch_file('day16', + 'vexpress-v2p-ca9.dtb'), + wait_for='QEMU advent calendar') + +if __name__ == '__main__': + LinuxKernelTest.main() diff --git a/tests/functional/arm/test_virt.py b/tests/functional/arm/test_virt.py new file mode 100755 index 0000000..7b65491 --- /dev/null +++ b/tests/functional/arm/test_virt.py @@ -0,0 +1,30 @@ +#!/usr/bin/env python3 +# +# Functional test that boots a Linux kernel and checks the console +# +# SPDX-License-Identifier: GPL-2.0-or-later + +from qemu_test import LinuxKernelTest, Asset + +class ArmVirtMachine(LinuxKernelTest): + + ASSET_KERNEL = Asset( + ('https://archives.fedoraproject.org/pub/archive/fedora/linux/' + 'releases/29/Everything/armhfp/os/images/pxeboot/vmlinuz'), + '18dd5f1a9a28bd539f9d047f7c0677211bae528e8712b40ca5a229a4ad8e2591') + + def test_arm_virt(self): + self.set_machine('virt') + kernel_path = self.ASSET_KERNEL.fetch() + + self.vm.set_console() + kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE + + 'console=ttyAMA0') + self.vm.add_args('-kernel', kernel_path, + '-append', kernel_command_line) + self.vm.launch() + console_pattern = 'Kernel command line: %s' % kernel_command_line + self.wait_for_console_pattern(console_pattern) + +if __name__ == '__main__': + LinuxKernelTest.main() diff --git a/tests/functional/meson.build b/tests/functional/meson.build index a7f8c88..6989446 100644 --- a/tests/functional/meson.build +++ b/tests/functional/meson.build @@ -11,27 +11,7 @@ endif subdir('aarch64') subdir('alpha') - -test_arm_timeouts = { - 'arm_aspeed_palmetto' : 120, - 'arm_aspeed_romulus' : 120, - 'arm_aspeed_witherspoon' : 120, - 'arm_aspeed_ast2500' : 720, - 'arm_aspeed_ast2600' : 1200, - 'arm_aspeed_bletchley' : 480, - 'arm_aspeed_catalina' : 480, - 'arm_aspeed_gb200nvl_bmc' : 480, - 'arm_aspeed_rainier' : 480, - 'arm_bpim2u' : 500, - 'arm_collie' : 180, - 'arm_cubieboard' : 360, - 'arm_orangepi' : 540, - 'arm_quanta_gsj' : 240, - 'arm_raspi2' : 120, - 'arm_replay' : 240, - 'arm_tuxrun' : 240, - 'arm_sx1' : 360, -} +subdir('arm') test_mips_timeouts = { 'mips_malta' : 480, @@ -97,46 +77,6 @@ tests_generic_linuxuser = [ tests_generic_bsduser = [ ] -tests_arm_system_quick = [ - 'arm_migration', -] - -tests_arm_system_thorough = [ - 'arm_aspeed_ast1030', - 'arm_aspeed_palmetto', - 'arm_aspeed_romulus', - 'arm_aspeed_witherspoon', - 'arm_aspeed_ast2500', - 'arm_aspeed_ast2600', - 'arm_aspeed_bletchley', - 'arm_aspeed_catalina', - 'arm_aspeed_gb200nvl_bmc', - 'arm_aspeed_rainier', - 'arm_bpim2u', - 'arm_canona1100', - 'arm_collie', - 'arm_cubieboard', - 'arm_emcraft_sf2', - 'arm_integratorcp', - 'arm_max78000fthr', - 'arm_microbit', - 'arm_orangepi', - 'arm_quanta_gsj', - 'arm_raspi2', - 'arm_realview', - 'arm_replay', - 'arm_smdkc210', - 'arm_stellaris', - 'arm_sx1', - 'arm_vexpress', - 'arm_virt', - 'arm_tuxrun', -] - -tests_arm_linuxuser_thorough = [ - 'arm_bflt', -] - tests_avr_system_thorough = [ 'avr_mega2560', 'avr_uno', diff --git a/tests/functional/test_arm_aspeed_ast1030.py b/tests/functional/test_arm_aspeed_ast1030.py deleted file mode 100755 index 77037f0..0000000 --- a/tests/functional/test_arm_aspeed_ast1030.py +++ /dev/null @@ -1,73 +0,0 @@ -#!/usr/bin/env python3 -# -# Functional test that boots the ASPEED SoCs with firmware -# -# Copyright (C) 2022 ASPEED Technology Inc -# -# SPDX-License-Identifier: GPL-2.0-or-later - -from qemu_test import LinuxKernelTest, Asset -from qemu_test import exec_command_and_wait_for_pattern - - -class AST1030Machine(LinuxKernelTest): - - ASSET_ZEPHYR_3_00 = Asset( - ('https://github.com/AspeedTech-BMC' - '/zephyr/releases/download/v00.03.00/ast1030-evb-demo.zip'), - '37fe3ecd4a1b9d620971a15b96492a81093435396eeac69b6f3e384262ff555f') - - def test_ast1030_zephyros_3_00(self): - self.set_machine('ast1030-evb') - - kernel_name = "ast1030-evb-demo/zephyr.elf" - kernel_file = self.archive_extract( - self.ASSET_ZEPHYR_3_00, member=kernel_name) - - self.vm.set_console() - self.vm.add_args('-kernel', kernel_file, '-nographic') - self.vm.launch() - self.wait_for_console_pattern("Booting Zephyr OS") - exec_command_and_wait_for_pattern(self, "help", - "Available commands") - - ASSET_ZEPHYR_1_07 = Asset( - ('https://github.com/AspeedTech-BMC' - '/zephyr/releases/download/v00.01.07/ast1030-evb-demo.zip'), - 'ad52e27959746988afaed8429bf4e12ab988c05c4d07c9d90e13ec6f7be4574c') - - def test_ast1030_zephyros_1_07(self): - self.set_machine('ast1030-evb') - - kernel_name = "ast1030-evb-demo/zephyr.bin" - kernel_file = self.archive_extract( - self.ASSET_ZEPHYR_1_07, member=kernel_name) - - self.vm.set_console() - self.vm.add_args('-kernel', kernel_file, '-nographic') - self.vm.launch() - self.wait_for_console_pattern("Booting Zephyr OS") - for shell_cmd in [ - 'kernel stacks', - 'otp info conf', - 'otp info scu', - 'hwinfo devid', - 'crypto aes256_cbc_vault', - 'random get', - 'jtag JTAG1 sw_xfer high TMS', - 'adc ADC0 resolution 12', - 'adc ADC0 read 42', - 'adc ADC1 read 69', - 'i2c scan I2C_0', - 'i3c attach I3C_0', - 'hash test', - 'kernel uptime', - 'kernel reboot warm', - 'kernel uptime', - 'kernel reboot cold', - 'kernel uptime', - ]: exec_command_and_wait_for_pattern(self, shell_cmd, "uart:~$") - - -if __name__ == '__main__': - LinuxKernelTest.main() diff --git a/tests/functional/test_arm_aspeed_ast2500.py b/tests/functional/test_arm_aspeed_ast2500.py deleted file mode 100755 index 6923fe8..0000000 --- a/tests/functional/test_arm_aspeed_ast2500.py +++ /dev/null @@ -1,56 +0,0 @@ -#!/usr/bin/env python3 -# -# Functional test that boots the ASPEED machines -# -# SPDX-License-Identifier: GPL-2.0-or-later - -from qemu_test import Asset, exec_command_and_wait_for_pattern -from aspeed import AspeedTest - - -class AST2500Machine(AspeedTest): - - ASSET_BR2_202411_AST2500_FLASH = Asset( - ('https://github.com/legoater/qemu-aspeed-boot/raw/master/' - 'images/ast2500-evb/buildroot-2024.11/flash.img'), - '641e6906c18c0f19a2aeb48099d66d4771929c361001d554d0d45c667413e13a') - - def test_arm_ast2500_evb_buildroot(self): - self.set_machine('ast2500-evb') - - image_path = self.ASSET_BR2_202411_AST2500_FLASH.fetch() - - self.vm.add_args('-device', - 'tmp105,bus=aspeed.i2c.bus.3,address=0x4d,id=tmp-test') - self.do_test_arm_aspeed_buildroot_start(image_path, '0x0', - 'ast2500-evb login:') - - exec_command_and_wait_for_pattern(self, - 'echo lm75 0x4d > /sys/class/i2c-dev/i2c-3/device/new_device', - 'i2c i2c-3: new_device: Instantiated device lm75 at 0x4d') - exec_command_and_wait_for_pattern(self, - 'cat /sys/class/hwmon/hwmon1/temp1_input', '0') - self.vm.cmd('qom-set', path='/machine/peripheral/tmp-test', - property='temperature', value=18000) - exec_command_and_wait_for_pattern(self, - 'cat /sys/class/hwmon/hwmon1/temp1_input', '18000') - - self.do_test_arm_aspeed_buildroot_poweroff() - - ASSET_SDK_V906_AST2500 = Asset( - 'https://github.com/AspeedTech-BMC/openbmc/releases/download/v09.06/ast2500-default-obmc.tar.gz', - '542db84645b4efd8aed50385d7f4dd1caff379a987032311cfa7b563a3addb2a') - - def test_arm_ast2500_evb_sdk(self): - self.set_machine('ast2500-evb') - - self.archive_extract(self.ASSET_SDK_V906_AST2500) - - self.do_test_arm_aspeed_sdk_start( - self.scratch_file("ast2500-default", "image-bmc")) - - self.wait_for_console_pattern('ast2500-default login:') - - -if __name__ == '__main__': - AspeedTest.main() diff --git a/tests/functional/test_arm_aspeed_ast2600.py b/tests/functional/test_arm_aspeed_ast2600.py deleted file mode 100755 index fdae4c9..0000000 --- a/tests/functional/test_arm_aspeed_ast2600.py +++ /dev/null @@ -1,140 +0,0 @@ -#!/usr/bin/env python3 -# -# Functional test that boots the ASPEED machines -# -# SPDX-License-Identifier: GPL-2.0-or-later - -import os -import time -import tempfile -import subprocess - -from qemu_test import Asset -from aspeed import AspeedTest -from qemu_test import exec_command_and_wait_for_pattern, skipIfMissingCommands - - -class AST2600Machine(AspeedTest): - - ASSET_BR2_202411_AST2600_FLASH = Asset( - ('https://github.com/legoater/qemu-aspeed-boot/raw/master/' - 'images/ast2600-evb/buildroot-2024.11/flash.img'), - '4bb2f3dfdea31199b51d66b42f686dc5374c144a7346fdc650194a5578b73609') - - def test_arm_ast2600_evb_buildroot(self): - self.set_machine('ast2600-evb') - - image_path = self.ASSET_BR2_202411_AST2600_FLASH.fetch() - - self.vm.add_args('-device', - 'tmp105,bus=aspeed.i2c.bus.3,address=0x4d,id=tmp-test') - self.vm.add_args('-device', - 'ds1338,bus=aspeed.i2c.bus.3,address=0x32') - self.vm.add_args('-device', - 'i2c-echo,bus=aspeed.i2c.bus.3,address=0x42') - self.do_test_arm_aspeed_buildroot_start(image_path, '0xf00', - 'ast2600-evb login:') - - exec_command_and_wait_for_pattern(self, - 'echo lm75 0x4d > /sys/class/i2c-dev/i2c-3/device/new_device', - 'i2c i2c-3: new_device: Instantiated device lm75 at 0x4d') - exec_command_and_wait_for_pattern(self, - 'cat /sys/class/hwmon/hwmon1/temp1_input', '0') - self.vm.cmd('qom-set', path='/machine/peripheral/tmp-test', - property='temperature', value=18000) - exec_command_and_wait_for_pattern(self, - 'cat /sys/class/hwmon/hwmon1/temp1_input', '18000') - - exec_command_and_wait_for_pattern(self, - 'echo ds1307 0x32 > /sys/class/i2c-dev/i2c-3/device/new_device', - 'i2c i2c-3: new_device: Instantiated device ds1307 at 0x32') - year = time.strftime("%Y") - exec_command_and_wait_for_pattern(self, 'hwclock -f /dev/rtc1', year) - - exec_command_and_wait_for_pattern(self, - 'echo slave-24c02 0x1064 > /sys/bus/i2c/devices/i2c-3/new_device', - 'i2c i2c-3: new_device: Instantiated device slave-24c02 at 0x64') - exec_command_and_wait_for_pattern(self, - 'i2cset -y 3 0x42 0x64 0x00 0xaa i', '#') - exec_command_and_wait_for_pattern(self, - 'hexdump /sys/bus/i2c/devices/3-1064/slave-eeprom', - '0000000 ffaa ffff ffff ffff ffff ffff ffff ffff') - self.do_test_arm_aspeed_buildroot_poweroff() - - ASSET_BR2_202302_AST2600_TPM_FLASH = Asset( - ('https://github.com/legoater/qemu-aspeed-boot/raw/master/' - 'images/ast2600-evb/buildroot-2023.02-tpm/flash.img'), - 'a46009ae8a5403a0826d607215e731a8c68d27c14c41e55331706b8f9c7bd997') - - @skipIfMissingCommands('swtpm') - def test_arm_ast2600_evb_buildroot_tpm(self): - self.set_machine('ast2600-evb') - - image_path = self.ASSET_BR2_202302_AST2600_TPM_FLASH.fetch() - - tpmstate_dir = tempfile.TemporaryDirectory(prefix="qemu_") - socket = os.path.join(tpmstate_dir.name, 'swtpm-socket') - - # We must put the TPM state dir in /tmp/, not the build dir, - # because some distros use AppArmor to lock down swtpm and - # restrict the set of locations it can access files in. - subprocess.run(['swtpm', 'socket', '-d', '--tpm2', - '--tpmstate', f'dir={tpmstate_dir.name}', - '--ctrl', f'type=unixio,path={socket}']) - - self.vm.add_args('-chardev', f'socket,id=chrtpm,path={socket}') - self.vm.add_args('-tpmdev', 'emulator,id=tpm0,chardev=chrtpm') - self.vm.add_args('-device', - 'tpm-tis-i2c,tpmdev=tpm0,bus=aspeed.i2c.bus.12,address=0x2e') - self.do_test_arm_aspeed_buildroot_start(image_path, '0xf00', 'Aspeed AST2600 EVB') - - exec_command_and_wait_for_pattern(self, - 'echo tpm_tis_i2c 0x2e > /sys/bus/i2c/devices/i2c-12/new_device', - 'tpm_tis_i2c 12-002e: 2.0 TPM (device-id 0x1, rev-id 1)') - exec_command_and_wait_for_pattern(self, - 'cat /sys/class/tpm/tpm0/pcr-sha256/0', - 'B804724EA13F52A9072BA87FE8FDCC497DFC9DF9AA15B9088694639C431688E0') - - self.do_test_arm_aspeed_buildroot_poweroff() - - ASSET_SDK_V906_AST2600 = Asset( - 'https://github.com/AspeedTech-BMC/openbmc/releases/download/v09.06/ast2600-default-obmc.tar.gz', - '768d76e247896ad78c154b9cff4f766da2ce65f217d620b286a4a03a8a4f68f5') - - def test_arm_ast2600_evb_sdk(self): - self.set_machine('ast2600-evb') - - self.archive_extract(self.ASSET_SDK_V906_AST2600) - - self.vm.add_args('-device', - 'tmp105,bus=aspeed.i2c.bus.5,address=0x4d,id=tmp-test') - self.vm.add_args('-device', - 'ds1338,bus=aspeed.i2c.bus.5,address=0x32') - self.do_test_arm_aspeed_sdk_start( - self.scratch_file("ast2600-default", "image-bmc")) - - self.wait_for_console_pattern('ast2600-default login:') - - exec_command_and_wait_for_pattern(self, 'root', 'Password:') - exec_command_and_wait_for_pattern(self, '0penBmc', - 'root@ast2600-default:~#') - - exec_command_and_wait_for_pattern(self, - 'echo lm75 0x4d > /sys/class/i2c-dev/i2c-5/device/new_device', - 'i2c i2c-5: new_device: Instantiated device lm75 at 0x4d') - exec_command_and_wait_for_pattern(self, - 'cat /sys/class/hwmon/hwmon19/temp1_input', '0') - self.vm.cmd('qom-set', path='/machine/peripheral/tmp-test', - property='temperature', value=18000) - exec_command_and_wait_for_pattern(self, - 'cat /sys/class/hwmon/hwmon19/temp1_input', '18000') - - exec_command_and_wait_for_pattern(self, - 'echo ds1307 0x32 > /sys/class/i2c-dev/i2c-5/device/new_device', - 'i2c i2c-5: new_device: Instantiated device ds1307 at 0x32') - year = time.strftime("%Y") - exec_command_and_wait_for_pattern(self, - '/sbin/hwclock -f /dev/rtc1', year) - -if __name__ == '__main__': - AspeedTest.main() diff --git a/tests/functional/test_arm_aspeed_bletchley.py b/tests/functional/test_arm_aspeed_bletchley.py deleted file mode 100644 index 5a60b24..0000000 --- a/tests/functional/test_arm_aspeed_bletchley.py +++ /dev/null @@ -1,25 +0,0 @@ -#!/usr/bin/env python3 -# -# Functional test that boots the ASPEED machines -# -# SPDX-License-Identifier: GPL-2.0-or-later - -from qemu_test import Asset -from aspeed import AspeedTest - - -class BletchleyMachine(AspeedTest): - - ASSET_BLETCHLEY_FLASH = Asset( - 'https://github.com/legoater/qemu-aspeed-boot/raw/master/images/bletchley-bmc/openbmc-20250128071329/obmc-phosphor-image-bletchley-20250128071329.static.mtd.xz', - 'db21d04d47d7bb2a276f59d308614b4dfb70b9c7c81facbbca40a3977a2d8844') - - def test_arm_ast2600_bletchley_openbmc(self): - image_path = self.uncompress(self.ASSET_BLETCHLEY_FLASH) - - self.do_test_arm_aspeed_openbmc('bletchley-bmc', image=image_path, - uboot='2019.04', cpu_id='0xf00', - soc='AST2600 rev A3') - -if __name__ == '__main__': - AspeedTest.main() diff --git a/tests/functional/test_arm_aspeed_catalina.py b/tests/functional/test_arm_aspeed_catalina.py deleted file mode 100755 index dc2f24e..0000000 --- a/tests/functional/test_arm_aspeed_catalina.py +++ /dev/null @@ -1,25 +0,0 @@ -#!/usr/bin/env python3 -# -# Functional test that boots the ASPEED machines -# -# SPDX-License-Identifier: GPL-2.0-or-later - -from qemu_test import Asset -from aspeed import AspeedTest - - -class CatalinaMachine(AspeedTest): - - ASSET_CATALINA_FLASH = Asset( - 'https://github.com/legoater/qemu-aspeed-boot/raw/a866feb5ef81245b4827a214584bf6bcc72939f6/images/catalina-bmc/obmc-phosphor-image-catalina-20250619123021.static.mtd.xz', - '287402e1ba021991e06be1d098f509444a02a3d81a73a932f66528b159e864f9') - - def test_arm_ast2600_catalina_openbmc(self): - image_path = self.uncompress(self.ASSET_CATALINA_FLASH) - - self.do_test_arm_aspeed_openbmc('catalina-bmc', image=image_path, - uboot='2019.04', cpu_id='0xf00', - soc='AST2600 rev A3') - -if __name__ == '__main__': - AspeedTest.main() diff --git a/tests/functional/test_arm_aspeed_gb200nvl_bmc.py b/tests/functional/test_arm_aspeed_gb200nvl_bmc.py deleted file mode 100644 index 8e8e3f0..0000000 --- a/tests/functional/test_arm_aspeed_gb200nvl_bmc.py +++ /dev/null @@ -1,26 +0,0 @@ -#!/usr/bin/env python3 -# -# Functional test that boots the ASPEED machines -# -# SPDX-License-Identifier: GPL-2.0-or-later - -from qemu_test import Asset -from aspeed import AspeedTest - - -class GB200Machine(AspeedTest): - - ASSET_GB200_FLASH = Asset( - 'https://github.com/legoater/qemu-aspeed-boot/raw/refs/heads/master/images/gb200nvl-obmc/obmc-phosphor-image-gb200nvl-obmc-20250702182348.static.mtd.xz', - 'b84819317cb3dc762895ad507705978ef000bfc77c50c33a63bdd37921db0dbc') - - def test_arm_aspeed_gb200_openbmc(self): - image_path = self.uncompress(self.ASSET_GB200_FLASH) - - self.do_test_arm_aspeed_openbmc('gb200nvl-bmc', image=image_path, - uboot='2019.04', cpu_id='0xf00', - soc='AST2600 rev A3', - image_hostname='gb200nvl-obmc') - -if __name__ == '__main__': - AspeedTest.main() diff --git a/tests/functional/test_arm_aspeed_palmetto.py b/tests/functional/test_arm_aspeed_palmetto.py deleted file mode 100755 index ff0b821..0000000 --- a/tests/functional/test_arm_aspeed_palmetto.py +++ /dev/null @@ -1,25 +0,0 @@ -#!/usr/bin/env python3 -# -# Functional test that boots the ASPEED machines -# -# SPDX-License-Identifier: GPL-2.0-or-later - -from qemu_test import Asset -from aspeed import AspeedTest - - -class PalmettoMachine(AspeedTest): - - ASSET_PALMETTO_FLASH = Asset( - 'https://github.com/legoater/qemu-aspeed-boot/raw/master/images/palmetto-bmc/openbmc-20250128071432/obmc-phosphor-image-palmetto-20250128071432.static.mtd', - 'bce7c392eec75c707a91cfc8fad7ca9a69d7e4f10df936930d65c1cb9897ac81') - - def test_arm_ast2400_palmetto_openbmc(self): - image_path = self.ASSET_PALMETTO_FLASH.fetch() - - self.do_test_arm_aspeed_openbmc('palmetto-bmc', image=image_path, - uboot='2019.04', cpu_id='0x0', - soc='AST2400 rev A1') - -if __name__ == '__main__': - AspeedTest.main() diff --git a/tests/functional/test_arm_aspeed_rainier.py b/tests/functional/test_arm_aspeed_rainier.py deleted file mode 100755 index 602d619..0000000 --- a/tests/functional/test_arm_aspeed_rainier.py +++ /dev/null @@ -1,65 +0,0 @@ -#!/usr/bin/env python3 -# -# Functional test that boots the ASPEED machines -# -# SPDX-License-Identifier: GPL-2.0-or-later - -from qemu_test import Asset -from aspeed import AspeedTest - -class RainierMachine(AspeedTest): - - ASSET_RAINIER_EMMC = Asset( - ('https://fileserver.linaro.org/s/B6pJTwWEkzSDi36/download/' - 'mmc-p10bmc-20240617.qcow2'), - 'd523fb478d2b84d5adc5658d08502bc64b1486955683814f89c6137518acd90b') - - def test_arm_aspeed_emmc_boot(self): - self.set_machine('rainier-bmc') - self.require_netdev('user') - - image_path = self.ASSET_RAINIER_EMMC.fetch() - - self.vm.set_console() - self.vm.add_args('-drive', - 'file=' + image_path + ',if=sd,id=sd2,index=2', - '-net', 'nic', '-net', 'user', '-snapshot') - self.vm.launch() - - self.wait_for_console_pattern('U-Boot SPL 2019.04') - self.wait_for_console_pattern('Trying to boot from MMC1') - self.wait_for_console_pattern('U-Boot 2019.04') - self.wait_for_console_pattern('eMMC 2nd Boot') - self.wait_for_console_pattern('## Loading kernel from FIT Image') - self.wait_for_console_pattern('Starting kernel ...') - self.wait_for_console_pattern('Booting Linux on physical CPU 0xf00') - self.wait_for_console_pattern('mmcblk0: p1 p2 p3 p4 p5 p6 p7') - self.wait_for_console_pattern('IBM eBMC (OpenBMC for IBM Enterprise') - - ASSET_DEBIAN_LINUX_ARMHF_DEB = Asset( - ('http://snapshot.debian.org/archive/debian/20220606T211338Z/pool/main/l/linux/linux-image-5.17.0-2-armmp_5.17.6-1%2Bb1_armhf.deb'), - '8acb2b4439faedc2f3ed4bdb2847ad4f6e0491f73debaeb7f660c8abe4dcdc0e') - - def test_arm_debian_kernel_boot(self): - self.set_machine('rainier-bmc') - - kernel_path = self.archive_extract( - self.ASSET_DEBIAN_LINUX_ARMHF_DEB, - member='boot/vmlinuz-5.17.0-2-armmp') - dtb_path = self.archive_extract( - self.ASSET_DEBIAN_LINUX_ARMHF_DEB, - member='usr/lib/linux-image-5.17.0-2-armmp/aspeed-bmc-ibm-rainier.dtb') - - self.vm.set_console() - self.vm.add_args('-kernel', kernel_path, - '-dtb', dtb_path, - '-net', 'nic') - self.vm.launch() - - self.wait_for_console_pattern("Booting Linux on physical CPU 0xf00") - self.wait_for_console_pattern("SMP: Total of 2 processors activated") - self.wait_for_console_pattern("No filesystem could mount root") - - -if __name__ == '__main__': - AspeedTest.main() diff --git a/tests/functional/test_arm_aspeed_romulus.py b/tests/functional/test_arm_aspeed_romulus.py deleted file mode 100755 index 0447212..0000000 --- a/tests/functional/test_arm_aspeed_romulus.py +++ /dev/null @@ -1,25 +0,0 @@ -#!/usr/bin/env python3 -# -# Functional test that boots the ASPEED machines -# -# SPDX-License-Identifier: GPL-2.0-or-later - -from qemu_test import Asset -from aspeed import AspeedTest - - -class RomulusMachine(AspeedTest): - - ASSET_ROMULUS_FLASH = Asset( - 'https://github.com/legoater/qemu-aspeed-boot/raw/master/images/romulus-bmc/openbmc-20250128071340/obmc-phosphor-image-romulus-20250128071340.static.mtd', - '6d031376440c82ed9d087d25e9fa76aea75b42f80daa252ec402c0bc3cf6cf5b') - - def test_arm_ast2500_romulus_openbmc(self): - image_path = self.ASSET_ROMULUS_FLASH.fetch() - - self.do_test_arm_aspeed_openbmc('romulus-bmc', image=image_path, - uboot='2019.04', cpu_id='0x0', - soc='AST2500 rev A1') - -if __name__ == '__main__': - AspeedTest.main() diff --git a/tests/functional/test_arm_aspeed_witherspoon.py b/tests/functional/test_arm_aspeed_witherspoon.py deleted file mode 100644 index 51a2d47..0000000 --- a/tests/functional/test_arm_aspeed_witherspoon.py +++ /dev/null @@ -1,25 +0,0 @@ -#!/usr/bin/env python3 -# -# Functional test that boots the ASPEED machines -# -# SPDX-License-Identifier: GPL-2.0-or-later - -from qemu_test import Asset -from aspeed import AspeedTest - - -class WitherspoonMachine(AspeedTest): - - ASSET_WITHERSPOON_FLASH = Asset( - 'https://github.com/legoater/qemu-aspeed-boot/raw/master/images/witherspoon-bmc/openbmc-20240618035022/obmc-phosphor-image-witherspoon-20240618035022.ubi.mtd', - '937d9ed449ea6c6cbed983519088a42d0cafe276bcfe4fce07772ca6673f9213') - - def test_arm_ast2500_witherspoon_openbmc(self): - image_path = self.ASSET_WITHERSPOON_FLASH.fetch() - - self.do_test_arm_aspeed_openbmc('witherspoon-bmc', image=image_path, - uboot='2016.07', cpu_id='0x0', - soc='AST2500 rev A1') - -if __name__ == '__main__': - AspeedTest.main() diff --git a/tests/functional/test_arm_bflt.py b/tests/functional/test_arm_bflt.py deleted file mode 100755 index f273fc8..0000000 --- a/tests/functional/test_arm_bflt.py +++ /dev/null @@ -1,41 +0,0 @@ -#!/usr/bin/env python3 -# -# Test the bFLT loader format -# -# Copyright (C) 2019 Philippe Mathieu-Daudé -# -# SPDX-License-Identifier: GPL-2.0-or-later - -import bz2 - -from qemu_test import QemuUserTest, Asset -from qemu_test import skipIfMissingCommands, skipUntrustedTest - - -class LoadBFLT(QemuUserTest): - - ASSET_ROOTFS = Asset( - ('https://elinux.org/images/5/51/Stm32_mini_rootfs.cpio.bz2'), - 'eefb788e4980c9e8d6c9d60ce7d15d4da6bf4fbc6a80f487673824600d5ba9cc') - - @skipIfMissingCommands('cpio') - @skipUntrustedTest() - def test_stm32(self): - # See https://elinux.org/STM32#User_Space - rootfs_path_bz2 = self.ASSET_ROOTFS.fetch() - busybox_path = self.scratch_file("bin", "busybox") - - with bz2.open(rootfs_path_bz2, 'rb') as cpio_handle: - self.archive_extract(cpio_handle, format="cpio") - - res = self.run_cmd(busybox_path) - ver = 'BusyBox v1.24.0.git (2015-02-03 22:17:13 CET) multi-call binary.' - self.assertIn(ver, res.stdout) - - res = self.run_cmd(busybox_path, ['uname', '-a']) - unm = 'armv7l GNU/Linux' - self.assertIn(unm, res.stdout) - - -if __name__ == '__main__': - QemuUserTest.main() diff --git a/tests/functional/test_arm_bpim2u.py b/tests/functional/test_arm_bpim2u.py deleted file mode 100755 index 8bed64b..0000000 --- a/tests/functional/test_arm_bpim2u.py +++ /dev/null @@ -1,180 +0,0 @@ -#!/usr/bin/env python3 -# -# Functional test that boots a Linux kernel on a Banana Pi machine -# and checks the console -# -# SPDX-License-Identifier: GPL-2.0-or-later - -import os - -from qemu_test import LinuxKernelTest, exec_command_and_wait_for_pattern -from qemu_test import Asset, interrupt_interactive_console_until_pattern -from qemu_test import skipBigDataTest -from qemu_test.utils import image_pow2ceil_expand - - -class BananaPiMachine(LinuxKernelTest): - - ASSET_DEB = Asset( - ('https://apt.armbian.com/pool/main/l/linux-6.6.16/' - 'linux-image-current-sunxi_24.2.1_armhf__6.6.16-Seb3e-D6b4a-P2359-Ce96bHfe66-HK01ba-V014b-B067e-R448a.deb'), - '3d968c15b121ede871dce49d13ee7644d6f74b6b121b84c9a40f51b0c80d6d22') - - ASSET_INITRD = Asset( - ('https://github.com/groeck/linux-build-test/raw/' - '2eb0a73b5d5a28df3170c546ddaaa9757e1e0848/rootfs/' - 'arm/rootfs-armv7a.cpio.gz'), - '2c8dbdb16ea7af2dfbcbea96044dde639fb07d09fd3c4fb31f2027ef71e55ddd') - - ASSET_ROOTFS = Asset( - ('http://storage.kernelci.org/images/rootfs/buildroot/' - 'buildroot-baseline/20230703.0/armel/rootfs.ext2.xz'), - '42b44a12965ac0afe9a88378527fb698a7dc76af50495efc2361ee1595b4e5c6') - - ASSET_SD_IMAGE = Asset( - ('https://downloads.openwrt.org/releases/22.03.3/targets/sunxi/cortexa7/' - 'openwrt-22.03.3-sunxi-cortexa7-sinovoip_bananapi-m2-ultra-ext4-sdcard.img.gz'), - '5b41b4e11423e562c6011640f9a7cd3bdd0a3d42b83430f7caa70a432e6cd82c') - - def test_arm_bpim2u(self): - self.set_machine('bpim2u') - kernel_path = self.archive_extract( - self.ASSET_DEB, member='boot/vmlinuz-6.6.16-current-sunxi') - dtb_path = ('usr/lib/linux-image-6.6.16-current-sunxi/' - 'sun8i-r40-bananapi-m2-ultra.dtb') - dtb_path = self.archive_extract(self.ASSET_DEB, member=dtb_path) - - self.vm.set_console() - kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE + - 'console=ttyS0,115200n8 ' - 'earlycon=uart,mmio32,0x1c28000') - self.vm.add_args('-kernel', kernel_path, - '-dtb', dtb_path, - '-append', kernel_command_line) - self.vm.launch() - console_pattern = 'Kernel command line: %s' % kernel_command_line - self.wait_for_console_pattern(console_pattern) - os.remove(kernel_path) - os.remove(dtb_path) - - def test_arm_bpim2u_initrd(self): - self.set_machine('bpim2u') - kernel_path = self.archive_extract( - self.ASSET_DEB, member='boot/vmlinuz-6.6.16-current-sunxi') - dtb_path = ('usr/lib/linux-image-6.6.16-current-sunxi/' - 'sun8i-r40-bananapi-m2-ultra.dtb') - dtb_path = self.archive_extract(self.ASSET_DEB, member=dtb_path) - initrd_path = self.uncompress(self.ASSET_INITRD) - - self.vm.set_console() - kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE + - 'console=ttyS0,115200 ' - 'panic=-1 noreboot') - self.vm.add_args('-kernel', kernel_path, - '-dtb', dtb_path, - '-initrd', initrd_path, - '-append', kernel_command_line, - '-no-reboot') - self.vm.launch() - self.wait_for_console_pattern('Boot successful.') - - exec_command_and_wait_for_pattern(self, 'cat /proc/cpuinfo', - 'Allwinner sun8i Family') - exec_command_and_wait_for_pattern(self, 'cat /proc/iomem', - 'system-control@1c00000') - exec_command_and_wait_for_pattern(self, 'reboot', - 'reboot: Restarting system') - # Wait for VM to shut down gracefully - self.vm.wait() - os.remove(kernel_path) - os.remove(dtb_path) - os.remove(initrd_path) - - def test_arm_bpim2u_gmac(self): - self.set_machine('bpim2u') - self.require_netdev('user') - - deb_path = self.ASSET_DEB.fetch() - kernel_path = self.archive_extract( - self.ASSET_DEB, member='boot/vmlinuz-6.6.16-current-sunxi') - dtb_path = ('usr/lib/linux-image-6.6.16-current-sunxi/' - 'sun8i-r40-bananapi-m2-ultra.dtb') - dtb_path = self.archive_extract(self.ASSET_DEB, member=dtb_path) - rootfs_path = self.uncompress(self.ASSET_ROOTFS) - image_pow2ceil_expand(rootfs_path) - - self.vm.set_console() - kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE + - 'console=ttyS0,115200 ' - 'root=b300 rootwait rw ' - 'panic=-1 noreboot') - self.vm.add_args('-kernel', kernel_path, - '-dtb', dtb_path, - '-drive', 'file=' + rootfs_path + ',if=sd,format=raw', - '-net', 'nic,model=gmac,netdev=host_gmac', - '-netdev', 'user,id=host_gmac', - '-append', kernel_command_line, - '-no-reboot') - self.vm.launch() - shell_ready = "/bin/sh: can't access tty; job control turned off" - self.wait_for_console_pattern(shell_ready) - - exec_command_and_wait_for_pattern(self, 'cat /proc/cpuinfo', - 'Allwinner sun8i Family') - exec_command_and_wait_for_pattern(self, 'cat /proc/partitions', - 'mmcblk') - exec_command_and_wait_for_pattern(self, 'ifconfig eth0 up', - 'eth0: Link is Up') - exec_command_and_wait_for_pattern(self, 'udhcpc eth0', - 'udhcpc: lease of 10.0.2.15 obtained') - exec_command_and_wait_for_pattern(self, 'ping -c 3 10.0.2.2', - '3 packets transmitted, 3 packets received, 0% packet loss') - exec_command_and_wait_for_pattern(self, 'reboot', - 'reboot: Restarting system') - # Wait for VM to shut down gracefully - self.vm.wait() - os.remove(kernel_path) - os.remove(dtb_path) - os.remove(rootfs_path) - - @skipBigDataTest() - def test_arm_bpim2u_openwrt_22_03_3(self): - self.set_machine('bpim2u') - self.require_netdev('user') - - # This test download a 8.9 MiB compressed image and expand it - # to 127 MiB. - image_path = self.uncompress(self.ASSET_SD_IMAGE) - image_pow2ceil_expand(image_path) - - self.vm.set_console() - self.vm.add_args('-drive', 'file=' + image_path + ',if=sd,format=raw', - '-nic', 'user', - '-no-reboot') - self.vm.launch() - - kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE + - 'usbcore.nousb ' - 'noreboot') - - self.wait_for_console_pattern('U-Boot SPL') - - interrupt_interactive_console_until_pattern( - self, 'Hit any key to stop autoboot:', '=>') - exec_command_and_wait_for_pattern(self, "setenv extraargs '" + - kernel_command_line + "'", '=>') - exec_command_and_wait_for_pattern(self, 'boot', 'Starting kernel ...') - - self.wait_for_console_pattern( - 'Please press Enter to activate this console.') - - exec_command_and_wait_for_pattern(self, ' ', 'root@') - - exec_command_and_wait_for_pattern(self, 'cat /proc/cpuinfo', - 'Allwinner sun8i Family') - exec_command_and_wait_for_pattern(self, 'cat /proc/iomem', - 'system-control@1c00000') - os.remove(image_path) - -if __name__ == '__main__': - LinuxKernelTest.main() diff --git a/tests/functional/test_arm_canona1100.py b/tests/functional/test_arm_canona1100.py deleted file mode 100755 index 21a1a59..0000000 --- a/tests/functional/test_arm_canona1100.py +++ /dev/null @@ -1,37 +0,0 @@ -#!/usr/bin/env python3 -# -# Functional test that boots the canon-a1100 machine with firmware -# -# Copyright (c) 2020 Red Hat, Inc. -# -# Author: -# Thomas Huth -# -# This work is licensed under the terms of the GNU GPL, version 2 or -# later. See the COPYING file in the top-level directory. - -from qemu_test import QemuSystemTest, Asset -from qemu_test import wait_for_console_pattern - - -class CanonA1100Machine(QemuSystemTest): - """Boots the barebox firmware and checks that the console is operational""" - - timeout = 90 - - ASSET_BIOS = Asset(('https://qemu-advcal.gitlab.io' - '/qac-best-of-multiarch/download/day18.tar.xz'), - '28e71874ce985be66b7fd1345ed88cb2523b982f899c8d2900d6353054a1be49') - - def test_arm_canona1100(self): - self.set_machine('canon-a1100') - - bios = self.archive_extract(self.ASSET_BIOS, - member="day18/barebox.canon-a1100.bin") - self.vm.set_console() - self.vm.add_args('-bios', bios) - self.vm.launch() - wait_for_console_pattern(self, 'running /env/bin/init') - -if __name__ == '__main__': - QemuSystemTest.main() diff --git a/tests/functional/test_arm_collie.py b/tests/functional/test_arm_collie.py deleted file mode 100755 index fe1be3d..0000000 --- a/tests/functional/test_arm_collie.py +++ /dev/null @@ -1,31 +0,0 @@ -#!/usr/bin/env python3 -# -# Functional test that boots a Linux kernel on a collie machine -# and checks the console -# -# SPDX-License-Identifier: GPL-2.0-or-later - -from qemu_test import LinuxKernelTest, Asset - - -class CollieTest(LinuxKernelTest): - - ASSET_ZIMAGE = Asset( - 'https://github.com/groeck/linux-test-downloads/raw/225223f2ad7d637b34426810bf6c3b727b76a718/collie/zImage', - '10ace8abf9e0875ef8a83b8829cc3b5b50bc6d7bc3ca29f19f49f5673a43c13b') - - ASSET_ROOTFS = Asset( - 'https://github.com/groeck/linux-test-downloads/raw/225223f2ad7d637b34426810bf6c3b727b76a718/collie/rootfs-sa110.cpio', - '89ccaaa5c6b33331887047e1618ffe81b0f55909173944347d5d2426f3bcc1f2') - - def test_arm_collie(self): - self.set_machine('collie') - zimage_path = self.ASSET_ZIMAGE.fetch() - rootfs_path = self.ASSET_ROOTFS.fetch() - self.vm.add_args('-append', 'rdinit=/sbin/init console=ttySA1') - self.launch_kernel(zimage_path, - initrd=rootfs_path, - wait_for='reboot: Restarting system') - -if __name__ == '__main__': - LinuxKernelTest.main() diff --git a/tests/functional/test_arm_cubieboard.py b/tests/functional/test_arm_cubieboard.py deleted file mode 100755 index b536c2f..0000000 --- a/tests/functional/test_arm_cubieboard.py +++ /dev/null @@ -1,144 +0,0 @@ -#!/usr/bin/env python3 -# -# Functional test that boots a Linux kernel and checks the console -# -# SPDX-License-Identifier: GPL-2.0-or-later - -from qemu_test import LinuxKernelTest, Asset, exec_command_and_wait_for_pattern -from qemu_test import interrupt_interactive_console_until_pattern -from qemu_test import skipBigDataTest -from qemu_test.utils import image_pow2ceil_expand - - -class CubieboardMachine(LinuxKernelTest): - - ASSET_DEB = Asset( - ('https://apt.armbian.com/pool/main/l/linux-6.6.16/' - 'linux-image-current-sunxi_24.2.1_armhf__6.6.16-Seb3e-D6b4a-P2359-Ce96bHfe66-HK01ba-V014b-B067e-R448a.deb'), - '3d968c15b121ede871dce49d13ee7644d6f74b6b121b84c9a40f51b0c80d6d22') - - ASSET_INITRD = Asset( - ('https://github.com/groeck/linux-build-test/raw/' - '2eb0a73b5d5a28df3170c546ddaaa9757e1e0848/rootfs/' - 'arm/rootfs-armv5.cpio.gz'), - '334b8d256db67a3f2b3ad070aa08b5ade39624e0e7e35b02f4359a577bc8f39b') - - ASSET_SATA_ROOTFS = Asset( - ('https://github.com/groeck/linux-build-test/raw/' - '2eb0a73b5d5a28df3170c546ddaaa9757e1e0848/rootfs/' - 'arm/rootfs-armv5.ext2.gz'), - '17fc750da568580b39372133051ef2f0a963c0c0b369b845614442d025701745') - - ASSET_OPENWRT = Asset( - ('https://downloads.openwrt.org/releases/22.03.2/targets/sunxi/cortexa8/' - 'openwrt-22.03.2-sunxi-cortexa8-cubietech_a10-cubieboard-ext4-sdcard.img.gz'), - '94b5ecbfbc0b3b56276e5146b899eafa2ac5dc2d08733d6705af9f144f39f554') - - def test_arm_cubieboard_initrd(self): - self.set_machine('cubieboard') - kernel_path = self.archive_extract( - self.ASSET_DEB, member='boot/vmlinuz-6.6.16-current-sunxi') - dtb_path = ('usr/lib/linux-image-6.6.16-current-sunxi/' + - 'sun4i-a10-cubieboard.dtb') - dtb_path = self.archive_extract(self.ASSET_DEB, member=dtb_path) - initrd_path = self.uncompress(self.ASSET_INITRD) - - self.vm.set_console() - kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE + - 'console=ttyS0,115200 ' - 'usbcore.nousb ' - 'panic=-1 noreboot') - self.vm.add_args('-kernel', kernel_path, - '-dtb', dtb_path, - '-initrd', initrd_path, - '-append', kernel_command_line, - '-no-reboot') - self.vm.launch() - self.wait_for_console_pattern('Boot successful.') - - exec_command_and_wait_for_pattern(self, 'cat /proc/cpuinfo', - 'Allwinner sun4i/sun5i') - exec_command_and_wait_for_pattern(self, 'cat /proc/iomem', - 'system-control@1c00000') - exec_command_and_wait_for_pattern(self, 'reboot', - 'reboot: Restarting system') - # Wait for VM to shut down gracefully - self.vm.wait() - - def test_arm_cubieboard_sata(self): - self.set_machine('cubieboard') - kernel_path = self.archive_extract( - self.ASSET_DEB, member='boot/vmlinuz-6.6.16-current-sunxi') - dtb_path = ('usr/lib/linux-image-6.6.16-current-sunxi/' + - 'sun4i-a10-cubieboard.dtb') - dtb_path = self.archive_extract(self.ASSET_DEB, member=dtb_path) - - rootfs_path = self.uncompress(self.ASSET_SATA_ROOTFS) - - self.vm.set_console() - kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE + - 'console=ttyS0,115200 ' - 'usbcore.nousb ' - 'root=/dev/sda ro ' - 'panic=-1 noreboot') - self.vm.add_args('-kernel', kernel_path, - '-dtb', dtb_path, - '-drive', 'if=none,format=raw,id=disk0,file=' - + rootfs_path, - '-device', 'ide-hd,bus=ide.0,drive=disk0', - '-append', kernel_command_line, - '-no-reboot') - self.vm.launch() - self.wait_for_console_pattern('Boot successful.') - - exec_command_and_wait_for_pattern(self, 'cat /proc/cpuinfo', - 'Allwinner sun4i/sun5i') - exec_command_and_wait_for_pattern(self, 'cat /proc/partitions', - 'sda') - exec_command_and_wait_for_pattern(self, 'reboot', - 'reboot: Restarting system') - # Wait for VM to shut down gracefully - self.vm.wait() - - @skipBigDataTest() - def test_arm_cubieboard_openwrt_22_03_2(self): - # This test download a 7.5 MiB compressed image and expand it - # to 126 MiB. - self.set_machine('cubieboard') - self.require_netdev('user') - - image_path = self.uncompress(self.ASSET_OPENWRT) - image_pow2ceil_expand(image_path) - - self.vm.set_console() - self.vm.add_args('-drive', 'file=' + image_path + ',if=sd,format=raw', - '-nic', 'user', - '-no-reboot') - self.vm.launch() - - kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE + - 'usbcore.nousb ' - 'noreboot') - - self.wait_for_console_pattern('U-Boot SPL') - - interrupt_interactive_console_until_pattern( - self, 'Hit any key to stop autoboot:', '=>') - exec_command_and_wait_for_pattern(self, "setenv extraargs '" + - kernel_command_line + "'", '=>') - exec_command_and_wait_for_pattern(self, 'boot', 'Starting kernel ...') - - self.wait_for_console_pattern( - 'Please press Enter to activate this console.') - - exec_command_and_wait_for_pattern(self, ' ', 'root@') - - exec_command_and_wait_for_pattern(self, 'cat /proc/cpuinfo', - 'Allwinner sun4i/sun5i') - exec_command_and_wait_for_pattern(self, 'reboot', - 'reboot: Restarting system') - # Wait for VM to shut down gracefully - self.vm.wait() - -if __name__ == '__main__': - LinuxKernelTest.main() diff --git a/tests/functional/test_arm_emcraft_sf2.py b/tests/functional/test_arm_emcraft_sf2.py deleted file mode 100755 index f9f3f06..0000000 --- a/tests/functional/test_arm_emcraft_sf2.py +++ /dev/null @@ -1,52 +0,0 @@ -#!/usr/bin/env python3 -# -# Functional test that boots a Linux kernel and checks the console -# -# SPDX-License-Identifier: GPL-2.0-or-later - -import os -import shutil - -from qemu_test import LinuxKernelTest, Asset, exec_command_and_wait_for_pattern -from qemu_test.utils import file_truncate - -class EmcraftSf2Machine(LinuxKernelTest): - - ASSET_UBOOT = Asset( - ('https://raw.githubusercontent.com/Subbaraya-Sundeep/qemu-test-binaries/' - 'fe371d32e50ca682391e1e70ab98c2942aeffb01/u-boot'), - '5c6a15103375db11b21f2236473679a9dbbed6d89652bfcdd501c263d68ab725') - - ASSET_SPI = Asset( - ('https://raw.githubusercontent.com/Subbaraya-Sundeep/qemu-test-binaries/' - 'fe371d32e50ca682391e1e70ab98c2942aeffb01/spi.bin'), - 'cd9bdd2c4cb55a59c3adb6bcf74881667c4500dde0570a43aa3be2b17eecfdb6') - - def test_arm_emcraft_sf2(self): - self.set_machine('emcraft-sf2') - self.require_netdev('user') - - uboot_path = self.ASSET_UBOOT.fetch() - spi_path = self.ASSET_SPI.fetch() - spi_path_rw = self.scratch_file('spi.bin') - shutil.copy(spi_path, spi_path_rw) - os.chmod(spi_path_rw, 0o600) - - file_truncate(spi_path_rw, 16 << 20) # Spansion S25FL128SDPBHICO is 16 MiB - - self.vm.set_console() - kernel_command_line = self.KERNEL_COMMON_COMMAND_LINE - self.vm.add_args('-kernel', uboot_path, - '-append', kernel_command_line, - '-drive', 'file=' + spi_path_rw + ',if=mtd,format=raw', - '-no-reboot') - self.vm.launch() - self.wait_for_console_pattern('Enter \'help\' for a list') - - exec_command_and_wait_for_pattern(self, 'ifconfig eth0 10.0.2.15', - 'eth0: link becomes ready') - exec_command_and_wait_for_pattern(self, 'ping -c 3 10.0.2.2', - '3 packets transmitted, 3 packets received, 0% packet loss') - -if __name__ == '__main__': - LinuxKernelTest.main() diff --git a/tests/functional/test_arm_integratorcp.py b/tests/functional/test_arm_integratorcp.py deleted file mode 100755 index 4f00924..0000000 --- a/tests/functional/test_arm_integratorcp.py +++ /dev/null @@ -1,95 +0,0 @@ -#!/usr/bin/env python3 -# -# Functional test that boots a Linux kernel and checks the console -# -# Copyright (c) 2020 Red Hat, Inc. -# -# Author: -# Thomas Huth -# -# This work is licensed under the terms of the GNU GPL, version 2 or -# later. See the COPYING file in the top-level directory. -# -# SPDX-License-Identifier: GPL-2.0-or-later - -import logging - -from qemu_test import QemuSystemTest, Asset -from qemu_test import wait_for_console_pattern -from qemu_test import skipIfMissingImports, skipUntrustedTest - - -class IntegratorMachine(QemuSystemTest): - - timeout = 90 - - ASSET_KERNEL = Asset( - ('https://github.com/zayac/qemu-arm/raw/master/' - 'arm-test/kernel/zImage.integrator'), - '26e7c7e8f943de785d95bd3c74d66451604a9b6a7a3d25dceb279e7548fd8e78') - - ASSET_INITRD = Asset( - ('https://github.com/zayac/qemu-arm/raw/master/' - 'arm-test/kernel/arm_root.img'), - 'e187c27fb342ad148c7f33475fbed124933e0b3f4be8c74bc4f3426a4793373a') - - ASSET_TUXLOGO = Asset( - ('https://github.com/torvalds/linux/raw/v2.6.12/' - 'drivers/video/logo/logo_linux_vga16.ppm'), - 'b762f0d91ec018887ad1b334543c2fdf9be9fdfc87672b409211efaa3ea0ef79') - - def boot_integratorcp(self): - kernel_path = self.ASSET_KERNEL.fetch() - initrd_path = self.ASSET_INITRD.fetch() - - self.set_machine('integratorcp') - self.vm.set_console() - self.vm.add_args('-kernel', kernel_path, - '-initrd', initrd_path, - '-append', 'printk.time=0 console=ttyAMA0') - self.vm.launch() - - @skipUntrustedTest() - def test_integratorcp_console(self): - """ - Boots the Linux kernel and checks that the console is operational - """ - self.boot_integratorcp() - wait_for_console_pattern(self, 'Log in as root') - - @skipIfMissingImports("numpy", "cv2") - @skipUntrustedTest() - def test_framebuffer_tux_logo(self): - """ - Boot Linux and verify the Tux logo is displayed on the framebuffer. - """ - import numpy as np - import cv2 - - screendump_path = self.scratch_file("screendump.pbm") - tuxlogo_path = self.ASSET_TUXLOGO.fetch() - - self.boot_integratorcp() - framebuffer_ready = 'Console: switching to colour frame buffer device' - wait_for_console_pattern(self, framebuffer_ready) - self.vm.cmd('human-monitor-command', command_line='stop') - res = self.vm.cmd('human-monitor-command', - command_line='screendump %s' % screendump_path) - if 'unknown command' in res: - self.skipTest('screendump not available') - logger = logging.getLogger('framebuffer') - - cpu_count = 1 - match_threshold = 0.92 - screendump_bgr = cv2.imread(screendump_path) - screendump_gray = cv2.cvtColor(screendump_bgr, cv2.COLOR_BGR2GRAY) - result = cv2.matchTemplate(screendump_gray, cv2.imread(tuxlogo_path, 0), - cv2.TM_CCOEFF_NORMED) - loc = np.where(result >= match_threshold) - tux_count = 0 - for tux_count, pt in enumerate(zip(*loc[::-1]), start=1): - logger.debug('found Tux at position [x, y] = %s', pt) - self.assertGreaterEqual(tux_count, cpu_count) - -if __name__ == '__main__': - QemuSystemTest.main() diff --git a/tests/functional/test_arm_max78000fthr.py b/tests/functional/test_arm_max78000fthr.py deleted file mode 100755 index a82980b..0000000 --- a/tests/functional/test_arm_max78000fthr.py +++ /dev/null @@ -1,48 +0,0 @@ -#!/usr/bin/env python3 -# -# Functional test that checks the max78000fthr machine. -# Tests ICC, GCR, TRNG, AES, and UART -# -# SPDX-License-Identifier: GPL-2.0-or-later - -from qemu_test import QemuSystemTest, Asset, exec_command_and_wait_for_pattern -from qemu_test import wait_for_console_pattern - - -class Max78000Machine(QemuSystemTest): - - ASSET_FW = Asset( - 'https://github.com/JacksonDonaldson/max78000Test/raw/main/build/max78000.bin', - '86940b4bf60931bc6a8aa5db4b9f7f3cf8f64dbbd7ac534647980e536cf3adf7') - - def test_fthr(self): - self.set_machine('max78000fthr') - fw_path = self.ASSET_FW.fetch() - self.vm.set_console() - self.vm.add_args('-kernel', fw_path) - self.vm.add_args('-device', "loader,file=" + fw_path + ",addr=0x10000000") - self.vm.launch() - - wait_for_console_pattern(self, 'started') - - # i -> prints instruction cache values - exec_command_and_wait_for_pattern(self, 'i', 'CTRL: 00010001') - - # r -> gcr resets the machine - exec_command_and_wait_for_pattern(self, 'r', 'started') - - # z -> sets some memory, then has gcr zero it - exec_command_and_wait_for_pattern(self, 'z', 'initial value: 12345678') - wait_for_console_pattern(self, "after memz: 00000000") - - # t -> runs trng - exec_command_and_wait_for_pattern(self, 't', 'random data:') - - # a -> runs aes - exec_command_and_wait_for_pattern(self, 'a', - 'encrypted to : a47ca9dd e0df4c86 a070af6e 91710dec') - wait_for_console_pattern(self, - 'encrypted to : cab7a28e bf456751 9049fcea 8960494b') - -if __name__ == '__main__': - QemuSystemTest.main() diff --git a/tests/functional/test_arm_microbit.py b/tests/functional/test_arm_microbit.py deleted file mode 100755 index 68ea4e7..0000000 --- a/tests/functional/test_arm_microbit.py +++ /dev/null @@ -1,31 +0,0 @@ -#!/usr/bin/env python3 -# -# SPDX-License-Identifier: GPL-2.0-or-later -# -# Copyright 2025, The QEMU Project Developers. -# -# A functional test that runs MicroPython on the arm microbit machine. - -from qemu_test import QemuSystemTest, Asset, exec_command_and_wait_for_pattern -from qemu_test import wait_for_console_pattern - - -class MicrobitMachine(QemuSystemTest): - - ASSET_MICRO = Asset('https://ozlabs.org/~joel/microbit-micropython.hex', - '021641f93dfb11767d4978dbb3ca7f475d1b13c69e7f4aec3382f212636bffd6') - - def test_arm_microbit(self): - self.set_machine('microbit') - - micropython = self.ASSET_MICRO.fetch() - self.vm.set_console() - self.vm.add_args('-device', f'loader,file={micropython}') - self.vm.launch() - wait_for_console_pattern(self, 'Type "help()" for more information.') - exec_command_and_wait_for_pattern(self, 'import machine as mch', '>>>') - exec_command_and_wait_for_pattern(self, 'mch.reset()', 'MicroPython') - wait_for_console_pattern(self, '>>>') - -if __name__ == '__main__': - QemuSystemTest.main() diff --git a/tests/functional/test_arm_migration.py b/tests/functional/test_arm_migration.py deleted file mode 100755 index 0aa89f4..0000000 --- a/tests/functional/test_arm_migration.py +++ /dev/null @@ -1,26 +0,0 @@ -#!/usr/bin/env python3 -# -# SPDX-License-Identifier: GPL-2.0-or-later -# -# arm migration test - -from migration import MigrationTest - - -class ArmMigrationTest(MigrationTest): - - def test_migration_with_tcp_localhost(self): - self.set_machine('npcm750-evb') - self.migration_with_tcp_localhost() - - def test_migration_with_unix(self): - self.set_machine('npcm750-evb') - self.migration_with_unix() - - def test_migration_with_exec(self): - self.set_machine('npcm750-evb') - self.migration_with_exec() - - -if __name__ == '__main__': - MigrationTest.main() diff --git a/tests/functional/test_arm_orangepi.py b/tests/functional/test_arm_orangepi.py deleted file mode 100755 index f9bfa8c..0000000 --- a/tests/functional/test_arm_orangepi.py +++ /dev/null @@ -1,237 +0,0 @@ -#!/usr/bin/env python3 -# -# Functional test that boots a Linux kernel on an Orange Pi machine -# and checks the console -# -# SPDX-License-Identifier: GPL-2.0-or-later - -import os -import shutil - -from qemu_test import LinuxKernelTest, exec_command_and_wait_for_pattern -from qemu_test import Asset, interrupt_interactive_console_until_pattern -from qemu_test import wait_for_console_pattern, skipBigDataTest -from qemu_test.utils import image_pow2ceil_expand - - -class OrangePiMachine(LinuxKernelTest): - - ASSET_DEB = Asset( - ('https://apt.armbian.com/pool/main/l/linux-6.6.16/' - 'linux-image-current-sunxi_24.2.1_armhf__6.6.16-Seb3e-D6b4a-P2359-Ce96bHfe66-HK01ba-V014b-B067e-R448a.deb'), - '3d968c15b121ede871dce49d13ee7644d6f74b6b121b84c9a40f51b0c80d6d22') - - ASSET_INITRD = Asset( - ('https://github.com/groeck/linux-build-test/raw/' - '2eb0a73b5d5a28df3170c546ddaaa9757e1e0848/rootfs/' - 'arm/rootfs-armv7a.cpio.gz'), - '2c8dbdb16ea7af2dfbcbea96044dde639fb07d09fd3c4fb31f2027ef71e55ddd') - - ASSET_ROOTFS = Asset( - ('http://storage.kernelci.org/images/rootfs/buildroot/' - 'buildroot-baseline/20230703.0/armel/rootfs.ext2.xz'), - '42b44a12965ac0afe9a88378527fb698a7dc76af50495efc2361ee1595b4e5c6') - - ASSET_ARMBIAN = Asset( - ('https://k-space.ee.armbian.com/archive/orangepipc/archive/' - 'Armbian_23.8.1_Orangepipc_jammy_current_6.1.47.img.xz'), - 'b386dff6552513b5f164ea00f94814a6b0f1da9fb90b83725e949cf797e11afb') - - ASSET_UBOOT = Asset( - ('http://snapshot.debian.org/archive/debian/20200108T145233Z/pool/' - 'main/u/u-boot/u-boot-sunxi_2020.01%2Bdfsg-1_armhf.deb'), - '9223d94dc283ab54df41ce9d6f69025a5b47fece29fb67a714e23aa0cdf3bdfa') - - ASSET_NETBSD = Asset( - ('https://archive.netbsd.org/pub/NetBSD-archive/NetBSD-9.0/' - 'evbarm-earmv7hf/binary/gzimg/armv7.img.gz'), - '20d3e07dc057e15c12452620e90ecab2047f0f7940d9cba8182ebc795927177f') - - def test_arm_orangepi(self): - self.set_machine('orangepi-pc') - kernel_path = self.archive_extract( - self.ASSET_DEB, member='boot/vmlinuz-6.6.16-current-sunxi') - dtb_path = ('usr/lib/linux-image-6.6.16-current-sunxi/' + - 'sun8i-h3-orangepi-pc.dtb') - dtb_path = self.archive_extract(self.ASSET_DEB, member=dtb_path) - - self.vm.set_console() - kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE + - 'console=ttyS0,115200n8 ' - 'earlycon=uart,mmio32,0x1c28000') - self.vm.add_args('-kernel', kernel_path, - '-dtb', dtb_path, - '-append', kernel_command_line) - self.vm.launch() - console_pattern = 'Kernel command line: %s' % kernel_command_line - self.wait_for_console_pattern(console_pattern) - os.remove(kernel_path) - os.remove(dtb_path) - - def test_arm_orangepi_initrd(self): - self.set_machine('orangepi-pc') - kernel_path = self.archive_extract( - self.ASSET_DEB, member='boot/vmlinuz-6.6.16-current-sunxi') - dtb_path = ('usr/lib/linux-image-6.6.16-current-sunxi/' + - 'sun8i-h3-orangepi-pc.dtb') - dtb_path = self.archive_extract(self.ASSET_DEB, member=dtb_path) - initrd_path = self.uncompress(self.ASSET_INITRD) - - self.vm.set_console() - kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE + - 'console=ttyS0,115200 ' - 'panic=-1 noreboot') - self.vm.add_args('-kernel', kernel_path, - '-dtb', dtb_path, - '-initrd', initrd_path, - '-append', kernel_command_line, - '-no-reboot') - self.vm.launch() - self.wait_for_console_pattern('Boot successful.') - - exec_command_and_wait_for_pattern(self, 'cat /proc/cpuinfo', - 'Allwinner sun8i Family') - exec_command_and_wait_for_pattern(self, 'cat /proc/iomem', - 'system-control@1c00000') - exec_command_and_wait_for_pattern(self, 'reboot', - 'reboot: Restarting system') - # Wait for VM to shut down gracefully - self.vm.wait() - os.remove(kernel_path) - os.remove(dtb_path) - os.remove(initrd_path) - - def test_arm_orangepi_sd(self): - self.set_machine('orangepi-pc') - self.require_netdev('user') - kernel_path = self.archive_extract( - self.ASSET_DEB, member='boot/vmlinuz-6.6.16-current-sunxi') - dtb_path = ('usr/lib/linux-image-6.6.16-current-sunxi/' + - 'sun8i-h3-orangepi-pc.dtb') - dtb_path = self.archive_extract(self.ASSET_DEB, member=dtb_path) - rootfs_path = self.uncompress(self.ASSET_ROOTFS) - image_pow2ceil_expand(rootfs_path) - - self.vm.set_console() - kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE + - 'console=ttyS0,115200 ' - 'root=/dev/mmcblk0 rootwait rw ' - 'panic=-1 noreboot') - self.vm.add_args('-kernel', kernel_path, - '-dtb', dtb_path, - '-drive', 'file=' + rootfs_path + ',if=sd,format=raw', - '-append', kernel_command_line, - '-no-reboot') - self.vm.launch() - shell_ready = "/bin/sh: can't access tty; job control turned off" - self.wait_for_console_pattern(shell_ready) - - exec_command_and_wait_for_pattern(self, 'cat /proc/cpuinfo', - 'Allwinner sun8i Family') - exec_command_and_wait_for_pattern(self, 'cat /proc/partitions', - 'mmcblk0') - exec_command_and_wait_for_pattern(self, 'ifconfig eth0 up', - 'eth0: Link is Up') - exec_command_and_wait_for_pattern(self, 'udhcpc eth0', - 'udhcpc: lease of 10.0.2.15 obtained') - exec_command_and_wait_for_pattern(self, 'ping -c 3 10.0.2.2', - '3 packets transmitted, 3 packets received, 0% packet loss') - exec_command_and_wait_for_pattern(self, 'reboot', - 'reboot: Restarting system') - # Wait for VM to shut down gracefully - self.vm.wait() - os.remove(kernel_path) - os.remove(dtb_path) - os.remove(rootfs_path) - - @skipBigDataTest() - def test_arm_orangepi_armbian(self): - self.set_machine('orangepi-pc') - self.require_netdev('user') - - # This test download a 275 MiB compressed image and expand it - # to 1036 MiB, but the underlying filesystem is 1552 MiB... - # As we expand it to 2 GiB we are safe. - image_path = self.uncompress(self.ASSET_ARMBIAN) - image_pow2ceil_expand(image_path) - - self.vm.set_console() - self.vm.add_args('-drive', 'file=' + image_path + ',if=sd,format=raw', - '-nic', 'user', - '-no-reboot') - self.vm.launch() - - kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE + - 'console=ttyS0,115200 ' - 'loglevel=7 ' - 'nosmp ' - 'systemd.default_timeout_start_sec=9000 ' - 'systemd.mask=armbian-zram-config.service ' - 'systemd.mask=armbian-ramlog.service') - - self.wait_for_console_pattern('U-Boot SPL') - self.wait_for_console_pattern('Autoboot in ') - exec_command_and_wait_for_pattern(self, ' ', '=>') - exec_command_and_wait_for_pattern(self, "setenv extraargs '" + - kernel_command_line + "'", '=>') - exec_command_and_wait_for_pattern(self, 'boot', 'Starting kernel ...') - - self.wait_for_console_pattern('systemd[1]: Hostname set ' + - 'to ') - self.wait_for_console_pattern('Starting Load Kernel Modules...') - - @skipBigDataTest() - def test_arm_orangepi_uboot_netbsd9(self): - self.set_machine('orangepi-pc') - self.require_netdev('user') - - # This test download a 304MB compressed image and expand it to 2GB - # We use the common OrangePi PC 'plus' build of U-Boot for our secondary - # program loader (SPL). We will then set the path to the more specific - # OrangePi "PC" device tree blob with 'setenv fdtfile' in U-Boot prompt, - # before to boot NetBSD. - uboot_path = 'usr/lib/u-boot/orangepi_plus/u-boot-sunxi-with-spl.bin' - uboot_path = self.archive_extract(self.ASSET_UBOOT, member=uboot_path) - image_path = self.uncompress(self.ASSET_NETBSD) - image_pow2ceil_expand(image_path) - image_drive_args = 'if=sd,format=raw,snapshot=on,file=' + image_path - - # dd if=u-boot-sunxi-with-spl.bin of=armv7.img bs=1K seek=8 conv=notrunc - with open(uboot_path, 'rb') as f_in: - with open(image_path, 'r+b') as f_out: - f_out.seek(8 * 1024) - shutil.copyfileobj(f_in, f_out) - - self.vm.set_console() - self.vm.add_args('-nic', 'user', - '-drive', image_drive_args, - '-global', 'allwinner-rtc.base-year=2000', - '-no-reboot') - self.vm.launch() - wait_for_console_pattern(self, 'U-Boot 2020.01+dfsg-1') - interrupt_interactive_console_until_pattern(self, - 'Hit any key to stop autoboot:', - 'switch to partitions #0, OK') - - exec_command_and_wait_for_pattern(self, '', '=>') - cmd = 'setenv bootargs root=ld0a' - exec_command_and_wait_for_pattern(self, cmd, '=>') - cmd = 'setenv kernel netbsd-GENERIC.ub' - exec_command_and_wait_for_pattern(self, cmd, '=>') - cmd = 'setenv fdtfile dtb/sun8i-h3-orangepi-pc.dtb' - exec_command_and_wait_for_pattern(self, cmd, '=>') - cmd = ("setenv bootcmd 'fatload mmc 0:1 ${kernel_addr_r} ${kernel}; " - "fatload mmc 0:1 ${fdt_addr_r} ${fdtfile}; " - "fdt addr ${fdt_addr_r}; " - "bootm ${kernel_addr_r} - ${fdt_addr_r}'") - exec_command_and_wait_for_pattern(self, cmd, '=>') - - exec_command_and_wait_for_pattern(self, 'boot', - 'Booting kernel from Legacy Image') - wait_for_console_pattern(self, 'Starting kernel ...') - wait_for_console_pattern(self, 'NetBSD 9.0 (GENERIC)') - # Wait for user-space - wait_for_console_pattern(self, 'Starting root file system check') - -if __name__ == '__main__': - LinuxKernelTest.main() diff --git a/tests/functional/test_arm_quanta_gsj.py b/tests/functional/test_arm_quanta_gsj.py deleted file mode 100755 index cb0545f..0000000 --- a/tests/functional/test_arm_quanta_gsj.py +++ /dev/null @@ -1,92 +0,0 @@ -#!/usr/bin/env python3 -# -# Functional test that boots a Linux kernel and checks the console -# -# SPDX-License-Identifier: GPL-2.0-or-later - -from qemu_test import LinuxKernelTest, Asset, exec_command_and_wait_for_pattern -from qemu_test import interrupt_interactive_console_until_pattern, skipSlowTest - - -class EmcraftSf2Machine(LinuxKernelTest): - - ASSET_IMAGE = Asset( - ('https://github.com/hskinnemoen/openbmc/releases/download/' - '20200711-gsj-qemu-0/obmc-phosphor-image-gsj.static.mtd.gz'), - 'eccd4e375cde53034c84aece5c511932cacf838d9fd3f63da368a511757da72b') - - ASSET_INITRD = Asset( - ('https://github.com/hskinnemoen/openbmc/releases/download/' - '20200711-gsj-qemu-0/obmc-phosphor-initramfs-gsj.cpio.xz'), - '37b05009fc54db1434beac12bd7ff99a2e751a2f032ee18d9042f991dd0cdeaa') - - ASSET_KERNEL = Asset( - ('https://github.com/hskinnemoen/openbmc/releases/download/' - '20200711-gsj-qemu-0/uImage-gsj.bin'), - 'ce6d6b37bff46c74fc7b1e90da10a431cc37a62cdb35ec199fa73473d0790110') - - ASSET_DTB = Asset( - ('https://github.com/hskinnemoen/openbmc/releases/download/' - '20200711-gsj-qemu-0/nuvoton-npcm730-gsj.dtb'), - '3249b2da787d4b9ad4e61f315b160abfceb87b5e1895a7ce898ce7f40c8d4045') - - @skipSlowTest() - def test_arm_quanta_gsj(self): - self.set_machine('quanta-gsj') - image_path = self.uncompress(self.ASSET_IMAGE, format='gz') - - self.vm.set_console() - drive_args = 'file=' + image_path + ',if=mtd,bus=0,unit=0' - self.vm.add_args('-drive', drive_args) - self.vm.launch() - - # Disable drivers and services that stall for a long time during boot, - # to avoid running past the 90-second timeout. These may be removed - # as the corresponding device support is added. - kernel_command_line = self.KERNEL_COMMON_COMMAND_LINE + ( - 'console=${console} ' - 'mem=${mem} ' - 'initcall_blacklist=npcm_i2c_bus_driver_init ' - 'systemd.mask=systemd-random-seed.service ' - 'systemd.mask=dropbearkey.service ' - ) - - self.wait_for_console_pattern('> BootBlock by Nuvoton') - self.wait_for_console_pattern('>Device: Poleg BMC NPCM730') - self.wait_for_console_pattern('>Skip DDR init.') - self.wait_for_console_pattern('U-Boot ') - interrupt_interactive_console_until_pattern( - self, 'Hit any key to stop autoboot:', 'U-Boot>') - exec_command_and_wait_for_pattern( - self, "setenv bootargs ${bootargs} " + kernel_command_line, - 'U-Boot>') - exec_command_and_wait_for_pattern( - self, 'run romboot', 'Booting Kernel from flash') - self.wait_for_console_pattern('Booting Linux on physical CPU 0x0') - self.wait_for_console_pattern('CPU1: thread -1, cpu 1, socket 0') - self.wait_for_console_pattern('OpenBMC Project Reference Distro') - self.wait_for_console_pattern('gsj login:') - - def test_arm_quanta_gsj_initrd(self): - self.set_machine('quanta-gsj') - initrd_path = self.ASSET_INITRD.fetch() - kernel_path = self.ASSET_KERNEL.fetch() - dtb_path = self.ASSET_DTB.fetch() - - self.vm.set_console() - kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE + - 'console=ttyS0,115200n8 ' - 'earlycon=uart8250,mmio32,0xf0001000') - self.vm.add_args('-kernel', kernel_path, - '-initrd', initrd_path, - '-dtb', dtb_path, - '-append', kernel_command_line) - self.vm.launch() - - self.wait_for_console_pattern('Booting Linux on physical CPU 0x0') - self.wait_for_console_pattern('CPU1: thread -1, cpu 1, socket 0') - self.wait_for_console_pattern( - 'Give root password for system maintenance') - -if __name__ == '__main__': - LinuxKernelTest.main() diff --git a/tests/functional/test_arm_raspi2.py b/tests/functional/test_arm_raspi2.py deleted file mode 100755 index d3c7aaa..0000000 --- a/tests/functional/test_arm_raspi2.py +++ /dev/null @@ -1,92 +0,0 @@ -#!/usr/bin/env python3 -# -# Functional test that boots a Linux kernel on a Raspberry Pi machine -# and checks the console -# -# Copyright (c) 2019 Philippe Mathieu-Daudé -# -# SPDX-License-Identifier: GPL-2.0-or-later - -from qemu_test import LinuxKernelTest, Asset -from qemu_test import exec_command_and_wait_for_pattern - - -class ArmRaspi2Machine(LinuxKernelTest): - - ASSET_KERNEL_20190215 = Asset( - ('http://archive.raspberrypi.org/debian/' - 'pool/main/r/raspberrypi-firmware/' - 'raspberrypi-kernel_1.20190215-1_armhf.deb'), - '9f1759f7228113da24f5ee2aa6312946ec09a83e076aba9406c46ff776dfb291') - - ASSET_INITRD = Asset( - ('https://github.com/groeck/linux-build-test/raw/' - '2eb0a73b5d5a28df3170c546ddaaa9757e1e0848/rootfs/' - 'arm/rootfs-armv7a.cpio.gz'), - '2c8dbdb16ea7af2dfbcbea96044dde639fb07d09fd3c4fb31f2027ef71e55ddd') - - def do_test_arm_raspi2(self, uart_id): - """ - The kernel can be rebuilt using the kernel source referenced - and following the instructions on the on: - https://www.raspberrypi.org/documentation/linux/kernel/building.md - """ - serial_kernel_cmdline = { - 0: 'earlycon=pl011,0x3f201000 console=ttyAMA0', - } - kernel_path = self.archive_extract(self.ASSET_KERNEL_20190215, - member='boot/kernel7.img') - dtb_path = self.archive_extract(self.ASSET_KERNEL_20190215, - member='boot/bcm2709-rpi-2-b.dtb') - - self.set_machine('raspi2b') - self.vm.set_console() - kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE + - serial_kernel_cmdline[uart_id] + - ' root=/dev/mmcblk0p2 rootwait ' + - 'dwc_otg.fiq_fsm_enable=0') - self.vm.add_args('-kernel', kernel_path, - '-dtb', dtb_path, - '-append', kernel_command_line, - '-device', 'usb-kbd') - self.vm.launch() - - console_pattern = 'Kernel command line: %s' % kernel_command_line - self.wait_for_console_pattern(console_pattern) - self.wait_for_console_pattern('Product: QEMU USB Keyboard') - - def test_arm_raspi2_uart0(self): - self.do_test_arm_raspi2(0) - - def test_arm_raspi2_initrd(self): - kernel_path = self.archive_extract(self.ASSET_KERNEL_20190215, - member='boot/kernel7.img') - dtb_path = self.archive_extract(self.ASSET_KERNEL_20190215, - member='boot/bcm2709-rpi-2-b.dtb') - initrd_path = self.uncompress(self.ASSET_INITRD) - - self.set_machine('raspi2b') - self.vm.set_console() - kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE + - 'earlycon=pl011,0x3f201000 console=ttyAMA0 ' - 'panic=-1 noreboot ' + - 'dwc_otg.fiq_fsm_enable=0') - self.vm.add_args('-kernel', kernel_path, - '-dtb', dtb_path, - '-initrd', initrd_path, - '-append', kernel_command_line, - '-no-reboot') - self.vm.launch() - self.wait_for_console_pattern('Boot successful.') - - exec_command_and_wait_for_pattern(self, 'cat /proc/cpuinfo', - 'BCM2835') - exec_command_and_wait_for_pattern(self, 'cat /proc/iomem', - '/soc/cprman@7e101000') - exec_command_and_wait_for_pattern(self, 'halt', 'reboot: System halted') - # Wait for VM to shut down gracefully - self.vm.wait() - - -if __name__ == '__main__': - LinuxKernelTest.main() diff --git a/tests/functional/test_arm_realview.py b/tests/functional/test_arm_realview.py deleted file mode 100755 index 82cc964..0000000 --- a/tests/functional/test_arm_realview.py +++ /dev/null @@ -1,47 +0,0 @@ -#!/usr/bin/env python3 -# -# Functional test that boots a Linux kernel on a realview arm machine -# and checks the console -# -# SPDX-License-Identifier: GPL-2.0-or-later - -from qemu_test import LinuxKernelTest, exec_command_and_wait_for_pattern -from qemu_test import Asset - - -class RealviewMachine(LinuxKernelTest): - - ASSET_REALVIEW_MPCORE = Asset( - ('https://archive.openwrt.org/chaos_calmer/15.05.1/realview/generic/' - 'openwrt-15.05.1-realview-vmlinux-initramfs.elf'), - 'd3a01037f33e7512d46d50975588d5c3a0e0cbf25f37afab44775c2a2be523e6') - - def test_realview_ep_mpcore(self): - self.require_netdev('user') - self.set_machine('realview-eb-mpcore') - kernel_path = self.ASSET_REALVIEW_MPCORE.fetch() - self.vm.set_console() - kernel_param = 'console=ttyAMA0 mem=128M quiet' - self.vm.add_args('-kernel', kernel_path, - '-append', kernel_param) - self.vm.launch() - self.wait_for_console_pattern('Please press Enter to activate') - prompt = ':/#' - exec_command_and_wait_for_pattern(self, '', prompt) - exec_command_and_wait_for_pattern(self, 'dmesg', kernel_param) - self.wait_for_console_pattern(prompt) - exec_command_and_wait_for_pattern(self, - ('while ! dmesg | grep "br-lan: port 1(eth0) entered" ;' - ' do sleep 1 ; done'), - 'entered forwarding state') - self.wait_for_console_pattern(prompt) - exec_command_and_wait_for_pattern(self, - 'while ! ifconfig | grep "10.0.2.15" ; do sleep 1 ; done', - 'addr:10.0.2.15') - self.wait_for_console_pattern(prompt) - exec_command_and_wait_for_pattern(self, 'ping -c 1 10.0.2.2', - '1 packets received, 0% packet loss') - - -if __name__ == '__main__': - LinuxKernelTest.main() diff --git a/tests/functional/test_arm_replay.py b/tests/functional/test_arm_replay.py deleted file mode 100755 index e002e6a..0000000 --- a/tests/functional/test_arm_replay.py +++ /dev/null @@ -1,69 +0,0 @@ -#!/usr/bin/env python3 -# -# Replay test that boots a Linux kernel on arm machines and checks the console -# -# SPDX-License-Identifier: GPL-2.0-or-later - -from qemu_test import Asset -from replay_kernel import ReplayKernelBase - - -class ArmReplay(ReplayKernelBase): - - ASSET_VIRT = Asset( - ('https://archives.fedoraproject.org/pub/archive/fedora/linux/' - 'releases/29/Everything/armhfp/os/images/pxeboot/vmlinuz'), - '18dd5f1a9a28bd539f9d047f7c0677211bae528e8712b40ca5a229a4ad8e2591') - - def test_virt(self): - self.set_machine('virt') - kernel_path = self.ASSET_VIRT.fetch() - kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE + - 'console=ttyAMA0') - console_pattern = 'VFS: Cannot open root device' - self.run_rr(kernel_path, kernel_command_line, console_pattern, shift=1) - - ASSET_CUBIE_KERNEL = Asset( - ('https://apt.armbian.com/pool/main/l/linux-6.6.16/' - 'linux-image-current-sunxi_24.2.1_armhf_' - '_6.6.16-Seb3e-D6b4a-P2359-Ce96bHfe66-HK01ba-V014b-B067e-R448a.deb'), - '3d968c15b121ede871dce49d13ee7644d6f74b6b121b84c9a40f51b0c80d6d22') - - ASSET_CUBIE_INITRD = Asset( - ('https://github.com/groeck/linux-build-test/raw/' - '2eb0a73b5d5a28df3170c546ddaaa9757e1e0848/rootfs/arm/rootfs-armv5.cpio.gz'), - '334b8d256db67a3f2b3ad070aa08b5ade39624e0e7e35b02f4359a577bc8f39b') - - def test_cubieboard(self): - self.set_machine('cubieboard') - kernel_path = self.archive_extract(self.ASSET_CUBIE_KERNEL, - member='boot/vmlinuz-6.6.16-current-sunxi') - dtb_path = self.archive_extract(self.ASSET_CUBIE_KERNEL, - member='usr/lib/linux-image-6.6.16-current-sunxi/sun4i-a10-cubieboard.dtb') - initrd_path = self.uncompress(self.ASSET_CUBIE_INITRD) - - kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE + - 'console=ttyS0,115200 ' - 'usbcore.nousb ' - 'panic=-1 noreboot') - console_pattern = 'Boot successful.' - self.run_rr(kernel_path, kernel_command_line, console_pattern, shift=1, - args=('-dtb', dtb_path, - '-initrd', initrd_path, - '-no-reboot')) - - ASSET_DAY16 = Asset( - 'https://qemu-advcal.gitlab.io/qac-best-of-multiarch/download/day16.tar.xz', - '63311adb2d4c4e7a73214a86d29988add87266a909719c56acfadd026b4110a7') - - def test_vexpressa9(self): - self.set_machine('vexpress-a9') - self.archive_extract(self.ASSET_DAY16) - kernel_path = self.scratch_file('day16', 'winter.zImage') - dtb_path = self.scratch_file('day16', 'vexpress-v2p-ca9.dtb') - self.run_rr(kernel_path, self.REPLAY_KERNEL_COMMAND_LINE, - 'QEMU advent calendar', args=('-dtb', dtb_path)) - - -if __name__ == '__main__': - ReplayKernelBase.main() diff --git a/tests/functional/test_arm_smdkc210.py b/tests/functional/test_arm_smdkc210.py deleted file mode 100755 index 3154e7f..0000000 --- a/tests/functional/test_arm_smdkc210.py +++ /dev/null @@ -1,51 +0,0 @@ -#!/usr/bin/env python3 -# -# Functional test that boots a Linux kernel and checks the console -# -# SPDX-License-Identifier: GPL-2.0-or-later - -from qemu_test import LinuxKernelTest, Asset - - -class Smdkc210Machine(LinuxKernelTest): - - ASSET_DEB = Asset( - ('https://snapshot.debian.org/archive/debian/20190928T224601Z/pool/' - 'main/l/linux/linux-image-4.19.0-6-armmp_4.19.67-2+deb10u1_armhf.deb'), - '421804e7579ef40d554c962850dbdf1bfc79f7fa7faec9d391397170dc806c3e') - - ASSET_ROOTFS = Asset( - ('https://github.com/groeck/linux-build-test/raw/' - '2eb0a73b5d5a28df3170c546ddaaa9757e1e0848/rootfs/arm/' - 'rootfs-armv5.cpio.gz'), - '334b8d256db67a3f2b3ad070aa08b5ade39624e0e7e35b02f4359a577bc8f39b') - - def test_arm_exynos4210_initrd(self): - self.set_machine('smdkc210') - - kernel_path = self.archive_extract(self.ASSET_DEB, - member='boot/vmlinuz-4.19.0-6-armmp') - dtb_path = 'usr/lib/linux-image-4.19.0-6-armmp/exynos4210-smdkv310.dtb' - dtb_path = self.archive_extract(self.ASSET_DEB, member=dtb_path) - - initrd_path = self.uncompress(self.ASSET_ROOTFS) - - self.vm.set_console() - kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE + - 'earlycon=exynos4210,0x13800000 earlyprintk ' + - 'console=ttySAC0,115200n8 ' + - 'random.trust_cpu=off cryptomgr.notests ' + - 'cpuidle.off=1 panic=-1 noreboot') - - self.vm.add_args('-kernel', kernel_path, - '-dtb', dtb_path, - '-initrd', initrd_path, - '-append', kernel_command_line, - '-no-reboot') - self.vm.launch() - - self.wait_for_console_pattern('Boot successful.') - # TODO user command, for now the uart is stuck - -if __name__ == '__main__': - LinuxKernelTest.main() diff --git a/tests/functional/test_arm_stellaris.py b/tests/functional/test_arm_stellaris.py deleted file mode 100755 index cbd21cb..0000000 --- a/tests/functional/test_arm_stellaris.py +++ /dev/null @@ -1,48 +0,0 @@ -#!/usr/bin/env python3 -# -# Functional test that checks the serial console of the stellaris machines -# -# SPDX-License-Identifier: GPL-2.0-or-later - -from qemu_test import QemuSystemTest, Asset, exec_command_and_wait_for_pattern -from qemu_test import wait_for_console_pattern - - -class StellarisMachine(QemuSystemTest): - - ASSET_DAY22 = Asset( - 'https://www.qemu-advent-calendar.org/2023/download/day22.tar.gz', - 'ae3a63ef4b7a22c21bfc7fc0d85e402fe95e223308ed23ac854405016431ff51') - - def test_lm3s6965evb(self): - self.set_machine('lm3s6965evb') - kernel_path = self.archive_extract(self.ASSET_DAY22, - member='day22/day22.bin') - self.vm.set_console() - self.vm.add_args('-kernel', kernel_path) - self.vm.launch() - - wait_for_console_pattern(self, 'In a one horse open') - - ASSET_NOTMAIN = Asset( - 'https://github.com/Ahelion/QemuArmM4FDemoSw/raw/master/build/notmain.bin', - '6ceda031aa081a420fca2fca9e137fa681d6e3820d820ad1917736cb265e611a') - - def test_lm3s811evb(self): - self.set_machine('lm3s811evb') - kernel_path = self.ASSET_NOTMAIN.fetch() - - self.vm.set_console() - self.vm.add_args('-cpu', 'cortex-m4') - self.vm.add_args('-kernel', kernel_path) - self.vm.launch() - - # The test kernel emits an initial '!' and then waits for input. - # For each character that we send it responds with a certain - # other ASCII character. - wait_for_console_pattern(self, '!') - exec_command_and_wait_for_pattern(self, '789', 'cdf') - - -if __name__ == '__main__': - QemuSystemTest.main() diff --git a/tests/functional/test_arm_sx1.py b/tests/functional/test_arm_sx1.py deleted file mode 100755 index 25800b3..0000000 --- a/tests/functional/test_arm_sx1.py +++ /dev/null @@ -1,73 +0,0 @@ -#!/usr/bin/env python3 -# -# Copyright (c) 2024 Linaro Ltd. -# -# Functional test that boots a Linux kernel on an sx1 machine -# and checks the console. We have three variants: -# * just boot initrd -# * boot with filesystem on SD card -# * boot from flash -# In all cases these images have a userspace that is configured -# to immediately reboot the system on successful boot, so we -# only need to wait for QEMU to exit (via -no-reboot). -# -# SPDX-License-Identifier: GPL-2.0-or-later - -from qemu_test import LinuxKernelTest, Asset - - -class SX1Test(LinuxKernelTest): - - ASSET_ZIMAGE = Asset( - 'https://github.com/groeck/linux-test-downloads/raw/225223f2ad7d637b34426810bf6c3b727b76a718/sx1/zImage', - 'a0271899a8dc2165f9e0adb2d0a57fc839ae3a469722ffc56c77e108a8887615') - - ASSET_INITRD = Asset( - 'https://github.com/groeck/linux-test-downloads/raw/225223f2ad7d637b34426810bf6c3b727b76a718/sx1/rootfs-armv4.cpio', - '35b0721249821aa544cd85b85d3cb8901db4c6d128eed86ab261e5d9e37d58f8') - - ASSET_SD_FS = Asset( - 'https://github.com/groeck/linux-test-downloads/raw/225223f2ad7d637b34426810bf6c3b727b76a718/sx1/rootfs-armv4.ext2', - 'c1db7f43ef92469ebc8605013728c8950e7608439f01d13678994f0ce101c3a8') - - ASSET_FLASH = Asset( - 'https://github.com/groeck/linux-test-downloads/raw/225223f2ad7d637b34426810bf6c3b727b76a718/sx1/flash', - '17e6a2758fa38efd2666be0879d4751fd37d194f25168a8deede420df519b676') - - CONSOLE_ARGS = 'console=ttyS0,115200 earlycon=uart8250,mmio32,0xfffb0000,115200n8' - - def test_arm_sx1_initrd(self): - self.set_machine('sx1') - zimage_path = self.ASSET_ZIMAGE.fetch() - initrd_path = self.ASSET_INITRD.fetch() - self.vm.add_args('-append', f'kunit.enable=0 rdinit=/sbin/init {self.CONSOLE_ARGS}') - self.vm.add_args('-no-reboot') - self.launch_kernel(zimage_path, - initrd=initrd_path, - wait_for='Boot successful') - self.vm.wait(timeout=120) - - def test_arm_sx1_sd(self): - self.set_machine('sx1') - zimage_path = self.ASSET_ZIMAGE.fetch() - sd_fs_path = self.ASSET_SD_FS.fetch() - self.vm.add_args('-append', f'kunit.enable=0 root=/dev/mmcblk0 rootwait {self.CONSOLE_ARGS}') - self.vm.add_args('-no-reboot') - self.vm.add_args('-snapshot') - self.vm.add_args('-drive', f'format=raw,if=sd,file={sd_fs_path}') - self.launch_kernel(zimage_path, wait_for='Boot successful') - self.vm.wait(timeout=120) - - def test_arm_sx1_flash(self): - self.set_machine('sx1') - zimage_path = self.ASSET_ZIMAGE.fetch() - flash_path = self.ASSET_FLASH.fetch() - self.vm.add_args('-append', f'kunit.enable=0 root=/dev/mtdblock3 rootwait {self.CONSOLE_ARGS}') - self.vm.add_args('-no-reboot') - self.vm.add_args('-snapshot') - self.vm.add_args('-drive', f'format=raw,if=pflash,file={flash_path}') - self.launch_kernel(zimage_path, wait_for='Boot successful') - self.vm.wait(timeout=120) - -if __name__ == '__main__': - LinuxKernelTest.main() diff --git a/tests/functional/test_arm_tuxrun.py b/tests/functional/test_arm_tuxrun.py deleted file mode 100755 index 4ac85f4..0000000 --- a/tests/functional/test_arm_tuxrun.py +++ /dev/null @@ -1,70 +0,0 @@ -#!/usr/bin/env python3 -# -# Functional test that boots known good tuxboot images the same way -# that tuxrun (www.tuxrun.org) does. This tool is used by things like -# the LKFT project to run regression tests on kernels. -# -# Copyright (c) 2023 Linaro Ltd. -# -# Author: -# Alex Bennée -# -# SPDX-License-Identifier: GPL-2.0-or-later - -from qemu_test import Asset -from qemu_test.tuxruntest import TuxRunBaselineTest - -class TuxRunArmTest(TuxRunBaselineTest): - - ASSET_ARMV5_KERNEL = Asset( - 'https://storage.tuxboot.com/buildroot/20241119/armv5/zImage', - '3931a3908dbcf0ec0fe292d035ffc4dfed95f797dedd4a59ccfcf7a46e6f92d4') - ASSET_ARMV5_ROOTFS = Asset( - 'https://storage.tuxboot.com/buildroot/20241119/armv5/rootfs.ext4.zst', - '60ff78b68c7021df378e4fc2d66d3b016484d1acc7e07fb8920c1d8e30f4571f') - ASSET_ARMV5_DTB = Asset( - 'https://storage.tuxboot.com/buildroot/20241119/armv5/versatile-pb.dtb', - '50988e69ef3f3b08bfb9146e8fe414129990029e8dfbed444953b7e14809530a') - - def test_armv5(self): - self.set_machine('versatilepb') - self.cpu='arm926' - self.console='ttyAMA0' - self.wait_for_shutdown=False - self.common_tuxrun(kernel_asset=self.ASSET_ARMV5_KERNEL, - rootfs_asset=self.ASSET_ARMV5_ROOTFS, - dtb_asset=self.ASSET_ARMV5_DTB, - drive="virtio-blk-pci") - - ASSET_ARMV7_KERNEL = Asset( - 'https://storage.tuxboot.com/buildroot/20241119/armv7/zImage', - '1377bc3d90de5ce57ab17cd67429fe8b15c2e9964248c775c682b67e6299b991') - ASSET_ARMV7_ROOTFS = Asset( - 'https://storage.tuxboot.com/buildroot/20241119/armv7/rootfs.ext4.zst', - 'ed2cbc69bd6b3fbd5cafb5ee961393c7cfbe726446f14301c67d6b1f28bfdb51') - - def test_armv7(self): - self.set_machine('virt') - self.cpu='cortex-a15' - self.console='ttyAMA0' - self.wait_for_shutdown=False - self.common_tuxrun(kernel_asset=self.ASSET_ARMV7_KERNEL, - rootfs_asset=self.ASSET_ARMV7_ROOTFS) - - ASSET_ARMV7BE_KERNEL = Asset( - 'https://storage.tuxboot.com/buildroot/20241119/armv7be/zImage', - 'a244e6da99f1bbd254827ec7681bd4aac9eb1aa05aaebc6b15e5d289ebb683f3') - ASSET_ARMV7BE_ROOTFS = Asset( - 'https://storage.tuxboot.com/buildroot/20241119/armv7be/rootfs.ext4.zst', - 'd4f9c57860a512163f30ecc69b2174d1a1bdeb853a43dc49a09cfcfe84e428ea') - - def test_armv7be(self): - self.set_machine('virt') - self.cpu='cortex-a15' - self.console='ttyAMA0' - self.wait_for_shutdown=False - self.common_tuxrun(kernel_asset=self.ASSET_ARMV7BE_KERNEL, - rootfs_asset=self.ASSET_ARMV7BE_ROOTFS) - -if __name__ == '__main__': - TuxRunBaselineTest.main() diff --git a/tests/functional/test_arm_vexpress.py b/tests/functional/test_arm_vexpress.py deleted file mode 100755 index 6b11552..0000000 --- a/tests/functional/test_arm_vexpress.py +++ /dev/null @@ -1,26 +0,0 @@ -#!/usr/bin/env python3 -# -# Functional test that boots a Linux kernel on an versatile express machine -# and checks the console -# -# SPDX-License-Identifier: GPL-2.0-or-later - -from qemu_test import LinuxKernelTest, Asset - - -class VExpressTest(LinuxKernelTest): - - ASSET_DAY16 = Asset( - 'https://qemu-advcal.gitlab.io/qac-best-of-multiarch/download/day16.tar.xz', - '63311adb2d4c4e7a73214a86d29988add87266a909719c56acfadd026b4110a7') - - def test_arm_vexpressa9(self): - self.set_machine('vexpress-a9') - self.archive_extract(self.ASSET_DAY16) - self.launch_kernel(self.scratch_file('day16', 'winter.zImage'), - dtb=self.scratch_file('day16', - 'vexpress-v2p-ca9.dtb'), - wait_for='QEMU advent calendar') - -if __name__ == '__main__': - LinuxKernelTest.main() diff --git a/tests/functional/test_arm_virt.py b/tests/functional/test_arm_virt.py deleted file mode 100755 index 7b65491..0000000 --- a/tests/functional/test_arm_virt.py +++ /dev/null @@ -1,30 +0,0 @@ -#!/usr/bin/env python3 -# -# Functional test that boots a Linux kernel and checks the console -# -# SPDX-License-Identifier: GPL-2.0-or-later - -from qemu_test import LinuxKernelTest, Asset - -class ArmVirtMachine(LinuxKernelTest): - - ASSET_KERNEL = Asset( - ('https://archives.fedoraproject.org/pub/archive/fedora/linux/' - 'releases/29/Everything/armhfp/os/images/pxeboot/vmlinuz'), - '18dd5f1a9a28bd539f9d047f7c0677211bae528e8712b40ca5a229a4ad8e2591') - - def test_arm_virt(self): - self.set_machine('virt') - kernel_path = self.ASSET_KERNEL.fetch() - - self.vm.set_console() - kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE + - 'console=ttyAMA0') - self.vm.add_args('-kernel', kernel_path, - '-append', kernel_command_line) - self.vm.launch() - console_pattern = 'Kernel command line: %s' % kernel_command_line - self.wait_for_console_pattern(console_pattern) - -if __name__ == '__main__': - LinuxKernelTest.main() -- cgit v1.1 From dc8f7a1bf724cb90d37c5bdfcdb80a5c74befc11 Mon Sep 17 00:00:00 2001 From: Thomas Huth Date: Tue, 19 Aug 2025 13:23:45 +0200 Subject: tests/functional: Move avr tests into architecture specific folder MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The tests/functional folder has become quite crowded, thus move the avr tests into a target-specific subfolder. Reviewed-by: Pierrick Bouvier Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Thomas Huth Message-ID: <20250819112403.432587-9-thuth@redhat.com> --- tests/functional/avr/meson.build | 6 +++++ tests/functional/avr/test_mega2560.py | 49 +++++++++++++++++++++++++++++++++++ tests/functional/avr/test_uno.py | 32 +++++++++++++++++++++++ tests/functional/meson.build | 6 +---- tests/functional/test_avr_mega2560.py | 49 ----------------------------------- tests/functional/test_avr_uno.py | 32 ----------------------- 6 files changed, 88 insertions(+), 86 deletions(-) create mode 100644 tests/functional/avr/meson.build create mode 100755 tests/functional/avr/test_mega2560.py create mode 100755 tests/functional/avr/test_uno.py delete mode 100755 tests/functional/test_avr_mega2560.py delete mode 100755 tests/functional/test_avr_uno.py (limited to 'tests') diff --git a/tests/functional/avr/meson.build b/tests/functional/avr/meson.build new file mode 100644 index 0000000..7a2cb70 --- /dev/null +++ b/tests/functional/avr/meson.build @@ -0,0 +1,6 @@ +# SPDX-License-Identifier: GPL-2.0-or-later + +tests_avr_system_thorough = [ + 'mega2560', + 'uno', +] diff --git a/tests/functional/avr/test_mega2560.py b/tests/functional/avr/test_mega2560.py new file mode 100755 index 0000000..6359b72 --- /dev/null +++ b/tests/functional/avr/test_mega2560.py @@ -0,0 +1,49 @@ +#!/usr/bin/env python3 +# +# QEMU AVR integration tests +# +# Copyright (c) 2019-2020 Michael Rolnik +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + +from qemu_test import QemuSystemTest, Asset, wait_for_console_pattern + + +class AVR6Machine(QemuSystemTest): + + ASSET_ROM = Asset(('https://github.com/seharris/qemu-avr-tests' + '/raw/36c3e67b8755dcf/free-rtos/Demo' + '/AVR_ATMega2560_GCC/demo.elf'), + 'ee4833bd65fc69e84a79ed1c608affddbd499a60e63acf87d9113618401904e4') + + def test_freertos(self): + """ + https://github.com/seharris/qemu-avr-tests/raw/master/free-rtos/Demo/AVR_ATMega2560_GCC/demo.elf + constantly prints out 'ABCDEFGHIJKLMNOPQRSTUVWXABCDEFGHIJKLMNOPQRSTUVWX' + """ + rom_path = self.ASSET_ROM.fetch() + + self.set_machine('arduino-mega-2560-v3') + self.vm.add_args('-bios', rom_path) + self.vm.add_args('-nographic') + self.vm.set_console() + self.vm.launch() + + wait_for_console_pattern(self, + 'XABCDEFGHIJKLMNOPQRSTUVWXABCDEFGHIJKLMNOPQRSTUVWXA') + + +if __name__ == '__main__': + QemuSystemTest.main() diff --git a/tests/functional/avr/test_uno.py b/tests/functional/avr/test_uno.py new file mode 100755 index 0000000..adb3b73 --- /dev/null +++ b/tests/functional/avr/test_uno.py @@ -0,0 +1,32 @@ +#!/usr/bin/env python3 +# +# QEMU AVR Arduino UNO functional test +# +# SPDX-License-Identifier: GPL-2.0-or-later + +from qemu_test import QemuSystemTest, Asset, wait_for_console_pattern + + +class UnoMachine(QemuSystemTest): + + ASSET_UNO = Asset( + ('https://github.com/RahulRNandan/LED_Blink_AVR/raw/' + 'c6d602cbb974a193/build/main.elf'), + '3009a4e2cf5c5b65142f538abdf66d4dc6bc6beab7e552fff9ae314583761b72') + + def test_uno(self): + """ + The binary constantly prints out 'LED Blink' + """ + self.set_machine('arduino-uno') + rom_path = self.ASSET_UNO.fetch() + + self.vm.add_args('-bios', rom_path) + self.vm.set_console() + self.vm.launch() + + wait_for_console_pattern(self, 'LED Blink') + + +if __name__ == '__main__': + QemuSystemTest.main() diff --git a/tests/functional/meson.build b/tests/functional/meson.build index 6989446..81eaa9c 100644 --- a/tests/functional/meson.build +++ b/tests/functional/meson.build @@ -12,6 +12,7 @@ endif subdir('aarch64') subdir('alpha') subdir('arm') +subdir('avr') test_mips_timeouts = { 'mips_malta' : 480, @@ -77,11 +78,6 @@ tests_generic_linuxuser = [ tests_generic_bsduser = [ ] -tests_avr_system_thorough = [ - 'avr_mega2560', - 'avr_uno', -] - tests_hppa_system_quick = [ 'hppa_seabios', ] diff --git a/tests/functional/test_avr_mega2560.py b/tests/functional/test_avr_mega2560.py deleted file mode 100755 index 6359b72..0000000 --- a/tests/functional/test_avr_mega2560.py +++ /dev/null @@ -1,49 +0,0 @@ -#!/usr/bin/env python3 -# -# QEMU AVR integration tests -# -# Copyright (c) 2019-2020 Michael Rolnik -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . -# - -from qemu_test import QemuSystemTest, Asset, wait_for_console_pattern - - -class AVR6Machine(QemuSystemTest): - - ASSET_ROM = Asset(('https://github.com/seharris/qemu-avr-tests' - '/raw/36c3e67b8755dcf/free-rtos/Demo' - '/AVR_ATMega2560_GCC/demo.elf'), - 'ee4833bd65fc69e84a79ed1c608affddbd499a60e63acf87d9113618401904e4') - - def test_freertos(self): - """ - https://github.com/seharris/qemu-avr-tests/raw/master/free-rtos/Demo/AVR_ATMega2560_GCC/demo.elf - constantly prints out 'ABCDEFGHIJKLMNOPQRSTUVWXABCDEFGHIJKLMNOPQRSTUVWX' - """ - rom_path = self.ASSET_ROM.fetch() - - self.set_machine('arduino-mega-2560-v3') - self.vm.add_args('-bios', rom_path) - self.vm.add_args('-nographic') - self.vm.set_console() - self.vm.launch() - - wait_for_console_pattern(self, - 'XABCDEFGHIJKLMNOPQRSTUVWXABCDEFGHIJKLMNOPQRSTUVWXA') - - -if __name__ == '__main__': - QemuSystemTest.main() diff --git a/tests/functional/test_avr_uno.py b/tests/functional/test_avr_uno.py deleted file mode 100755 index adb3b73..0000000 --- a/tests/functional/test_avr_uno.py +++ /dev/null @@ -1,32 +0,0 @@ -#!/usr/bin/env python3 -# -# QEMU AVR Arduino UNO functional test -# -# SPDX-License-Identifier: GPL-2.0-or-later - -from qemu_test import QemuSystemTest, Asset, wait_for_console_pattern - - -class UnoMachine(QemuSystemTest): - - ASSET_UNO = Asset( - ('https://github.com/RahulRNandan/LED_Blink_AVR/raw/' - 'c6d602cbb974a193/build/main.elf'), - '3009a4e2cf5c5b65142f538abdf66d4dc6bc6beab7e552fff9ae314583761b72') - - def test_uno(self): - """ - The binary constantly prints out 'LED Blink' - """ - self.set_machine('arduino-uno') - rom_path = self.ASSET_UNO.fetch() - - self.vm.add_args('-bios', rom_path) - self.vm.set_console() - self.vm.launch() - - wait_for_console_pattern(self, 'LED Blink') - - -if __name__ == '__main__': - QemuSystemTest.main() -- cgit v1.1 From e538303d31bb0b537285571b9b56674e7c90b120 Mon Sep 17 00:00:00 2001 From: Thomas Huth Date: Tue, 19 Aug 2025 13:23:46 +0200 Subject: tests/functional: Move hppa tests into architecture specific folder MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The tests/functional folder has become quite crowded, thus move the avr tests into a target-specific subfolder. Reviewed-by: Pierrick Bouvier Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Thomas Huth Message-ID: <20250819112403.432587-10-thuth@redhat.com> --- tests/functional/hppa/meson.build | 5 +++++ tests/functional/hppa/test_seabios.py | 35 +++++++++++++++++++++++++++++++++++ tests/functional/meson.build | 5 +---- tests/functional/test_hppa_seabios.py | 35 ----------------------------------- 4 files changed, 41 insertions(+), 39 deletions(-) create mode 100644 tests/functional/hppa/meson.build create mode 100755 tests/functional/hppa/test_seabios.py delete mode 100755 tests/functional/test_hppa_seabios.py (limited to 'tests') diff --git a/tests/functional/hppa/meson.build b/tests/functional/hppa/meson.build new file mode 100644 index 0000000..a334837 --- /dev/null +++ b/tests/functional/hppa/meson.build @@ -0,0 +1,5 @@ +# SPDX-License-Identifier: GPL-2.0-or-later + +tests_hppa_system_quick = [ + 'seabios', +] diff --git a/tests/functional/hppa/test_seabios.py b/tests/functional/hppa/test_seabios.py new file mode 100755 index 0000000..661b246 --- /dev/null +++ b/tests/functional/hppa/test_seabios.py @@ -0,0 +1,35 @@ +#!/usr/bin/env python3 +# +# SeaBIOS boot test for HPPA machines +# +# Copyright (c) 2024 Linaro, Ltd +# +# SPDX-License-Identifier: GPL-2.0-or-later + +from qemu_test import QemuSystemTest +from qemu_test import wait_for_console_pattern + +class HppaSeabios(QemuSystemTest): + + timeout = 5 + MACH_BITS = {'B160L': 32, 'C3700': 64} + + def boot_seabios(self): + mach = self.machine + bits = self.MACH_BITS[mach] + self.vm.add_args('-no-shutdown') + self.vm.set_console() + self.vm.launch() + wait_for_console_pattern(self, f'SeaBIOS PA-RISC {bits}-bit Firmware') + wait_for_console_pattern(self, f'Emulated machine: HP {mach} ({bits}-bit') + + def test_hppa_32(self): + self.set_machine('B160L') + self.boot_seabios() + + def test_hppa_64(self): + self.set_machine('C3700') + self.boot_seabios() + +if __name__ == '__main__': + QemuSystemTest.main() diff --git a/tests/functional/meson.build b/tests/functional/meson.build index 81eaa9c..8f85c13 100644 --- a/tests/functional/meson.build +++ b/tests/functional/meson.build @@ -13,6 +13,7 @@ subdir('aarch64') subdir('alpha') subdir('arm') subdir('avr') +subdir('hppa') test_mips_timeouts = { 'mips_malta' : 480, @@ -78,10 +79,6 @@ tests_generic_linuxuser = [ tests_generic_bsduser = [ ] -tests_hppa_system_quick = [ - 'hppa_seabios', -] - tests_i386_system_quick = [ 'i386_migration', ] diff --git a/tests/functional/test_hppa_seabios.py b/tests/functional/test_hppa_seabios.py deleted file mode 100755 index 661b246..0000000 --- a/tests/functional/test_hppa_seabios.py +++ /dev/null @@ -1,35 +0,0 @@ -#!/usr/bin/env python3 -# -# SeaBIOS boot test for HPPA machines -# -# Copyright (c) 2024 Linaro, Ltd -# -# SPDX-License-Identifier: GPL-2.0-or-later - -from qemu_test import QemuSystemTest -from qemu_test import wait_for_console_pattern - -class HppaSeabios(QemuSystemTest): - - timeout = 5 - MACH_BITS = {'B160L': 32, 'C3700': 64} - - def boot_seabios(self): - mach = self.machine - bits = self.MACH_BITS[mach] - self.vm.add_args('-no-shutdown') - self.vm.set_console() - self.vm.launch() - wait_for_console_pattern(self, f'SeaBIOS PA-RISC {bits}-bit Firmware') - wait_for_console_pattern(self, f'Emulated machine: HP {mach} ({bits}-bit') - - def test_hppa_32(self): - self.set_machine('B160L') - self.boot_seabios() - - def test_hppa_64(self): - self.set_machine('C3700') - self.boot_seabios() - -if __name__ == '__main__': - QemuSystemTest.main() -- cgit v1.1 From 84b30c4587719297955e1fe2a22face5cc84587c Mon Sep 17 00:00:00 2001 From: Thomas Huth Date: Tue, 19 Aug 2025 13:23:47 +0200 Subject: tests/functional: Move i386 tests into architecture specific folder The tests/functional folder has become quite crowded, thus move the i386 tests into a target-specific subfolder. Reviewed-by: Pierrick Bouvier Signed-off-by: Thomas Huth Message-ID: <20250819112403.432587-11-thuth@redhat.com> --- tests/functional/i386/meson.build | 10 ++++++++++ tests/functional/i386/test_migration.py | 26 ++++++++++++++++++++++++ tests/functional/i386/test_replay.py | 28 ++++++++++++++++++++++++++ tests/functional/i386/test_tuxrun.py | 35 +++++++++++++++++++++++++++++++++ tests/functional/meson.build | 10 +--------- tests/functional/test_i386_migration.py | 26 ------------------------ tests/functional/test_i386_replay.py | 28 -------------------------- tests/functional/test_i386_tuxrun.py | 35 --------------------------------- 8 files changed, 100 insertions(+), 98 deletions(-) create mode 100644 tests/functional/i386/meson.build create mode 100755 tests/functional/i386/test_migration.py create mode 100755 tests/functional/i386/test_replay.py create mode 100755 tests/functional/i386/test_tuxrun.py delete mode 100755 tests/functional/test_i386_migration.py delete mode 100755 tests/functional/test_i386_replay.py delete mode 100755 tests/functional/test_i386_tuxrun.py (limited to 'tests') diff --git a/tests/functional/i386/meson.build b/tests/functional/i386/meson.build new file mode 100644 index 0000000..23d8c21 --- /dev/null +++ b/tests/functional/i386/meson.build @@ -0,0 +1,10 @@ +# SPDX-License-Identifier: GPL-2.0-or-later + +tests_i386_system_quick = [ + 'migration', +] + +tests_i386_system_thorough = [ + 'replay', + 'tuxrun', +] diff --git a/tests/functional/i386/test_migration.py b/tests/functional/i386/test_migration.py new file mode 100755 index 0000000..a57f316 --- /dev/null +++ b/tests/functional/i386/test_migration.py @@ -0,0 +1,26 @@ +#!/usr/bin/env python3 +# +# SPDX-License-Identifier: GPL-2.0-or-later +# +# i386 migration test + +from migration import MigrationTest + + +class I386MigrationTest(MigrationTest): + + def test_migration_with_tcp_localhost(self): + self.set_machine('isapc') + self.migration_with_tcp_localhost() + + def test_migration_with_unix(self): + self.set_machine('isapc') + self.migration_with_unix() + + def test_migration_with_exec(self): + self.set_machine('isapc') + self.migration_with_exec() + + +if __name__ == '__main__': + MigrationTest.main() diff --git a/tests/functional/i386/test_replay.py b/tests/functional/i386/test_replay.py new file mode 100755 index 0000000..7c4c260 --- /dev/null +++ b/tests/functional/i386/test_replay.py @@ -0,0 +1,28 @@ +#!/usr/bin/env python3 +# +# Replay test that boots a Linux kernel on a i386 machine +# and checks the console +# +# SPDX-License-Identifier: GPL-2.0-or-later + +from qemu_test import Asset +from replay_kernel import ReplayKernelBase + + +class I386Replay(ReplayKernelBase): + + ASSET_KERNEL = Asset( + 'https://storage.tuxboot.com/20230331/i386/bzImage', + 'a3e5b32a354729e65910f5a1ffcda7c14a6c12a55e8213fb86e277f1b76ed956') + + def test_pc(self): + self.set_machine('pc') + kernel_url = () + kernel_path = self.ASSET_KERNEL.fetch() + kernel_command_line = self.KERNEL_COMMON_COMMAND_LINE + 'console=ttyS0' + console_pattern = 'VFS: Cannot open root device' + self.run_rr(kernel_path, kernel_command_line, console_pattern, shift=5) + + +if __name__ == '__main__': + ReplayKernelBase.main() diff --git a/tests/functional/i386/test_tuxrun.py b/tests/functional/i386/test_tuxrun.py new file mode 100755 index 0000000..f3ccf11 --- /dev/null +++ b/tests/functional/i386/test_tuxrun.py @@ -0,0 +1,35 @@ +#!/usr/bin/env python3 +# +# Functional test that boots known good tuxboot images the same way +# that tuxrun (www.tuxrun.org) does. This tool is used by things like +# the LKFT project to run regression tests on kernels. +# +# Copyright (c) 2023 Linaro Ltd. +# +# Author: +# Alex Bennée +# +# SPDX-License-Identifier: GPL-2.0-or-later + +from qemu_test import Asset +from qemu_test.tuxruntest import TuxRunBaselineTest + +class TuxRunI386Test(TuxRunBaselineTest): + + ASSET_I386_KERNEL = Asset( + 'https://storage.tuxboot.com/buildroot/20241119/i386/bzImage', + '47fb44e38e34101eb0f71a2a01742b959d40ed5fd67cefb5608a39be11d3b74e') + ASSET_I386_ROOTFS = Asset( + 'https://storage.tuxboot.com/buildroot/20241119/i386/rootfs.ext4.zst', + 'a1a3b3b4c9dccd6475b58db95c107b468b736b700f6620985a8ed050a73d51c8') + + def test_i386(self): + self.set_machine('q35') + self.cpu="coreduo" + self.wait_for_shutdown=False + self.common_tuxrun(kernel_asset=self.ASSET_I386_KERNEL, + rootfs_asset=self.ASSET_I386_ROOTFS, + drive="virtio-blk-pci") + +if __name__ == '__main__': + TuxRunBaselineTest.main() diff --git a/tests/functional/meson.build b/tests/functional/meson.build index 8f85c13..f1fc017 100644 --- a/tests/functional/meson.build +++ b/tests/functional/meson.build @@ -14,6 +14,7 @@ subdir('alpha') subdir('arm') subdir('avr') subdir('hppa') +subdir('i386') test_mips_timeouts = { 'mips_malta' : 480, @@ -79,15 +80,6 @@ tests_generic_linuxuser = [ tests_generic_bsduser = [ ] -tests_i386_system_quick = [ - 'i386_migration', -] - -tests_i386_system_thorough = [ - 'i386_replay', - 'i386_tuxrun', -] - tests_loongarch64_system_thorough = [ 'loongarch64_virt', ] diff --git a/tests/functional/test_i386_migration.py b/tests/functional/test_i386_migration.py deleted file mode 100755 index a57f316..0000000 --- a/tests/functional/test_i386_migration.py +++ /dev/null @@ -1,26 +0,0 @@ -#!/usr/bin/env python3 -# -# SPDX-License-Identifier: GPL-2.0-or-later -# -# i386 migration test - -from migration import MigrationTest - - -class I386MigrationTest(MigrationTest): - - def test_migration_with_tcp_localhost(self): - self.set_machine('isapc') - self.migration_with_tcp_localhost() - - def test_migration_with_unix(self): - self.set_machine('isapc') - self.migration_with_unix() - - def test_migration_with_exec(self): - self.set_machine('isapc') - self.migration_with_exec() - - -if __name__ == '__main__': - MigrationTest.main() diff --git a/tests/functional/test_i386_replay.py b/tests/functional/test_i386_replay.py deleted file mode 100755 index 7c4c260..0000000 --- a/tests/functional/test_i386_replay.py +++ /dev/null @@ -1,28 +0,0 @@ -#!/usr/bin/env python3 -# -# Replay test that boots a Linux kernel on a i386 machine -# and checks the console -# -# SPDX-License-Identifier: GPL-2.0-or-later - -from qemu_test import Asset -from replay_kernel import ReplayKernelBase - - -class I386Replay(ReplayKernelBase): - - ASSET_KERNEL = Asset( - 'https://storage.tuxboot.com/20230331/i386/bzImage', - 'a3e5b32a354729e65910f5a1ffcda7c14a6c12a55e8213fb86e277f1b76ed956') - - def test_pc(self): - self.set_machine('pc') - kernel_url = () - kernel_path = self.ASSET_KERNEL.fetch() - kernel_command_line = self.KERNEL_COMMON_COMMAND_LINE + 'console=ttyS0' - console_pattern = 'VFS: Cannot open root device' - self.run_rr(kernel_path, kernel_command_line, console_pattern, shift=5) - - -if __name__ == '__main__': - ReplayKernelBase.main() diff --git a/tests/functional/test_i386_tuxrun.py b/tests/functional/test_i386_tuxrun.py deleted file mode 100755 index f3ccf11..0000000 --- a/tests/functional/test_i386_tuxrun.py +++ /dev/null @@ -1,35 +0,0 @@ -#!/usr/bin/env python3 -# -# Functional test that boots known good tuxboot images the same way -# that tuxrun (www.tuxrun.org) does. This tool is used by things like -# the LKFT project to run regression tests on kernels. -# -# Copyright (c) 2023 Linaro Ltd. -# -# Author: -# Alex Bennée -# -# SPDX-License-Identifier: GPL-2.0-or-later - -from qemu_test import Asset -from qemu_test.tuxruntest import TuxRunBaselineTest - -class TuxRunI386Test(TuxRunBaselineTest): - - ASSET_I386_KERNEL = Asset( - 'https://storage.tuxboot.com/buildroot/20241119/i386/bzImage', - '47fb44e38e34101eb0f71a2a01742b959d40ed5fd67cefb5608a39be11d3b74e') - ASSET_I386_ROOTFS = Asset( - 'https://storage.tuxboot.com/buildroot/20241119/i386/rootfs.ext4.zst', - 'a1a3b3b4c9dccd6475b58db95c107b468b736b700f6620985a8ed050a73d51c8') - - def test_i386(self): - self.set_machine('q35') - self.cpu="coreduo" - self.wait_for_shutdown=False - self.common_tuxrun(kernel_asset=self.ASSET_I386_KERNEL, - rootfs_asset=self.ASSET_I386_ROOTFS, - drive="virtio-blk-pci") - -if __name__ == '__main__': - TuxRunBaselineTest.main() -- cgit v1.1 From 6bd38ef0f9af38364509005385ff2ac897ad3913 Mon Sep 17 00:00:00 2001 From: Thomas Huth Date: Tue, 19 Aug 2025 13:23:48 +0200 Subject: tests/functional: Move loongarch64 tests into architecture specific folder MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The tests/functional folder has become quite crowded, thus move the loongarch64 tests into a target-specific subfolder. Reviewed-by: Pierrick Bouvier Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Thomas Huth Message-ID: <20250819112403.432587-12-thuth@redhat.com> --- tests/functional/loongarch64/meson.build | 5 +++ tests/functional/loongarch64/test_virt.py | 62 +++++++++++++++++++++++++++++++ tests/functional/meson.build | 5 +-- tests/functional/test_loongarch64_virt.py | 62 ------------------------------- 4 files changed, 68 insertions(+), 66 deletions(-) create mode 100644 tests/functional/loongarch64/meson.build create mode 100755 tests/functional/loongarch64/test_virt.py delete mode 100755 tests/functional/test_loongarch64_virt.py (limited to 'tests') diff --git a/tests/functional/loongarch64/meson.build b/tests/functional/loongarch64/meson.build new file mode 100644 index 0000000..d168717 --- /dev/null +++ b/tests/functional/loongarch64/meson.build @@ -0,0 +1,5 @@ +# SPDX-License-Identifier: GPL-2.0-or-later + +tests_loongarch64_system_thorough = [ + 'virt', +] diff --git a/tests/functional/loongarch64/test_virt.py b/tests/functional/loongarch64/test_virt.py new file mode 100755 index 0000000..b7d9abf --- /dev/null +++ b/tests/functional/loongarch64/test_virt.py @@ -0,0 +1,62 @@ +#!/usr/bin/env python3 +# +# SPDX-License-Identifier: GPL-2.0-or-later +# +# LoongArch virt test. +# +# Copyright (c) 2023 Loongson Technology Corporation Limited +# + +from qemu_test import QemuSystemTest, Asset +from qemu_test import exec_command_and_wait_for_pattern +from qemu_test import wait_for_console_pattern + +class LoongArchMachine(QemuSystemTest): + KERNEL_COMMON_COMMAND_LINE = 'printk.time=0 ' + + timeout = 120 + + ASSET_KERNEL = Asset( + ('https://github.com/yangxiaojuan-loongson/qemu-binary/' + 'releases/download/2024-11-26/vmlinuz.efi'), + '08b88a45f48a5fd92260bae895be4e5175be2397481a6f7821b9f39b2965b79e') + ASSET_INITRD = Asset( + ('https://github.com/yangxiaojuan-loongson/qemu-binary/' + 'releases/download/2024-11-26/ramdisk'), + '03d6fb6f8ee64ecac961120a0bdacf741f17b3bee2141f17fa01908c8baf176a') + ASSET_BIOS = Asset( + ('https://github.com/yangxiaojuan-loongson/qemu-binary/' + 'releases/download/2024-11-26/QEMU_EFI.fd'), + 'f55fbf5d92e885844631ae9bfa8887f659bbb4f6ef2beea9e9ff8bc0603b6697') + + def wait_for_console_pattern(self, success_message, vm=None): + wait_for_console_pattern(self, success_message, + failure_message='Kernel panic - not syncing', + vm=vm) + + def test_loongarch64_devices(self): + + self.set_machine('virt') + + kernel_path = self.ASSET_KERNEL.fetch() + initrd_path = self.ASSET_INITRD.fetch() + bios_path = self.ASSET_BIOS.fetch() + + self.vm.set_console() + kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE + + 'root=/dev/ram rdinit=/sbin/init console=ttyS0,115200') + self.vm.add_args('-nographic', + '-smp', '4', + '-m', '1024', + '-cpu', 'la464', + '-kernel', kernel_path, + '-initrd', initrd_path, + '-bios', bios_path, + '-append', kernel_command_line) + self.vm.launch() + self.wait_for_console_pattern('Run /sbin/init as init process') + exec_command_and_wait_for_pattern(self, 'cat /proc/cpuinfo', + 'processor : 3') + +if __name__ == '__main__': + QemuSystemTest.main() diff --git a/tests/functional/meson.build b/tests/functional/meson.build index f1fc017..e2e66dc 100644 --- a/tests/functional/meson.build +++ b/tests/functional/meson.build @@ -15,6 +15,7 @@ subdir('arm') subdir('avr') subdir('hppa') subdir('i386') +subdir('loongarch64') test_mips_timeouts = { 'mips_malta' : 480, @@ -80,10 +81,6 @@ tests_generic_linuxuser = [ tests_generic_bsduser = [ ] -tests_loongarch64_system_thorough = [ - 'loongarch64_virt', -] - tests_m68k_system_thorough = [ 'm68k_mcf5208evb', 'm68k_nextcube', diff --git a/tests/functional/test_loongarch64_virt.py b/tests/functional/test_loongarch64_virt.py deleted file mode 100755 index b7d9abf..0000000 --- a/tests/functional/test_loongarch64_virt.py +++ /dev/null @@ -1,62 +0,0 @@ -#!/usr/bin/env python3 -# -# SPDX-License-Identifier: GPL-2.0-or-later -# -# LoongArch virt test. -# -# Copyright (c) 2023 Loongson Technology Corporation Limited -# - -from qemu_test import QemuSystemTest, Asset -from qemu_test import exec_command_and_wait_for_pattern -from qemu_test import wait_for_console_pattern - -class LoongArchMachine(QemuSystemTest): - KERNEL_COMMON_COMMAND_LINE = 'printk.time=0 ' - - timeout = 120 - - ASSET_KERNEL = Asset( - ('https://github.com/yangxiaojuan-loongson/qemu-binary/' - 'releases/download/2024-11-26/vmlinuz.efi'), - '08b88a45f48a5fd92260bae895be4e5175be2397481a6f7821b9f39b2965b79e') - ASSET_INITRD = Asset( - ('https://github.com/yangxiaojuan-loongson/qemu-binary/' - 'releases/download/2024-11-26/ramdisk'), - '03d6fb6f8ee64ecac961120a0bdacf741f17b3bee2141f17fa01908c8baf176a') - ASSET_BIOS = Asset( - ('https://github.com/yangxiaojuan-loongson/qemu-binary/' - 'releases/download/2024-11-26/QEMU_EFI.fd'), - 'f55fbf5d92e885844631ae9bfa8887f659bbb4f6ef2beea9e9ff8bc0603b6697') - - def wait_for_console_pattern(self, success_message, vm=None): - wait_for_console_pattern(self, success_message, - failure_message='Kernel panic - not syncing', - vm=vm) - - def test_loongarch64_devices(self): - - self.set_machine('virt') - - kernel_path = self.ASSET_KERNEL.fetch() - initrd_path = self.ASSET_INITRD.fetch() - bios_path = self.ASSET_BIOS.fetch() - - self.vm.set_console() - kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE + - 'root=/dev/ram rdinit=/sbin/init console=ttyS0,115200') - self.vm.add_args('-nographic', - '-smp', '4', - '-m', '1024', - '-cpu', 'la464', - '-kernel', kernel_path, - '-initrd', initrd_path, - '-bios', bios_path, - '-append', kernel_command_line) - self.vm.launch() - self.wait_for_console_pattern('Run /sbin/init as init process') - exec_command_and_wait_for_pattern(self, 'cat /proc/cpuinfo', - 'processor : 3') - -if __name__ == '__main__': - QemuSystemTest.main() -- cgit v1.1 From 0ae63d0e19b22d45cd354b428b4b530223f53d7b Mon Sep 17 00:00:00 2001 From: Thomas Huth Date: Tue, 19 Aug 2025 13:23:49 +0200 Subject: tests/functional: Move m68k tests into architecture specific folder MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The tests/functional folder has become quite crowded, thus move the m68k tests into a target-specific subfolder. Reviewed-by: Pierrick Bouvier Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Thomas Huth Message-ID: <20250819112403.432587-13-thuth@redhat.com> --- tests/functional/m68k/meson.build | 9 +++++ tests/functional/m68k/test_mcf5208evb.py | 27 ++++++++++++++ tests/functional/m68k/test_nextcube.py | 64 ++++++++++++++++++++++++++++++++ tests/functional/m68k/test_q800.py | 37 ++++++++++++++++++ tests/functional/m68k/test_replay.py | 43 +++++++++++++++++++++ tests/functional/m68k/test_tuxrun.py | 34 +++++++++++++++++ tests/functional/meson.build | 9 +---- tests/functional/test_m68k_mcf5208evb.py | 27 -------------- tests/functional/test_m68k_nextcube.py | 64 -------------------------------- tests/functional/test_m68k_q800.py | 37 ------------------ tests/functional/test_m68k_replay.py | 43 --------------------- tests/functional/test_m68k_tuxrun.py | 34 ----------------- 12 files changed, 215 insertions(+), 213 deletions(-) create mode 100644 tests/functional/m68k/meson.build create mode 100755 tests/functional/m68k/test_mcf5208evb.py create mode 100755 tests/functional/m68k/test_nextcube.py create mode 100755 tests/functional/m68k/test_q800.py create mode 100755 tests/functional/m68k/test_replay.py create mode 100755 tests/functional/m68k/test_tuxrun.py delete mode 100755 tests/functional/test_m68k_mcf5208evb.py delete mode 100755 tests/functional/test_m68k_nextcube.py delete mode 100755 tests/functional/test_m68k_q800.py delete mode 100755 tests/functional/test_m68k_replay.py delete mode 100755 tests/functional/test_m68k_tuxrun.py (limited to 'tests') diff --git a/tests/functional/m68k/meson.build b/tests/functional/m68k/meson.build new file mode 100644 index 0000000..e29044a --- /dev/null +++ b/tests/functional/m68k/meson.build @@ -0,0 +1,9 @@ +# SPDX-License-Identifier: GPL-2.0-or-later + +tests_m68k_system_thorough = [ + 'mcf5208evb', + 'nextcube', + 'replay', + 'q800', + 'tuxrun', +] diff --git a/tests/functional/m68k/test_mcf5208evb.py b/tests/functional/m68k/test_mcf5208evb.py new file mode 100755 index 0000000..c7d1998 --- /dev/null +++ b/tests/functional/m68k/test_mcf5208evb.py @@ -0,0 +1,27 @@ +#!/usr/bin/env python3 +# +# Functional test that boots a Linux kernel on an MCF5208EVB machine +# and checks the console +# +# SPDX-License-Identifier: GPL-2.0-or-later + +from qemu_test import LinuxKernelTest, Asset + + +class Mcf5208EvbTest(LinuxKernelTest): + + ASSET_DAY07 = Asset( + 'https://qemu-advcal.gitlab.io/qac-best-of-multiarch/download/day07.tar.xz', + '753c2f3837126b7c6ba92d0b1e0b156e8a2c5131d2d576bb0b9a763fae73c08a') + + def test_m68k_mcf5208evb(self): + self.set_machine('mcf5208evb') + self.archive_extract(self.ASSET_DAY07) + self.vm.set_console() + self.vm.add_args('-kernel', + self.scratch_file('day07', 'sanity-clause.elf')) + self.vm.launch() + self.wait_for_console_pattern('QEMU advent calendar') + +if __name__ == '__main__': + LinuxKernelTest.main() diff --git a/tests/functional/m68k/test_nextcube.py b/tests/functional/m68k/test_nextcube.py new file mode 100755 index 0000000..13c72bd --- /dev/null +++ b/tests/functional/m68k/test_nextcube.py @@ -0,0 +1,64 @@ +#!/usr/bin/env python3 +# +# Functional test that boots a VM and run OCR on the framebuffer +# +# Copyright (c) 2019 Philippe Mathieu-Daudé +# +# This work is licensed under the terms of the GNU GPL, version 2 or +# later. See the COPYING file in the top-level directory. + +import time + +from qemu_test import QemuSystemTest, Asset +from qemu_test import skipIfMissingImports, skipIfMissingCommands +from qemu_test.tesseract import tesseract_ocr + + +class NextCubeMachine(QemuSystemTest): + + timeout = 15 + + ASSET_ROM = Asset(('https://sourceforge.net/p/previous/code/1350/tree/' + 'trunk/src/Rev_2.5_v66.BIN?format=raw'), + '1b753890b67095b73e104c939ddf62eca9e7d0aedde5108e3893b0ed9d8000a4') + + def check_bootrom_framebuffer(self, screenshot_path): + rom_path = self.ASSET_ROM.fetch() + + self.vm.add_args('-bios', rom_path) + self.vm.launch() + + self.log.info('VM launched, waiting for display') + # TODO: wait for the 'displaysurface_create 1120x832' trace-event. + time.sleep(2) + + res = self.vm.cmd('human-monitor-command', + command_line='screendump %s' % screenshot_path) + if 'unknown command' in res: + self.skipTest('screendump not available') + + @skipIfMissingImports("PIL") + def test_bootrom_framebuffer_size(self): + self.set_machine('next-cube') + screenshot_path = self.scratch_file("dump.ppm") + self.check_bootrom_framebuffer(screenshot_path) + + from PIL import Image + width, height = Image.open(screenshot_path).size + self.assertEqual(width, 1120) + self.assertEqual(height, 832) + + @skipIfMissingCommands('tesseract') + def test_bootrom_framebuffer_ocr_with_tesseract(self): + self.set_machine('next-cube') + screenshot_path = self.scratch_file("dump.ppm") + self.check_bootrom_framebuffer(screenshot_path) + lines = tesseract_ocr(screenshot_path) + text = '\n'.join(lines) + self.assertIn('Testing the FPU', text) + self.assertIn('System test failed. Error code', text) + self.assertIn('Boot command', text) + self.assertIn('Next>', text) + +if __name__ == '__main__': + QemuSystemTest.main() diff --git a/tests/functional/m68k/test_q800.py b/tests/functional/m68k/test_q800.py new file mode 100755 index 0000000..b3e6553 --- /dev/null +++ b/tests/functional/m68k/test_q800.py @@ -0,0 +1,37 @@ +#!/usr/bin/env python3 +# +# Functional test for testing the q800 m68k machine +# +# This work is licensed under the terms of the GNU GPL, version 2 or +# later. See the COPYING file in the top-level directory. + +from qemu_test import LinuxKernelTest, Asset + +class Q800MachineTest(LinuxKernelTest): + + ASSET_KERNEL = Asset( + ('https://snapshot.debian.org/' + 'archive/debian-ports/20191021T083923Z/pool-m68k/main/l/linux/' + 'kernel-image-5.3.0-1-m68k-di_5.3.7-1_m68k.udeb'), + '949e50d74d4b9bc15d26c06d402717b7a4c0e32ff8100014f5930d8024de7b73') + + def test_m68k_q800(self): + self.set_machine('q800') + + kernel_path = self.archive_extract(self.ASSET_KERNEL, + member='boot/vmlinux-5.3.0-1-m68k') + + self.vm.set_console() + kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE + + 'console=ttyS0 vga=off') + self.vm.add_args('-kernel', kernel_path, + '-append', kernel_command_line, + '-audio', 'none') + self.vm.launch() + console_pattern = 'Kernel command line: %s' % kernel_command_line + self.wait_for_console_pattern(console_pattern) + console_pattern = 'No filesystem could mount root' + self.wait_for_console_pattern(console_pattern) + +if __name__ == '__main__': + LinuxKernelTest.main() diff --git a/tests/functional/m68k/test_replay.py b/tests/functional/m68k/test_replay.py new file mode 100755 index 0000000..213d6ae --- /dev/null +++ b/tests/functional/m68k/test_replay.py @@ -0,0 +1,43 @@ +#!/usr/bin/env python3 +# +# Replay test that boots a Linux kernel on an m68k machine +# and checks the console +# +# SPDX-License-Identifier: GPL-2.0-or-later + +from qemu_test import Asset +from replay_kernel import ReplayKernelBase + + +class M68kReplay(ReplayKernelBase): + + ASSET_Q800 = Asset( + ('https://snapshot.debian.org/' + 'archive/debian-ports/20191021T083923Z/pool-m68k/main/l/linux/' + 'kernel-image-5.3.0-1-m68k-di_5.3.7-1_m68k.udeb'), + '949e50d74d4b9bc15d26c06d402717b7a4c0e32ff8100014f5930d8024de7b73') + + def test_q800(self): + self.set_machine('q800') + kernel_path = self.archive_extract(self.ASSET_Q800, + member='boot/vmlinux-5.3.0-1-m68k') + kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE + + 'console=ttyS0 vga=off') + console_pattern = 'No filesystem could mount root' + self.run_rr(kernel_path, kernel_command_line, console_pattern, + args=('-audio', 'none')) + + ASSET_MCF5208 = Asset( + 'https://qemu-advcal.gitlab.io/qac-best-of-multiarch/download/day07.tar.xz', + '753c2f3837126b7c6ba92d0b1e0b156e8a2c5131d2d576bb0b9a763fae73c08a') + + def test_mcf5208evb(self): + self.set_machine('mcf5208evb') + kernel_path = self.archive_extract(self.ASSET_MCF5208, + member='day07/sanity-clause.elf') + self.run_rr(kernel_path, self.KERNEL_COMMON_COMMAND_LINE, + 'QEMU advent calendar') + + +if __name__ == '__main__': + ReplayKernelBase.main() diff --git a/tests/functional/m68k/test_tuxrun.py b/tests/functional/m68k/test_tuxrun.py new file mode 100755 index 0000000..7eacba1 --- /dev/null +++ b/tests/functional/m68k/test_tuxrun.py @@ -0,0 +1,34 @@ +#!/usr/bin/env python3 +# +# Functional test that boots known good tuxboot images the same way +# that tuxrun (www.tuxrun.org) does. This tool is used by things like +# the LKFT project to run regression tests on kernels. +# +# Copyright (c) 2024 Linaro Ltd. +# +# Author: +# Alex Bennée +# +# SPDX-License-Identifier: GPL-2.0-or-later + +from qemu_test import Asset +from qemu_test.tuxruntest import TuxRunBaselineTest + +class TuxRunM68KTest(TuxRunBaselineTest): + + ASSET_M68K_KERNEL = Asset( + 'https://storage.tuxboot.com/buildroot/20241119/m68k/vmlinux', + '7754e1d5cec753ccf1dc6894729a7f54c1a4965631ebf56df8e4ce1163ad19d8') + ASSET_M68K_ROOTFS = Asset( + 'https://storage.tuxboot.com/buildroot/20241119/m68k/rootfs.ext4.zst', + '557962ffff265607912e82232cf21adbe0e4e5a88e1e1d411ce848c37f0213e9') + + def test_m68k(self): + self.set_machine('virt') + self.cpu="m68040" + self.common_tuxrun(kernel_asset=self.ASSET_M68K_KERNEL, + rootfs_asset=self.ASSET_M68K_ROOTFS, + drive="virtio-blk-device") + +if __name__ == '__main__': + TuxRunBaselineTest.main() diff --git a/tests/functional/meson.build b/tests/functional/meson.build index e2e66dc..d32dd4a 100644 --- a/tests/functional/meson.build +++ b/tests/functional/meson.build @@ -16,6 +16,7 @@ subdir('avr') subdir('hppa') subdir('i386') subdir('loongarch64') +subdir('m68k') test_mips_timeouts = { 'mips_malta' : 480, @@ -81,14 +82,6 @@ tests_generic_linuxuser = [ tests_generic_bsduser = [ ] -tests_m68k_system_thorough = [ - 'm68k_mcf5208evb', - 'm68k_nextcube', - 'm68k_replay', - 'm68k_q800', - 'm68k_tuxrun', -] - tests_microblaze_system_thorough = [ 'microblaze_replay', 'microblaze_s3adsp1800' diff --git a/tests/functional/test_m68k_mcf5208evb.py b/tests/functional/test_m68k_mcf5208evb.py deleted file mode 100755 index c7d1998..0000000 --- a/tests/functional/test_m68k_mcf5208evb.py +++ /dev/null @@ -1,27 +0,0 @@ -#!/usr/bin/env python3 -# -# Functional test that boots a Linux kernel on an MCF5208EVB machine -# and checks the console -# -# SPDX-License-Identifier: GPL-2.0-or-later - -from qemu_test import LinuxKernelTest, Asset - - -class Mcf5208EvbTest(LinuxKernelTest): - - ASSET_DAY07 = Asset( - 'https://qemu-advcal.gitlab.io/qac-best-of-multiarch/download/day07.tar.xz', - '753c2f3837126b7c6ba92d0b1e0b156e8a2c5131d2d576bb0b9a763fae73c08a') - - def test_m68k_mcf5208evb(self): - self.set_machine('mcf5208evb') - self.archive_extract(self.ASSET_DAY07) - self.vm.set_console() - self.vm.add_args('-kernel', - self.scratch_file('day07', 'sanity-clause.elf')) - self.vm.launch() - self.wait_for_console_pattern('QEMU advent calendar') - -if __name__ == '__main__': - LinuxKernelTest.main() diff --git a/tests/functional/test_m68k_nextcube.py b/tests/functional/test_m68k_nextcube.py deleted file mode 100755 index 13c72bd..0000000 --- a/tests/functional/test_m68k_nextcube.py +++ /dev/null @@ -1,64 +0,0 @@ -#!/usr/bin/env python3 -# -# Functional test that boots a VM and run OCR on the framebuffer -# -# Copyright (c) 2019 Philippe Mathieu-Daudé -# -# This work is licensed under the terms of the GNU GPL, version 2 or -# later. See the COPYING file in the top-level directory. - -import time - -from qemu_test import QemuSystemTest, Asset -from qemu_test import skipIfMissingImports, skipIfMissingCommands -from qemu_test.tesseract import tesseract_ocr - - -class NextCubeMachine(QemuSystemTest): - - timeout = 15 - - ASSET_ROM = Asset(('https://sourceforge.net/p/previous/code/1350/tree/' - 'trunk/src/Rev_2.5_v66.BIN?format=raw'), - '1b753890b67095b73e104c939ddf62eca9e7d0aedde5108e3893b0ed9d8000a4') - - def check_bootrom_framebuffer(self, screenshot_path): - rom_path = self.ASSET_ROM.fetch() - - self.vm.add_args('-bios', rom_path) - self.vm.launch() - - self.log.info('VM launched, waiting for display') - # TODO: wait for the 'displaysurface_create 1120x832' trace-event. - time.sleep(2) - - res = self.vm.cmd('human-monitor-command', - command_line='screendump %s' % screenshot_path) - if 'unknown command' in res: - self.skipTest('screendump not available') - - @skipIfMissingImports("PIL") - def test_bootrom_framebuffer_size(self): - self.set_machine('next-cube') - screenshot_path = self.scratch_file("dump.ppm") - self.check_bootrom_framebuffer(screenshot_path) - - from PIL import Image - width, height = Image.open(screenshot_path).size - self.assertEqual(width, 1120) - self.assertEqual(height, 832) - - @skipIfMissingCommands('tesseract') - def test_bootrom_framebuffer_ocr_with_tesseract(self): - self.set_machine('next-cube') - screenshot_path = self.scratch_file("dump.ppm") - self.check_bootrom_framebuffer(screenshot_path) - lines = tesseract_ocr(screenshot_path) - text = '\n'.join(lines) - self.assertIn('Testing the FPU', text) - self.assertIn('System test failed. Error code', text) - self.assertIn('Boot command', text) - self.assertIn('Next>', text) - -if __name__ == '__main__': - QemuSystemTest.main() diff --git a/tests/functional/test_m68k_q800.py b/tests/functional/test_m68k_q800.py deleted file mode 100755 index b3e6553..0000000 --- a/tests/functional/test_m68k_q800.py +++ /dev/null @@ -1,37 +0,0 @@ -#!/usr/bin/env python3 -# -# Functional test for testing the q800 m68k machine -# -# This work is licensed under the terms of the GNU GPL, version 2 or -# later. See the COPYING file in the top-level directory. - -from qemu_test import LinuxKernelTest, Asset - -class Q800MachineTest(LinuxKernelTest): - - ASSET_KERNEL = Asset( - ('https://snapshot.debian.org/' - 'archive/debian-ports/20191021T083923Z/pool-m68k/main/l/linux/' - 'kernel-image-5.3.0-1-m68k-di_5.3.7-1_m68k.udeb'), - '949e50d74d4b9bc15d26c06d402717b7a4c0e32ff8100014f5930d8024de7b73') - - def test_m68k_q800(self): - self.set_machine('q800') - - kernel_path = self.archive_extract(self.ASSET_KERNEL, - member='boot/vmlinux-5.3.0-1-m68k') - - self.vm.set_console() - kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE + - 'console=ttyS0 vga=off') - self.vm.add_args('-kernel', kernel_path, - '-append', kernel_command_line, - '-audio', 'none') - self.vm.launch() - console_pattern = 'Kernel command line: %s' % kernel_command_line - self.wait_for_console_pattern(console_pattern) - console_pattern = 'No filesystem could mount root' - self.wait_for_console_pattern(console_pattern) - -if __name__ == '__main__': - LinuxKernelTest.main() diff --git a/tests/functional/test_m68k_replay.py b/tests/functional/test_m68k_replay.py deleted file mode 100755 index 213d6ae..0000000 --- a/tests/functional/test_m68k_replay.py +++ /dev/null @@ -1,43 +0,0 @@ -#!/usr/bin/env python3 -# -# Replay test that boots a Linux kernel on an m68k machine -# and checks the console -# -# SPDX-License-Identifier: GPL-2.0-or-later - -from qemu_test import Asset -from replay_kernel import ReplayKernelBase - - -class M68kReplay(ReplayKernelBase): - - ASSET_Q800 = Asset( - ('https://snapshot.debian.org/' - 'archive/debian-ports/20191021T083923Z/pool-m68k/main/l/linux/' - 'kernel-image-5.3.0-1-m68k-di_5.3.7-1_m68k.udeb'), - '949e50d74d4b9bc15d26c06d402717b7a4c0e32ff8100014f5930d8024de7b73') - - def test_q800(self): - self.set_machine('q800') - kernel_path = self.archive_extract(self.ASSET_Q800, - member='boot/vmlinux-5.3.0-1-m68k') - kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE + - 'console=ttyS0 vga=off') - console_pattern = 'No filesystem could mount root' - self.run_rr(kernel_path, kernel_command_line, console_pattern, - args=('-audio', 'none')) - - ASSET_MCF5208 = Asset( - 'https://qemu-advcal.gitlab.io/qac-best-of-multiarch/download/day07.tar.xz', - '753c2f3837126b7c6ba92d0b1e0b156e8a2c5131d2d576bb0b9a763fae73c08a') - - def test_mcf5208evb(self): - self.set_machine('mcf5208evb') - kernel_path = self.archive_extract(self.ASSET_MCF5208, - member='day07/sanity-clause.elf') - self.run_rr(kernel_path, self.KERNEL_COMMON_COMMAND_LINE, - 'QEMU advent calendar') - - -if __name__ == '__main__': - ReplayKernelBase.main() diff --git a/tests/functional/test_m68k_tuxrun.py b/tests/functional/test_m68k_tuxrun.py deleted file mode 100755 index 7eacba1..0000000 --- a/tests/functional/test_m68k_tuxrun.py +++ /dev/null @@ -1,34 +0,0 @@ -#!/usr/bin/env python3 -# -# Functional test that boots known good tuxboot images the same way -# that tuxrun (www.tuxrun.org) does. This tool is used by things like -# the LKFT project to run regression tests on kernels. -# -# Copyright (c) 2024 Linaro Ltd. -# -# Author: -# Alex Bennée -# -# SPDX-License-Identifier: GPL-2.0-or-later - -from qemu_test import Asset -from qemu_test.tuxruntest import TuxRunBaselineTest - -class TuxRunM68KTest(TuxRunBaselineTest): - - ASSET_M68K_KERNEL = Asset( - 'https://storage.tuxboot.com/buildroot/20241119/m68k/vmlinux', - '7754e1d5cec753ccf1dc6894729a7f54c1a4965631ebf56df8e4ce1163ad19d8') - ASSET_M68K_ROOTFS = Asset( - 'https://storage.tuxboot.com/buildroot/20241119/m68k/rootfs.ext4.zst', - '557962ffff265607912e82232cf21adbe0e4e5a88e1e1d411ce848c37f0213e9') - - def test_m68k(self): - self.set_machine('virt') - self.cpu="m68040" - self.common_tuxrun(kernel_asset=self.ASSET_M68K_KERNEL, - rootfs_asset=self.ASSET_M68K_ROOTFS, - drive="virtio-blk-device") - -if __name__ == '__main__': - TuxRunBaselineTest.main() -- cgit v1.1 From 67adbc8b6f40f6a2370d4a0ba479d3778d147cbc Mon Sep 17 00:00:00 2001 From: Thomas Huth Date: Tue, 19 Aug 2025 13:23:50 +0200 Subject: tests/functional: Move microblaze tests into architecture specific folder MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The tests/functional folder has become quite crowded, thus move the microblaze tests into a target-specific subfolder. Reviewed-by: Pierrick Bouvier Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Thomas Huth Message-ID: <20250819112403.432587-14-thuth@redhat.com> --- tests/functional/meson.build | 11 +--- tests/functional/microblaze/meson.build | 6 ++ tests/functional/microblaze/test_replay.py | 28 +++++++++ tests/functional/microblaze/test_s3adsp1800.py | 76 ++++++++++++++++++++++++ tests/functional/microblazeel/meson.build | 5 ++ tests/functional/microblazeel/test_s3adsp1800.py | 26 ++++++++ tests/functional/test_microblaze_replay.py | 28 --------- tests/functional/test_microblaze_s3adsp1800.py | 76 ------------------------ tests/functional/test_microblazeel_s3adsp1800.py | 26 -------- 9 files changed, 143 insertions(+), 139 deletions(-) create mode 100644 tests/functional/microblaze/meson.build create mode 100755 tests/functional/microblaze/test_replay.py create mode 100755 tests/functional/microblaze/test_s3adsp1800.py create mode 100644 tests/functional/microblazeel/meson.build create mode 100755 tests/functional/microblazeel/test_s3adsp1800.py delete mode 100755 tests/functional/test_microblaze_replay.py delete mode 100755 tests/functional/test_microblaze_s3adsp1800.py delete mode 100755 tests/functional/test_microblazeel_s3adsp1800.py (limited to 'tests') diff --git a/tests/functional/meson.build b/tests/functional/meson.build index d32dd4a..fee6805 100644 --- a/tests/functional/meson.build +++ b/tests/functional/meson.build @@ -17,6 +17,8 @@ subdir('hppa') subdir('i386') subdir('loongarch64') subdir('m68k') +subdir('microblaze') +subdir('microblazeel') test_mips_timeouts = { 'mips_malta' : 480, @@ -82,15 +84,6 @@ tests_generic_linuxuser = [ tests_generic_bsduser = [ ] -tests_microblaze_system_thorough = [ - 'microblaze_replay', - 'microblaze_s3adsp1800' -] - -tests_microblazeel_system_thorough = [ - 'microblazeel_s3adsp1800' -] - tests_mips_system_thorough = [ 'mips_malta', 'mips_replay', diff --git a/tests/functional/microblaze/meson.build b/tests/functional/microblaze/meson.build new file mode 100644 index 0000000..8069ca9 --- /dev/null +++ b/tests/functional/microblaze/meson.build @@ -0,0 +1,6 @@ +# SPDX-License-Identifier: GPL-2.0-or-later + +tests_microblaze_system_thorough = [ + 'replay', + 's3adsp1800' +] diff --git a/tests/functional/microblaze/test_replay.py b/tests/functional/microblaze/test_replay.py new file mode 100755 index 0000000..7484c41 --- /dev/null +++ b/tests/functional/microblaze/test_replay.py @@ -0,0 +1,28 @@ +#!/usr/bin/env python3 +# +# Replay test that boots a Linux kernel on an microblaze machine +# and checks the console +# +# SPDX-License-Identifier: GPL-2.0-or-later + +from qemu_test import Asset +from replay_kernel import ReplayKernelBase + + +class MicroblazeReplay(ReplayKernelBase): + + ASSET_DAY17 = Asset( + ('https://qemu-advcal.gitlab.io/qac-best-of-multiarch/download/' + 'day17.tar.xz'), + '3ba7439dfbea7af4876662c97f8e1f0cdad9231fc166e4861d17042489270057') + + def test_microblaze_s3adsp1800(self): + self.set_machine('petalogix-s3adsp1800') + kernel_path = self.archive_extract(self.ASSET_DAY17, + member='day17/ballerina.bin') + self.run_rr(kernel_path, self.REPLAY_KERNEL_COMMAND_LINE, + 'QEMU advent calendar') + + +if __name__ == '__main__': + ReplayKernelBase.main() diff --git a/tests/functional/microblaze/test_s3adsp1800.py b/tests/functional/microblaze/test_s3adsp1800.py new file mode 100755 index 0000000..f093b16 --- /dev/null +++ b/tests/functional/microblaze/test_s3adsp1800.py @@ -0,0 +1,76 @@ +#!/usr/bin/env python3 +# +# Functional test that boots a microblaze Linux kernel and checks the console +# +# Copyright (c) 2018, 2021 Red Hat, Inc. +# +# This work is licensed under the terms of the GNU GPL, version 2 or +# later. See the COPYING file in the top-level directory. + +from qemu_test import exec_command_and_wait_for_pattern +from qemu_test import QemuSystemTest, Asset +from qemu_test import wait_for_console_pattern + + +class MicroblazeMachine(QemuSystemTest): + + timeout = 90 + + ASSET_IMAGE_BE = Asset( + ('https://qemu-advcal.gitlab.io/qac-best-of-multiarch/download/' + 'day17.tar.xz'), + '3ba7439dfbea7af4876662c97f8e1f0cdad9231fc166e4861d17042489270057') + + ASSET_IMAGE_LE = Asset( + ('http://www.qemu-advent-calendar.org/2023/download/day13.tar.gz'), + 'b9b3d43c5dd79db88ada495cc6e0d1f591153fe41355e925d791fbf44de50c22') + + def do_ballerina_be_test(self, force_endianness=False): + self.set_machine('petalogix-s3adsp1800') + self.archive_extract(self.ASSET_IMAGE_BE) + self.vm.set_console() + self.vm.add_args('-kernel', + self.scratch_file('day17', 'ballerina.bin')) + if force_endianness: + self.vm.add_args('-M', 'endianness=big') + self.vm.launch() + wait_for_console_pattern(self, 'This architecture does not have ' + 'kernel memory protection') + # Note: + # The kernel sometimes gets stuck after the "This architecture ..." + # message, that's why we don't test for a later string here. This + # needs some investigation by a microblaze wizard one day... + + def do_xmaton_le_test(self, force_endianness=False): + self.require_netdev('user') + self.set_machine('petalogix-s3adsp1800') + self.archive_extract(self.ASSET_IMAGE_LE) + self.vm.set_console() + self.vm.add_args('-kernel', self.scratch_file('day13', 'xmaton.bin')) + if force_endianness: + self.vm.add_args('-M', 'endianness=little') + tftproot = self.scratch_file('day13') + self.vm.add_args('-nic', f'user,tftp={tftproot}') + self.vm.launch() + wait_for_console_pattern(self, 'QEMU Advent Calendar 2023') + wait_for_console_pattern(self, 'buildroot login:') + exec_command_and_wait_for_pattern(self, 'root', '#') + exec_command_and_wait_for_pattern(self, + 'tftp -g -r xmaton.png 10.0.2.2 ; md5sum xmaton.png', + '821cd3cab8efd16ad6ee5acc3642a8ea') + + +class MicroblazeBigEndianMachine(MicroblazeMachine): + + ASSET_IMAGE_BE = MicroblazeMachine.ASSET_IMAGE_BE + ASSET_IMAGE_LE = MicroblazeMachine.ASSET_IMAGE_LE + + def test_microblaze_s3adsp1800_legacy_be(self): + self.do_ballerina_be_test() + + def test_microblaze_s3adsp1800_legacy_le(self): + self.do_xmaton_le_test(force_endianness=True) + + +if __name__ == '__main__': + QemuSystemTest.main() diff --git a/tests/functional/microblazeel/meson.build b/tests/functional/microblazeel/meson.build new file mode 100644 index 0000000..27619dc --- /dev/null +++ b/tests/functional/microblazeel/meson.build @@ -0,0 +1,5 @@ +# SPDX-License-Identifier: GPL-2.0-or-later + +tests_microblazeel_system_thorough = [ + 's3adsp1800' +] diff --git a/tests/functional/microblazeel/test_s3adsp1800.py b/tests/functional/microblazeel/test_s3adsp1800.py new file mode 100755 index 0000000..75ce885 --- /dev/null +++ b/tests/functional/microblazeel/test_s3adsp1800.py @@ -0,0 +1,26 @@ +#!/usr/bin/env python3 +# +# Functional test that boots a microblaze Linux kernel and checks the console +# +# Copyright (c) 2018, 2021 Red Hat, Inc. +# +# This work is licensed under the terms of the GNU GPL, version 2 or +# later. See the COPYING file in the top-level directory. + +from microblaze.test_s3adsp1800 import MicroblazeMachine + + +class MicroblazeLittleEndianMachine(MicroblazeMachine): + + ASSET_IMAGE_LE = MicroblazeMachine.ASSET_IMAGE_LE + ASSET_IMAGE_BE = MicroblazeMachine.ASSET_IMAGE_BE + + def test_microblaze_s3adsp1800_legacy_le(self): + self.do_xmaton_le_test() + + def test_microblaze_s3adsp1800_legacy_be(self): + self.do_ballerina_be_test(force_endianness=True) + + +if __name__ == '__main__': + MicroblazeMachine.main() diff --git a/tests/functional/test_microblaze_replay.py b/tests/functional/test_microblaze_replay.py deleted file mode 100755 index 7484c41..0000000 --- a/tests/functional/test_microblaze_replay.py +++ /dev/null @@ -1,28 +0,0 @@ -#!/usr/bin/env python3 -# -# Replay test that boots a Linux kernel on an microblaze machine -# and checks the console -# -# SPDX-License-Identifier: GPL-2.0-or-later - -from qemu_test import Asset -from replay_kernel import ReplayKernelBase - - -class MicroblazeReplay(ReplayKernelBase): - - ASSET_DAY17 = Asset( - ('https://qemu-advcal.gitlab.io/qac-best-of-multiarch/download/' - 'day17.tar.xz'), - '3ba7439dfbea7af4876662c97f8e1f0cdad9231fc166e4861d17042489270057') - - def test_microblaze_s3adsp1800(self): - self.set_machine('petalogix-s3adsp1800') - kernel_path = self.archive_extract(self.ASSET_DAY17, - member='day17/ballerina.bin') - self.run_rr(kernel_path, self.REPLAY_KERNEL_COMMAND_LINE, - 'QEMU advent calendar') - - -if __name__ == '__main__': - ReplayKernelBase.main() diff --git a/tests/functional/test_microblaze_s3adsp1800.py b/tests/functional/test_microblaze_s3adsp1800.py deleted file mode 100755 index f093b16..0000000 --- a/tests/functional/test_microblaze_s3adsp1800.py +++ /dev/null @@ -1,76 +0,0 @@ -#!/usr/bin/env python3 -# -# Functional test that boots a microblaze Linux kernel and checks the console -# -# Copyright (c) 2018, 2021 Red Hat, Inc. -# -# This work is licensed under the terms of the GNU GPL, version 2 or -# later. See the COPYING file in the top-level directory. - -from qemu_test import exec_command_and_wait_for_pattern -from qemu_test import QemuSystemTest, Asset -from qemu_test import wait_for_console_pattern - - -class MicroblazeMachine(QemuSystemTest): - - timeout = 90 - - ASSET_IMAGE_BE = Asset( - ('https://qemu-advcal.gitlab.io/qac-best-of-multiarch/download/' - 'day17.tar.xz'), - '3ba7439dfbea7af4876662c97f8e1f0cdad9231fc166e4861d17042489270057') - - ASSET_IMAGE_LE = Asset( - ('http://www.qemu-advent-calendar.org/2023/download/day13.tar.gz'), - 'b9b3d43c5dd79db88ada495cc6e0d1f591153fe41355e925d791fbf44de50c22') - - def do_ballerina_be_test(self, force_endianness=False): - self.set_machine('petalogix-s3adsp1800') - self.archive_extract(self.ASSET_IMAGE_BE) - self.vm.set_console() - self.vm.add_args('-kernel', - self.scratch_file('day17', 'ballerina.bin')) - if force_endianness: - self.vm.add_args('-M', 'endianness=big') - self.vm.launch() - wait_for_console_pattern(self, 'This architecture does not have ' - 'kernel memory protection') - # Note: - # The kernel sometimes gets stuck after the "This architecture ..." - # message, that's why we don't test for a later string here. This - # needs some investigation by a microblaze wizard one day... - - def do_xmaton_le_test(self, force_endianness=False): - self.require_netdev('user') - self.set_machine('petalogix-s3adsp1800') - self.archive_extract(self.ASSET_IMAGE_LE) - self.vm.set_console() - self.vm.add_args('-kernel', self.scratch_file('day13', 'xmaton.bin')) - if force_endianness: - self.vm.add_args('-M', 'endianness=little') - tftproot = self.scratch_file('day13') - self.vm.add_args('-nic', f'user,tftp={tftproot}') - self.vm.launch() - wait_for_console_pattern(self, 'QEMU Advent Calendar 2023') - wait_for_console_pattern(self, 'buildroot login:') - exec_command_and_wait_for_pattern(self, 'root', '#') - exec_command_and_wait_for_pattern(self, - 'tftp -g -r xmaton.png 10.0.2.2 ; md5sum xmaton.png', - '821cd3cab8efd16ad6ee5acc3642a8ea') - - -class MicroblazeBigEndianMachine(MicroblazeMachine): - - ASSET_IMAGE_BE = MicroblazeMachine.ASSET_IMAGE_BE - ASSET_IMAGE_LE = MicroblazeMachine.ASSET_IMAGE_LE - - def test_microblaze_s3adsp1800_legacy_be(self): - self.do_ballerina_be_test() - - def test_microblaze_s3adsp1800_legacy_le(self): - self.do_xmaton_le_test(force_endianness=True) - - -if __name__ == '__main__': - QemuSystemTest.main() diff --git a/tests/functional/test_microblazeel_s3adsp1800.py b/tests/functional/test_microblazeel_s3adsp1800.py deleted file mode 100755 index 915902d..0000000 --- a/tests/functional/test_microblazeel_s3adsp1800.py +++ /dev/null @@ -1,26 +0,0 @@ -#!/usr/bin/env python3 -# -# Functional test that boots a microblaze Linux kernel and checks the console -# -# Copyright (c) 2018, 2021 Red Hat, Inc. -# -# This work is licensed under the terms of the GNU GPL, version 2 or -# later. See the COPYING file in the top-level directory. - -from test_microblaze_s3adsp1800 import MicroblazeMachine - - -class MicroblazeLittleEndianMachine(MicroblazeMachine): - - ASSET_IMAGE_LE = MicroblazeMachine.ASSET_IMAGE_LE - ASSET_IMAGE_BE = MicroblazeMachine.ASSET_IMAGE_BE - - def test_microblaze_s3adsp1800_legacy_le(self): - self.do_xmaton_le_test() - - def test_microblaze_s3adsp1800_legacy_be(self): - self.do_ballerina_be_test(force_endianness=True) - - -if __name__ == '__main__': - MicroblazeMachine.main() -- cgit v1.1 From f227c45e5b6e928a413fcf7176b59aac4e430c82 Mon Sep 17 00:00:00 2001 From: Thomas Huth Date: Tue, 19 Aug 2025 13:23:51 +0200 Subject: tests/functional: Move mips tests into target-specific folders MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The tests/functional folder has become quite crowded, thus move the mips tests into a target-specific subfolder. Reviewed-by: Pierrick Bouvier Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Thomas Huth Message-ID: <20250819112403.432587-15-thuth@redhat.com> --- tests/functional/meson.build | 47 +------ tests/functional/mips/meson.build | 11 ++ tests/functional/mips/test_malta.py | 196 ++++++++++++++++++++++++++ tests/functional/mips/test_replay.py | 55 ++++++++ tests/functional/mips/test_tuxrun.py | 36 +++++ tests/functional/mips64/meson.build | 10 ++ tests/functional/mips64/test_malta.py | 35 +++++ tests/functional/mips64/test_tuxrun.py | 35 +++++ tests/functional/mips64el/meson.build | 14 ++ tests/functional/mips64el/test_fuloong2e.py | 64 +++++++++ tests/functional/mips64el/test_loongson3v.py | 36 +++++ tests/functional/mips64el/test_malta.py | 197 +++++++++++++++++++++++++++ tests/functional/mips64el/test_replay.py | 56 ++++++++ tests/functional/mips64el/test_tuxrun.py | 35 +++++ tests/functional/mipsel/meson.build | 12 ++ tests/functional/mipsel/test_malta.py | 108 +++++++++++++++ tests/functional/mipsel/test_replay.py | 54 ++++++++ tests/functional/mipsel/test_tuxrun.py | 36 +++++ tests/functional/test_mips64_malta.py | 35 ----- tests/functional/test_mips64_tuxrun.py | 35 ----- tests/functional/test_mips64el_fuloong2e.py | 64 --------- tests/functional/test_mips64el_loongson3v.py | 36 ----- tests/functional/test_mips64el_malta.py | 197 --------------------------- tests/functional/test_mips64el_replay.py | 56 -------- tests/functional/test_mips64el_tuxrun.py | 35 ----- tests/functional/test_mips_malta.py | 196 -------------------------- tests/functional/test_mips_replay.py | 55 -------- tests/functional/test_mips_tuxrun.py | 36 ----- tests/functional/test_mipsel_malta.py | 108 --------------- tests/functional/test_mipsel_replay.py | 54 -------- tests/functional/test_mipsel_tuxrun.py | 36 ----- 31 files changed, 994 insertions(+), 986 deletions(-) create mode 100644 tests/functional/mips/meson.build create mode 100755 tests/functional/mips/test_malta.py create mode 100755 tests/functional/mips/test_replay.py create mode 100755 tests/functional/mips/test_tuxrun.py create mode 100644 tests/functional/mips64/meson.build create mode 100755 tests/functional/mips64/test_malta.py create mode 100755 tests/functional/mips64/test_tuxrun.py create mode 100644 tests/functional/mips64el/meson.build create mode 100755 tests/functional/mips64el/test_fuloong2e.py create mode 100755 tests/functional/mips64el/test_loongson3v.py create mode 100755 tests/functional/mips64el/test_malta.py create mode 100755 tests/functional/mips64el/test_replay.py create mode 100755 tests/functional/mips64el/test_tuxrun.py create mode 100644 tests/functional/mipsel/meson.build create mode 100755 tests/functional/mipsel/test_malta.py create mode 100755 tests/functional/mipsel/test_replay.py create mode 100755 tests/functional/mipsel/test_tuxrun.py delete mode 100755 tests/functional/test_mips64_malta.py delete mode 100755 tests/functional/test_mips64_tuxrun.py delete mode 100755 tests/functional/test_mips64el_fuloong2e.py delete mode 100755 tests/functional/test_mips64el_loongson3v.py delete mode 100755 tests/functional/test_mips64el_malta.py delete mode 100755 tests/functional/test_mips64el_replay.py delete mode 100755 tests/functional/test_mips64el_tuxrun.py delete mode 100755 tests/functional/test_mips_malta.py delete mode 100755 tests/functional/test_mips_replay.py delete mode 100755 tests/functional/test_mips_tuxrun.py delete mode 100755 tests/functional/test_mipsel_malta.py delete mode 100644 tests/functional/test_mipsel_replay.py delete mode 100755 tests/functional/test_mipsel_tuxrun.py (limited to 'tests') diff --git a/tests/functional/meson.build b/tests/functional/meson.build index fee6805..52969a3 100644 --- a/tests/functional/meson.build +++ b/tests/functional/meson.build @@ -19,24 +19,10 @@ subdir('loongarch64') subdir('m68k') subdir('microblaze') subdir('microblazeel') - -test_mips_timeouts = { - 'mips_malta' : 480, -} - -test_mipsel_timeouts = { - 'mipsel_malta' : 420, - 'mipsel_replay' : 480, -} - -test_mips64_timeouts = { - 'mips64_malta' : 240, -} - -test_mips64el_timeouts = { - 'mips64el_malta' : 420, - 'mips64el_replay' : 180, -} +subdir('mips') +subdir('mipsel') +subdir('mips64') +subdir('mips64el') test_ppc_timeouts = { 'ppc_40p' : 240, @@ -84,31 +70,6 @@ tests_generic_linuxuser = [ tests_generic_bsduser = [ ] -tests_mips_system_thorough = [ - 'mips_malta', - 'mips_replay', - 'mips_tuxrun', -] - -tests_mipsel_system_thorough = [ - 'mipsel_malta', - 'mipsel_replay', - 'mipsel_tuxrun', -] - -tests_mips64_system_thorough = [ - 'mips64_malta', - 'mips64_tuxrun', -] - -tests_mips64el_system_thorough = [ - 'mips64el_fuloong2e', - 'mips64el_loongson3v', - 'mips64el_malta', - 'mips64el_replay', - 'mips64el_tuxrun', -] - tests_or1k_system_thorough = [ 'or1k_replay', 'or1k_sim', diff --git a/tests/functional/mips/meson.build b/tests/functional/mips/meson.build new file mode 100644 index 0000000..49aaf53 --- /dev/null +++ b/tests/functional/mips/meson.build @@ -0,0 +1,11 @@ +# SPDX-License-Identifier: GPL-2.0-or-later + +test_mips_timeouts = { + 'malta' : 480, +} + +tests_mips_system_thorough = [ + 'malta', + 'replay', + 'tuxrun', +] diff --git a/tests/functional/mips/test_malta.py b/tests/functional/mips/test_malta.py new file mode 100755 index 0000000..30279f0 --- /dev/null +++ b/tests/functional/mips/test_malta.py @@ -0,0 +1,196 @@ +#!/usr/bin/env python3 +# +# Functional tests for the big-endian 32-bit MIPS Malta board +# +# Copyright (c) Philippe Mathieu-Daudé +# +# SPDX-License-Identifier: GPL-2.0-or-later + +import os + +from qemu_test import LinuxKernelTest, Asset, wait_for_console_pattern +from qemu_test import exec_command_and_wait_for_pattern + + +def mips_run_common_commands(test, prompt='#'): + exec_command_and_wait_for_pattern(test, + 'uname -m', + 'mips') + exec_command_and_wait_for_pattern(test, + 'grep XT-PIC /proc/interrupts', + 'timer') + wait_for_console_pattern(test, prompt) + exec_command_and_wait_for_pattern(test, + 'grep XT-PIC /proc/interrupts', + 'serial') + wait_for_console_pattern(test, prompt) + exec_command_and_wait_for_pattern(test, + 'grep XT-PIC /proc/interrupts', + 'ata_piix') + wait_for_console_pattern(test, prompt) + exec_command_and_wait_for_pattern(test, + 'grep XT-PIC /proc/interrupts', + 'rtc') + wait_for_console_pattern(test, prompt) + exec_command_and_wait_for_pattern(test, + 'cat /proc/devices', + 'input') + wait_for_console_pattern(test, prompt) + exec_command_and_wait_for_pattern(test, + 'cat /proc/devices', + 'fb') + wait_for_console_pattern(test, prompt) + exec_command_and_wait_for_pattern(test, + 'cat /proc/ioports', + ' : serial') + wait_for_console_pattern(test, prompt) + exec_command_and_wait_for_pattern(test, + 'cat /proc/ioports', + ' : ata_piix') + wait_for_console_pattern(test, prompt) + +def mips_check_wheezy(test, kernel_path, image_path, kernel_command_line, + dl_file, hsum, nic='pcnet', cpuinfo='MIPS 24Kc'): + test.require_netdev('user') + test.require_device(nic) + test.set_machine('malta') + + port=8080 + test.vm.add_args('-kernel', kernel_path, + '-append', kernel_command_line, + '-drive', 'file=%s,snapshot=on' % image_path, + '-netdev', 'user,id=n1' + + ',tftp=' + os.path.basename(kernel_path) + + ',hostfwd=tcp:127.0.0.1:0-:%d' % port, + '-device', f'{nic},netdev=n1', + '-no-reboot') + test.vm.set_console() + test.vm.launch() + + wait_for_console_pattern(test, 'login: ', 'Oops') + exec_command_and_wait_for_pattern(test, 'root', 'Password:') + exec_command_and_wait_for_pattern(test, 'root', ':~# ') + mips_run_common_commands(test) + + exec_command_and_wait_for_pattern(test, 'cd /', '# ') + test.check_http_download(dl_file, hsum, port, + pythoncmd='python -m SimpleHTTPServer') + + exec_command_and_wait_for_pattern(test, 'cat /proc/cpuinfo', cpuinfo) + exec_command_and_wait_for_pattern(test, 'cat /proc/devices', 'usb') + exec_command_and_wait_for_pattern(test, 'cat /proc/ioports', + ' : piix4_smbus') + exec_command_and_wait_for_pattern(test, 'lspci -d 11ab:4620', + 'GT-64120') + exec_command_and_wait_for_pattern(test, + 'cat /sys/bus/i2c/devices/i2c-0/name', + 'SMBus PIIX4 adapter') + exec_command_and_wait_for_pattern(test, 'cat /proc/mtd', 'YAMON') + # Empty 'Board Config' (64KB) + exec_command_and_wait_for_pattern(test, 'md5sum /dev/mtd2ro', + '0dfbe8aa4c20b52e1b8bf3cb6cbdf193') + + +class MaltaMachineConsole(LinuxKernelTest): + + ASSET_KERNEL_2_63_2 = Asset( + ('http://snapshot.debian.org/archive/debian/' + '20130217T032700Z/pool/main/l/linux-2.6/' + 'linux-image-2.6.32-5-4kc-malta_2.6.32-48_mips.deb'), + '16ca524148afb0626f483163e5edf352bc1ab0e4fc7b9f9d473252762f2c7a43') + + def test_mips_malta(self): + kernel_path = self.archive_extract( + self.ASSET_KERNEL_2_63_2, + member='boot/vmlinux-2.6.32-5-4kc-malta') + + self.set_machine('malta') + self.vm.set_console() + kernel_command_line = self.KERNEL_COMMON_COMMAND_LINE + 'console=ttyS0' + self.vm.add_args('-kernel', kernel_path, + '-append', kernel_command_line) + self.vm.launch() + console_pattern = 'Kernel command line: %s' % kernel_command_line + self.wait_for_console_pattern(console_pattern) + + ASSET_KERNEL_4_5_0 = Asset( + ('http://snapshot.debian.org/archive/debian/' + '20160601T041800Z/pool/main/l/linux/' + 'linux-image-4.5.0-2-4kc-malta_4.5.5-1_mips.deb'), + '526b17d5889840888b76fc2c36a0ebde182c9b1410a3a1e68203c3b160eb2027') + + ASSET_INITRD = Asset( + ('https://github.com/groeck/linux-build-test/raw/' + '8584a59ed9e5eb5ee7ca91f6d74bbb06619205b8/rootfs/' + 'mips/rootfs.cpio.gz'), + 'dcfe3a7fe3200da3a00d176b95caaa086495eb158f2bff64afc67d7e1eb2cddc') + + def test_mips_malta_cpio(self): + self.require_netdev('user') + self.set_machine('malta') + self.require_device('pcnet') + + kernel_path = self.archive_extract( + self.ASSET_KERNEL_4_5_0, + member='boot/vmlinux-4.5.0-2-4kc-malta') + initrd_path = self.uncompress(self.ASSET_INITRD) + + self.vm.set_console() + kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE + + 'console=ttyS0 console=tty ' + + 'rdinit=/sbin/init noreboot') + self.vm.add_args('-kernel', kernel_path, + '-initrd', initrd_path, + '-append', kernel_command_line, + '-netdev', 'user,id=n1,tftp=' + self.scratch_file('boot'), + '-device', 'pcnet,netdev=n1', + '-no-reboot') + self.vm.launch() + self.wait_for_console_pattern('Boot successful.') + + exec_command_and_wait_for_pattern(self, 'cat /proc/cpuinfo', + 'BogoMIPS') + exec_command_and_wait_for_pattern(self, 'uname -a', + '4.5.0-2-4kc-malta #1 Debian') + mips_run_common_commands(self) + + exec_command_and_wait_for_pattern(self, 'ip link set eth0 up', + 'eth0: link up') + exec_command_and_wait_for_pattern(self, + 'ip addr add 10.0.2.15 dev eth0', + '#') + exec_command_and_wait_for_pattern(self, 'route add default eth0', '#') + exec_command_and_wait_for_pattern(self, + 'tftp -g -r vmlinux-4.5.0-2-4kc-malta 10.0.2.2', '#') + exec_command_and_wait_for_pattern(self, + 'md5sum vmlinux-4.5.0-2-4kc-malta', + 'a98218a7efbdefb2dfdf9ecd08c98318') + + exec_command_and_wait_for_pattern(self, 'reboot', + 'reboot: Restarting system') + # Wait for VM to shut down gracefully + self.vm.wait() + + ASSET_WHEEZY_KERNEL = Asset( + ('https://people.debian.org/~aurel32/qemu/mips/' + 'vmlinux-3.2.0-4-4kc-malta'), + '0377fcda31299213c10b8e5babe7260ef99188b3ae1aca6f56594abb71e7f67e') + + ASSET_WHEEZY_DISK = Asset( + ('https://people.debian.org/~aurel32/qemu/mips/' + 'debian_wheezy_mips_standard.qcow2'), + 'de03599285b8382ad309309a6c4869f6c6c42a5cfc983342bab9ec0dfa7849a2') + + def test_wheezy(self): + kernel_path = self.ASSET_WHEEZY_KERNEL.fetch() + image_path = self.ASSET_WHEEZY_DISK.fetch() + kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE + + 'console=ttyS0 root=/dev/sda1') + mips_check_wheezy(self, + kernel_path, image_path, kernel_command_line, nic='e1000', + dl_file='/boot/initrd.img-3.2.0-4-4kc-malta', + hsum='ff0c0369143d9bbb9a6e6bc79322a2be535619df639e84103237f406e87493dc') + + +if __name__ == '__main__': + LinuxKernelTest.main() diff --git a/tests/functional/mips/test_replay.py b/tests/functional/mips/test_replay.py new file mode 100755 index 0000000..4327481 --- /dev/null +++ b/tests/functional/mips/test_replay.py @@ -0,0 +1,55 @@ +#!/usr/bin/env python3 +# +# Replay tests for the big-endian 32-bit MIPS Malta board +# +# SPDX-License-Identifier: GPL-2.0-or-later + +from qemu_test import Asset, skipSlowTest +from replay_kernel import ReplayKernelBase + + +class MipsReplay(ReplayKernelBase): + + ASSET_KERNEL_2_63_2 = Asset( + ('http://snapshot.debian.org/archive/debian/' + '20130217T032700Z/pool/main/l/linux-2.6/' + 'linux-image-2.6.32-5-4kc-malta_2.6.32-48_mips.deb'), + '16ca524148afb0626f483163e5edf352bc1ab0e4fc7b9f9d473252762f2c7a43') + + def test_replay_mips_malta(self): + self.set_machine('malta') + kernel_path = self.archive_extract(self.ASSET_KERNEL_2_63_2, + member='boot/vmlinux-2.6.32-5-4kc-malta') + kernel_command_line = self.KERNEL_COMMON_COMMAND_LINE + 'console=ttyS0' + console_pattern = 'Kernel command line: %s' % kernel_command_line + self.run_rr(kernel_path, kernel_command_line, console_pattern, shift=5) + + ASSET_KERNEL_4_5_0 = Asset( + ('http://snapshot.debian.org/archive/debian/' + '20160601T041800Z/pool/main/l/linux/' + 'linux-image-4.5.0-2-4kc-malta_4.5.5-1_mips.deb'), + '526b17d5889840888b76fc2c36a0ebde182c9b1410a3a1e68203c3b160eb2027') + + ASSET_INITRD = Asset( + ('https://github.com/groeck/linux-build-test/raw/' + '8584a59ed9e5eb5ee7ca91f6d74bbb06619205b8/rootfs/' + 'mips/rootfs.cpio.gz'), + 'dcfe3a7fe3200da3a00d176b95caaa086495eb158f2bff64afc67d7e1eb2cddc') + + @skipSlowTest() + def test_replay_mips_malta_cpio(self): + self.set_machine('malta') + kernel_path = self.archive_extract(self.ASSET_KERNEL_4_5_0, + member='boot/vmlinux-4.5.0-2-4kc-malta') + initrd_path = self.uncompress(self.ASSET_INITRD) + + kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE + + 'console=ttyS0 console=tty ' + 'rdinit=/sbin/init noreboot') + console_pattern = 'Boot successful.' + self.run_rr(kernel_path, kernel_command_line, console_pattern, shift=5, + args=('-initrd', initrd_path)) + + +if __name__ == '__main__': + ReplayKernelBase.main() diff --git a/tests/functional/mips/test_tuxrun.py b/tests/functional/mips/test_tuxrun.py new file mode 100755 index 0000000..6771dbd --- /dev/null +++ b/tests/functional/mips/test_tuxrun.py @@ -0,0 +1,36 @@ +#!/usr/bin/env python3 +# +# Functional test that boots known good tuxboot images the same way +# that tuxrun (www.tuxrun.org) does. This tool is used by things like +# the LKFT project to run regression tests on kernels. +# +# Copyright (c) 2023 Linaro Ltd. +# +# Author: +# Alex Bennée +# +# SPDX-License-Identifier: GPL-2.0-or-later + +from qemu_test import Asset +from qemu_test.tuxruntest import TuxRunBaselineTest + +class TuxRunMipsTest(TuxRunBaselineTest): + + ASSET_MIPS_KERNEL = Asset( + 'https://storage.tuxboot.com/buildroot/20241119/mips32/vmlinux', + 'b6f97fc698ae8c96456ad8c996c7454228074df0d7520dedd0a15e2913700a19') + ASSET_MIPS_ROOTFS = Asset( + 'https://storage.tuxboot.com/buildroot/20241119/mips32/rootfs.ext4.zst', + '87055cf3cbde3fd134e5039e7b87feb03231d8c4b21ee712b8ba3308dfa72f50') + + def test_mips32(self): + self.set_machine('malta') + self.cpu="mips32r6-generic" + self.root="sda" + self.wait_for_shutdown=False + self.common_tuxrun(kernel_asset=self.ASSET_MIPS_KERNEL, + rootfs_asset=self.ASSET_MIPS_ROOTFS, + drive="driver=ide-hd,bus=ide.0,unit=0") + +if __name__ == '__main__': + TuxRunBaselineTest.main() diff --git a/tests/functional/mips64/meson.build b/tests/functional/mips64/meson.build new file mode 100644 index 0000000..3ff2118 --- /dev/null +++ b/tests/functional/mips64/meson.build @@ -0,0 +1,10 @@ +# SPDX-License-Identifier: GPL-2.0-or-later + +test_mips64_timeouts = { + 'malta' : 240, +} + +tests_mips64_system_thorough = [ + 'malta', + 'tuxrun', +] diff --git a/tests/functional/mips64/test_malta.py b/tests/functional/mips64/test_malta.py new file mode 100755 index 0000000..a553d3c --- /dev/null +++ b/tests/functional/mips64/test_malta.py @@ -0,0 +1,35 @@ +#!/usr/bin/env python3 +# +# Functional tests for the big-endian 64-bit MIPS Malta board +# +# SPDX-License-Identifier: GPL-2.0-or-later + +from qemu_test import LinuxKernelTest, Asset +from mips.test_malta import mips_check_wheezy + + +class MaltaMachineConsole(LinuxKernelTest): + + ASSET_WHEEZY_KERNEL = Asset( + ('https://people.debian.org/~aurel32/qemu/mips/' + 'vmlinux-3.2.0-4-5kc-malta'), + '3e4ec154db080b3f1839f04dde83120654a33e5e1716863de576c47cb94f68f6') + + ASSET_WHEEZY_DISK = Asset( + ('https://people.debian.org/~aurel32/qemu/mips/' + 'debian_wheezy_mips_standard.qcow2'), + 'de03599285b8382ad309309a6c4869f6c6c42a5cfc983342bab9ec0dfa7849a2') + + def test_wheezy(self): + kernel_path = self.ASSET_WHEEZY_KERNEL.fetch() + image_path = self.ASSET_WHEEZY_DISK.fetch() + kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE + + 'console=ttyS0 root=/dev/sda1') + mips_check_wheezy(self, + kernel_path, image_path, kernel_command_line, cpuinfo='MIPS 20Kc', + dl_file='/boot/initrd.img-3.2.0-4-5kc-malta', + hsum='d98b953bb4a41c0fc0fd8d19bbc691c08989ac52568c1d3054d92dfd890d3f06') + + +if __name__ == '__main__': + LinuxKernelTest.main() diff --git a/tests/functional/mips64/test_tuxrun.py b/tests/functional/mips64/test_tuxrun.py new file mode 100755 index 0000000..0e4c659 --- /dev/null +++ b/tests/functional/mips64/test_tuxrun.py @@ -0,0 +1,35 @@ +#!/usr/bin/env python3 +# +# Functional test that boots known good tuxboot images the same way +# that tuxrun (www.tuxrun.org) does. This tool is used by things like +# the LKFT project to run regression tests on kernels. +# +# Copyright (c) 2023 Linaro Ltd. +# +# Author: +# Alex Bennée +# +# SPDX-License-Identifier: GPL-2.0-or-later + +from qemu_test import Asset +from qemu_test.tuxruntest import TuxRunBaselineTest + +class TuxRunMips64Test(TuxRunBaselineTest): + + ASSET_MIPS64_KERNEL = Asset( + 'https://storage.tuxboot.com/buildroot/20241119/mips64/vmlinux', + 'fe2882d216898ba2c56b49ba59f46ad392f36871f7fe325373cd926848b9dbdc') + ASSET_MIPS64_ROOTFS = Asset( + 'https://storage.tuxboot.com/buildroot/20241119/mips64/rootfs.ext4.zst', + 'b8c98400216b6d4fb3b3ff05e9929aa015948b596cf0b82234813c84a4f7f4d5') + + def test_mips64(self): + self.set_machine('malta') + self.root="sda" + self.wait_for_shutdown=False + self.common_tuxrun(kernel_asset=self.ASSET_MIPS64_KERNEL, + rootfs_asset=self.ASSET_MIPS64_ROOTFS, + drive="driver=ide-hd,bus=ide.0,unit=0") + +if __name__ == '__main__': + TuxRunBaselineTest.main() diff --git a/tests/functional/mips64el/meson.build b/tests/functional/mips64el/meson.build new file mode 100644 index 0000000..69ec501 --- /dev/null +++ b/tests/functional/mips64el/meson.build @@ -0,0 +1,14 @@ +# SPDX-License-Identifier: GPL-2.0-or-later + +test_mips64el_timeouts = { + 'malta' : 420, + 'replay' : 180, +} + +tests_mips64el_system_thorough = [ + 'fuloong2e', + 'loongson3v', + 'malta', + 'replay', + 'tuxrun', +] diff --git a/tests/functional/mips64el/test_fuloong2e.py b/tests/functional/mips64el/test_fuloong2e.py new file mode 100755 index 0000000..35e500b --- /dev/null +++ b/tests/functional/mips64el/test_fuloong2e.py @@ -0,0 +1,64 @@ +#!/usr/bin/env python3 +# +# Functional tests for the Lemote Fuloong-2E machine. +# +# Copyright (c) 2019 Philippe Mathieu-Daudé +# +# This work is licensed under the terms of the GNU GPL, version 2 or later. +# See the COPYING file in the top-level directory. +# +# SPDX-License-Identifier: GPL-2.0-or-later + +import os +import subprocess + +from qemu_test import LinuxKernelTest, Asset +from qemu_test import wait_for_console_pattern, skipUntrustedTest +from unittest import skipUnless + +class MipsFuloong2e(LinuxKernelTest): + + timeout = 60 + + ASSET_KERNEL = Asset( + ('http://archive.debian.org/debian/pool/main/l/linux/' + 'linux-image-3.16.0-6-loongson-2e_3.16.56-1+deb8u1_mipsel.deb'), + '2a70f15b397f4ced632b0c15cb22660394190644146d804d60a4796eefbe1f50') + + def test_linux_kernel_3_16(self): + kernel_path = self.archive_extract( + self.ASSET_KERNEL, + member='boot/vmlinux-3.16.0-6-loongson-2e') + + self.set_machine('fuloong2e') + self.vm.set_console() + kernel_command_line = self.KERNEL_COMMON_COMMAND_LINE + 'console=ttyS0' + self.vm.add_args('-kernel', kernel_path, + '-append', kernel_command_line) + self.vm.launch() + console_pattern = 'Kernel command line: %s' % kernel_command_line + self.wait_for_console_pattern(console_pattern) + + @skipUntrustedTest() + @skipUnless(os.getenv('RESCUE_YL_PATH'), 'RESCUE_YL_PATH not available') + def test_linux_kernel_2_6_27_isa_serial(self): + # Recovery system for the Yeeloong laptop + # (enough to test the fuloong2e southbridge, accessing its ISA bus) + # http://dev.lemote.com/files/resource/download/rescue/rescue-yl + sha = 'ab588d3316777c62cc81baa20ac92e98b01955c244dff3794b711bc34e26e51d' + kernel_path = os.getenv('RESCUE_YL_PATH') + output = subprocess.check_output(['sha256sum', kernel_path]) + checksum = output.split()[0] + assert checksum.decode("utf-8") == sha + + self.set_machine('fuloong2e') + self.vm.set_console() + self.vm.add_args('-kernel', kernel_path) + self.vm.launch() + wait_for_console_pattern(self, 'Linux version 2.6.27.7lemote') + cpu_revision = 'CPU revision is: 00006302 (ICT Loongson-2)' + wait_for_console_pattern(self, cpu_revision) + + +if __name__ == '__main__': + LinuxKernelTest.main() diff --git a/tests/functional/mips64el/test_loongson3v.py b/tests/functional/mips64el/test_loongson3v.py new file mode 100755 index 0000000..f85371e --- /dev/null +++ b/tests/functional/mips64el/test_loongson3v.py @@ -0,0 +1,36 @@ +#!/usr/bin/env python3 +# +# Functional tests for the Generic Loongson-3 Platform. +# +# Copyright (c) 2021 Jiaxun Yang +# +# This work is licensed under the terms of the GNU GPL, version 2 or later. +# See the COPYING file in the top-level directory. +# +# SPDX-License-Identifier: GPL-2.0-or-later + +from qemu_test import QemuSystemTest, Asset +from qemu_test import wait_for_console_pattern, skipUntrustedTest + + +class MipsLoongson3v(QemuSystemTest): + timeout = 60 + + ASSET_PMON = Asset( + ('https://github.com/loongson-community/pmon/' + 'releases/download/20210112/pmon-3avirt.bin'), + 'fcdf6bb2cb7885a4a62f31fcb0d5e368bac7b6cea28f40c6dfa678af22fea20a') + + @skipUntrustedTest() + def test_pmon_serial_console(self): + self.set_machine('loongson3-virt') + + pmon_path = self.ASSET_PMON.fetch() + + self.vm.set_console() + self.vm.add_args('-bios', pmon_path) + self.vm.launch() + wait_for_console_pattern(self, 'CPU GODSON3 BogoMIPS:') + +if __name__ == '__main__': + QemuSystemTest.main() diff --git a/tests/functional/mips64el/test_malta.py b/tests/functional/mips64el/test_malta.py new file mode 100755 index 0000000..8fdc49b --- /dev/null +++ b/tests/functional/mips64el/test_malta.py @@ -0,0 +1,197 @@ +#!/usr/bin/env python3 +# +# Functional tests for the little-endian 64-bit MIPS Malta board +# +# Copyright (c) Philippe Mathieu-Daudé +# +# This work is licensed under the terms of the GNU GPL, version 2 or later. +# See the COPYING file in the top-level directory. +# +# SPDX-License-Identifier: GPL-2.0-or-later + +import os +import logging + +from qemu_test import LinuxKernelTest, Asset +from qemu_test import exec_command_and_wait_for_pattern +from qemu_test import skipIfMissingImports, skipFlakyTest, skipUntrustedTest + +from mips.test_malta import mips_check_wheezy + + +class MaltaMachineConsole(LinuxKernelTest): + + ASSET_KERNEL_2_63_2 = Asset( + ('http://snapshot.debian.org/archive/debian/' + '20130217T032700Z/pool/main/l/linux-2.6/' + 'linux-image-2.6.32-5-5kc-malta_2.6.32-48_mipsel.deb'), + '35eb476f03be589824b0310358f1c447d85e645b88cbcd2ac02b97ef560f9f8d') + + def test_mips64el_malta(self): + """ + This test requires the ar tool to extract "data.tar.gz" from + the Debian package. + + The kernel can be rebuilt using this Debian kernel source [1] and + following the instructions on [2]. + + [1] http://snapshot.debian.org/package/linux-2.6/2.6.32-48/ + #linux-source-2.6.32_2.6.32-48 + [2] https://kernel-team.pages.debian.net/kernel-handbook/ + ch-common-tasks.html#s-common-official + """ + kernel_path = self.archive_extract( + self.ASSET_KERNEL_2_63_2, + member='boot/vmlinux-2.6.32-5-5kc-malta') + + self.set_machine('malta') + self.vm.set_console() + kernel_command_line = self.KERNEL_COMMON_COMMAND_LINE + 'console=ttyS0' + self.vm.add_args('-kernel', kernel_path, + '-append', kernel_command_line) + self.vm.launch() + console_pattern = 'Kernel command line: %s' % kernel_command_line + self.wait_for_console_pattern(console_pattern) + + ASSET_KERNEL_3_19_3 = Asset( + ('https://github.com/philmd/qemu-testing-blob/' + 'raw/9ad2df38/mips/malta/mips64el/' + 'vmlinux-3.19.3.mtoman.20150408'), + '8d3beb003bc66051ead98e7172139017fcf9ce2172576541c57e86418dfa5ab8') + + ASSET_CPIO_R1 = Asset( + ('https://github.com/groeck/linux-build-test/' + 'raw/8584a59e/rootfs/mipsel64/' + 'rootfs.mipsel64r1.cpio.gz'), + '75ba10cd35fb44e32948eeb26974f061b703c81c4ba2fab1ebcacf1d1bec3b61') + + @skipUntrustedTest() + def test_mips64el_malta_5KEc_cpio(self): + kernel_path = self.ASSET_KERNEL_3_19_3.fetch() + initrd_path = self.uncompress(self.ASSET_CPIO_R1) + + self.set_machine('malta') + self.vm.set_console() + kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE + + 'console=ttyS0 console=tty ' + + 'rdinit=/sbin/init noreboot') + self.vm.add_args('-cpu', '5KEc', + '-kernel', kernel_path, + '-initrd', initrd_path, + '-append', kernel_command_line, + '-no-reboot') + self.vm.launch() + self.wait_for_console_pattern('Boot successful.') + + exec_command_and_wait_for_pattern(self, 'cat /proc/cpuinfo', + 'MIPS 5KE') + exec_command_and_wait_for_pattern(self, 'uname -a', + '3.19.3.mtoman.20150408') + exec_command_and_wait_for_pattern(self, 'reboot', + 'reboot: Restarting system') + # Wait for VM to shut down gracefully + self.vm.wait() + + ASSET_WHEEZY_KERNEL = Asset( + ('https://people.debian.org/~aurel32/qemu/mipsel/' + 'vmlinux-3.2.0-4-5kc-malta'), + '5e8b725244c59745bb8b64f5d8f49f25fecfa549f3395fb6d19a3b9e5065b85b') + + ASSET_WHEEZY_DISK = Asset( + ('https://people.debian.org/~aurel32/qemu/mipsel/' + 'debian_wheezy_mipsel_standard.qcow2'), + '454f09ae39f7e6461c84727b927100d2c7813841f2a0a5dce328114887ecf914') + + def test_wheezy(self): + kernel_path = self.ASSET_WHEEZY_KERNEL.fetch() + image_path = self.ASSET_WHEEZY_DISK.fetch() + kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE + + 'console=ttyS0 root=/dev/sda1') + mips_check_wheezy(self, + kernel_path, image_path, kernel_command_line, cpuinfo='MIPS 20Kc', + dl_file='/boot/initrd.img-3.2.0-4-5kc-malta', + hsum='7579f8b56c1187c7c04d0dc3c0c56c7a6314c5ddd3a9bf8803ecc7cf8a3be9f8') + + +@skipIfMissingImports('numpy', 'cv2') +class MaltaMachineFramebuffer(LinuxKernelTest): + + timeout = 30 + + ASSET_KERNEL_4_7_0 = Asset( + ('https://github.com/philmd/qemu-testing-blob/raw/a5966ca4b5/' + 'mips/malta/mips64el/vmlinux-4.7.0-rc1.I6400.gz'), + '1f64efc59968a3c328672e6b10213fe574bb2308d9d2ed44e75e40be59e9fbc2') + + ASSET_TUXLOGO = Asset( + ('https://github.com/torvalds/linux/raw/v2.6.12/' + 'drivers/video/logo/logo_linux_vga16.ppm'), + 'b762f0d91ec018887ad1b334543c2fdf9be9fdfc87672b409211efaa3ea0ef79') + + def do_test_i6400_framebuffer_logo(self, cpu_cores_count): + """ + Boot Linux kernel and check Tux logo is displayed on the framebuffer. + """ + + import numpy as np + import cv2 + + screendump_path = self.scratch_file('screendump.pbm') + + kernel_path = self.uncompress(self.ASSET_KERNEL_4_7_0) + + tuxlogo_path = self.ASSET_TUXLOGO.fetch() + + self.set_machine('malta') + self.vm.set_console() + kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE + + 'clocksource=GIC console=tty0 console=ttyS0') + self.vm.add_args('-kernel', kernel_path, + '-cpu', 'I6400', + '-smp', '%u' % cpu_cores_count, + '-vga', 'std', + '-append', kernel_command_line) + self.vm.launch() + framebuffer_ready = 'Console: switching to colour frame buffer device' + self.wait_for_console_pattern(framebuffer_ready) + self.vm.cmd('human-monitor-command', command_line='stop') + res = self.vm.cmd('human-monitor-command', + command_line='screendump %s' % screendump_path) + if 'unknown command' in res: + self.skipTest('screendump not available') + logger = logging.getLogger('framebuffer') + + match_threshold = 0.95 + screendump_bgr = cv2.imread(screendump_path, cv2.IMREAD_COLOR) + tuxlogo_bgr = cv2.imread(tuxlogo_path, cv2.IMREAD_COLOR) + result = cv2.matchTemplate(screendump_bgr, tuxlogo_bgr, + cv2.TM_CCOEFF_NORMED) + loc = np.where(result >= match_threshold) + tuxlogo_count = 0 + h, w = tuxlogo_bgr.shape[:2] + debug_png = os.getenv('QEMU_TEST_CV2_SCREENDUMP_PNG_PATH') + for tuxlogo_count, pt in enumerate(zip(*loc[::-1]), start=1): + logger.debug('found Tux at position (x, y) = %s', pt) + cv2.rectangle(screendump_bgr, pt, + (pt[0] + w, pt[1] + h), (0, 0, 255), 2) + if debug_png: + cv2.imwrite(debug_png, screendump_bgr) + self.assertGreaterEqual(tuxlogo_count, cpu_cores_count) + + def test_mips_malta_i6400_framebuffer_logo_1core(self): + self.do_test_i6400_framebuffer_logo(1) + + # XXX file tracking bug + @skipFlakyTest(bug_url=None) + def test_mips_malta_i6400_framebuffer_logo_7cores(self): + self.do_test_i6400_framebuffer_logo(7) + + @skipFlakyTest(bug_url=None) + def test_mips_malta_i6400_framebuffer_logo_8cores(self): + self.do_test_i6400_framebuffer_logo(8) + + +from mipsel.test_malta import MaltaMachineYAMON + +if __name__ == '__main__': + LinuxKernelTest.main() diff --git a/tests/functional/mips64el/test_replay.py b/tests/functional/mips64el/test_replay.py new file mode 100755 index 0000000..26a6ccf --- /dev/null +++ b/tests/functional/mips64el/test_replay.py @@ -0,0 +1,56 @@ +#!/usr/bin/env python3 +# +# Replay tests for the little-endian 64-bit MIPS Malta board +# +# SPDX-License-Identifier: GPL-2.0-or-later + +from qemu_test import Asset, skipUntrustedTest +from replay_kernel import ReplayKernelBase + + +class Mips64elReplay(ReplayKernelBase): + + ASSET_KERNEL_2_63_2 = Asset( + ('http://snapshot.debian.org/archive/debian/' + '20130217T032700Z/pool/main/l/linux-2.6/' + 'linux-image-2.6.32-5-5kc-malta_2.6.32-48_mipsel.deb'), + '35eb476f03be589824b0310358f1c447d85e645b88cbcd2ac02b97ef560f9f8d') + + def test_replay_mips64el_malta(self): + self.set_machine('malta') + kernel_path = self.archive_extract(self.ASSET_KERNEL_2_63_2, + member='boot/vmlinux-2.6.32-5-5kc-malta') + kernel_command_line = self.KERNEL_COMMON_COMMAND_LINE + 'console=ttyS0' + console_pattern = 'Kernel command line: %s' % kernel_command_line + self.run_rr(kernel_path, kernel_command_line, console_pattern, shift=5) + + + ASSET_KERNEL_3_19_3 = Asset( + ('https://github.com/philmd/qemu-testing-blob/' + 'raw/9ad2df38/mips/malta/mips64el/' + 'vmlinux-3.19.3.mtoman.20150408'), + '8d3beb003bc66051ead98e7172139017fcf9ce2172576541c57e86418dfa5ab8') + + ASSET_CPIO_R1 = Asset( + ('https://github.com/groeck/linux-build-test/' + 'raw/8584a59e/rootfs/mipsel64/' + 'rootfs.mipsel64r1.cpio.gz'), + '75ba10cd35fb44e32948eeb26974f061b703c81c4ba2fab1ebcacf1d1bec3b61') + + @skipUntrustedTest() + def test_replay_mips64el_malta_5KEc_cpio(self): + self.set_machine('malta') + self.cpu = '5KEc' + kernel_path = self.ASSET_KERNEL_3_19_3.fetch() + initrd_path = self.uncompress(self.ASSET_CPIO_R1) + + kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE + + 'console=ttyS0 console=tty ' + 'rdinit=/sbin/init noreboot') + console_pattern = 'Boot successful.' + self.run_rr(kernel_path, kernel_command_line, console_pattern, shift=5, + args=('-initrd', initrd_path)) + + +if __name__ == '__main__': + ReplayKernelBase.main() diff --git a/tests/functional/mips64el/test_tuxrun.py b/tests/functional/mips64el/test_tuxrun.py new file mode 100755 index 0000000..0a24757 --- /dev/null +++ b/tests/functional/mips64el/test_tuxrun.py @@ -0,0 +1,35 @@ +#!/usr/bin/env python3 +# +# Functional test that boots known good tuxboot images the same way +# that tuxrun (www.tuxrun.org) does. This tool is used by things like +# the LKFT project to run regression tests on kernels. +# +# Copyright (c) 2023 Linaro Ltd. +# +# Author: +# Alex Bennée +# +# SPDX-License-Identifier: GPL-2.0-or-later + +from qemu_test import Asset +from qemu_test.tuxruntest import TuxRunBaselineTest + +class TuxRunMips64ELTest(TuxRunBaselineTest): + + ASSET_MIPS64EL_KERNEL = Asset( + 'https://storage.tuxboot.com/buildroot/20241119/mips64el/vmlinux', + '0d2829a96f005229839c4cd586d4d8a136ea4b488d29821611c8e97f2266bfa9') + ASSET_MIPS64EL_ROOTFS = Asset( + 'https://storage.tuxboot.com/buildroot/20241119/mips64el/rootfs.ext4.zst', + '69c8b69a4f1582ce4c6f01a994968f5d73bffb2fc99cbeeeb26c8b5a28eaeb84') + + def test_mips64el(self): + self.set_machine('malta') + self.root="sda" + self.wait_for_shutdown=False + self.common_tuxrun(kernel_asset=self.ASSET_MIPS64EL_KERNEL, + rootfs_asset=self.ASSET_MIPS64EL_ROOTFS, + drive="driver=ide-hd,bus=ide.0,unit=0") + +if __name__ == '__main__': + TuxRunBaselineTest.main() diff --git a/tests/functional/mipsel/meson.build b/tests/functional/mipsel/meson.build new file mode 100644 index 0000000..8bfdf06 --- /dev/null +++ b/tests/functional/mipsel/meson.build @@ -0,0 +1,12 @@ +# SPDX-License-Identifier: GPL-2.0-or-later + +test_mipsel_timeouts = { + 'malta' : 420, + 'replay' : 480, +} + +tests_mipsel_system_thorough = [ + 'malta', + 'replay', + 'tuxrun', +] diff --git a/tests/functional/mipsel/test_malta.py b/tests/functional/mipsel/test_malta.py new file mode 100755 index 0000000..427e163 --- /dev/null +++ b/tests/functional/mipsel/test_malta.py @@ -0,0 +1,108 @@ +#!/usr/bin/env python3 +# +# Functional tests for the little-endian 32-bit MIPS Malta board +# +# Copyright (c) Philippe Mathieu-Daudé +# +# This work is licensed under the terms of the GNU GPL, version 2 or later. +# See the COPYING file in the top-level directory. +# +# SPDX-License-Identifier: GPL-2.0-or-later + +from qemu_test import QemuSystemTest, LinuxKernelTest, Asset +from qemu_test import interrupt_interactive_console_until_pattern +from qemu_test import wait_for_console_pattern + +from mips.test_malta import mips_check_wheezy + + +class MaltaMachineConsole(LinuxKernelTest): + + ASSET_KERNEL_4K = Asset( + ('http://mipsdistros.mips.com/LinuxDistro/nanomips/' + 'kernels/v4.15.18-432-gb2eb9a8b07a1-20180627102142/' + 'generic_nano32r6el_page4k.xz'), + '019e034094ac6cf3aa77df5e130fb023ce4dbc804b04bfcc560c6403e1ae6bdb') + ASSET_KERNEL_16K = Asset( + ('http://mipsdistros.mips.com/LinuxDistro/nanomips/' + 'kernels/v4.15.18-432-gb2eb9a8b07a1-20180627102142/' + 'generic_nano32r6el_page16k_up.xz'), + '3a54a10b3108c16a448dca9ea3db378733a27423befc2a45a5bdf990bd85e12c') + ASSET_KERNEL_64K = Asset( + ('http://mipsdistros.mips.com/LinuxDistro/nanomips/' + 'kernels/v4.15.18-432-gb2eb9a8b07a1-20180627102142/' + 'generic_nano32r6el_page64k_dbg.xz'), + 'ce21ff4b07a981ecb8a39db2876616f5a2473eb2ab459c6f67465b9914b0c6b6') + + def do_test_mips_malta32el_nanomips(self, kernel): + kernel_path = self.uncompress(kernel) + + self.set_machine('malta') + self.vm.set_console() + kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE + + 'mem=256m@@0x0 ' + + 'console=ttyS0') + self.vm.add_args('-cpu', 'I7200', + '-no-reboot', + '-kernel', kernel_path, + '-append', kernel_command_line) + self.vm.launch() + console_pattern = 'Kernel command line: %s' % kernel_command_line + self.wait_for_console_pattern(console_pattern) + + def test_mips_malta32el_nanomips_4k(self): + self.do_test_mips_malta32el_nanomips(self.ASSET_KERNEL_4K) + + def test_mips_malta32el_nanomips_16k_up(self): + self.do_test_mips_malta32el_nanomips(self.ASSET_KERNEL_16K) + + def test_mips_malta32el_nanomips_64k_dbg(self): + self.do_test_mips_malta32el_nanomips(self.ASSET_KERNEL_64K) + + ASSET_WHEEZY_KERNEL = Asset( + ('https://people.debian.org/~aurel32/qemu/mipsel/' + 'vmlinux-3.2.0-4-4kc-malta'), + 'dc8a3648305b0201ca7a5cd135fe2890067a65d93c38728022bb0e656ad2bf9a') + + ASSET_WHEEZY_DISK = Asset( + ('https://people.debian.org/~aurel32/qemu/mipsel/' + 'debian_wheezy_mipsel_standard.qcow2'), + '454f09ae39f7e6461c84727b927100d2c7813841f2a0a5dce328114887ecf914') + + def test_wheezy(self): + kernel_path = self.ASSET_WHEEZY_KERNEL.fetch() + image_path = self.ASSET_WHEEZY_DISK.fetch() + kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE + + 'console=ttyS0 root=/dev/sda1') + mips_check_wheezy(self, + kernel_path, image_path, kernel_command_line, + dl_file='/boot/initrd.img-3.2.0-4-4kc-malta', + hsum='9fc9f250ed56a74e35e704ddfd5a1c5a5625adefc5c9da91f649288d3ca000f0') + + +class MaltaMachineYAMON(QemuSystemTest): + + ASSET_YAMON_ROM = Asset( + ('https://s3-eu-west-1.amazonaws.com/downloads-mips/mips-downloads/' + 'YAMON/yamon-bin-02.22.zip'), + 'eef86f0eed0ef554f041dcd47b87eebea0e6f9f1184ed31f7e9e8b4a803860ab') + + def test_mipsel_malta_yamon(self): + yamon_bin = 'yamon-02.22.bin' + self.archive_extract(self.ASSET_YAMON_ROM) + yamon_path = self.scratch_file(yamon_bin) + + self.set_machine('malta') + self.vm.set_console() + self.vm.add_args('-bios', yamon_path) + self.vm.launch() + + prompt = 'YAMON>' + pattern = 'YAMON ROM Monitor' + interrupt_interactive_console_until_pattern(self, pattern, prompt) + wait_for_console_pattern(self, prompt) + self.vm.shutdown() + + +if __name__ == '__main__': + QemuSystemTest.main() diff --git a/tests/functional/mipsel/test_replay.py b/tests/functional/mipsel/test_replay.py new file mode 100755 index 0000000..5f4796c --- /dev/null +++ b/tests/functional/mipsel/test_replay.py @@ -0,0 +1,54 @@ +#!/usr/bin/env python3 +# +# Replay tests for the little-endian 32-bit MIPS Malta board +# +# SPDX-License-Identifier: GPL-2.0-or-later + +from qemu_test import Asset, skipSlowTest +from replay_kernel import ReplayKernelBase + + +class MipselReplay(ReplayKernelBase): + + ASSET_KERNEL_4K = Asset( + ('http://mipsdistros.mips.com/LinuxDistro/nanomips/' + 'kernels/v4.15.18-432-gb2eb9a8b07a1-20180627102142/' + 'generic_nano32r6el_page4k.xz'), + '019e034094ac6cf3aa77df5e130fb023ce4dbc804b04bfcc560c6403e1ae6bdb') + ASSET_KERNEL_16K = Asset( + ('http://mipsdistros.mips.com/LinuxDistro/nanomips/' + 'kernels/v4.15.18-432-gb2eb9a8b07a1-20180627102142/' + 'generic_nano32r6el_page16k_up.xz'), + '3a54a10b3108c16a448dca9ea3db378733a27423befc2a45a5bdf990bd85e12c') + ASSET_KERNEL_64K = Asset( + ('http://mipsdistros.mips.com/LinuxDistro/nanomips/' + 'kernels/v4.15.18-432-gb2eb9a8b07a1-20180627102142/' + 'generic_nano32r6el_page64k_dbg.xz'), + 'ce21ff4b07a981ecb8a39db2876616f5a2473eb2ab459c6f67465b9914b0c6b6') + + def do_test_replay_mips_malta32el_nanomips(self, kernel_asset): + self.set_machine('malta') + self.cpu = 'I7200' + kernel_path = self.uncompress(kernel_asset) + + kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE + + 'mem=256m@@0x0 ' + 'console=ttyS0') + console_pattern = 'Kernel command line: %s' % kernel_command_line + self.run_rr(kernel_path, kernel_command_line, console_pattern, shift=5) + + @skipSlowTest() + def test_replay_mips_malta32el_nanomips_4k(self): + self.do_test_replay_mips_malta32el_nanomips(self.ASSET_KERNEL_4K) + + @skipSlowTest() + def test_replay_mips_malta32el_nanomips_16k_up(self): + self.do_test_replay_mips_malta32el_nanomips(self.ASSET_KERNEL_16K) + + @skipSlowTest() + def test_replay_mips_malta32el_nanomips_64k_dbg(self): + self.do_test_replay_mips_malta32el_nanomips(self.ASSET_KERNEL_64K) + + +if __name__ == '__main__': + ReplayKernelBase.main() diff --git a/tests/functional/mipsel/test_tuxrun.py b/tests/functional/mipsel/test_tuxrun.py new file mode 100755 index 0000000..d4b39ba --- /dev/null +++ b/tests/functional/mipsel/test_tuxrun.py @@ -0,0 +1,36 @@ +#!/usr/bin/env python3 +# +# Functional test that boots known good tuxboot images the same way +# that tuxrun (www.tuxrun.org) does. This tool is used by things like +# the LKFT project to run regression tests on kernels. +# +# Copyright (c) 2023 Linaro Ltd. +# +# Author: +# Alex Bennée +# +# SPDX-License-Identifier: GPL-2.0-or-later + +from qemu_test import Asset +from qemu_test.tuxruntest import TuxRunBaselineTest + +class TuxRunMipsELTest(TuxRunBaselineTest): + + ASSET_MIPSEL_KERNEL = Asset( + 'https://storage.tuxboot.com/buildroot/20241119/mips32el/vmlinux', + '660dd8c7a6ca7a32d37b4e6348865532ab0edb66802e8cc07869338444cf4929') + ASSET_MIPSEL_ROOTFS = Asset( + 'https://storage.tuxboot.com/buildroot/20241119/mips32el/rootfs.ext4.zst', + 'c5d69542bcaed54a4f34671671eb4be5c608ee02671d4d0436544367816a73b1') + + def test_mips32el(self): + self.set_machine('malta') + self.cpu="mips32r6-generic" + self.root="sda" + self.wait_for_shutdown=False + self.common_tuxrun(kernel_asset=self.ASSET_MIPSEL_KERNEL, + rootfs_asset=self.ASSET_MIPSEL_ROOTFS, + drive="driver=ide-hd,bus=ide.0,unit=0") + +if __name__ == '__main__': + TuxRunBaselineTest.main() diff --git a/tests/functional/test_mips64_malta.py b/tests/functional/test_mips64_malta.py deleted file mode 100755 index 53c3e0c..0000000 --- a/tests/functional/test_mips64_malta.py +++ /dev/null @@ -1,35 +0,0 @@ -#!/usr/bin/env python3 -# -# Functional tests for the big-endian 64-bit MIPS Malta board -# -# SPDX-License-Identifier: GPL-2.0-or-later - -from qemu_test import LinuxKernelTest, Asset -from test_mips_malta import mips_check_wheezy - - -class MaltaMachineConsole(LinuxKernelTest): - - ASSET_WHEEZY_KERNEL = Asset( - ('https://people.debian.org/~aurel32/qemu/mips/' - 'vmlinux-3.2.0-4-5kc-malta'), - '3e4ec154db080b3f1839f04dde83120654a33e5e1716863de576c47cb94f68f6') - - ASSET_WHEEZY_DISK = Asset( - ('https://people.debian.org/~aurel32/qemu/mips/' - 'debian_wheezy_mips_standard.qcow2'), - 'de03599285b8382ad309309a6c4869f6c6c42a5cfc983342bab9ec0dfa7849a2') - - def test_wheezy(self): - kernel_path = self.ASSET_WHEEZY_KERNEL.fetch() - image_path = self.ASSET_WHEEZY_DISK.fetch() - kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE - + 'console=ttyS0 root=/dev/sda1') - mips_check_wheezy(self, - kernel_path, image_path, kernel_command_line, cpuinfo='MIPS 20Kc', - dl_file='/boot/initrd.img-3.2.0-4-5kc-malta', - hsum='d98b953bb4a41c0fc0fd8d19bbc691c08989ac52568c1d3054d92dfd890d3f06') - - -if __name__ == '__main__': - LinuxKernelTest.main() diff --git a/tests/functional/test_mips64_tuxrun.py b/tests/functional/test_mips64_tuxrun.py deleted file mode 100755 index 0e4c659..0000000 --- a/tests/functional/test_mips64_tuxrun.py +++ /dev/null @@ -1,35 +0,0 @@ -#!/usr/bin/env python3 -# -# Functional test that boots known good tuxboot images the same way -# that tuxrun (www.tuxrun.org) does. This tool is used by things like -# the LKFT project to run regression tests on kernels. -# -# Copyright (c) 2023 Linaro Ltd. -# -# Author: -# Alex Bennée -# -# SPDX-License-Identifier: GPL-2.0-or-later - -from qemu_test import Asset -from qemu_test.tuxruntest import TuxRunBaselineTest - -class TuxRunMips64Test(TuxRunBaselineTest): - - ASSET_MIPS64_KERNEL = Asset( - 'https://storage.tuxboot.com/buildroot/20241119/mips64/vmlinux', - 'fe2882d216898ba2c56b49ba59f46ad392f36871f7fe325373cd926848b9dbdc') - ASSET_MIPS64_ROOTFS = Asset( - 'https://storage.tuxboot.com/buildroot/20241119/mips64/rootfs.ext4.zst', - 'b8c98400216b6d4fb3b3ff05e9929aa015948b596cf0b82234813c84a4f7f4d5') - - def test_mips64(self): - self.set_machine('malta') - self.root="sda" - self.wait_for_shutdown=False - self.common_tuxrun(kernel_asset=self.ASSET_MIPS64_KERNEL, - rootfs_asset=self.ASSET_MIPS64_ROOTFS, - drive="driver=ide-hd,bus=ide.0,unit=0") - -if __name__ == '__main__': - TuxRunBaselineTest.main() diff --git a/tests/functional/test_mips64el_fuloong2e.py b/tests/functional/test_mips64el_fuloong2e.py deleted file mode 100755 index 35e500b..0000000 --- a/tests/functional/test_mips64el_fuloong2e.py +++ /dev/null @@ -1,64 +0,0 @@ -#!/usr/bin/env python3 -# -# Functional tests for the Lemote Fuloong-2E machine. -# -# Copyright (c) 2019 Philippe Mathieu-Daudé -# -# This work is licensed under the terms of the GNU GPL, version 2 or later. -# See the COPYING file in the top-level directory. -# -# SPDX-License-Identifier: GPL-2.0-or-later - -import os -import subprocess - -from qemu_test import LinuxKernelTest, Asset -from qemu_test import wait_for_console_pattern, skipUntrustedTest -from unittest import skipUnless - -class MipsFuloong2e(LinuxKernelTest): - - timeout = 60 - - ASSET_KERNEL = Asset( - ('http://archive.debian.org/debian/pool/main/l/linux/' - 'linux-image-3.16.0-6-loongson-2e_3.16.56-1+deb8u1_mipsel.deb'), - '2a70f15b397f4ced632b0c15cb22660394190644146d804d60a4796eefbe1f50') - - def test_linux_kernel_3_16(self): - kernel_path = self.archive_extract( - self.ASSET_KERNEL, - member='boot/vmlinux-3.16.0-6-loongson-2e') - - self.set_machine('fuloong2e') - self.vm.set_console() - kernel_command_line = self.KERNEL_COMMON_COMMAND_LINE + 'console=ttyS0' - self.vm.add_args('-kernel', kernel_path, - '-append', kernel_command_line) - self.vm.launch() - console_pattern = 'Kernel command line: %s' % kernel_command_line - self.wait_for_console_pattern(console_pattern) - - @skipUntrustedTest() - @skipUnless(os.getenv('RESCUE_YL_PATH'), 'RESCUE_YL_PATH not available') - def test_linux_kernel_2_6_27_isa_serial(self): - # Recovery system for the Yeeloong laptop - # (enough to test the fuloong2e southbridge, accessing its ISA bus) - # http://dev.lemote.com/files/resource/download/rescue/rescue-yl - sha = 'ab588d3316777c62cc81baa20ac92e98b01955c244dff3794b711bc34e26e51d' - kernel_path = os.getenv('RESCUE_YL_PATH') - output = subprocess.check_output(['sha256sum', kernel_path]) - checksum = output.split()[0] - assert checksum.decode("utf-8") == sha - - self.set_machine('fuloong2e') - self.vm.set_console() - self.vm.add_args('-kernel', kernel_path) - self.vm.launch() - wait_for_console_pattern(self, 'Linux version 2.6.27.7lemote') - cpu_revision = 'CPU revision is: 00006302 (ICT Loongson-2)' - wait_for_console_pattern(self, cpu_revision) - - -if __name__ == '__main__': - LinuxKernelTest.main() diff --git a/tests/functional/test_mips64el_loongson3v.py b/tests/functional/test_mips64el_loongson3v.py deleted file mode 100755 index f85371e..0000000 --- a/tests/functional/test_mips64el_loongson3v.py +++ /dev/null @@ -1,36 +0,0 @@ -#!/usr/bin/env python3 -# -# Functional tests for the Generic Loongson-3 Platform. -# -# Copyright (c) 2021 Jiaxun Yang -# -# This work is licensed under the terms of the GNU GPL, version 2 or later. -# See the COPYING file in the top-level directory. -# -# SPDX-License-Identifier: GPL-2.0-or-later - -from qemu_test import QemuSystemTest, Asset -from qemu_test import wait_for_console_pattern, skipUntrustedTest - - -class MipsLoongson3v(QemuSystemTest): - timeout = 60 - - ASSET_PMON = Asset( - ('https://github.com/loongson-community/pmon/' - 'releases/download/20210112/pmon-3avirt.bin'), - 'fcdf6bb2cb7885a4a62f31fcb0d5e368bac7b6cea28f40c6dfa678af22fea20a') - - @skipUntrustedTest() - def test_pmon_serial_console(self): - self.set_machine('loongson3-virt') - - pmon_path = self.ASSET_PMON.fetch() - - self.vm.set_console() - self.vm.add_args('-bios', pmon_path) - self.vm.launch() - wait_for_console_pattern(self, 'CPU GODSON3 BogoMIPS:') - -if __name__ == '__main__': - QemuSystemTest.main() diff --git a/tests/functional/test_mips64el_malta.py b/tests/functional/test_mips64el_malta.py deleted file mode 100755 index 3cc79b7..0000000 --- a/tests/functional/test_mips64el_malta.py +++ /dev/null @@ -1,197 +0,0 @@ -#!/usr/bin/env python3 -# -# Functional tests for the little-endian 64-bit MIPS Malta board -# -# Copyright (c) Philippe Mathieu-Daudé -# -# This work is licensed under the terms of the GNU GPL, version 2 or later. -# See the COPYING file in the top-level directory. -# -# SPDX-License-Identifier: GPL-2.0-or-later - -import os -import logging - -from qemu_test import LinuxKernelTest, Asset -from qemu_test import exec_command_and_wait_for_pattern -from qemu_test import skipIfMissingImports, skipFlakyTest, skipUntrustedTest - -from test_mips_malta import mips_check_wheezy - - -class MaltaMachineConsole(LinuxKernelTest): - - ASSET_KERNEL_2_63_2 = Asset( - ('http://snapshot.debian.org/archive/debian/' - '20130217T032700Z/pool/main/l/linux-2.6/' - 'linux-image-2.6.32-5-5kc-malta_2.6.32-48_mipsel.deb'), - '35eb476f03be589824b0310358f1c447d85e645b88cbcd2ac02b97ef560f9f8d') - - def test_mips64el_malta(self): - """ - This test requires the ar tool to extract "data.tar.gz" from - the Debian package. - - The kernel can be rebuilt using this Debian kernel source [1] and - following the instructions on [2]. - - [1] http://snapshot.debian.org/package/linux-2.6/2.6.32-48/ - #linux-source-2.6.32_2.6.32-48 - [2] https://kernel-team.pages.debian.net/kernel-handbook/ - ch-common-tasks.html#s-common-official - """ - kernel_path = self.archive_extract( - self.ASSET_KERNEL_2_63_2, - member='boot/vmlinux-2.6.32-5-5kc-malta') - - self.set_machine('malta') - self.vm.set_console() - kernel_command_line = self.KERNEL_COMMON_COMMAND_LINE + 'console=ttyS0' - self.vm.add_args('-kernel', kernel_path, - '-append', kernel_command_line) - self.vm.launch() - console_pattern = 'Kernel command line: %s' % kernel_command_line - self.wait_for_console_pattern(console_pattern) - - ASSET_KERNEL_3_19_3 = Asset( - ('https://github.com/philmd/qemu-testing-blob/' - 'raw/9ad2df38/mips/malta/mips64el/' - 'vmlinux-3.19.3.mtoman.20150408'), - '8d3beb003bc66051ead98e7172139017fcf9ce2172576541c57e86418dfa5ab8') - - ASSET_CPIO_R1 = Asset( - ('https://github.com/groeck/linux-build-test/' - 'raw/8584a59e/rootfs/mipsel64/' - 'rootfs.mipsel64r1.cpio.gz'), - '75ba10cd35fb44e32948eeb26974f061b703c81c4ba2fab1ebcacf1d1bec3b61') - - @skipUntrustedTest() - def test_mips64el_malta_5KEc_cpio(self): - kernel_path = self.ASSET_KERNEL_3_19_3.fetch() - initrd_path = self.uncompress(self.ASSET_CPIO_R1) - - self.set_machine('malta') - self.vm.set_console() - kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE - + 'console=ttyS0 console=tty ' - + 'rdinit=/sbin/init noreboot') - self.vm.add_args('-cpu', '5KEc', - '-kernel', kernel_path, - '-initrd', initrd_path, - '-append', kernel_command_line, - '-no-reboot') - self.vm.launch() - self.wait_for_console_pattern('Boot successful.') - - exec_command_and_wait_for_pattern(self, 'cat /proc/cpuinfo', - 'MIPS 5KE') - exec_command_and_wait_for_pattern(self, 'uname -a', - '3.19.3.mtoman.20150408') - exec_command_and_wait_for_pattern(self, 'reboot', - 'reboot: Restarting system') - # Wait for VM to shut down gracefully - self.vm.wait() - - ASSET_WHEEZY_KERNEL = Asset( - ('https://people.debian.org/~aurel32/qemu/mipsel/' - 'vmlinux-3.2.0-4-5kc-malta'), - '5e8b725244c59745bb8b64f5d8f49f25fecfa549f3395fb6d19a3b9e5065b85b') - - ASSET_WHEEZY_DISK = Asset( - ('https://people.debian.org/~aurel32/qemu/mipsel/' - 'debian_wheezy_mipsel_standard.qcow2'), - '454f09ae39f7e6461c84727b927100d2c7813841f2a0a5dce328114887ecf914') - - def test_wheezy(self): - kernel_path = self.ASSET_WHEEZY_KERNEL.fetch() - image_path = self.ASSET_WHEEZY_DISK.fetch() - kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE - + 'console=ttyS0 root=/dev/sda1') - mips_check_wheezy(self, - kernel_path, image_path, kernel_command_line, cpuinfo='MIPS 20Kc', - dl_file='/boot/initrd.img-3.2.0-4-5kc-malta', - hsum='7579f8b56c1187c7c04d0dc3c0c56c7a6314c5ddd3a9bf8803ecc7cf8a3be9f8') - - -@skipIfMissingImports('numpy', 'cv2') -class MaltaMachineFramebuffer(LinuxKernelTest): - - timeout = 30 - - ASSET_KERNEL_4_7_0 = Asset( - ('https://github.com/philmd/qemu-testing-blob/raw/a5966ca4b5/' - 'mips/malta/mips64el/vmlinux-4.7.0-rc1.I6400.gz'), - '1f64efc59968a3c328672e6b10213fe574bb2308d9d2ed44e75e40be59e9fbc2') - - ASSET_TUXLOGO = Asset( - ('https://github.com/torvalds/linux/raw/v2.6.12/' - 'drivers/video/logo/logo_linux_vga16.ppm'), - 'b762f0d91ec018887ad1b334543c2fdf9be9fdfc87672b409211efaa3ea0ef79') - - def do_test_i6400_framebuffer_logo(self, cpu_cores_count): - """ - Boot Linux kernel and check Tux logo is displayed on the framebuffer. - """ - - import numpy as np - import cv2 - - screendump_path = self.scratch_file('screendump.pbm') - - kernel_path = self.uncompress(self.ASSET_KERNEL_4_7_0) - - tuxlogo_path = self.ASSET_TUXLOGO.fetch() - - self.set_machine('malta') - self.vm.set_console() - kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE + - 'clocksource=GIC console=tty0 console=ttyS0') - self.vm.add_args('-kernel', kernel_path, - '-cpu', 'I6400', - '-smp', '%u' % cpu_cores_count, - '-vga', 'std', - '-append', kernel_command_line) - self.vm.launch() - framebuffer_ready = 'Console: switching to colour frame buffer device' - self.wait_for_console_pattern(framebuffer_ready) - self.vm.cmd('human-monitor-command', command_line='stop') - res = self.vm.cmd('human-monitor-command', - command_line='screendump %s' % screendump_path) - if 'unknown command' in res: - self.skipTest('screendump not available') - logger = logging.getLogger('framebuffer') - - match_threshold = 0.95 - screendump_bgr = cv2.imread(screendump_path, cv2.IMREAD_COLOR) - tuxlogo_bgr = cv2.imread(tuxlogo_path, cv2.IMREAD_COLOR) - result = cv2.matchTemplate(screendump_bgr, tuxlogo_bgr, - cv2.TM_CCOEFF_NORMED) - loc = np.where(result >= match_threshold) - tuxlogo_count = 0 - h, w = tuxlogo_bgr.shape[:2] - debug_png = os.getenv('QEMU_TEST_CV2_SCREENDUMP_PNG_PATH') - for tuxlogo_count, pt in enumerate(zip(*loc[::-1]), start=1): - logger.debug('found Tux at position (x, y) = %s', pt) - cv2.rectangle(screendump_bgr, pt, - (pt[0] + w, pt[1] + h), (0, 0, 255), 2) - if debug_png: - cv2.imwrite(debug_png, screendump_bgr) - self.assertGreaterEqual(tuxlogo_count, cpu_cores_count) - - def test_mips_malta_i6400_framebuffer_logo_1core(self): - self.do_test_i6400_framebuffer_logo(1) - - # XXX file tracking bug - @skipFlakyTest(bug_url=None) - def test_mips_malta_i6400_framebuffer_logo_7cores(self): - self.do_test_i6400_framebuffer_logo(7) - - @skipFlakyTest(bug_url=None) - def test_mips_malta_i6400_framebuffer_logo_8cores(self): - self.do_test_i6400_framebuffer_logo(8) - - -from test_mipsel_malta import MaltaMachineYAMON - -if __name__ == '__main__': - LinuxKernelTest.main() diff --git a/tests/functional/test_mips64el_replay.py b/tests/functional/test_mips64el_replay.py deleted file mode 100755 index 26a6ccf..0000000 --- a/tests/functional/test_mips64el_replay.py +++ /dev/null @@ -1,56 +0,0 @@ -#!/usr/bin/env python3 -# -# Replay tests for the little-endian 64-bit MIPS Malta board -# -# SPDX-License-Identifier: GPL-2.0-or-later - -from qemu_test import Asset, skipUntrustedTest -from replay_kernel import ReplayKernelBase - - -class Mips64elReplay(ReplayKernelBase): - - ASSET_KERNEL_2_63_2 = Asset( - ('http://snapshot.debian.org/archive/debian/' - '20130217T032700Z/pool/main/l/linux-2.6/' - 'linux-image-2.6.32-5-5kc-malta_2.6.32-48_mipsel.deb'), - '35eb476f03be589824b0310358f1c447d85e645b88cbcd2ac02b97ef560f9f8d') - - def test_replay_mips64el_malta(self): - self.set_machine('malta') - kernel_path = self.archive_extract(self.ASSET_KERNEL_2_63_2, - member='boot/vmlinux-2.6.32-5-5kc-malta') - kernel_command_line = self.KERNEL_COMMON_COMMAND_LINE + 'console=ttyS0' - console_pattern = 'Kernel command line: %s' % kernel_command_line - self.run_rr(kernel_path, kernel_command_line, console_pattern, shift=5) - - - ASSET_KERNEL_3_19_3 = Asset( - ('https://github.com/philmd/qemu-testing-blob/' - 'raw/9ad2df38/mips/malta/mips64el/' - 'vmlinux-3.19.3.mtoman.20150408'), - '8d3beb003bc66051ead98e7172139017fcf9ce2172576541c57e86418dfa5ab8') - - ASSET_CPIO_R1 = Asset( - ('https://github.com/groeck/linux-build-test/' - 'raw/8584a59e/rootfs/mipsel64/' - 'rootfs.mipsel64r1.cpio.gz'), - '75ba10cd35fb44e32948eeb26974f061b703c81c4ba2fab1ebcacf1d1bec3b61') - - @skipUntrustedTest() - def test_replay_mips64el_malta_5KEc_cpio(self): - self.set_machine('malta') - self.cpu = '5KEc' - kernel_path = self.ASSET_KERNEL_3_19_3.fetch() - initrd_path = self.uncompress(self.ASSET_CPIO_R1) - - kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE + - 'console=ttyS0 console=tty ' - 'rdinit=/sbin/init noreboot') - console_pattern = 'Boot successful.' - self.run_rr(kernel_path, kernel_command_line, console_pattern, shift=5, - args=('-initrd', initrd_path)) - - -if __name__ == '__main__': - ReplayKernelBase.main() diff --git a/tests/functional/test_mips64el_tuxrun.py b/tests/functional/test_mips64el_tuxrun.py deleted file mode 100755 index 0a24757..0000000 --- a/tests/functional/test_mips64el_tuxrun.py +++ /dev/null @@ -1,35 +0,0 @@ -#!/usr/bin/env python3 -# -# Functional test that boots known good tuxboot images the same way -# that tuxrun (www.tuxrun.org) does. This tool is used by things like -# the LKFT project to run regression tests on kernels. -# -# Copyright (c) 2023 Linaro Ltd. -# -# Author: -# Alex Bennée -# -# SPDX-License-Identifier: GPL-2.0-or-later - -from qemu_test import Asset -from qemu_test.tuxruntest import TuxRunBaselineTest - -class TuxRunMips64ELTest(TuxRunBaselineTest): - - ASSET_MIPS64EL_KERNEL = Asset( - 'https://storage.tuxboot.com/buildroot/20241119/mips64el/vmlinux', - '0d2829a96f005229839c4cd586d4d8a136ea4b488d29821611c8e97f2266bfa9') - ASSET_MIPS64EL_ROOTFS = Asset( - 'https://storage.tuxboot.com/buildroot/20241119/mips64el/rootfs.ext4.zst', - '69c8b69a4f1582ce4c6f01a994968f5d73bffb2fc99cbeeeb26c8b5a28eaeb84') - - def test_mips64el(self): - self.set_machine('malta') - self.root="sda" - self.wait_for_shutdown=False - self.common_tuxrun(kernel_asset=self.ASSET_MIPS64EL_KERNEL, - rootfs_asset=self.ASSET_MIPS64EL_ROOTFS, - drive="driver=ide-hd,bus=ide.0,unit=0") - -if __name__ == '__main__': - TuxRunBaselineTest.main() diff --git a/tests/functional/test_mips_malta.py b/tests/functional/test_mips_malta.py deleted file mode 100755 index 30279f0..0000000 --- a/tests/functional/test_mips_malta.py +++ /dev/null @@ -1,196 +0,0 @@ -#!/usr/bin/env python3 -# -# Functional tests for the big-endian 32-bit MIPS Malta board -# -# Copyright (c) Philippe Mathieu-Daudé -# -# SPDX-License-Identifier: GPL-2.0-or-later - -import os - -from qemu_test import LinuxKernelTest, Asset, wait_for_console_pattern -from qemu_test import exec_command_and_wait_for_pattern - - -def mips_run_common_commands(test, prompt='#'): - exec_command_and_wait_for_pattern(test, - 'uname -m', - 'mips') - exec_command_and_wait_for_pattern(test, - 'grep XT-PIC /proc/interrupts', - 'timer') - wait_for_console_pattern(test, prompt) - exec_command_and_wait_for_pattern(test, - 'grep XT-PIC /proc/interrupts', - 'serial') - wait_for_console_pattern(test, prompt) - exec_command_and_wait_for_pattern(test, - 'grep XT-PIC /proc/interrupts', - 'ata_piix') - wait_for_console_pattern(test, prompt) - exec_command_and_wait_for_pattern(test, - 'grep XT-PIC /proc/interrupts', - 'rtc') - wait_for_console_pattern(test, prompt) - exec_command_and_wait_for_pattern(test, - 'cat /proc/devices', - 'input') - wait_for_console_pattern(test, prompt) - exec_command_and_wait_for_pattern(test, - 'cat /proc/devices', - 'fb') - wait_for_console_pattern(test, prompt) - exec_command_and_wait_for_pattern(test, - 'cat /proc/ioports', - ' : serial') - wait_for_console_pattern(test, prompt) - exec_command_and_wait_for_pattern(test, - 'cat /proc/ioports', - ' : ata_piix') - wait_for_console_pattern(test, prompt) - -def mips_check_wheezy(test, kernel_path, image_path, kernel_command_line, - dl_file, hsum, nic='pcnet', cpuinfo='MIPS 24Kc'): - test.require_netdev('user') - test.require_device(nic) - test.set_machine('malta') - - port=8080 - test.vm.add_args('-kernel', kernel_path, - '-append', kernel_command_line, - '-drive', 'file=%s,snapshot=on' % image_path, - '-netdev', 'user,id=n1' + - ',tftp=' + os.path.basename(kernel_path) + - ',hostfwd=tcp:127.0.0.1:0-:%d' % port, - '-device', f'{nic},netdev=n1', - '-no-reboot') - test.vm.set_console() - test.vm.launch() - - wait_for_console_pattern(test, 'login: ', 'Oops') - exec_command_and_wait_for_pattern(test, 'root', 'Password:') - exec_command_and_wait_for_pattern(test, 'root', ':~# ') - mips_run_common_commands(test) - - exec_command_and_wait_for_pattern(test, 'cd /', '# ') - test.check_http_download(dl_file, hsum, port, - pythoncmd='python -m SimpleHTTPServer') - - exec_command_and_wait_for_pattern(test, 'cat /proc/cpuinfo', cpuinfo) - exec_command_and_wait_for_pattern(test, 'cat /proc/devices', 'usb') - exec_command_and_wait_for_pattern(test, 'cat /proc/ioports', - ' : piix4_smbus') - exec_command_and_wait_for_pattern(test, 'lspci -d 11ab:4620', - 'GT-64120') - exec_command_and_wait_for_pattern(test, - 'cat /sys/bus/i2c/devices/i2c-0/name', - 'SMBus PIIX4 adapter') - exec_command_and_wait_for_pattern(test, 'cat /proc/mtd', 'YAMON') - # Empty 'Board Config' (64KB) - exec_command_and_wait_for_pattern(test, 'md5sum /dev/mtd2ro', - '0dfbe8aa4c20b52e1b8bf3cb6cbdf193') - - -class MaltaMachineConsole(LinuxKernelTest): - - ASSET_KERNEL_2_63_2 = Asset( - ('http://snapshot.debian.org/archive/debian/' - '20130217T032700Z/pool/main/l/linux-2.6/' - 'linux-image-2.6.32-5-4kc-malta_2.6.32-48_mips.deb'), - '16ca524148afb0626f483163e5edf352bc1ab0e4fc7b9f9d473252762f2c7a43') - - def test_mips_malta(self): - kernel_path = self.archive_extract( - self.ASSET_KERNEL_2_63_2, - member='boot/vmlinux-2.6.32-5-4kc-malta') - - self.set_machine('malta') - self.vm.set_console() - kernel_command_line = self.KERNEL_COMMON_COMMAND_LINE + 'console=ttyS0' - self.vm.add_args('-kernel', kernel_path, - '-append', kernel_command_line) - self.vm.launch() - console_pattern = 'Kernel command line: %s' % kernel_command_line - self.wait_for_console_pattern(console_pattern) - - ASSET_KERNEL_4_5_0 = Asset( - ('http://snapshot.debian.org/archive/debian/' - '20160601T041800Z/pool/main/l/linux/' - 'linux-image-4.5.0-2-4kc-malta_4.5.5-1_mips.deb'), - '526b17d5889840888b76fc2c36a0ebde182c9b1410a3a1e68203c3b160eb2027') - - ASSET_INITRD = Asset( - ('https://github.com/groeck/linux-build-test/raw/' - '8584a59ed9e5eb5ee7ca91f6d74bbb06619205b8/rootfs/' - 'mips/rootfs.cpio.gz'), - 'dcfe3a7fe3200da3a00d176b95caaa086495eb158f2bff64afc67d7e1eb2cddc') - - def test_mips_malta_cpio(self): - self.require_netdev('user') - self.set_machine('malta') - self.require_device('pcnet') - - kernel_path = self.archive_extract( - self.ASSET_KERNEL_4_5_0, - member='boot/vmlinux-4.5.0-2-4kc-malta') - initrd_path = self.uncompress(self.ASSET_INITRD) - - self.vm.set_console() - kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE - + 'console=ttyS0 console=tty ' - + 'rdinit=/sbin/init noreboot') - self.vm.add_args('-kernel', kernel_path, - '-initrd', initrd_path, - '-append', kernel_command_line, - '-netdev', 'user,id=n1,tftp=' + self.scratch_file('boot'), - '-device', 'pcnet,netdev=n1', - '-no-reboot') - self.vm.launch() - self.wait_for_console_pattern('Boot successful.') - - exec_command_and_wait_for_pattern(self, 'cat /proc/cpuinfo', - 'BogoMIPS') - exec_command_and_wait_for_pattern(self, 'uname -a', - '4.5.0-2-4kc-malta #1 Debian') - mips_run_common_commands(self) - - exec_command_and_wait_for_pattern(self, 'ip link set eth0 up', - 'eth0: link up') - exec_command_and_wait_for_pattern(self, - 'ip addr add 10.0.2.15 dev eth0', - '#') - exec_command_and_wait_for_pattern(self, 'route add default eth0', '#') - exec_command_and_wait_for_pattern(self, - 'tftp -g -r vmlinux-4.5.0-2-4kc-malta 10.0.2.2', '#') - exec_command_and_wait_for_pattern(self, - 'md5sum vmlinux-4.5.0-2-4kc-malta', - 'a98218a7efbdefb2dfdf9ecd08c98318') - - exec_command_and_wait_for_pattern(self, 'reboot', - 'reboot: Restarting system') - # Wait for VM to shut down gracefully - self.vm.wait() - - ASSET_WHEEZY_KERNEL = Asset( - ('https://people.debian.org/~aurel32/qemu/mips/' - 'vmlinux-3.2.0-4-4kc-malta'), - '0377fcda31299213c10b8e5babe7260ef99188b3ae1aca6f56594abb71e7f67e') - - ASSET_WHEEZY_DISK = Asset( - ('https://people.debian.org/~aurel32/qemu/mips/' - 'debian_wheezy_mips_standard.qcow2'), - 'de03599285b8382ad309309a6c4869f6c6c42a5cfc983342bab9ec0dfa7849a2') - - def test_wheezy(self): - kernel_path = self.ASSET_WHEEZY_KERNEL.fetch() - image_path = self.ASSET_WHEEZY_DISK.fetch() - kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE - + 'console=ttyS0 root=/dev/sda1') - mips_check_wheezy(self, - kernel_path, image_path, kernel_command_line, nic='e1000', - dl_file='/boot/initrd.img-3.2.0-4-4kc-malta', - hsum='ff0c0369143d9bbb9a6e6bc79322a2be535619df639e84103237f406e87493dc') - - -if __name__ == '__main__': - LinuxKernelTest.main() diff --git a/tests/functional/test_mips_replay.py b/tests/functional/test_mips_replay.py deleted file mode 100755 index 4327481..0000000 --- a/tests/functional/test_mips_replay.py +++ /dev/null @@ -1,55 +0,0 @@ -#!/usr/bin/env python3 -# -# Replay tests for the big-endian 32-bit MIPS Malta board -# -# SPDX-License-Identifier: GPL-2.0-or-later - -from qemu_test import Asset, skipSlowTest -from replay_kernel import ReplayKernelBase - - -class MipsReplay(ReplayKernelBase): - - ASSET_KERNEL_2_63_2 = Asset( - ('http://snapshot.debian.org/archive/debian/' - '20130217T032700Z/pool/main/l/linux-2.6/' - 'linux-image-2.6.32-5-4kc-malta_2.6.32-48_mips.deb'), - '16ca524148afb0626f483163e5edf352bc1ab0e4fc7b9f9d473252762f2c7a43') - - def test_replay_mips_malta(self): - self.set_machine('malta') - kernel_path = self.archive_extract(self.ASSET_KERNEL_2_63_2, - member='boot/vmlinux-2.6.32-5-4kc-malta') - kernel_command_line = self.KERNEL_COMMON_COMMAND_LINE + 'console=ttyS0' - console_pattern = 'Kernel command line: %s' % kernel_command_line - self.run_rr(kernel_path, kernel_command_line, console_pattern, shift=5) - - ASSET_KERNEL_4_5_0 = Asset( - ('http://snapshot.debian.org/archive/debian/' - '20160601T041800Z/pool/main/l/linux/' - 'linux-image-4.5.0-2-4kc-malta_4.5.5-1_mips.deb'), - '526b17d5889840888b76fc2c36a0ebde182c9b1410a3a1e68203c3b160eb2027') - - ASSET_INITRD = Asset( - ('https://github.com/groeck/linux-build-test/raw/' - '8584a59ed9e5eb5ee7ca91f6d74bbb06619205b8/rootfs/' - 'mips/rootfs.cpio.gz'), - 'dcfe3a7fe3200da3a00d176b95caaa086495eb158f2bff64afc67d7e1eb2cddc') - - @skipSlowTest() - def test_replay_mips_malta_cpio(self): - self.set_machine('malta') - kernel_path = self.archive_extract(self.ASSET_KERNEL_4_5_0, - member='boot/vmlinux-4.5.0-2-4kc-malta') - initrd_path = self.uncompress(self.ASSET_INITRD) - - kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE + - 'console=ttyS0 console=tty ' - 'rdinit=/sbin/init noreboot') - console_pattern = 'Boot successful.' - self.run_rr(kernel_path, kernel_command_line, console_pattern, shift=5, - args=('-initrd', initrd_path)) - - -if __name__ == '__main__': - ReplayKernelBase.main() diff --git a/tests/functional/test_mips_tuxrun.py b/tests/functional/test_mips_tuxrun.py deleted file mode 100755 index 6771dbd..0000000 --- a/tests/functional/test_mips_tuxrun.py +++ /dev/null @@ -1,36 +0,0 @@ -#!/usr/bin/env python3 -# -# Functional test that boots known good tuxboot images the same way -# that tuxrun (www.tuxrun.org) does. This tool is used by things like -# the LKFT project to run regression tests on kernels. -# -# Copyright (c) 2023 Linaro Ltd. -# -# Author: -# Alex Bennée -# -# SPDX-License-Identifier: GPL-2.0-or-later - -from qemu_test import Asset -from qemu_test.tuxruntest import TuxRunBaselineTest - -class TuxRunMipsTest(TuxRunBaselineTest): - - ASSET_MIPS_KERNEL = Asset( - 'https://storage.tuxboot.com/buildroot/20241119/mips32/vmlinux', - 'b6f97fc698ae8c96456ad8c996c7454228074df0d7520dedd0a15e2913700a19') - ASSET_MIPS_ROOTFS = Asset( - 'https://storage.tuxboot.com/buildroot/20241119/mips32/rootfs.ext4.zst', - '87055cf3cbde3fd134e5039e7b87feb03231d8c4b21ee712b8ba3308dfa72f50') - - def test_mips32(self): - self.set_machine('malta') - self.cpu="mips32r6-generic" - self.root="sda" - self.wait_for_shutdown=False - self.common_tuxrun(kernel_asset=self.ASSET_MIPS_KERNEL, - rootfs_asset=self.ASSET_MIPS_ROOTFS, - drive="driver=ide-hd,bus=ide.0,unit=0") - -if __name__ == '__main__': - TuxRunBaselineTest.main() diff --git a/tests/functional/test_mipsel_malta.py b/tests/functional/test_mipsel_malta.py deleted file mode 100755 index 9ee2884..0000000 --- a/tests/functional/test_mipsel_malta.py +++ /dev/null @@ -1,108 +0,0 @@ -#!/usr/bin/env python3 -# -# Functional tests for the little-endian 32-bit MIPS Malta board -# -# Copyright (c) Philippe Mathieu-Daudé -# -# This work is licensed under the terms of the GNU GPL, version 2 or later. -# See the COPYING file in the top-level directory. -# -# SPDX-License-Identifier: GPL-2.0-or-later - -from qemu_test import QemuSystemTest, LinuxKernelTest, Asset -from qemu_test import interrupt_interactive_console_until_pattern -from qemu_test import wait_for_console_pattern - -from test_mips_malta import mips_check_wheezy - - -class MaltaMachineConsole(LinuxKernelTest): - - ASSET_KERNEL_4K = Asset( - ('http://mipsdistros.mips.com/LinuxDistro/nanomips/' - 'kernels/v4.15.18-432-gb2eb9a8b07a1-20180627102142/' - 'generic_nano32r6el_page4k.xz'), - '019e034094ac6cf3aa77df5e130fb023ce4dbc804b04bfcc560c6403e1ae6bdb') - ASSET_KERNEL_16K = Asset( - ('http://mipsdistros.mips.com/LinuxDistro/nanomips/' - 'kernels/v4.15.18-432-gb2eb9a8b07a1-20180627102142/' - 'generic_nano32r6el_page16k_up.xz'), - '3a54a10b3108c16a448dca9ea3db378733a27423befc2a45a5bdf990bd85e12c') - ASSET_KERNEL_64K = Asset( - ('http://mipsdistros.mips.com/LinuxDistro/nanomips/' - 'kernels/v4.15.18-432-gb2eb9a8b07a1-20180627102142/' - 'generic_nano32r6el_page64k_dbg.xz'), - 'ce21ff4b07a981ecb8a39db2876616f5a2473eb2ab459c6f67465b9914b0c6b6') - - def do_test_mips_malta32el_nanomips(self, kernel): - kernel_path = self.uncompress(kernel) - - self.set_machine('malta') - self.vm.set_console() - kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE - + 'mem=256m@@0x0 ' - + 'console=ttyS0') - self.vm.add_args('-cpu', 'I7200', - '-no-reboot', - '-kernel', kernel_path, - '-append', kernel_command_line) - self.vm.launch() - console_pattern = 'Kernel command line: %s' % kernel_command_line - self.wait_for_console_pattern(console_pattern) - - def test_mips_malta32el_nanomips_4k(self): - self.do_test_mips_malta32el_nanomips(self.ASSET_KERNEL_4K) - - def test_mips_malta32el_nanomips_16k_up(self): - self.do_test_mips_malta32el_nanomips(self.ASSET_KERNEL_16K) - - def test_mips_malta32el_nanomips_64k_dbg(self): - self.do_test_mips_malta32el_nanomips(self.ASSET_KERNEL_64K) - - ASSET_WHEEZY_KERNEL = Asset( - ('https://people.debian.org/~aurel32/qemu/mipsel/' - 'vmlinux-3.2.0-4-4kc-malta'), - 'dc8a3648305b0201ca7a5cd135fe2890067a65d93c38728022bb0e656ad2bf9a') - - ASSET_WHEEZY_DISK = Asset( - ('https://people.debian.org/~aurel32/qemu/mipsel/' - 'debian_wheezy_mipsel_standard.qcow2'), - '454f09ae39f7e6461c84727b927100d2c7813841f2a0a5dce328114887ecf914') - - def test_wheezy(self): - kernel_path = self.ASSET_WHEEZY_KERNEL.fetch() - image_path = self.ASSET_WHEEZY_DISK.fetch() - kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE - + 'console=ttyS0 root=/dev/sda1') - mips_check_wheezy(self, - kernel_path, image_path, kernel_command_line, - dl_file='/boot/initrd.img-3.2.0-4-4kc-malta', - hsum='9fc9f250ed56a74e35e704ddfd5a1c5a5625adefc5c9da91f649288d3ca000f0') - - -class MaltaMachineYAMON(QemuSystemTest): - - ASSET_YAMON_ROM = Asset( - ('https://s3-eu-west-1.amazonaws.com/downloads-mips/mips-downloads/' - 'YAMON/yamon-bin-02.22.zip'), - 'eef86f0eed0ef554f041dcd47b87eebea0e6f9f1184ed31f7e9e8b4a803860ab') - - def test_mipsel_malta_yamon(self): - yamon_bin = 'yamon-02.22.bin' - self.archive_extract(self.ASSET_YAMON_ROM) - yamon_path = self.scratch_file(yamon_bin) - - self.set_machine('malta') - self.vm.set_console() - self.vm.add_args('-bios', yamon_path) - self.vm.launch() - - prompt = 'YAMON>' - pattern = 'YAMON ROM Monitor' - interrupt_interactive_console_until_pattern(self, pattern, prompt) - wait_for_console_pattern(self, prompt) - self.vm.shutdown() - - -if __name__ == '__main__': - QemuSystemTest.main() diff --git a/tests/functional/test_mipsel_replay.py b/tests/functional/test_mipsel_replay.py deleted file mode 100644 index 5f4796c..0000000 --- a/tests/functional/test_mipsel_replay.py +++ /dev/null @@ -1,54 +0,0 @@ -#!/usr/bin/env python3 -# -# Replay tests for the little-endian 32-bit MIPS Malta board -# -# SPDX-License-Identifier: GPL-2.0-or-later - -from qemu_test import Asset, skipSlowTest -from replay_kernel import ReplayKernelBase - - -class MipselReplay(ReplayKernelBase): - - ASSET_KERNEL_4K = Asset( - ('http://mipsdistros.mips.com/LinuxDistro/nanomips/' - 'kernels/v4.15.18-432-gb2eb9a8b07a1-20180627102142/' - 'generic_nano32r6el_page4k.xz'), - '019e034094ac6cf3aa77df5e130fb023ce4dbc804b04bfcc560c6403e1ae6bdb') - ASSET_KERNEL_16K = Asset( - ('http://mipsdistros.mips.com/LinuxDistro/nanomips/' - 'kernels/v4.15.18-432-gb2eb9a8b07a1-20180627102142/' - 'generic_nano32r6el_page16k_up.xz'), - '3a54a10b3108c16a448dca9ea3db378733a27423befc2a45a5bdf990bd85e12c') - ASSET_KERNEL_64K = Asset( - ('http://mipsdistros.mips.com/LinuxDistro/nanomips/' - 'kernels/v4.15.18-432-gb2eb9a8b07a1-20180627102142/' - 'generic_nano32r6el_page64k_dbg.xz'), - 'ce21ff4b07a981ecb8a39db2876616f5a2473eb2ab459c6f67465b9914b0c6b6') - - def do_test_replay_mips_malta32el_nanomips(self, kernel_asset): - self.set_machine('malta') - self.cpu = 'I7200' - kernel_path = self.uncompress(kernel_asset) - - kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE + - 'mem=256m@@0x0 ' - 'console=ttyS0') - console_pattern = 'Kernel command line: %s' % kernel_command_line - self.run_rr(kernel_path, kernel_command_line, console_pattern, shift=5) - - @skipSlowTest() - def test_replay_mips_malta32el_nanomips_4k(self): - self.do_test_replay_mips_malta32el_nanomips(self.ASSET_KERNEL_4K) - - @skipSlowTest() - def test_replay_mips_malta32el_nanomips_16k_up(self): - self.do_test_replay_mips_malta32el_nanomips(self.ASSET_KERNEL_16K) - - @skipSlowTest() - def test_replay_mips_malta32el_nanomips_64k_dbg(self): - self.do_test_replay_mips_malta32el_nanomips(self.ASSET_KERNEL_64K) - - -if __name__ == '__main__': - ReplayKernelBase.main() diff --git a/tests/functional/test_mipsel_tuxrun.py b/tests/functional/test_mipsel_tuxrun.py deleted file mode 100755 index d4b39ba..0000000 --- a/tests/functional/test_mipsel_tuxrun.py +++ /dev/null @@ -1,36 +0,0 @@ -#!/usr/bin/env python3 -# -# Functional test that boots known good tuxboot images the same way -# that tuxrun (www.tuxrun.org) does. This tool is used by things like -# the LKFT project to run regression tests on kernels. -# -# Copyright (c) 2023 Linaro Ltd. -# -# Author: -# Alex Bennée -# -# SPDX-License-Identifier: GPL-2.0-or-later - -from qemu_test import Asset -from qemu_test.tuxruntest import TuxRunBaselineTest - -class TuxRunMipsELTest(TuxRunBaselineTest): - - ASSET_MIPSEL_KERNEL = Asset( - 'https://storage.tuxboot.com/buildroot/20241119/mips32el/vmlinux', - '660dd8c7a6ca7a32d37b4e6348865532ab0edb66802e8cc07869338444cf4929') - ASSET_MIPSEL_ROOTFS = Asset( - 'https://storage.tuxboot.com/buildroot/20241119/mips32el/rootfs.ext4.zst', - 'c5d69542bcaed54a4f34671671eb4be5c608ee02671d4d0436544367816a73b1') - - def test_mips32el(self): - self.set_machine('malta') - self.cpu="mips32r6-generic" - self.root="sda" - self.wait_for_shutdown=False - self.common_tuxrun(kernel_asset=self.ASSET_MIPSEL_KERNEL, - rootfs_asset=self.ASSET_MIPSEL_ROOTFS, - drive="driver=ide-hd,bus=ide.0,unit=0") - -if __name__ == '__main__': - TuxRunBaselineTest.main() -- cgit v1.1 From ff94df87caeecf3fe2b77e06d2ffe483725bcb51 Mon Sep 17 00:00:00 2001 From: Thomas Huth Date: Tue, 19 Aug 2025 13:23:52 +0200 Subject: tests/functional: Move or1k tests into target-specific folders MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The tests/functional folder has become quite crowded, thus move the openrisc tests into a target-specific subfolder. Reviewed-by: Pierrick Bouvier Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Thomas Huth Message-ID: <20250819112403.432587-16-thuth@redhat.com> --- tests/functional/meson.build | 6 +----- tests/functional/or1k/meson.build | 6 ++++++ tests/functional/or1k/test_replay.py | 27 +++++++++++++++++++++++++++ tests/functional/or1k/test_sim.py | 26 ++++++++++++++++++++++++++ tests/functional/test_or1k_replay.py | 27 --------------------------- tests/functional/test_or1k_sim.py | 26 -------------------------- 6 files changed, 60 insertions(+), 58 deletions(-) create mode 100644 tests/functional/or1k/meson.build create mode 100755 tests/functional/or1k/test_replay.py create mode 100755 tests/functional/or1k/test_sim.py delete mode 100755 tests/functional/test_or1k_replay.py delete mode 100755 tests/functional/test_or1k_sim.py (limited to 'tests') diff --git a/tests/functional/meson.build b/tests/functional/meson.build index 52969a3..397303e 100644 --- a/tests/functional/meson.build +++ b/tests/functional/meson.build @@ -23,6 +23,7 @@ subdir('mips') subdir('mipsel') subdir('mips64') subdir('mips64el') +subdir('or1k') test_ppc_timeouts = { 'ppc_40p' : 240, @@ -70,11 +71,6 @@ tests_generic_linuxuser = [ tests_generic_bsduser = [ ] -tests_or1k_system_thorough = [ - 'or1k_replay', - 'or1k_sim', -] - tests_ppc_system_quick = [ 'ppc_migration', 'ppc_74xx', diff --git a/tests/functional/or1k/meson.build b/tests/functional/or1k/meson.build new file mode 100644 index 0000000..e246e2a --- /dev/null +++ b/tests/functional/or1k/meson.build @@ -0,0 +1,6 @@ +# SPDX-License-Identifier: GPL-2.0-or-later + +tests_or1k_system_thorough = [ + 'replay', + 'sim', +] diff --git a/tests/functional/or1k/test_replay.py b/tests/functional/or1k/test_replay.py new file mode 100755 index 0000000..2b60a93 --- /dev/null +++ b/tests/functional/or1k/test_replay.py @@ -0,0 +1,27 @@ +#!/usr/bin/env python3 +# +# Replay test that boots a Linux kernel on an OpenRISC-1000 SIM machine +# and checks the console +# +# SPDX-License-Identifier: GPL-2.0-or-later + +from qemu_test import Asset +from replay_kernel import ReplayKernelBase + + +class Or1kReplay(ReplayKernelBase): + + ASSET_DAY20 = Asset( + 'https://qemu-advcal.gitlab.io/qac-best-of-multiarch/download/day20.tar.xz', + 'ff9d7dd7c6bdba325bd85ee85c02db61ff653e129558aeffe6aff55bffb6763a') + + def test_sim(self): + self.set_machine('or1k-sim') + kernel_path = self.archive_extract(self.ASSET_DAY20, + member='day20/vmlinux') + self.run_rr(kernel_path, self.REPLAY_KERNEL_COMMAND_LINE, + 'QEMU advent calendar') + + +if __name__ == '__main__': + ReplayKernelBase.main() diff --git a/tests/functional/or1k/test_sim.py b/tests/functional/or1k/test_sim.py new file mode 100755 index 0000000..f9f0b69 --- /dev/null +++ b/tests/functional/or1k/test_sim.py @@ -0,0 +1,26 @@ +#!/usr/bin/env python3 +# +# Functional test that boots a Linux kernel on an OpenRISC-1000 SIM machine +# and checks the console +# +# SPDX-License-Identifier: GPL-2.0-or-later + +from qemu_test import LinuxKernelTest, Asset + + +class OpenRISC1kSimTest(LinuxKernelTest): + + ASSET_DAY20 = Asset( + 'https://qemu-advcal.gitlab.io/qac-best-of-multiarch/download/day20.tar.xz', + 'ff9d7dd7c6bdba325bd85ee85c02db61ff653e129558aeffe6aff55bffb6763a') + + def test_or1k_sim(self): + self.set_machine('or1k-sim') + self.archive_extract(self.ASSET_DAY20) + self.vm.set_console() + self.vm.add_args('-kernel', self.scratch_file('day20', 'vmlinux')) + self.vm.launch() + self.wait_for_console_pattern('QEMU advent calendar') + +if __name__ == '__main__': + LinuxKernelTest.main() diff --git a/tests/functional/test_or1k_replay.py b/tests/functional/test_or1k_replay.py deleted file mode 100755 index 2b60a93..0000000 --- a/tests/functional/test_or1k_replay.py +++ /dev/null @@ -1,27 +0,0 @@ -#!/usr/bin/env python3 -# -# Replay test that boots a Linux kernel on an OpenRISC-1000 SIM machine -# and checks the console -# -# SPDX-License-Identifier: GPL-2.0-or-later - -from qemu_test import Asset -from replay_kernel import ReplayKernelBase - - -class Or1kReplay(ReplayKernelBase): - - ASSET_DAY20 = Asset( - 'https://qemu-advcal.gitlab.io/qac-best-of-multiarch/download/day20.tar.xz', - 'ff9d7dd7c6bdba325bd85ee85c02db61ff653e129558aeffe6aff55bffb6763a') - - def test_sim(self): - self.set_machine('or1k-sim') - kernel_path = self.archive_extract(self.ASSET_DAY20, - member='day20/vmlinux') - self.run_rr(kernel_path, self.REPLAY_KERNEL_COMMAND_LINE, - 'QEMU advent calendar') - - -if __name__ == '__main__': - ReplayKernelBase.main() diff --git a/tests/functional/test_or1k_sim.py b/tests/functional/test_or1k_sim.py deleted file mode 100755 index f9f0b69..0000000 --- a/tests/functional/test_or1k_sim.py +++ /dev/null @@ -1,26 +0,0 @@ -#!/usr/bin/env python3 -# -# Functional test that boots a Linux kernel on an OpenRISC-1000 SIM machine -# and checks the console -# -# SPDX-License-Identifier: GPL-2.0-or-later - -from qemu_test import LinuxKernelTest, Asset - - -class OpenRISC1kSimTest(LinuxKernelTest): - - ASSET_DAY20 = Asset( - 'https://qemu-advcal.gitlab.io/qac-best-of-multiarch/download/day20.tar.xz', - 'ff9d7dd7c6bdba325bd85ee85c02db61ff653e129558aeffe6aff55bffb6763a') - - def test_or1k_sim(self): - self.set_machine('or1k-sim') - self.archive_extract(self.ASSET_DAY20) - self.vm.set_console() - self.vm.add_args('-kernel', self.scratch_file('day20', 'vmlinux')) - self.vm.launch() - self.wait_for_console_pattern('QEMU advent calendar') - -if __name__ == '__main__': - LinuxKernelTest.main() -- cgit v1.1 From 1cdb63218c975b20699714449131c6745a512a1f Mon Sep 17 00:00:00 2001 From: Thomas Huth Date: Tue, 19 Aug 2025 13:23:53 +0200 Subject: tests/functional: Move ppc/ppc64 tests into target-specific folders The tests/functional folder has become quite crowded, thus move the ppc and ppc64 tests into a target-specific subfolder. Reviewed-by: Pierrick Bouvier Signed-off-by: Thomas Huth Message-ID: <20250819112403.432587-17-thuth@redhat.com> --- tests/functional/meson.build | 47 +------- tests/functional/ppc/meson.build | 22 ++++ tests/functional/ppc/test_40p.py | 94 +++++++++++++++ tests/functional/ppc/test_74xx.py | 126 ++++++++++++++++++++ tests/functional/ppc/test_amiga.py | 43 +++++++ tests/functional/ppc/test_bamboo.py | 48 ++++++++ tests/functional/ppc/test_mac.py | 36 ++++++ tests/functional/ppc/test_migration.py | 26 +++++ tests/functional/ppc/test_mpc8544ds.py | 37 ++++++ tests/functional/ppc/test_replay.py | 34 ++++++ tests/functional/ppc/test_sam460ex.py | 38 ++++++ tests/functional/ppc/test_tuxrun.py | 35 ++++++ tests/functional/ppc/test_virtex_ml507.py | 39 +++++++ tests/functional/ppc64/meson.build | 25 ++++ tests/functional/ppc64/test_e500.py | 44 +++++++ tests/functional/ppc64/test_hv.py | 165 +++++++++++++++++++++++++++ tests/functional/ppc64/test_mac99.py | 44 +++++++ tests/functional/ppc64/test_migration.py | 26 +++++ tests/functional/ppc64/test_powernv.py | 118 +++++++++++++++++++ tests/functional/ppc64/test_pseries.py | 91 +++++++++++++++ tests/functional/ppc64/test_replay.py | 50 ++++++++ tests/functional/ppc64/test_reverse_debug.py | 41 +++++++ tests/functional/ppc64/test_tuxrun.py | 113 ++++++++++++++++++ tests/functional/test_ppc64_e500.py | 44 ------- tests/functional/test_ppc64_hv.py | 165 --------------------------- tests/functional/test_ppc64_mac99.py | 44 ------- tests/functional/test_ppc64_migration.py | 26 ----- tests/functional/test_ppc64_powernv.py | 118 ------------------- tests/functional/test_ppc64_pseries.py | 91 --------------- tests/functional/test_ppc64_replay.py | 50 -------- tests/functional/test_ppc64_reverse_debug.py | 41 ------- tests/functional/test_ppc64_tuxrun.py | 113 ------------------ tests/functional/test_ppc_40p.py | 94 --------------- tests/functional/test_ppc_74xx.py | 126 -------------------- tests/functional/test_ppc_amiga.py | 43 ------- tests/functional/test_ppc_bamboo.py | 48 -------- tests/functional/test_ppc_mac.py | 36 ------ tests/functional/test_ppc_migration.py | 26 ----- tests/functional/test_ppc_mpc8544ds.py | 37 ------ tests/functional/test_ppc_replay.py | 34 ------ tests/functional/test_ppc_sam460ex.py | 38 ------ tests/functional/test_ppc_tuxrun.py | 35 ------ tests/functional/test_ppc_virtex_ml507.py | 39 ------- 43 files changed, 1297 insertions(+), 1293 deletions(-) create mode 100644 tests/functional/ppc/meson.build create mode 100755 tests/functional/ppc/test_40p.py create mode 100755 tests/functional/ppc/test_74xx.py create mode 100755 tests/functional/ppc/test_amiga.py create mode 100755 tests/functional/ppc/test_bamboo.py create mode 100755 tests/functional/ppc/test_mac.py create mode 100755 tests/functional/ppc/test_migration.py create mode 100755 tests/functional/ppc/test_mpc8544ds.py create mode 100755 tests/functional/ppc/test_replay.py create mode 100755 tests/functional/ppc/test_sam460ex.py create mode 100755 tests/functional/ppc/test_tuxrun.py create mode 100755 tests/functional/ppc/test_virtex_ml507.py create mode 100644 tests/functional/ppc64/meson.build create mode 100755 tests/functional/ppc64/test_e500.py create mode 100755 tests/functional/ppc64/test_hv.py create mode 100755 tests/functional/ppc64/test_mac99.py create mode 100755 tests/functional/ppc64/test_migration.py create mode 100755 tests/functional/ppc64/test_powernv.py create mode 100755 tests/functional/ppc64/test_pseries.py create mode 100755 tests/functional/ppc64/test_replay.py create mode 100755 tests/functional/ppc64/test_reverse_debug.py create mode 100755 tests/functional/ppc64/test_tuxrun.py delete mode 100755 tests/functional/test_ppc64_e500.py delete mode 100755 tests/functional/test_ppc64_hv.py delete mode 100755 tests/functional/test_ppc64_mac99.py delete mode 100755 tests/functional/test_ppc64_migration.py delete mode 100755 tests/functional/test_ppc64_powernv.py delete mode 100755 tests/functional/test_ppc64_pseries.py delete mode 100755 tests/functional/test_ppc64_replay.py delete mode 100755 tests/functional/test_ppc64_reverse_debug.py delete mode 100755 tests/functional/test_ppc64_tuxrun.py delete mode 100755 tests/functional/test_ppc_40p.py delete mode 100755 tests/functional/test_ppc_74xx.py delete mode 100755 tests/functional/test_ppc_amiga.py delete mode 100755 tests/functional/test_ppc_bamboo.py delete mode 100755 tests/functional/test_ppc_mac.py delete mode 100755 tests/functional/test_ppc_migration.py delete mode 100755 tests/functional/test_ppc_mpc8544ds.py delete mode 100755 tests/functional/test_ppc_replay.py delete mode 100644 tests/functional/test_ppc_sam460ex.py delete mode 100755 tests/functional/test_ppc_tuxrun.py delete mode 100755 tests/functional/test_ppc_virtex_ml507.py (limited to 'tests') diff --git a/tests/functional/meson.build b/tests/functional/meson.build index 397303e..3caeea5 100644 --- a/tests/functional/meson.build +++ b/tests/functional/meson.build @@ -24,19 +24,8 @@ subdir('mipsel') subdir('mips64') subdir('mips64el') subdir('or1k') - -test_ppc_timeouts = { - 'ppc_40p' : 240, -} - -test_ppc64_timeouts = { - 'ppc64_hv' : 1000, - 'ppc64_powernv' : 480, - 'ppc64_pseries' : 480, - 'ppc64_replay' : 210, - 'ppc64_tuxrun' : 420, - 'ppc64_mac99' : 120, -} +subdir('ppc') +subdir('ppc64') test_riscv64_timeouts = { 'riscv64_tuxrun' : 120, @@ -71,38 +60,6 @@ tests_generic_linuxuser = [ tests_generic_bsduser = [ ] -tests_ppc_system_quick = [ - 'ppc_migration', - 'ppc_74xx', -] - -tests_ppc_system_thorough = [ - 'ppc_40p', - 'ppc_amiga', - 'ppc_bamboo', - 'ppc_mac', - 'ppc_mpc8544ds', - 'ppc_replay', - 'ppc_sam460ex', - 'ppc_tuxrun', - 'ppc_virtex_ml507', -] - -tests_ppc64_system_quick = [ - 'ppc64_migration', -] - -tests_ppc64_system_thorough = [ - 'ppc64_e500', - 'ppc64_hv', - 'ppc64_powernv', - 'ppc64_pseries', - 'ppc64_replay', - 'ppc64_reverse_debug', - 'ppc64_tuxrun', - 'ppc64_mac99', -] - tests_riscv32_system_quick = [ 'riscv32_migration', 'riscv_opensbi', diff --git a/tests/functional/ppc/meson.build b/tests/functional/ppc/meson.build new file mode 100644 index 0000000..3d56201 --- /dev/null +++ b/tests/functional/ppc/meson.build @@ -0,0 +1,22 @@ +# SPDX-License-Identifier: GPL-2.0-or-later + +test_ppc_timeouts = { + '40p' : 240, +} + +tests_ppc_system_quick = [ + 'migration', + '74xx', +] + +tests_ppc_system_thorough = [ + '40p', + 'amiga', + 'bamboo', + 'mac', + 'mpc8544ds', + 'replay', + 'sam460ex', + 'tuxrun', + 'virtex_ml507', +] diff --git a/tests/functional/ppc/test_40p.py b/tests/functional/ppc/test_40p.py new file mode 100755 index 0000000..614972a --- /dev/null +++ b/tests/functional/ppc/test_40p.py @@ -0,0 +1,94 @@ +#!/usr/bin/env python3 +# +# Functional test that boots a PReP/40p machine and checks its serial console. +# +# Copyright (c) Philippe Mathieu-Daudé +# +# This work is licensed under the terms of the GNU GPL, version 2 or +# later. See the COPYING file in the top-level directory. + +from qemu_test import QemuSystemTest, Asset +from qemu_test import wait_for_console_pattern, skipUntrustedTest +from qemu_test import exec_command_and_wait_for_pattern + + +class IbmPrep40pMachine(QemuSystemTest): + + timeout = 60 + + ASSET_BIOS = Asset( + ('http://ftpmirror.your.org/pub/misc/' + 'ftp.software.ibm.com/rs6000/firmware/' + '7020-40p/P12H0456.IMG'), + 'd957f79c73f760d1455d2286fcd901ed6d06167320eb73511b478a939be25b3f') + ASSET_NETBSD40 = Asset( + ('https://archive.netbsd.org/pub/NetBSD-archive/' + 'NetBSD-4.0/prep/installation/floppy/generic_com0.fs'), + 'f86236e9d01b3f0dd0f5d3b8d5bbd40c68e78b4db560a108358f5ad58e636619') + ASSET_NETBSD71 = Asset( + ('https://archive.netbsd.org/pub/NetBSD-archive/' + 'NetBSD-7.1.2/iso/NetBSD-7.1.2-prep.iso'), + 'cc7cb290b06aaa839362deb7bd9f417ac5015557db24088508330f76c3f825ec') + + # 12H0455 PPS Firmware Licensed Materials + # Property of IBM (C) Copyright IBM Corp. 1994. + # All rights reserved. + # U.S. Government Users Restricted Rights - Use, duplication or disclosure + # restricted by GSA ADP Schedule Contract with IBM Corp. + @skipUntrustedTest() + def test_factory_firmware_and_netbsd(self): + self.set_machine('40p') + self.require_accelerator("tcg") + bios_path = self.ASSET_BIOS.fetch() + drive_path = self.ASSET_NETBSD40.fetch() + + self.vm.set_console() + self.vm.add_args('-bios', bios_path, + '-drive', + f"file={drive_path},format=raw,if=floppy,read-only=true") + self.vm.launch() + os_banner = 'NetBSD 4.0 (GENERIC) #0: Sun Dec 16 00:49:40 PST 2007' + wait_for_console_pattern(self, os_banner) + wait_for_console_pattern(self, 'Model: IBM PPS Model 6015') + + def test_openbios_192m(self): + self.set_machine('40p') + self.require_accelerator("tcg") + self.vm.set_console() + self.vm.add_args('-m', '192') # test fw_cfg + + self.vm.launch() + wait_for_console_pattern(self, '>> OpenBIOS') + wait_for_console_pattern(self, '>> Memory: 192M') + wait_for_console_pattern(self, '>> CPU type PowerPC,604') + + def test_openbios_and_netbsd(self): + self.set_machine('40p') + self.require_accelerator("tcg") + drive_path = self.ASSET_NETBSD71.fetch() + self.vm.set_console() + self.vm.add_args('-cdrom', drive_path, + '-boot', 'd') + + self.vm.launch() + wait_for_console_pattern(self, 'NetBSD/prep BOOT, Revision 1.9') + + ASSET_40P_SANDALFOOT = Asset( + 'http://www.juneau-lug.org/zImage.initrd.sandalfoot', + '749ab02f576c6dc8f33b9fb022ecb44bf6a35a0472f2ea6a5e9956bc15933901') + + def test_openbios_and_linux(self): + self.set_machine('40p') + self.require_accelerator("tcg") + drive_path = self.ASSET_40P_SANDALFOOT.fetch() + self.vm.set_console() + self.vm.add_args('-cdrom', drive_path, + '-boot', 'd') + + self.vm.launch() + wait_for_console_pattern(self, 'Please press Enter to activate this console.') + exec_command_and_wait_for_pattern(self, '\012', '#') + exec_command_and_wait_for_pattern(self, 'uname -a', 'Linux ppc 2.4.18') + +if __name__ == '__main__': + QemuSystemTest.main() diff --git a/tests/functional/ppc/test_74xx.py b/tests/functional/ppc/test_74xx.py new file mode 100755 index 0000000..5386016 --- /dev/null +++ b/tests/functional/ppc/test_74xx.py @@ -0,0 +1,126 @@ +#!/usr/bin/env python3 +# +# Smoke tests for 74xx cpus (aka G4). +# +# Copyright (c) 2021, IBM Corp. +# +# This work is licensed under the terms of the GNU GPL, version 2 or +# later. See the COPYING file in the top-level directory. + +from qemu_test import QemuSystemTest +from qemu_test import wait_for_console_pattern + +class ppc74xxCpu(QemuSystemTest): + + timeout = 5 + + def test_ppc_7400(self): + self.require_accelerator("tcg") + self.set_machine('g3beige') + self.vm.set_console() + self.vm.add_args('-cpu', '7400') + self.vm.launch() + wait_for_console_pattern(self, '>> OpenBIOS') + wait_for_console_pattern(self, '>> CPU type PowerPC,G4') + + def test_ppc_7410(self): + self.require_accelerator("tcg") + self.set_machine('g3beige') + self.vm.set_console() + self.vm.add_args('-cpu', '7410') + self.vm.launch() + wait_for_console_pattern(self, '>> OpenBIOS') + wait_for_console_pattern(self, '>> CPU type PowerPC,74xx') + + def test_ppc_7441(self): + self.require_accelerator("tcg") + self.set_machine('g3beige') + self.vm.set_console() + self.vm.add_args('-cpu', '7441') + self.vm.launch() + wait_for_console_pattern(self, '>> OpenBIOS') + wait_for_console_pattern(self, '>> CPU type PowerPC,G4') + + def test_ppc_7445(self): + self.require_accelerator("tcg") + self.set_machine('g3beige') + self.vm.set_console() + self.vm.add_args('-cpu', '7445') + self.vm.launch() + wait_for_console_pattern(self, '>> OpenBIOS') + wait_for_console_pattern(self, '>> CPU type PowerPC,G4') + + def test_ppc_7447(self): + self.require_accelerator("tcg") + self.set_machine('g3beige') + self.vm.set_console() + self.vm.add_args('-cpu', '7447') + self.vm.launch() + wait_for_console_pattern(self, '>> OpenBIOS') + wait_for_console_pattern(self, '>> CPU type PowerPC,G4') + + def test_ppc_7447a(self): + self.require_accelerator("tcg") + self.set_machine('g3beige') + self.vm.set_console() + self.vm.add_args('-cpu', '7447a') + self.vm.launch() + wait_for_console_pattern(self, '>> OpenBIOS') + wait_for_console_pattern(self, '>> CPU type PowerPC,G4') + + def test_ppc_7448(self): + self.require_accelerator("tcg") + self.set_machine('g3beige') + self.vm.set_console() + self.vm.add_args('-cpu', '7448') + self.vm.launch() + wait_for_console_pattern(self, '>> OpenBIOS') + wait_for_console_pattern(self, '>> CPU type PowerPC,MPC86xx') + + def test_ppc_7450(self): + self.require_accelerator("tcg") + self.set_machine('g3beige') + self.vm.set_console() + self.vm.add_args('-cpu', '7450') + self.vm.launch() + wait_for_console_pattern(self, '>> OpenBIOS') + wait_for_console_pattern(self, '>> CPU type PowerPC,G4') + + def test_ppc_7451(self): + self.require_accelerator("tcg") + self.set_machine('g3beige') + self.vm.set_console() + self.vm.add_args('-cpu', '7451') + self.vm.launch() + wait_for_console_pattern(self, '>> OpenBIOS') + wait_for_console_pattern(self, '>> CPU type PowerPC,G4') + + def test_ppc_7455(self): + self.require_accelerator("tcg") + self.set_machine('g3beige') + self.vm.set_console() + self.vm.add_args('-cpu', '7455') + self.vm.launch() + wait_for_console_pattern(self, '>> OpenBIOS') + wait_for_console_pattern(self, '>> CPU type PowerPC,G4') + + def test_ppc_7457(self): + self.require_accelerator("tcg") + self.set_machine('g3beige') + self.vm.set_console() + self.vm.add_args('-cpu', '7457') + self.vm.launch() + wait_for_console_pattern(self, '>> OpenBIOS') + wait_for_console_pattern(self, '>> CPU type PowerPC,G4') + + def test_ppc_7457a(self): + self.require_accelerator("tcg") + self.set_machine('g3beige') + self.vm.set_console() + self.vm.add_args('-cpu', '7457a') + self.vm.launch() + wait_for_console_pattern(self, '>> OpenBIOS') + wait_for_console_pattern(self, '>> CPU type PowerPC,G4') + +if __name__ == '__main__': + QemuSystemTest.main() diff --git a/tests/functional/ppc/test_amiga.py b/tests/functional/ppc/test_amiga.py new file mode 100755 index 0000000..8600e2e --- /dev/null +++ b/tests/functional/ppc/test_amiga.py @@ -0,0 +1,43 @@ +#!/usr/bin/env python3 +# +# Test AmigaNG boards +# +# Copyright (c) 2023 BALATON Zoltan +# +# This work is licensed under the terms of the GNU GPL, version 2 or +# later. See the COPYING file in the top-level directory. + +import subprocess + +from qemu_test import QemuSystemTest, Asset +from qemu_test import wait_for_console_pattern + + +class AmigaOneMachine(QemuSystemTest): + + timeout = 90 + + ASSET_IMAGE = Asset( + ('https://www.hyperion-entertainment.com/index.php/' + 'downloads?view=download&format=raw&file=25'), + '8ff39330ba47d4f64de4ee8fd6809e9c010a9ef17fe51e95c3c1d53437cb481f') + + def test_ppc_amigaone(self): + self.require_accelerator("tcg") + self.set_machine('amigaone') + tar_name = 'A1Firmware_Floppy_05-Mar-2005.zip' + self.archive_extract(self.ASSET_IMAGE, format="zip") + bios = self.scratch_file("u-boot-amigaone.bin") + with open(bios, "wb") as bios_fh: + subprocess.run(['tail', '-c', '524288', + self.scratch_file("floppy_edition", + "updater.image")], + stdout=bios_fh) + + self.vm.set_console() + self.vm.add_args('-bios', bios) + self.vm.launch() + wait_for_console_pattern(self, 'FLASH:') + +if __name__ == '__main__': + QemuSystemTest.main() diff --git a/tests/functional/ppc/test_bamboo.py b/tests/functional/ppc/test_bamboo.py new file mode 100755 index 0000000..c634ae7 --- /dev/null +++ b/tests/functional/ppc/test_bamboo.py @@ -0,0 +1,48 @@ +#!/usr/bin/env python3 +# +# Test that Linux kernel boots on the ppc bamboo board and check the console +# +# Copyright (c) 2021 Red Hat +# +# This work is licensed under the terms of the GNU GPL, version 2 or +# later. See the COPYING file in the top-level directory. + +from qemu_test import QemuSystemTest, Asset +from qemu_test import wait_for_console_pattern +from qemu_test import exec_command_and_wait_for_pattern + + +class BambooMachine(QemuSystemTest): + + timeout = 90 + + ASSET_KERNEL = Asset( + ('https://github.com/legoater/qemu-ppc-boot/raw/refs/heads/main/' + 'buildroot/qemu_ppc_bamboo-2023.11-8-gdcd9f0f6eb-20240105/vmlinux'), + 'a2e12eb45b73491ac62fc0bbeb68dead0dc5c0f22cf83146558389209b420ad1') + ASSET_INITRD = Asset( + ('https://github.com/legoater/qemu-ppc-boot/raw/refs/heads/main/' + 'buildroot/qemu_ppc_bamboo-2023.11-8-gdcd9f0f6eb-20240105/rootfs.cpio'), + 'd2a36bdb8763b389765dc8c29d4904cec2bd001c587f92e85ab9eb10d5ddda54') + + def test_ppc_bamboo(self): + self.set_machine('bamboo') + self.require_accelerator("tcg") + self.require_netdev('user') + + kernel = self.ASSET_KERNEL.fetch() + initrd = self.ASSET_INITRD.fetch() + + self.vm.set_console() + self.vm.add_args('-kernel', kernel, + '-initrd', initrd, + '-nic', 'user,model=virtio-net-pci,restrict=on') + self.vm.launch() + wait_for_console_pattern(self, 'buildroot login:') + exec_command_and_wait_for_pattern(self, 'root', '#') + exec_command_and_wait_for_pattern(self, 'ping -c1 10.0.2.2', + '1 packets transmitted, 1 packets received, 0% packet loss') + exec_command_and_wait_for_pattern(self, 'halt', 'System Halted') + +if __name__ == '__main__': + QemuSystemTest.main() diff --git a/tests/functional/ppc/test_mac.py b/tests/functional/ppc/test_mac.py new file mode 100755 index 0000000..9e4bc1a --- /dev/null +++ b/tests/functional/ppc/test_mac.py @@ -0,0 +1,36 @@ +#!/usr/bin/env python3 +# +# Boot Linux kernel on a mac99 and g3beige ppc machine and check the console +# +# SPDX-License-Identifier: GPL-2.0-or-later + +from qemu_test import LinuxKernelTest, Asset + + +class MacTest(LinuxKernelTest): + + ASSET_DAY15 = Asset( + 'https://qemu-advcal.gitlab.io/qac-best-of-multiarch/download/day15.tar.xz', + '03e0757c131d2959decf293a3572d3b96c5a53587165bf05ce41b2818a2bccd5') + + def do_day15_test(self): + # mac99 also works with kvm_pr but we don't have a reliable way at + # the moment (e.g. by looking at /proc/modules) to detect whether + # we're running kvm_hv or kvm_pr. For now let's disable this test + # if we don't have TCG support. + self.require_accelerator("tcg") + self.archive_extract(self.ASSET_DAY15) + self.vm.add_args('-M', 'graphics=off') + self.launch_kernel(self.scratch_file('day15', 'invaders.elf'), + wait_for='QEMU advent calendar') + + def test_ppc_g3beige(self): + self.set_machine('g3beige') + self.do_day15_test() + + def test_ppc_mac99(self): + self.set_machine('mac99') + self.do_day15_test() + +if __name__ == '__main__': + LinuxKernelTest.main() diff --git a/tests/functional/ppc/test_migration.py b/tests/functional/ppc/test_migration.py new file mode 100755 index 0000000..a869282 --- /dev/null +++ b/tests/functional/ppc/test_migration.py @@ -0,0 +1,26 @@ +#!/usr/bin/env python3 +# +# SPDX-License-Identifier: GPL-2.0-or-later +# +# ppc migration test + +from migration import MigrationTest + + +class PpcMigrationTest(MigrationTest): + + def test_migration_with_tcp_localhost(self): + self.set_machine('sam460ex') + self.migration_with_tcp_localhost() + + def test_migration_with_unix(self): + self.set_machine('sam460ex') + self.migration_with_unix() + + def test_migration_with_exec(self): + self.set_machine('sam460ex') + self.migration_with_exec() + + +if __name__ == '__main__': + MigrationTest.main() diff --git a/tests/functional/ppc/test_mpc8544ds.py b/tests/functional/ppc/test_mpc8544ds.py new file mode 100755 index 0000000..0715410 --- /dev/null +++ b/tests/functional/ppc/test_mpc8544ds.py @@ -0,0 +1,37 @@ +#!/usr/bin/env python3 +# +# Test that Linux kernel boots on ppc machines and check the console +# +# Copyright (c) 2018, 2020 Red Hat, Inc. +# +# This work is licensed under the terms of the GNU GPL, version 2 or +# later. See the COPYING file in the top-level directory. + +from qemu_test import QemuSystemTest, Asset +from qemu_test import wait_for_console_pattern + + +class Mpc8544dsMachine(QemuSystemTest): + + timeout = 90 + KERNEL_COMMON_COMMAND_LINE = 'printk.time=0 ' + panic_message = 'Kernel panic - not syncing' + + ASSET_IMAGE = Asset( + ('https://qemu-advcal.gitlab.io/qac-best-of-multiarch/download/' + 'day04.tar.xz'), + '88bc83f3c9f3d633bcfc108a6342d677abca247066a2fb8d4636744a0d319f94') + + def test_ppc_mpc8544ds(self): + self.require_accelerator("tcg") + self.set_machine('mpc8544ds') + kernel_file = self.archive_extract(self.ASSET_IMAGE, + member='creek/creek.bin') + self.vm.set_console() + self.vm.add_args('-kernel', kernel_file) + self.vm.launch() + wait_for_console_pattern(self, 'QEMU advent calendar 2020', + self.panic_message) + +if __name__ == '__main__': + QemuSystemTest.main() diff --git a/tests/functional/ppc/test_replay.py b/tests/functional/ppc/test_replay.py new file mode 100755 index 0000000..8382070 --- /dev/null +++ b/tests/functional/ppc/test_replay.py @@ -0,0 +1,34 @@ +#!/usr/bin/env python3 +# +# Replay tests for ppc machines +# +# SPDX-License-Identifier: GPL-2.0-or-later + +from qemu_test import Asset +from replay_kernel import ReplayKernelBase + + +class PpcReplay(ReplayKernelBase): + + ASSET_DAY15 = Asset( + 'https://qemu-advcal.gitlab.io/qac-best-of-multiarch/download/day15.tar.xz', + '03e0757c131d2959decf293a3572d3b96c5a53587165bf05ce41b2818a2bccd5') + + def do_day15_test(self): + self.require_accelerator("tcg") + kernel_path = self.archive_extract(self.ASSET_DAY15, + member='day15/invaders.elf') + self.run_rr(kernel_path, self.REPLAY_KERNEL_COMMAND_LINE, + 'QEMU advent calendar', args=('-M', 'graphics=off')) + + def test_g3beige(self): + self.set_machine('g3beige') + self.do_day15_test() + + def test_mac99(self): + self.set_machine('mac99') + self.do_day15_test() + + +if __name__ == '__main__': + ReplayKernelBase.main() diff --git a/tests/functional/ppc/test_sam460ex.py b/tests/functional/ppc/test_sam460ex.py new file mode 100755 index 0000000..31cf9dd --- /dev/null +++ b/tests/functional/ppc/test_sam460ex.py @@ -0,0 +1,38 @@ +#!/usr/bin/env python3 +# +# Functional test that boots a sam460ex machine with a PPC 460EX CPU +# +# SPDX-License-Identifier: GPL-2.0-or-later + +from qemu_test import LinuxKernelTest, Asset +from qemu_test import exec_command_and_wait_for_pattern + + +class sam460exTest(LinuxKernelTest): + + ASSET_BR2_SAM460EX_LINUX = Asset( + 'https://github.com/legoater/qemu-ppc-boot/raw/refs/heads/main/buildroot/qemu_ppc_sam460ex-2023.11-8-gdcd9f0f6eb-20240105/vmlinux', + '6f46346f3e20e8b5fc050ff363f350f8b9d76a051b9e0bd7ea470cc680c14df2') + + def test_ppc_sam460ex_buildroot(self): + self.set_machine('sam460ex') + self.require_netdev('user') + + linux_path = self.ASSET_BR2_SAM460EX_LINUX.fetch() + + self.vm.set_console() + self.vm.add_args('-kernel', linux_path, + '-device', 'virtio-net-pci,netdev=net0', + '-netdev', 'user,id=net0') + self.vm.launch() + + self.wait_for_console_pattern('Linux version') + self.wait_for_console_pattern('Hardware name: amcc,canyonlands 460EX') + self.wait_for_console_pattern('/init as init process') + self.wait_for_console_pattern('lease of 10.0.2.15 obtained') + self.wait_for_console_pattern('buildroot login:') + exec_command_and_wait_for_pattern(self, 'root', '#') + exec_command_and_wait_for_pattern(self, 'poweroff', 'System Halted') + +if __name__ == '__main__': + LinuxKernelTest.main() diff --git a/tests/functional/ppc/test_tuxrun.py b/tests/functional/ppc/test_tuxrun.py new file mode 100755 index 0000000..5458a7f --- /dev/null +++ b/tests/functional/ppc/test_tuxrun.py @@ -0,0 +1,35 @@ +#!/usr/bin/env python3 +# +# Functional test that boots known good tuxboot images the same way +# that tuxrun (www.tuxrun.org) does. This tool is used by things like +# the LKFT project to run regression tests on kernels. +# +# Copyright (c) 2023 Linaro Ltd. +# +# Author: +# Alex Bennée +# +# SPDX-License-Identifier: GPL-2.0-or-later + +from qemu_test import Asset +from qemu_test.tuxruntest import TuxRunBaselineTest + +class TuxRunPPC32Test(TuxRunBaselineTest): + + ASSET_PPC32_KERNEL = Asset( + 'https://storage.tuxboot.com/buildroot/20241119/ppc32/uImage', + 'aa5d81deabdb255a318c4bc5ffd6fdd2b5da1ef39f1955dcc35b671d258b68e9') + ASSET_PPC32_ROOTFS = Asset( + 'https://storage.tuxboot.com/buildroot/20241119/ppc32/rootfs.ext4.zst', + '67554f830269d6bf53b67c7dd206bcc821e463993d526b1644066fea8117019b') + + def test_ppc32(self): + self.set_machine('ppce500') + self.cpu='e500mc' + self.wait_for_shutdown=False + self.common_tuxrun(kernel_asset=self.ASSET_PPC32_KERNEL, + rootfs_asset=self.ASSET_PPC32_ROOTFS, + drive="virtio-blk-pci") + +if __name__ == '__main__': + TuxRunBaselineTest.main() diff --git a/tests/functional/ppc/test_virtex_ml507.py b/tests/functional/ppc/test_virtex_ml507.py new file mode 100755 index 0000000..8fe4354 --- /dev/null +++ b/tests/functional/ppc/test_virtex_ml507.py @@ -0,0 +1,39 @@ +#!/usr/bin/env python3 +# +# Test that Linux kernel boots on ppc machines and check the console +# +# Copyright (c) 2018, 2020 Red Hat, Inc. +# +# This work is licensed under the terms of the GNU GPL, version 2 or +# later. See the COPYING file in the top-level directory. + +from qemu_test import QemuSystemTest, Asset +from qemu_test import wait_for_console_pattern + + +class VirtexMl507Machine(QemuSystemTest): + + timeout = 90 + KERNEL_COMMON_COMMAND_LINE = 'printk.time=0 ' + panic_message = 'Kernel panic - not syncing' + + ASSET_IMAGE = Asset( + ('https://qemu-advcal.gitlab.io/qac-best-of-multiarch/download/' + 'day08.tar.xz'), + 'cefe5b8aeb5e9d2d1d4fd22dcf48d917d68d5a765132bf2ddd6332dc393b824c') + + def test_ppc_virtex_ml507(self): + self.require_accelerator("tcg") + self.set_machine('virtex-ml507') + self.archive_extract(self.ASSET_IMAGE) + self.vm.set_console() + self.vm.add_args('-kernel', self.scratch_file('hippo', 'hippo.linux'), + '-dtb', self.scratch_file('hippo', + 'virtex440-ml507.dtb'), + '-m', '512') + self.vm.launch() + wait_for_console_pattern(self, 'QEMU advent calendar 2020', + self.panic_message) + +if __name__ == '__main__': + QemuSystemTest.main() diff --git a/tests/functional/ppc64/meson.build b/tests/functional/ppc64/meson.build new file mode 100644 index 0000000..842fe0f --- /dev/null +++ b/tests/functional/ppc64/meson.build @@ -0,0 +1,25 @@ +# SPDX-License-Identifier: GPL-2.0-or-later + +test_ppc64_timeouts = { + 'hv' : 1000, + 'mac99' : 120, + 'powernv' : 480, + 'pseries' : 480, + 'replay' : 210, + 'tuxrun' : 420, +} + +tests_ppc64_system_quick = [ + 'migration', +] + +tests_ppc64_system_thorough = [ + 'e500', + 'hv', + 'mac99', + 'powernv', + 'pseries', + 'replay', + 'reverse_debug', + 'tuxrun', +] diff --git a/tests/functional/ppc64/test_e500.py b/tests/functional/ppc64/test_e500.py new file mode 100755 index 0000000..f5fcad9 --- /dev/null +++ b/tests/functional/ppc64/test_e500.py @@ -0,0 +1,44 @@ +#!/usr/bin/env python3 +# +# Boot a Linux kernel on a e500 ppc64 machine and check the console +# +# SPDX-License-Identifier: GPL-2.0-or-later + +from qemu_test import LinuxKernelTest, Asset +from qemu_test import exec_command_and_wait_for_pattern + + +class E500Test(LinuxKernelTest): + + ASSET_BR2_E5500_UIMAGE = Asset( + 'https://github.com/legoater/qemu-ppc-boot/raw/refs/heads/main/buildroot/qemu_ppc64_e5500-2023.11-8-gdcd9f0f6eb-20240104/uImage', + '2478187c455d6cca3984e9dfde9c635d824ea16236b85fd6b4809f744706deda') + + ASSET_BR2_E5500_ROOTFS = Asset( + 'https://github.com/legoater/qemu-ppc-boot/raw/refs/heads/main//buildroot/qemu_ppc64_e5500-2023.11-8-gdcd9f0f6eb-20240104/rootfs.ext2', + '9035ef97237c84c7522baaff17d25cdfca4bb7a053d5e296e902919473423d76') + + def test_ppc64_e500_buildroot(self): + self.set_machine('ppce500') + self.require_netdev('user') + self.cpu = 'e5500' + + uimage_path = self.ASSET_BR2_E5500_UIMAGE.fetch() + rootfs_path = self.ASSET_BR2_E5500_ROOTFS.fetch() + + self.vm.set_console() + self.vm.add_args('-kernel', uimage_path, + '-append', 'root=/dev/vda', + '-drive', f'file={rootfs_path},if=virtio,format=raw', + '-snapshot', '-no-shutdown') + self.vm.launch() + + self.wait_for_console_pattern('Linux version') + self.wait_for_console_pattern('/init as init process') + self.wait_for_console_pattern('lease of 10.0.2.15') + self.wait_for_console_pattern('buildroot login:') + exec_command_and_wait_for_pattern(self, 'root', '#') + exec_command_and_wait_for_pattern(self, 'poweroff', 'Power down') + +if __name__ == '__main__': + LinuxKernelTest.main() diff --git a/tests/functional/ppc64/test_hv.py b/tests/functional/ppc64/test_hv.py new file mode 100755 index 0000000..d87f440 --- /dev/null +++ b/tests/functional/ppc64/test_hv.py @@ -0,0 +1,165 @@ +#!/usr/bin/env python3 +# +# Tests that specifically try to exercise hypervisor features of the +# target machines. powernv supports the Power hypervisor ISA, and +# pseries supports the nested-HV hypervisor spec. +# +# Copyright (c) 2023 IBM Corporation +# +# This work is licensed under the terms of the GNU GPL, version 2 or +# later. See the COPYING file in the top-level directory. + +import os +import subprocess + +from datetime import datetime +from qemu_test import QemuSystemTest, Asset +from qemu_test import wait_for_console_pattern, exec_command +from qemu_test import skipIfMissingCommands, skipBigDataTest +from qemu_test import exec_command_and_wait_for_pattern + +# Alpine is a light weight distro that supports QEMU. These tests boot +# that on the machine then run a QEMU guest inside it in KVM mode, +# that runs the same Alpine distro image. +# QEMU packages are downloaded and installed on each test. That's not a +# large download, but it may be more polite to create qcow2 image with +# QEMU already installed and use that. +# XXX: The order of these tests seems to matter, see git blame. +@skipIfMissingCommands("xorriso") +@skipBigDataTest() +class HypervisorTest(QemuSystemTest): + + timeout = 1000 + KERNEL_COMMON_COMMAND_LINE = 'printk.time=0 console=hvc0 ' + panic_message = 'Kernel panic - not syncing' + good_message = 'VFS: Cannot open root device' + + ASSET_ISO = Asset( + ('https://dl-cdn.alpinelinux.org/alpine/v3.21/' + 'releases/ppc64le/alpine-standard-3.21.0-ppc64le.iso'), + '7651ab4e3027604535c0b36e86c901b4695bf8fe97b908f5b48590f6baae8f30') + + def extract_from_iso(self, iso, path): + """ + Extracts a file from an iso file into the test workdir + + :param iso: path to the iso file + :param path: path within the iso file of the file to be extracted + :returns: path of the extracted file + """ + filename = self.scratch_file(os.path.basename(path)) + + cmd = "xorriso -osirrox on -indev %s -cpx %s %s" % (iso, path, filename) + subprocess.run(cmd.split(), + stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) + + os.chmod(filename, 0o600) + + return filename + + def setUp(self): + super().setUp() + + self.iso_path = self.ASSET_ISO.fetch() + self.vmlinuz = self.extract_from_iso(self.iso_path, '/boot/vmlinuz-lts') + self.initramfs = self.extract_from_iso(self.iso_path, '/boot/initramfs-lts') + + def do_start_alpine(self): + self.vm.set_console() + kernel_command_line = self.KERNEL_COMMON_COMMAND_LINE + self.vm.add_args("-kernel", self.vmlinuz) + self.vm.add_args("-initrd", self.initramfs) + self.vm.add_args("-smp", "4", "-m", "2g") + self.vm.add_args("-drive", f"file={self.iso_path},format=raw,if=none," + "id=drive0,read-only=true") + + self.vm.launch() + ps1='localhost:~#' + wait_for_console_pattern(self, 'localhost login:') + exec_command_and_wait_for_pattern(self, 'root', ps1) + # If the time is wrong, SSL certificates can fail. + exec_command_and_wait_for_pattern(self, 'date -s "' + datetime.utcnow().strftime('%Y-%m-%d %H:%M:%S' + '"'), ps1) + ps1='alpine:~#' + exec_command_and_wait_for_pattern(self, 'setup-alpine -qe', ps1) + exec_command_and_wait_for_pattern(self, 'setup-apkrepos -c1', ps1) + exec_command_and_wait_for_pattern(self, 'apk update', ps1) + # Could upgrade here but it usually should not be necessary + # exec_command_and_wait_for_pattern(self, 'apk upgrade --available', ps1) + + def do_stop_alpine(self): + exec_command(self, 'echo "TEST ME"') + wait_for_console_pattern(self, 'alpine:~#') + exec_command(self, 'poweroff') + wait_for_console_pattern(self, 'reboot: Power down') + self.vm.wait() + + def do_setup_kvm(self): + ps1='alpine:~#' + exec_command_and_wait_for_pattern(self, 'apk add qemu-system-ppc64', ps1) + exec_command_and_wait_for_pattern(self, 'modprobe kvm-hv', ps1) + + # This uses the host's block device as the source file for guest block + # device for install media. This is a bit hacky but allows reuse of the + # iso without having a passthrough filesystem configured. + def do_test_kvm(self, hpt=False): + if hpt: + append = 'disable_radix' + else: + append = '' + exec_command(self, 'qemu-system-ppc64 -nographic -smp 2 -m 1g ' + '-machine pseries,x-vof=on,accel=kvm ' + '-machine cap-cfpc=broken,cap-sbbc=broken,' + 'cap-ibs=broken,cap-ccf-assist=off ' + '-drive file=/dev/nvme0n1,format=raw,readonly=on ' + '-initrd /media/nvme0n1/boot/initramfs-lts ' + '-kernel /media/nvme0n1/boot/vmlinuz-lts ' + '-append \'usbcore.nousb ' + append + '\'') + # Alpine 3.21 kernel seems to crash in XHCI USB driver. + ps1='localhost:~#' + wait_for_console_pattern(self, 'localhost login:') + exec_command_and_wait_for_pattern(self, 'root', ps1) + exec_command(self, 'poweroff') + wait_for_console_pattern(self, 'reboot: Power down') + # Now wait for the host's prompt to come back + wait_for_console_pattern(self, 'alpine:~#') + + def test_hv_pseries(self): + self.require_accelerator("tcg") + self.require_netdev('user') + self.set_machine('pseries') + self.vm.add_args("-accel", "tcg,thread=multi") + self.vm.add_args('-device', 'nvme,serial=1234,drive=drive0') + self.vm.add_args("-machine", "x-vof=on,cap-nested-hv=on") + self.do_start_alpine() + self.do_setup_kvm() + self.do_test_kvm() + self.do_stop_alpine() + + def test_hv_pseries_kvm(self): + self.require_accelerator("kvm") + self.require_netdev('user') + self.set_machine('pseries') + self.vm.add_args("-accel", "kvm") + self.vm.add_args('-device', 'nvme,serial=1234,drive=drive0') + self.vm.add_args("-machine", "x-vof=on,cap-nested-hv=on,cap-ccf-assist=off") + self.do_start_alpine() + self.do_setup_kvm() + self.do_test_kvm() + self.do_stop_alpine() + + def test_hv_powernv(self): + self.require_accelerator("tcg") + self.require_netdev('user') + self.set_machine('powernv') + self.vm.add_args("-accel", "tcg,thread=multi") + self.vm.add_args('-device', 'nvme,bus=pcie.2,addr=0x0,serial=1234,drive=drive0', + '-device', 'e1000e,netdev=net0,mac=C0:FF:EE:00:00:02,bus=pcie.0,addr=0x0', + '-netdev', 'user,id=net0,hostfwd=::20022-:22,hostname=alpine') + self.do_start_alpine() + self.do_setup_kvm() + self.do_test_kvm() + self.do_test_kvm(True) + self.do_stop_alpine() + +if __name__ == '__main__': + QemuSystemTest.main() diff --git a/tests/functional/ppc64/test_mac99.py b/tests/functional/ppc64/test_mac99.py new file mode 100755 index 0000000..dfd9c01 --- /dev/null +++ b/tests/functional/ppc64/test_mac99.py @@ -0,0 +1,44 @@ +#!/usr/bin/env python3 +# +# Functional test that boots a mac99 machine with a PPC970 CPU +# +# SPDX-License-Identifier: GPL-2.0-or-later + +from qemu_test import LinuxKernelTest, Asset +from qemu_test import exec_command_and_wait_for_pattern + +class mac99Test(LinuxKernelTest): + + ASSET_BR2_MAC99_LINUX = Asset( + 'https://github.com/legoater/qemu-ppc-boot/raw/refs/heads/main/buildroot/qemu_ppc64_mac99-2023.11-8-gdcd9f0f6eb-20240105/vmlinux', + 'd59307437e4365f2cced0bbd1b04949f7397b282ef349b7cafd894d74aadfbff') + + ASSET_BR2_MAC99_ROOTFS = Asset( + 'https://github.com/legoater/qemu-ppc-boot/raw/refs/heads/main//buildroot/qemu_ppc64_mac99-2023.11-8-gdcd9f0f6eb-20240105/rootfs.ext2', + 'bbd5fd8af62f580bc4e585f326fe584e22856572633a8333178ea6d4ed4955a4') + + def test_ppc64_mac99_buildroot(self): + self.set_machine('mac99') + + linux_path = self.ASSET_BR2_MAC99_LINUX.fetch() + rootfs_path = self.ASSET_BR2_MAC99_ROOTFS.fetch() + + self.vm.set_console() + + # Note: We need '-nographic' to get a serial console + self.vm.add_args('-kernel', linux_path, + '-append', 'root=/dev/sda', + '-drive', f'file={rootfs_path},format=raw', + '-snapshot', '-nographic') + self.vm.launch() + + self.wait_for_console_pattern('>> OpenBIOS') + self.wait_for_console_pattern('Linux version') + self.wait_for_console_pattern('/init as init process') + self.wait_for_console_pattern('gem 0000:f0:0e.0 eth0: Link is up at 100 Mbps') + self.wait_for_console_pattern('buildroot login:') + exec_command_and_wait_for_pattern(self, 'root', '#') + exec_command_and_wait_for_pattern(self, 'poweroff', 'Power down') + +if __name__ == '__main__': + LinuxKernelTest.main() diff --git a/tests/functional/ppc64/test_migration.py b/tests/functional/ppc64/test_migration.py new file mode 100755 index 0000000..5dfdaaf --- /dev/null +++ b/tests/functional/ppc64/test_migration.py @@ -0,0 +1,26 @@ +#!/usr/bin/env python3 +# +# SPDX-License-Identifier: GPL-2.0-or-later +# +# ppc migration test + +from migration import MigrationTest + + +class PpcMigrationTest(MigrationTest): + + def test_migration_with_tcp_localhost(self): + self.set_machine('mac99') + self.migration_with_tcp_localhost() + + def test_migration_with_unix(self): + self.set_machine('mac99') + self.migration_with_unix() + + def test_migration_with_exec(self): + self.set_machine('mac99') + self.migration_with_exec() + + +if __name__ == '__main__': + MigrationTest.main() diff --git a/tests/functional/ppc64/test_powernv.py b/tests/functional/ppc64/test_powernv.py new file mode 100755 index 0000000..685e217 --- /dev/null +++ b/tests/functional/ppc64/test_powernv.py @@ -0,0 +1,118 @@ +#!/usr/bin/env python3 +# +# Test that Linux kernel boots on ppc powernv machines and check the console +# +# Copyright (c) 2018, 2020 Red Hat, Inc. +# +# This work is licensed under the terms of the GNU GPL, version 2 or +# later. See the COPYING file in the top-level directory. + +from qemu_test import LinuxKernelTest, Asset +from qemu_test import wait_for_console_pattern + +class powernvMachine(LinuxKernelTest): + + timeout = 90 + KERNEL_COMMON_COMMAND_LINE = 'printk.time=0 console=hvc0 ' + panic_message = 'Kernel panic - not syncing' + good_message = 'VFS: Cannot open root device' + + ASSET_KERNEL = Asset( + ('https://archives.fedoraproject.org/pub/archive/fedora-secondary/' + 'releases/29/Everything/ppc64le/os/ppc/ppc64/vmlinuz'), + '383c2f5c23bc0d9d32680c3924d3fd7ee25cc5ef97091ac1aa5e1d853422fc5f') + + def do_test_linux_boot(self, command_line = KERNEL_COMMON_COMMAND_LINE): + self.require_accelerator("tcg") + kernel_path = self.ASSET_KERNEL.fetch() + + self.vm.set_console() + self.vm.add_args('-kernel', kernel_path, + '-append', command_line) + self.vm.launch() + + def test_linux_boot(self): + self.set_machine('powernv') + self.do_test_linux_boot() + console_pattern = 'VFS: Cannot open root device' + wait_for_console_pattern(self, console_pattern, self.panic_message) + + def test_linux_smp_boot(self): + self.set_machine('powernv') + self.vm.add_args('-smp', '4') + self.do_test_linux_boot() + console_pattern = 'smp: Brought up 1 node, 4 CPUs' + wait_for_console_pattern(self, console_pattern, self.panic_message) + wait_for_console_pattern(self, self.good_message, self.panic_message) + + def test_linux_smp_hpt_boot(self): + self.set_machine('powernv') + self.vm.add_args('-smp', '4') + self.do_test_linux_boot(self.KERNEL_COMMON_COMMAND_LINE + + 'disable_radix') + console_pattern = 'smp: Brought up 1 node, 4 CPUs' + wait_for_console_pattern(self, 'hash-mmu: Initializing hash mmu', + self.panic_message) + wait_for_console_pattern(self, console_pattern, self.panic_message) + wait_for_console_pattern(self, self.good_message, self.panic_message) + + def test_linux_smt_boot(self): + self.set_machine('powernv') + self.vm.add_args('-smp', '4,threads=4') + self.do_test_linux_boot() + console_pattern = 'CPU maps initialized for 4 threads per core' + wait_for_console_pattern(self, console_pattern, self.panic_message) + console_pattern = 'smp: Brought up 1 node, 4 CPUs' + wait_for_console_pattern(self, console_pattern, self.panic_message) + wait_for_console_pattern(self, self.good_message, self.panic_message) + + def test_linux_big_boot(self): + self.set_machine('powernv') + self.vm.add_args('-smp', '16,threads=4,cores=2,sockets=2') + + # powernv does not support NUMA + self.do_test_linux_boot() + console_pattern = 'CPU maps initialized for 4 threads per core' + wait_for_console_pattern(self, console_pattern, self.panic_message) + console_pattern = 'smp: Brought up 2 nodes, 16 CPUs' + wait_for_console_pattern(self, console_pattern, self.panic_message) + wait_for_console_pattern(self, self.good_message, self.panic_message) + + + ASSET_EPAPR_KERNEL = Asset( + ('https://github.com/open-power/op-build/releases/download/v2.7/' + 'zImage.epapr'), + '0ab237df661727e5392cee97460e8674057a883c5f74381a128fa772588d45cd') + + def do_test_ppc64_powernv(self, proc): + self.require_accelerator("tcg") + kernel_path = self.ASSET_EPAPR_KERNEL.fetch() + self.vm.set_console() + self.vm.add_args('-kernel', kernel_path, + '-append', 'console=tty0 console=hvc0', + '-device', 'pcie-pci-bridge,id=bridge1,bus=pcie.1,addr=0x0', + '-device', 'nvme,bus=pcie.2,addr=0x0,serial=1234', + '-device', 'e1000e,bus=bridge1,addr=0x3', + '-device', 'nec-usb-xhci,bus=bridge1,addr=0x2') + self.vm.launch() + + self.wait_for_console_pattern("CPU: " + proc + " generation processor") + self.wait_for_console_pattern("zImage starting: loaded") + self.wait_for_console_pattern("Run /init as init process") + # Device detection output driven by udev probing is sometimes cut off + # from console output, suspect S14silence-console init script. + + def test_powernv8(self): + self.set_machine('powernv8') + self.do_test_ppc64_powernv('P8') + + def test_powernv9(self): + self.set_machine('powernv9') + self.do_test_ppc64_powernv('P9') + + def test_powernv10(self): + self.set_machine('powernv10') + self.do_test_ppc64_powernv('P10') + +if __name__ == '__main__': + LinuxKernelTest.main() diff --git a/tests/functional/ppc64/test_pseries.py b/tests/functional/ppc64/test_pseries.py new file mode 100755 index 0000000..6705793 --- /dev/null +++ b/tests/functional/ppc64/test_pseries.py @@ -0,0 +1,91 @@ +#!/usr/bin/env python3 +# +# Test that Linux kernel boots on ppc machines and check the console +# +# Copyright (c) 2018, 2020 Red Hat, Inc. +# +# This work is licensed under the terms of the GNU GPL, version 2 or +# later. See the COPYING file in the top-level directory. + +from qemu_test import QemuSystemTest, Asset +from qemu_test import wait_for_console_pattern + +class pseriesMachine(QemuSystemTest): + + timeout = 90 + KERNEL_COMMON_COMMAND_LINE = 'printk.time=0 console=hvc0 ' + panic_message = 'Kernel panic - not syncing' + good_message = 'VFS: Cannot open root device' + + ASSET_KERNEL = Asset( + ('https://archives.fedoraproject.org/pub/archive/fedora-secondary/' + 'releases/29/Everything/ppc64le/os/ppc/ppc64/vmlinuz'), + '383c2f5c23bc0d9d32680c3924d3fd7ee25cc5ef97091ac1aa5e1d853422fc5f') + + def do_test_ppc64_linux_boot(self, kernel_command_line = KERNEL_COMMON_COMMAND_LINE): + kernel_path = self.ASSET_KERNEL.fetch() + + self.vm.set_console() + self.vm.add_args('-kernel', kernel_path, + '-append', kernel_command_line) + self.vm.launch() + + def test_ppc64_vof_linux_boot(self): + self.set_machine('pseries') + self.vm.add_args('-machine', 'x-vof=on') + self.do_test_ppc64_linux_boot() + console_pattern = 'VFS: Cannot open root device' + wait_for_console_pattern(self, console_pattern, self.panic_message) + + def test_ppc64_linux_boot(self): + self.set_machine('pseries') + self.do_test_ppc64_linux_boot() + console_pattern = 'VFS: Cannot open root device' + wait_for_console_pattern(self, console_pattern, self.panic_message) + + def test_ppc64_linux_smp_boot(self): + self.set_machine('pseries') + self.vm.add_args('-smp', '4') + self.do_test_ppc64_linux_boot() + console_pattern = 'smp: Brought up 1 node, 4 CPUs' + wait_for_console_pattern(self, console_pattern, self.panic_message) + wait_for_console_pattern(self, self.good_message, self.panic_message) + + def test_ppc64_linux_hpt_smp_boot(self): + self.set_machine('pseries') + self.vm.add_args('-smp', '4') + self.do_test_ppc64_linux_boot(self.KERNEL_COMMON_COMMAND_LINE + + 'disable_radix') + console_pattern = 'smp: Brought up 1 node, 4 CPUs' + wait_for_console_pattern(self, 'hash-mmu: Initializing hash mmu', + self.panic_message) + wait_for_console_pattern(self, console_pattern, self.panic_message) + wait_for_console_pattern(self, self.good_message, self.panic_message) + + def test_ppc64_linux_smt_boot(self): + self.set_machine('pseries') + self.vm.add_args('-smp', '4,threads=4') + self.do_test_ppc64_linux_boot() + console_pattern = 'CPU maps initialized for 4 threads per core' + wait_for_console_pattern(self, console_pattern, self.panic_message) + console_pattern = 'smp: Brought up 1 node, 4 CPUs' + wait_for_console_pattern(self, console_pattern, self.panic_message) + wait_for_console_pattern(self, self.good_message, self.panic_message) + + def test_ppc64_linux_big_boot(self): + self.set_machine('pseries') + self.vm.add_args('-smp', '16,threads=4,cores=2,sockets=2') + self.vm.add_args('-m', '512M', + '-object', 'memory-backend-ram,size=256M,id=m0', + '-object', 'memory-backend-ram,size=256M,id=m1') + self.vm.add_args('-numa', 'node,nodeid=0,memdev=m0') + self.vm.add_args('-numa', 'node,nodeid=1,memdev=m1') + self.do_test_ppc64_linux_boot() + console_pattern = 'CPU maps initialized for 4 threads per core' + wait_for_console_pattern(self, console_pattern, self.panic_message) + console_pattern = 'smp: Brought up 2 nodes, 16 CPUs' + wait_for_console_pattern(self, console_pattern, self.panic_message) + wait_for_console_pattern(self, self.good_message, self.panic_message) + +if __name__ == '__main__': + QemuSystemTest.main() diff --git a/tests/functional/ppc64/test_replay.py b/tests/functional/ppc64/test_replay.py new file mode 100755 index 0000000..e8c9c4b --- /dev/null +++ b/tests/functional/ppc64/test_replay.py @@ -0,0 +1,50 @@ +#!/usr/bin/env python3 +# +# Replay test that boots a Linux kernel on ppc64 machines +# and checks the console +# +# SPDX-License-Identifier: GPL-2.0-or-later + +from qemu_test import Asset, skipFlakyTest +from replay_kernel import ReplayKernelBase + + +class Ppc64Replay(ReplayKernelBase): + + ASSET_DAY19 = Asset( + ('https://qemu-advcal.gitlab.io/qac-best-of-multiarch/download/' + 'day19.tar.xz'), + '20b1bb5a8488c664defbb5d283addc91a05335a936c63b3f5ff7eee74b725755') + + @skipFlakyTest('https://gitlab.com/qemu-project/qemu/-/issues/2523') + def test_ppc64_e500(self): + self.set_machine('ppce500') + self.cpu = 'e5500' + kernel_path = self.archive_extract(self.ASSET_DAY19, + member='day19/uImage') + self.run_rr(kernel_path, self.REPLAY_KERNEL_COMMAND_LINE, + 'QEMU advent calendar') + + ASSET_KERNEL = Asset( + ('https://archives.fedoraproject.org/pub/archive/fedora-secondary/' + 'releases/29/Everything/ppc64le/os/ppc/ppc64/vmlinuz'), + '383c2f5c23bc0d9d32680c3924d3fd7ee25cc5ef97091ac1aa5e1d853422fc5f') + + def test_ppc64_pseries(self): + self.set_machine('pseries') + kernel_path = self.ASSET_KERNEL.fetch() + kernel_command_line = self.KERNEL_COMMON_COMMAND_LINE + 'console=hvc0' + console_pattern = 'VFS: Cannot open root device' + self.run_rr(kernel_path, kernel_command_line, console_pattern) + + def test_ppc64_powernv(self): + self.set_machine('powernv') + kernel_path = self.ASSET_KERNEL.fetch() + kernel_command_line = self.KERNEL_COMMON_COMMAND_LINE + \ + 'console=tty0 console=hvc0' + console_pattern = 'VFS: Cannot open root device' + self.run_rr(kernel_path, kernel_command_line, console_pattern) + + +if __name__ == '__main__': + ReplayKernelBase.main() diff --git a/tests/functional/ppc64/test_reverse_debug.py b/tests/functional/ppc64/test_reverse_debug.py new file mode 100755 index 0000000..5931ade --- /dev/null +++ b/tests/functional/ppc64/test_reverse_debug.py @@ -0,0 +1,41 @@ +#!/usr/bin/env python3 +# +# SPDX-License-Identifier: GPL-2.0-or-later +# +# Reverse debugging test +# +# Copyright (c) 2020 ISP RAS +# +# Author: +# Pavel Dovgalyuk +# +# This work is licensed under the terms of the GNU GPL, version 2 or +# later. See the COPYING file in the top-level directory. + +from qemu_test import skipIfMissingImports, skipFlakyTest +from reverse_debugging import ReverseDebugging + + +@skipIfMissingImports('avocado.utils') +class ReverseDebugging_ppc64(ReverseDebugging): + + REG_PC = 0x40 + + @skipFlakyTest("https://gitlab.com/qemu-project/qemu/-/issues/1992") + def test_ppc64_pseries(self): + self.set_machine('pseries') + # SLOF branches back to its entry point, which causes this test + # to take the 'hit a breakpoint again' path. That's not a problem, + # just slightly different than the other machines. + self.endian_is_le = False + self.reverse_debugging() + + @skipFlakyTest("https://gitlab.com/qemu-project/qemu/-/issues/1992") + def test_ppc64_powernv(self): + self.set_machine('powernv') + self.endian_is_le = False + self.reverse_debugging() + + +if __name__ == '__main__': + ReverseDebugging.main() diff --git a/tests/functional/ppc64/test_tuxrun.py b/tests/functional/ppc64/test_tuxrun.py new file mode 100755 index 0000000..e8f79c6 --- /dev/null +++ b/tests/functional/ppc64/test_tuxrun.py @@ -0,0 +1,113 @@ +#!/usr/bin/env python3 +# +# Functional test that boots known good tuxboot images the same way +# that tuxrun (www.tuxrun.org) does. This tool is used by things like +# the LKFT project to run regression tests on kernels. +# +# Copyright (c) 2023 Linaro Ltd. +# +# Author: +# Alex Bennée +# +# SPDX-License-Identifier: GPL-2.0-or-later + +from subprocess import check_call, DEVNULL +import tempfile + +from qemu_test import Asset +from qemu_test.tuxruntest import TuxRunBaselineTest + +class TuxRunPPC64Test(TuxRunBaselineTest): + + def ppc64_common_tuxrun(self, kernel_asset, rootfs_asset, prefix): + self.set_machine('pseries') + self.cpu='POWER10' + self.console='hvc0' + self.root='sda' + self.extradev='spapr-vscsi' + # add device args to command line. + self.require_netdev('user') + self.vm.add_args('-netdev', 'user,id=vnet,hostfwd=:127.0.0.1:0-:22', + '-device', 'virtio-net,netdev=vnet') + self.vm.add_args('-netdev', '{"type":"user","id":"hostnet0"}', + '-device', '{"driver":"virtio-net-pci","netdev":' + '"hostnet0","id":"net0","mac":"52:54:00:4c:e3:86",' + '"bus":"pci.0","addr":"0x9"}') + self.vm.add_args('-device', '{"driver":"qemu-xhci","p2":15,"p3":15,' + '"id":"usb","bus":"pci.0","addr":"0x2"}') + self.vm.add_args('-device', '{"driver":"virtio-scsi-pci","id":"scsi0"' + ',"bus":"pci.0","addr":"0x3"}') + self.vm.add_args('-device', '{"driver":"virtio-serial-pci","id":' + '"virtio-serial0","bus":"pci.0","addr":"0x4"}') + self.vm.add_args('-device', '{"driver":"scsi-cd","bus":"scsi0.0"' + ',"channel":0,"scsi-id":0,"lun":0,"device_id":' + '"drive-scsi0-0-0-0","id":"scsi0-0-0-0"}') + self.vm.add_args('-device', '{"driver":"virtio-balloon-pci",' + '"id":"balloon0","bus":"pci.0","addr":"0x6"}') + self.vm.add_args('-audiodev', '{"id":"audio1","driver":"none"}') + self.vm.add_args('-device', '{"driver":"usb-tablet","id":"input0"' + ',"bus":"usb.0","port":"1"}') + self.vm.add_args('-device', '{"driver":"usb-kbd","id":"input1"' + ',"bus":"usb.0","port":"2"}') + self.vm.add_args('-device', '{"driver":"VGA","id":"video0",' + '"vgamem_mb":16,"bus":"pci.0","addr":"0x7"}') + self.vm.add_args('-object', '{"qom-type":"rng-random","id":"objrng0"' + ',"filename":"/dev/urandom"}', + '-device', '{"driver":"virtio-rng-pci","rng":"objrng0"' + ',"id":"rng0","bus":"pci.0","addr":"0x8"}') + self.vm.add_args('-object', '{"qom-type":"cryptodev-backend-builtin",' + '"id":"objcrypto0","queues":1}', + '-device', '{"driver":"virtio-crypto-pci",' + '"cryptodev":"objcrypto0","id":"crypto0","bus"' + ':"pci.0","addr":"0xa"}') + self.vm.add_args('-device', '{"driver":"spapr-pci-host-bridge"' + ',"index":1,"id":"pci.1"}') + self.vm.add_args('-device', '{"driver":"spapr-vscsi","id":"scsi1"' + ',"reg":12288}') + self.vm.add_args('-m', '1G,slots=32,maxmem=2G', + '-object', 'memory-backend-ram,id=ram1,size=1G', + '-device', 'pc-dimm,id=dimm1,memdev=ram1') + + # Create a temporary qcow2 and launch the test-case + with tempfile.NamedTemporaryFile(prefix=prefix, + suffix='.qcow2') as qcow2: + check_call([self.qemu_img, 'create', '-f', 'qcow2', + qcow2.name, ' 1G'], + stdout=DEVNULL, stderr=DEVNULL) + + self.vm.add_args('-drive', 'file=' + qcow2.name + + ',format=qcow2,if=none,id=' + 'drive-virtio-disk1', + '-device', 'virtio-blk-pci,bus=pci.0,' + 'addr=0xb,drive=drive-virtio-disk1,id=virtio-disk1' + ',bootindex=2') + self.common_tuxrun(kernel_asset, rootfs_asset=rootfs_asset, + drive="scsi-hd") + + ASSET_PPC64_KERNEL = Asset( + 'https://storage.tuxboot.com/buildroot/20241119/ppc64/vmlinux', + '8219d5cb26e7654ad7826fe8aee6290f7c01eef44f2cd6d26c15fe8f99e1c17c') + ASSET_PPC64_ROOTFS = Asset( + 'https://storage.tuxboot.com/buildroot/20241119/ppc64/rootfs.ext4.zst', + 'b68e12314303c5dd0fef37ae98021299a206085ae591893e73557af99a02d373') + + def test_ppc64(self): + self.ppc64_common_tuxrun(kernel_asset=self.ASSET_PPC64_KERNEL, + rootfs_asset=self.ASSET_PPC64_ROOTFS, + prefix='tuxrun_ppc64_') + + ASSET_PPC64LE_KERNEL = Asset( + 'https://storage.tuxboot.com/buildroot/20241119/ppc64le/vmlinux', + '21aea1fbc18bf6fa7d8ca4ea48d4940b2c8363c077acd564eb47d769b7495279') + ASSET_PPC64LE_ROOTFS = Asset( + 'https://storage.tuxboot.com/buildroot/20241119/ppc64le/rootfs.ext4.zst', + '67d36a3f9597b738e8b7359bdf04500f4d9bb82fc35eaa65aa439d888b2392f4') + + def test_ppc64le(self): + self.ppc64_common_tuxrun(kernel_asset=self.ASSET_PPC64LE_KERNEL, + rootfs_asset=self.ASSET_PPC64LE_ROOTFS, + prefix='tuxrun_ppc64le_') + + +if __name__ == '__main__': + TuxRunBaselineTest.main() diff --git a/tests/functional/test_ppc64_e500.py b/tests/functional/test_ppc64_e500.py deleted file mode 100755 index f5fcad9..0000000 --- a/tests/functional/test_ppc64_e500.py +++ /dev/null @@ -1,44 +0,0 @@ -#!/usr/bin/env python3 -# -# Boot a Linux kernel on a e500 ppc64 machine and check the console -# -# SPDX-License-Identifier: GPL-2.0-or-later - -from qemu_test import LinuxKernelTest, Asset -from qemu_test import exec_command_and_wait_for_pattern - - -class E500Test(LinuxKernelTest): - - ASSET_BR2_E5500_UIMAGE = Asset( - 'https://github.com/legoater/qemu-ppc-boot/raw/refs/heads/main/buildroot/qemu_ppc64_e5500-2023.11-8-gdcd9f0f6eb-20240104/uImage', - '2478187c455d6cca3984e9dfde9c635d824ea16236b85fd6b4809f744706deda') - - ASSET_BR2_E5500_ROOTFS = Asset( - 'https://github.com/legoater/qemu-ppc-boot/raw/refs/heads/main//buildroot/qemu_ppc64_e5500-2023.11-8-gdcd9f0f6eb-20240104/rootfs.ext2', - '9035ef97237c84c7522baaff17d25cdfca4bb7a053d5e296e902919473423d76') - - def test_ppc64_e500_buildroot(self): - self.set_machine('ppce500') - self.require_netdev('user') - self.cpu = 'e5500' - - uimage_path = self.ASSET_BR2_E5500_UIMAGE.fetch() - rootfs_path = self.ASSET_BR2_E5500_ROOTFS.fetch() - - self.vm.set_console() - self.vm.add_args('-kernel', uimage_path, - '-append', 'root=/dev/vda', - '-drive', f'file={rootfs_path},if=virtio,format=raw', - '-snapshot', '-no-shutdown') - self.vm.launch() - - self.wait_for_console_pattern('Linux version') - self.wait_for_console_pattern('/init as init process') - self.wait_for_console_pattern('lease of 10.0.2.15') - self.wait_for_console_pattern('buildroot login:') - exec_command_and_wait_for_pattern(self, 'root', '#') - exec_command_and_wait_for_pattern(self, 'poweroff', 'Power down') - -if __name__ == '__main__': - LinuxKernelTest.main() diff --git a/tests/functional/test_ppc64_hv.py b/tests/functional/test_ppc64_hv.py deleted file mode 100755 index d87f440..0000000 --- a/tests/functional/test_ppc64_hv.py +++ /dev/null @@ -1,165 +0,0 @@ -#!/usr/bin/env python3 -# -# Tests that specifically try to exercise hypervisor features of the -# target machines. powernv supports the Power hypervisor ISA, and -# pseries supports the nested-HV hypervisor spec. -# -# Copyright (c) 2023 IBM Corporation -# -# This work is licensed under the terms of the GNU GPL, version 2 or -# later. See the COPYING file in the top-level directory. - -import os -import subprocess - -from datetime import datetime -from qemu_test import QemuSystemTest, Asset -from qemu_test import wait_for_console_pattern, exec_command -from qemu_test import skipIfMissingCommands, skipBigDataTest -from qemu_test import exec_command_and_wait_for_pattern - -# Alpine is a light weight distro that supports QEMU. These tests boot -# that on the machine then run a QEMU guest inside it in KVM mode, -# that runs the same Alpine distro image. -# QEMU packages are downloaded and installed on each test. That's not a -# large download, but it may be more polite to create qcow2 image with -# QEMU already installed and use that. -# XXX: The order of these tests seems to matter, see git blame. -@skipIfMissingCommands("xorriso") -@skipBigDataTest() -class HypervisorTest(QemuSystemTest): - - timeout = 1000 - KERNEL_COMMON_COMMAND_LINE = 'printk.time=0 console=hvc0 ' - panic_message = 'Kernel panic - not syncing' - good_message = 'VFS: Cannot open root device' - - ASSET_ISO = Asset( - ('https://dl-cdn.alpinelinux.org/alpine/v3.21/' - 'releases/ppc64le/alpine-standard-3.21.0-ppc64le.iso'), - '7651ab4e3027604535c0b36e86c901b4695bf8fe97b908f5b48590f6baae8f30') - - def extract_from_iso(self, iso, path): - """ - Extracts a file from an iso file into the test workdir - - :param iso: path to the iso file - :param path: path within the iso file of the file to be extracted - :returns: path of the extracted file - """ - filename = self.scratch_file(os.path.basename(path)) - - cmd = "xorriso -osirrox on -indev %s -cpx %s %s" % (iso, path, filename) - subprocess.run(cmd.split(), - stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) - - os.chmod(filename, 0o600) - - return filename - - def setUp(self): - super().setUp() - - self.iso_path = self.ASSET_ISO.fetch() - self.vmlinuz = self.extract_from_iso(self.iso_path, '/boot/vmlinuz-lts') - self.initramfs = self.extract_from_iso(self.iso_path, '/boot/initramfs-lts') - - def do_start_alpine(self): - self.vm.set_console() - kernel_command_line = self.KERNEL_COMMON_COMMAND_LINE - self.vm.add_args("-kernel", self.vmlinuz) - self.vm.add_args("-initrd", self.initramfs) - self.vm.add_args("-smp", "4", "-m", "2g") - self.vm.add_args("-drive", f"file={self.iso_path},format=raw,if=none," - "id=drive0,read-only=true") - - self.vm.launch() - ps1='localhost:~#' - wait_for_console_pattern(self, 'localhost login:') - exec_command_and_wait_for_pattern(self, 'root', ps1) - # If the time is wrong, SSL certificates can fail. - exec_command_and_wait_for_pattern(self, 'date -s "' + datetime.utcnow().strftime('%Y-%m-%d %H:%M:%S' + '"'), ps1) - ps1='alpine:~#' - exec_command_and_wait_for_pattern(self, 'setup-alpine -qe', ps1) - exec_command_and_wait_for_pattern(self, 'setup-apkrepos -c1', ps1) - exec_command_and_wait_for_pattern(self, 'apk update', ps1) - # Could upgrade here but it usually should not be necessary - # exec_command_and_wait_for_pattern(self, 'apk upgrade --available', ps1) - - def do_stop_alpine(self): - exec_command(self, 'echo "TEST ME"') - wait_for_console_pattern(self, 'alpine:~#') - exec_command(self, 'poweroff') - wait_for_console_pattern(self, 'reboot: Power down') - self.vm.wait() - - def do_setup_kvm(self): - ps1='alpine:~#' - exec_command_and_wait_for_pattern(self, 'apk add qemu-system-ppc64', ps1) - exec_command_and_wait_for_pattern(self, 'modprobe kvm-hv', ps1) - - # This uses the host's block device as the source file for guest block - # device for install media. This is a bit hacky but allows reuse of the - # iso without having a passthrough filesystem configured. - def do_test_kvm(self, hpt=False): - if hpt: - append = 'disable_radix' - else: - append = '' - exec_command(self, 'qemu-system-ppc64 -nographic -smp 2 -m 1g ' - '-machine pseries,x-vof=on,accel=kvm ' - '-machine cap-cfpc=broken,cap-sbbc=broken,' - 'cap-ibs=broken,cap-ccf-assist=off ' - '-drive file=/dev/nvme0n1,format=raw,readonly=on ' - '-initrd /media/nvme0n1/boot/initramfs-lts ' - '-kernel /media/nvme0n1/boot/vmlinuz-lts ' - '-append \'usbcore.nousb ' + append + '\'') - # Alpine 3.21 kernel seems to crash in XHCI USB driver. - ps1='localhost:~#' - wait_for_console_pattern(self, 'localhost login:') - exec_command_and_wait_for_pattern(self, 'root', ps1) - exec_command(self, 'poweroff') - wait_for_console_pattern(self, 'reboot: Power down') - # Now wait for the host's prompt to come back - wait_for_console_pattern(self, 'alpine:~#') - - def test_hv_pseries(self): - self.require_accelerator("tcg") - self.require_netdev('user') - self.set_machine('pseries') - self.vm.add_args("-accel", "tcg,thread=multi") - self.vm.add_args('-device', 'nvme,serial=1234,drive=drive0') - self.vm.add_args("-machine", "x-vof=on,cap-nested-hv=on") - self.do_start_alpine() - self.do_setup_kvm() - self.do_test_kvm() - self.do_stop_alpine() - - def test_hv_pseries_kvm(self): - self.require_accelerator("kvm") - self.require_netdev('user') - self.set_machine('pseries') - self.vm.add_args("-accel", "kvm") - self.vm.add_args('-device', 'nvme,serial=1234,drive=drive0') - self.vm.add_args("-machine", "x-vof=on,cap-nested-hv=on,cap-ccf-assist=off") - self.do_start_alpine() - self.do_setup_kvm() - self.do_test_kvm() - self.do_stop_alpine() - - def test_hv_powernv(self): - self.require_accelerator("tcg") - self.require_netdev('user') - self.set_machine('powernv') - self.vm.add_args("-accel", "tcg,thread=multi") - self.vm.add_args('-device', 'nvme,bus=pcie.2,addr=0x0,serial=1234,drive=drive0', - '-device', 'e1000e,netdev=net0,mac=C0:FF:EE:00:00:02,bus=pcie.0,addr=0x0', - '-netdev', 'user,id=net0,hostfwd=::20022-:22,hostname=alpine') - self.do_start_alpine() - self.do_setup_kvm() - self.do_test_kvm() - self.do_test_kvm(True) - self.do_stop_alpine() - -if __name__ == '__main__': - QemuSystemTest.main() diff --git a/tests/functional/test_ppc64_mac99.py b/tests/functional/test_ppc64_mac99.py deleted file mode 100755 index dfd9c01..0000000 --- a/tests/functional/test_ppc64_mac99.py +++ /dev/null @@ -1,44 +0,0 @@ -#!/usr/bin/env python3 -# -# Functional test that boots a mac99 machine with a PPC970 CPU -# -# SPDX-License-Identifier: GPL-2.0-or-later - -from qemu_test import LinuxKernelTest, Asset -from qemu_test import exec_command_and_wait_for_pattern - -class mac99Test(LinuxKernelTest): - - ASSET_BR2_MAC99_LINUX = Asset( - 'https://github.com/legoater/qemu-ppc-boot/raw/refs/heads/main/buildroot/qemu_ppc64_mac99-2023.11-8-gdcd9f0f6eb-20240105/vmlinux', - 'd59307437e4365f2cced0bbd1b04949f7397b282ef349b7cafd894d74aadfbff') - - ASSET_BR2_MAC99_ROOTFS = Asset( - 'https://github.com/legoater/qemu-ppc-boot/raw/refs/heads/main//buildroot/qemu_ppc64_mac99-2023.11-8-gdcd9f0f6eb-20240105/rootfs.ext2', - 'bbd5fd8af62f580bc4e585f326fe584e22856572633a8333178ea6d4ed4955a4') - - def test_ppc64_mac99_buildroot(self): - self.set_machine('mac99') - - linux_path = self.ASSET_BR2_MAC99_LINUX.fetch() - rootfs_path = self.ASSET_BR2_MAC99_ROOTFS.fetch() - - self.vm.set_console() - - # Note: We need '-nographic' to get a serial console - self.vm.add_args('-kernel', linux_path, - '-append', 'root=/dev/sda', - '-drive', f'file={rootfs_path},format=raw', - '-snapshot', '-nographic') - self.vm.launch() - - self.wait_for_console_pattern('>> OpenBIOS') - self.wait_for_console_pattern('Linux version') - self.wait_for_console_pattern('/init as init process') - self.wait_for_console_pattern('gem 0000:f0:0e.0 eth0: Link is up at 100 Mbps') - self.wait_for_console_pattern('buildroot login:') - exec_command_and_wait_for_pattern(self, 'root', '#') - exec_command_and_wait_for_pattern(self, 'poweroff', 'Power down') - -if __name__ == '__main__': - LinuxKernelTest.main() diff --git a/tests/functional/test_ppc64_migration.py b/tests/functional/test_ppc64_migration.py deleted file mode 100755 index 5dfdaaf..0000000 --- a/tests/functional/test_ppc64_migration.py +++ /dev/null @@ -1,26 +0,0 @@ -#!/usr/bin/env python3 -# -# SPDX-License-Identifier: GPL-2.0-or-later -# -# ppc migration test - -from migration import MigrationTest - - -class PpcMigrationTest(MigrationTest): - - def test_migration_with_tcp_localhost(self): - self.set_machine('mac99') - self.migration_with_tcp_localhost() - - def test_migration_with_unix(self): - self.set_machine('mac99') - self.migration_with_unix() - - def test_migration_with_exec(self): - self.set_machine('mac99') - self.migration_with_exec() - - -if __name__ == '__main__': - MigrationTest.main() diff --git a/tests/functional/test_ppc64_powernv.py b/tests/functional/test_ppc64_powernv.py deleted file mode 100755 index 685e217..0000000 --- a/tests/functional/test_ppc64_powernv.py +++ /dev/null @@ -1,118 +0,0 @@ -#!/usr/bin/env python3 -# -# Test that Linux kernel boots on ppc powernv machines and check the console -# -# Copyright (c) 2018, 2020 Red Hat, Inc. -# -# This work is licensed under the terms of the GNU GPL, version 2 or -# later. See the COPYING file in the top-level directory. - -from qemu_test import LinuxKernelTest, Asset -from qemu_test import wait_for_console_pattern - -class powernvMachine(LinuxKernelTest): - - timeout = 90 - KERNEL_COMMON_COMMAND_LINE = 'printk.time=0 console=hvc0 ' - panic_message = 'Kernel panic - not syncing' - good_message = 'VFS: Cannot open root device' - - ASSET_KERNEL = Asset( - ('https://archives.fedoraproject.org/pub/archive/fedora-secondary/' - 'releases/29/Everything/ppc64le/os/ppc/ppc64/vmlinuz'), - '383c2f5c23bc0d9d32680c3924d3fd7ee25cc5ef97091ac1aa5e1d853422fc5f') - - def do_test_linux_boot(self, command_line = KERNEL_COMMON_COMMAND_LINE): - self.require_accelerator("tcg") - kernel_path = self.ASSET_KERNEL.fetch() - - self.vm.set_console() - self.vm.add_args('-kernel', kernel_path, - '-append', command_line) - self.vm.launch() - - def test_linux_boot(self): - self.set_machine('powernv') - self.do_test_linux_boot() - console_pattern = 'VFS: Cannot open root device' - wait_for_console_pattern(self, console_pattern, self.panic_message) - - def test_linux_smp_boot(self): - self.set_machine('powernv') - self.vm.add_args('-smp', '4') - self.do_test_linux_boot() - console_pattern = 'smp: Brought up 1 node, 4 CPUs' - wait_for_console_pattern(self, console_pattern, self.panic_message) - wait_for_console_pattern(self, self.good_message, self.panic_message) - - def test_linux_smp_hpt_boot(self): - self.set_machine('powernv') - self.vm.add_args('-smp', '4') - self.do_test_linux_boot(self.KERNEL_COMMON_COMMAND_LINE + - 'disable_radix') - console_pattern = 'smp: Brought up 1 node, 4 CPUs' - wait_for_console_pattern(self, 'hash-mmu: Initializing hash mmu', - self.panic_message) - wait_for_console_pattern(self, console_pattern, self.panic_message) - wait_for_console_pattern(self, self.good_message, self.panic_message) - - def test_linux_smt_boot(self): - self.set_machine('powernv') - self.vm.add_args('-smp', '4,threads=4') - self.do_test_linux_boot() - console_pattern = 'CPU maps initialized for 4 threads per core' - wait_for_console_pattern(self, console_pattern, self.panic_message) - console_pattern = 'smp: Brought up 1 node, 4 CPUs' - wait_for_console_pattern(self, console_pattern, self.panic_message) - wait_for_console_pattern(self, self.good_message, self.panic_message) - - def test_linux_big_boot(self): - self.set_machine('powernv') - self.vm.add_args('-smp', '16,threads=4,cores=2,sockets=2') - - # powernv does not support NUMA - self.do_test_linux_boot() - console_pattern = 'CPU maps initialized for 4 threads per core' - wait_for_console_pattern(self, console_pattern, self.panic_message) - console_pattern = 'smp: Brought up 2 nodes, 16 CPUs' - wait_for_console_pattern(self, console_pattern, self.panic_message) - wait_for_console_pattern(self, self.good_message, self.panic_message) - - - ASSET_EPAPR_KERNEL = Asset( - ('https://github.com/open-power/op-build/releases/download/v2.7/' - 'zImage.epapr'), - '0ab237df661727e5392cee97460e8674057a883c5f74381a128fa772588d45cd') - - def do_test_ppc64_powernv(self, proc): - self.require_accelerator("tcg") - kernel_path = self.ASSET_EPAPR_KERNEL.fetch() - self.vm.set_console() - self.vm.add_args('-kernel', kernel_path, - '-append', 'console=tty0 console=hvc0', - '-device', 'pcie-pci-bridge,id=bridge1,bus=pcie.1,addr=0x0', - '-device', 'nvme,bus=pcie.2,addr=0x0,serial=1234', - '-device', 'e1000e,bus=bridge1,addr=0x3', - '-device', 'nec-usb-xhci,bus=bridge1,addr=0x2') - self.vm.launch() - - self.wait_for_console_pattern("CPU: " + proc + " generation processor") - self.wait_for_console_pattern("zImage starting: loaded") - self.wait_for_console_pattern("Run /init as init process") - # Device detection output driven by udev probing is sometimes cut off - # from console output, suspect S14silence-console init script. - - def test_powernv8(self): - self.set_machine('powernv8') - self.do_test_ppc64_powernv('P8') - - def test_powernv9(self): - self.set_machine('powernv9') - self.do_test_ppc64_powernv('P9') - - def test_powernv10(self): - self.set_machine('powernv10') - self.do_test_ppc64_powernv('P10') - -if __name__ == '__main__': - LinuxKernelTest.main() diff --git a/tests/functional/test_ppc64_pseries.py b/tests/functional/test_ppc64_pseries.py deleted file mode 100755 index 6705793..0000000 --- a/tests/functional/test_ppc64_pseries.py +++ /dev/null @@ -1,91 +0,0 @@ -#!/usr/bin/env python3 -# -# Test that Linux kernel boots on ppc machines and check the console -# -# Copyright (c) 2018, 2020 Red Hat, Inc. -# -# This work is licensed under the terms of the GNU GPL, version 2 or -# later. See the COPYING file in the top-level directory. - -from qemu_test import QemuSystemTest, Asset -from qemu_test import wait_for_console_pattern - -class pseriesMachine(QemuSystemTest): - - timeout = 90 - KERNEL_COMMON_COMMAND_LINE = 'printk.time=0 console=hvc0 ' - panic_message = 'Kernel panic - not syncing' - good_message = 'VFS: Cannot open root device' - - ASSET_KERNEL = Asset( - ('https://archives.fedoraproject.org/pub/archive/fedora-secondary/' - 'releases/29/Everything/ppc64le/os/ppc/ppc64/vmlinuz'), - '383c2f5c23bc0d9d32680c3924d3fd7ee25cc5ef97091ac1aa5e1d853422fc5f') - - def do_test_ppc64_linux_boot(self, kernel_command_line = KERNEL_COMMON_COMMAND_LINE): - kernel_path = self.ASSET_KERNEL.fetch() - - self.vm.set_console() - self.vm.add_args('-kernel', kernel_path, - '-append', kernel_command_line) - self.vm.launch() - - def test_ppc64_vof_linux_boot(self): - self.set_machine('pseries') - self.vm.add_args('-machine', 'x-vof=on') - self.do_test_ppc64_linux_boot() - console_pattern = 'VFS: Cannot open root device' - wait_for_console_pattern(self, console_pattern, self.panic_message) - - def test_ppc64_linux_boot(self): - self.set_machine('pseries') - self.do_test_ppc64_linux_boot() - console_pattern = 'VFS: Cannot open root device' - wait_for_console_pattern(self, console_pattern, self.panic_message) - - def test_ppc64_linux_smp_boot(self): - self.set_machine('pseries') - self.vm.add_args('-smp', '4') - self.do_test_ppc64_linux_boot() - console_pattern = 'smp: Brought up 1 node, 4 CPUs' - wait_for_console_pattern(self, console_pattern, self.panic_message) - wait_for_console_pattern(self, self.good_message, self.panic_message) - - def test_ppc64_linux_hpt_smp_boot(self): - self.set_machine('pseries') - self.vm.add_args('-smp', '4') - self.do_test_ppc64_linux_boot(self.KERNEL_COMMON_COMMAND_LINE + - 'disable_radix') - console_pattern = 'smp: Brought up 1 node, 4 CPUs' - wait_for_console_pattern(self, 'hash-mmu: Initializing hash mmu', - self.panic_message) - wait_for_console_pattern(self, console_pattern, self.panic_message) - wait_for_console_pattern(self, self.good_message, self.panic_message) - - def test_ppc64_linux_smt_boot(self): - self.set_machine('pseries') - self.vm.add_args('-smp', '4,threads=4') - self.do_test_ppc64_linux_boot() - console_pattern = 'CPU maps initialized for 4 threads per core' - wait_for_console_pattern(self, console_pattern, self.panic_message) - console_pattern = 'smp: Brought up 1 node, 4 CPUs' - wait_for_console_pattern(self, console_pattern, self.panic_message) - wait_for_console_pattern(self, self.good_message, self.panic_message) - - def test_ppc64_linux_big_boot(self): - self.set_machine('pseries') - self.vm.add_args('-smp', '16,threads=4,cores=2,sockets=2') - self.vm.add_args('-m', '512M', - '-object', 'memory-backend-ram,size=256M,id=m0', - '-object', 'memory-backend-ram,size=256M,id=m1') - self.vm.add_args('-numa', 'node,nodeid=0,memdev=m0') - self.vm.add_args('-numa', 'node,nodeid=1,memdev=m1') - self.do_test_ppc64_linux_boot() - console_pattern = 'CPU maps initialized for 4 threads per core' - wait_for_console_pattern(self, console_pattern, self.panic_message) - console_pattern = 'smp: Brought up 2 nodes, 16 CPUs' - wait_for_console_pattern(self, console_pattern, self.panic_message) - wait_for_console_pattern(self, self.good_message, self.panic_message) - -if __name__ == '__main__': - QemuSystemTest.main() diff --git a/tests/functional/test_ppc64_replay.py b/tests/functional/test_ppc64_replay.py deleted file mode 100755 index e8c9c4b..0000000 --- a/tests/functional/test_ppc64_replay.py +++ /dev/null @@ -1,50 +0,0 @@ -#!/usr/bin/env python3 -# -# Replay test that boots a Linux kernel on ppc64 machines -# and checks the console -# -# SPDX-License-Identifier: GPL-2.0-or-later - -from qemu_test import Asset, skipFlakyTest -from replay_kernel import ReplayKernelBase - - -class Ppc64Replay(ReplayKernelBase): - - ASSET_DAY19 = Asset( - ('https://qemu-advcal.gitlab.io/qac-best-of-multiarch/download/' - 'day19.tar.xz'), - '20b1bb5a8488c664defbb5d283addc91a05335a936c63b3f5ff7eee74b725755') - - @skipFlakyTest('https://gitlab.com/qemu-project/qemu/-/issues/2523') - def test_ppc64_e500(self): - self.set_machine('ppce500') - self.cpu = 'e5500' - kernel_path = self.archive_extract(self.ASSET_DAY19, - member='day19/uImage') - self.run_rr(kernel_path, self.REPLAY_KERNEL_COMMAND_LINE, - 'QEMU advent calendar') - - ASSET_KERNEL = Asset( - ('https://archives.fedoraproject.org/pub/archive/fedora-secondary/' - 'releases/29/Everything/ppc64le/os/ppc/ppc64/vmlinuz'), - '383c2f5c23bc0d9d32680c3924d3fd7ee25cc5ef97091ac1aa5e1d853422fc5f') - - def test_ppc64_pseries(self): - self.set_machine('pseries') - kernel_path = self.ASSET_KERNEL.fetch() - kernel_command_line = self.KERNEL_COMMON_COMMAND_LINE + 'console=hvc0' - console_pattern = 'VFS: Cannot open root device' - self.run_rr(kernel_path, kernel_command_line, console_pattern) - - def test_ppc64_powernv(self): - self.set_machine('powernv') - kernel_path = self.ASSET_KERNEL.fetch() - kernel_command_line = self.KERNEL_COMMON_COMMAND_LINE + \ - 'console=tty0 console=hvc0' - console_pattern = 'VFS: Cannot open root device' - self.run_rr(kernel_path, kernel_command_line, console_pattern) - - -if __name__ == '__main__': - ReplayKernelBase.main() diff --git a/tests/functional/test_ppc64_reverse_debug.py b/tests/functional/test_ppc64_reverse_debug.py deleted file mode 100755 index 5931ade..0000000 --- a/tests/functional/test_ppc64_reverse_debug.py +++ /dev/null @@ -1,41 +0,0 @@ -#!/usr/bin/env python3 -# -# SPDX-License-Identifier: GPL-2.0-or-later -# -# Reverse debugging test -# -# Copyright (c) 2020 ISP RAS -# -# Author: -# Pavel Dovgalyuk -# -# This work is licensed under the terms of the GNU GPL, version 2 or -# later. See the COPYING file in the top-level directory. - -from qemu_test import skipIfMissingImports, skipFlakyTest -from reverse_debugging import ReverseDebugging - - -@skipIfMissingImports('avocado.utils') -class ReverseDebugging_ppc64(ReverseDebugging): - - REG_PC = 0x40 - - @skipFlakyTest("https://gitlab.com/qemu-project/qemu/-/issues/1992") - def test_ppc64_pseries(self): - self.set_machine('pseries') - # SLOF branches back to its entry point, which causes this test - # to take the 'hit a breakpoint again' path. That's not a problem, - # just slightly different than the other machines. - self.endian_is_le = False - self.reverse_debugging() - - @skipFlakyTest("https://gitlab.com/qemu-project/qemu/-/issues/1992") - def test_ppc64_powernv(self): - self.set_machine('powernv') - self.endian_is_le = False - self.reverse_debugging() - - -if __name__ == '__main__': - ReverseDebugging.main() diff --git a/tests/functional/test_ppc64_tuxrun.py b/tests/functional/test_ppc64_tuxrun.py deleted file mode 100755 index e8f79c6..0000000 --- a/tests/functional/test_ppc64_tuxrun.py +++ /dev/null @@ -1,113 +0,0 @@ -#!/usr/bin/env python3 -# -# Functional test that boots known good tuxboot images the same way -# that tuxrun (www.tuxrun.org) does. This tool is used by things like -# the LKFT project to run regression tests on kernels. -# -# Copyright (c) 2023 Linaro Ltd. -# -# Author: -# Alex Bennée -# -# SPDX-License-Identifier: GPL-2.0-or-later - -from subprocess import check_call, DEVNULL -import tempfile - -from qemu_test import Asset -from qemu_test.tuxruntest import TuxRunBaselineTest - -class TuxRunPPC64Test(TuxRunBaselineTest): - - def ppc64_common_tuxrun(self, kernel_asset, rootfs_asset, prefix): - self.set_machine('pseries') - self.cpu='POWER10' - self.console='hvc0' - self.root='sda' - self.extradev='spapr-vscsi' - # add device args to command line. - self.require_netdev('user') - self.vm.add_args('-netdev', 'user,id=vnet,hostfwd=:127.0.0.1:0-:22', - '-device', 'virtio-net,netdev=vnet') - self.vm.add_args('-netdev', '{"type":"user","id":"hostnet0"}', - '-device', '{"driver":"virtio-net-pci","netdev":' - '"hostnet0","id":"net0","mac":"52:54:00:4c:e3:86",' - '"bus":"pci.0","addr":"0x9"}') - self.vm.add_args('-device', '{"driver":"qemu-xhci","p2":15,"p3":15,' - '"id":"usb","bus":"pci.0","addr":"0x2"}') - self.vm.add_args('-device', '{"driver":"virtio-scsi-pci","id":"scsi0"' - ',"bus":"pci.0","addr":"0x3"}') - self.vm.add_args('-device', '{"driver":"virtio-serial-pci","id":' - '"virtio-serial0","bus":"pci.0","addr":"0x4"}') - self.vm.add_args('-device', '{"driver":"scsi-cd","bus":"scsi0.0"' - ',"channel":0,"scsi-id":0,"lun":0,"device_id":' - '"drive-scsi0-0-0-0","id":"scsi0-0-0-0"}') - self.vm.add_args('-device', '{"driver":"virtio-balloon-pci",' - '"id":"balloon0","bus":"pci.0","addr":"0x6"}') - self.vm.add_args('-audiodev', '{"id":"audio1","driver":"none"}') - self.vm.add_args('-device', '{"driver":"usb-tablet","id":"input0"' - ',"bus":"usb.0","port":"1"}') - self.vm.add_args('-device', '{"driver":"usb-kbd","id":"input1"' - ',"bus":"usb.0","port":"2"}') - self.vm.add_args('-device', '{"driver":"VGA","id":"video0",' - '"vgamem_mb":16,"bus":"pci.0","addr":"0x7"}') - self.vm.add_args('-object', '{"qom-type":"rng-random","id":"objrng0"' - ',"filename":"/dev/urandom"}', - '-device', '{"driver":"virtio-rng-pci","rng":"objrng0"' - ',"id":"rng0","bus":"pci.0","addr":"0x8"}') - self.vm.add_args('-object', '{"qom-type":"cryptodev-backend-builtin",' - '"id":"objcrypto0","queues":1}', - '-device', '{"driver":"virtio-crypto-pci",' - '"cryptodev":"objcrypto0","id":"crypto0","bus"' - ':"pci.0","addr":"0xa"}') - self.vm.add_args('-device', '{"driver":"spapr-pci-host-bridge"' - ',"index":1,"id":"pci.1"}') - self.vm.add_args('-device', '{"driver":"spapr-vscsi","id":"scsi1"' - ',"reg":12288}') - self.vm.add_args('-m', '1G,slots=32,maxmem=2G', - '-object', 'memory-backend-ram,id=ram1,size=1G', - '-device', 'pc-dimm,id=dimm1,memdev=ram1') - - # Create a temporary qcow2 and launch the test-case - with tempfile.NamedTemporaryFile(prefix=prefix, - suffix='.qcow2') as qcow2: - check_call([self.qemu_img, 'create', '-f', 'qcow2', - qcow2.name, ' 1G'], - stdout=DEVNULL, stderr=DEVNULL) - - self.vm.add_args('-drive', 'file=' + qcow2.name + - ',format=qcow2,if=none,id=' - 'drive-virtio-disk1', - '-device', 'virtio-blk-pci,bus=pci.0,' - 'addr=0xb,drive=drive-virtio-disk1,id=virtio-disk1' - ',bootindex=2') - self.common_tuxrun(kernel_asset, rootfs_asset=rootfs_asset, - drive="scsi-hd") - - ASSET_PPC64_KERNEL = Asset( - 'https://storage.tuxboot.com/buildroot/20241119/ppc64/vmlinux', - '8219d5cb26e7654ad7826fe8aee6290f7c01eef44f2cd6d26c15fe8f99e1c17c') - ASSET_PPC64_ROOTFS = Asset( - 'https://storage.tuxboot.com/buildroot/20241119/ppc64/rootfs.ext4.zst', - 'b68e12314303c5dd0fef37ae98021299a206085ae591893e73557af99a02d373') - - def test_ppc64(self): - self.ppc64_common_tuxrun(kernel_asset=self.ASSET_PPC64_KERNEL, - rootfs_asset=self.ASSET_PPC64_ROOTFS, - prefix='tuxrun_ppc64_') - - ASSET_PPC64LE_KERNEL = Asset( - 'https://storage.tuxboot.com/buildroot/20241119/ppc64le/vmlinux', - '21aea1fbc18bf6fa7d8ca4ea48d4940b2c8363c077acd564eb47d769b7495279') - ASSET_PPC64LE_ROOTFS = Asset( - 'https://storage.tuxboot.com/buildroot/20241119/ppc64le/rootfs.ext4.zst', - '67d36a3f9597b738e8b7359bdf04500f4d9bb82fc35eaa65aa439d888b2392f4') - - def test_ppc64le(self): - self.ppc64_common_tuxrun(kernel_asset=self.ASSET_PPC64LE_KERNEL, - rootfs_asset=self.ASSET_PPC64LE_ROOTFS, - prefix='tuxrun_ppc64le_') - - -if __name__ == '__main__': - TuxRunBaselineTest.main() diff --git a/tests/functional/test_ppc_40p.py b/tests/functional/test_ppc_40p.py deleted file mode 100755 index 614972a..0000000 --- a/tests/functional/test_ppc_40p.py +++ /dev/null @@ -1,94 +0,0 @@ -#!/usr/bin/env python3 -# -# Functional test that boots a PReP/40p machine and checks its serial console. -# -# Copyright (c) Philippe Mathieu-Daudé -# -# This work is licensed under the terms of the GNU GPL, version 2 or -# later. See the COPYING file in the top-level directory. - -from qemu_test import QemuSystemTest, Asset -from qemu_test import wait_for_console_pattern, skipUntrustedTest -from qemu_test import exec_command_and_wait_for_pattern - - -class IbmPrep40pMachine(QemuSystemTest): - - timeout = 60 - - ASSET_BIOS = Asset( - ('http://ftpmirror.your.org/pub/misc/' - 'ftp.software.ibm.com/rs6000/firmware/' - '7020-40p/P12H0456.IMG'), - 'd957f79c73f760d1455d2286fcd901ed6d06167320eb73511b478a939be25b3f') - ASSET_NETBSD40 = Asset( - ('https://archive.netbsd.org/pub/NetBSD-archive/' - 'NetBSD-4.0/prep/installation/floppy/generic_com0.fs'), - 'f86236e9d01b3f0dd0f5d3b8d5bbd40c68e78b4db560a108358f5ad58e636619') - ASSET_NETBSD71 = Asset( - ('https://archive.netbsd.org/pub/NetBSD-archive/' - 'NetBSD-7.1.2/iso/NetBSD-7.1.2-prep.iso'), - 'cc7cb290b06aaa839362deb7bd9f417ac5015557db24088508330f76c3f825ec') - - # 12H0455 PPS Firmware Licensed Materials - # Property of IBM (C) Copyright IBM Corp. 1994. - # All rights reserved. - # U.S. Government Users Restricted Rights - Use, duplication or disclosure - # restricted by GSA ADP Schedule Contract with IBM Corp. - @skipUntrustedTest() - def test_factory_firmware_and_netbsd(self): - self.set_machine('40p') - self.require_accelerator("tcg") - bios_path = self.ASSET_BIOS.fetch() - drive_path = self.ASSET_NETBSD40.fetch() - - self.vm.set_console() - self.vm.add_args('-bios', bios_path, - '-drive', - f"file={drive_path},format=raw,if=floppy,read-only=true") - self.vm.launch() - os_banner = 'NetBSD 4.0 (GENERIC) #0: Sun Dec 16 00:49:40 PST 2007' - wait_for_console_pattern(self, os_banner) - wait_for_console_pattern(self, 'Model: IBM PPS Model 6015') - - def test_openbios_192m(self): - self.set_machine('40p') - self.require_accelerator("tcg") - self.vm.set_console() - self.vm.add_args('-m', '192') # test fw_cfg - - self.vm.launch() - wait_for_console_pattern(self, '>> OpenBIOS') - wait_for_console_pattern(self, '>> Memory: 192M') - wait_for_console_pattern(self, '>> CPU type PowerPC,604') - - def test_openbios_and_netbsd(self): - self.set_machine('40p') - self.require_accelerator("tcg") - drive_path = self.ASSET_NETBSD71.fetch() - self.vm.set_console() - self.vm.add_args('-cdrom', drive_path, - '-boot', 'd') - - self.vm.launch() - wait_for_console_pattern(self, 'NetBSD/prep BOOT, Revision 1.9') - - ASSET_40P_SANDALFOOT = Asset( - 'http://www.juneau-lug.org/zImage.initrd.sandalfoot', - '749ab02f576c6dc8f33b9fb022ecb44bf6a35a0472f2ea6a5e9956bc15933901') - - def test_openbios_and_linux(self): - self.set_machine('40p') - self.require_accelerator("tcg") - drive_path = self.ASSET_40P_SANDALFOOT.fetch() - self.vm.set_console() - self.vm.add_args('-cdrom', drive_path, - '-boot', 'd') - - self.vm.launch() - wait_for_console_pattern(self, 'Please press Enter to activate this console.') - exec_command_and_wait_for_pattern(self, '\012', '#') - exec_command_and_wait_for_pattern(self, 'uname -a', 'Linux ppc 2.4.18') - -if __name__ == '__main__': - QemuSystemTest.main() diff --git a/tests/functional/test_ppc_74xx.py b/tests/functional/test_ppc_74xx.py deleted file mode 100755 index 5386016..0000000 --- a/tests/functional/test_ppc_74xx.py +++ /dev/null @@ -1,126 +0,0 @@ -#!/usr/bin/env python3 -# -# Smoke tests for 74xx cpus (aka G4). -# -# Copyright (c) 2021, IBM Corp. -# -# This work is licensed under the terms of the GNU GPL, version 2 or -# later. See the COPYING file in the top-level directory. - -from qemu_test import QemuSystemTest -from qemu_test import wait_for_console_pattern - -class ppc74xxCpu(QemuSystemTest): - - timeout = 5 - - def test_ppc_7400(self): - self.require_accelerator("tcg") - self.set_machine('g3beige') - self.vm.set_console() - self.vm.add_args('-cpu', '7400') - self.vm.launch() - wait_for_console_pattern(self, '>> OpenBIOS') - wait_for_console_pattern(self, '>> CPU type PowerPC,G4') - - def test_ppc_7410(self): - self.require_accelerator("tcg") - self.set_machine('g3beige') - self.vm.set_console() - self.vm.add_args('-cpu', '7410') - self.vm.launch() - wait_for_console_pattern(self, '>> OpenBIOS') - wait_for_console_pattern(self, '>> CPU type PowerPC,74xx') - - def test_ppc_7441(self): - self.require_accelerator("tcg") - self.set_machine('g3beige') - self.vm.set_console() - self.vm.add_args('-cpu', '7441') - self.vm.launch() - wait_for_console_pattern(self, '>> OpenBIOS') - wait_for_console_pattern(self, '>> CPU type PowerPC,G4') - - def test_ppc_7445(self): - self.require_accelerator("tcg") - self.set_machine('g3beige') - self.vm.set_console() - self.vm.add_args('-cpu', '7445') - self.vm.launch() - wait_for_console_pattern(self, '>> OpenBIOS') - wait_for_console_pattern(self, '>> CPU type PowerPC,G4') - - def test_ppc_7447(self): - self.require_accelerator("tcg") - self.set_machine('g3beige') - self.vm.set_console() - self.vm.add_args('-cpu', '7447') - self.vm.launch() - wait_for_console_pattern(self, '>> OpenBIOS') - wait_for_console_pattern(self, '>> CPU type PowerPC,G4') - - def test_ppc_7447a(self): - self.require_accelerator("tcg") - self.set_machine('g3beige') - self.vm.set_console() - self.vm.add_args('-cpu', '7447a') - self.vm.launch() - wait_for_console_pattern(self, '>> OpenBIOS') - wait_for_console_pattern(self, '>> CPU type PowerPC,G4') - - def test_ppc_7448(self): - self.require_accelerator("tcg") - self.set_machine('g3beige') - self.vm.set_console() - self.vm.add_args('-cpu', '7448') - self.vm.launch() - wait_for_console_pattern(self, '>> OpenBIOS') - wait_for_console_pattern(self, '>> CPU type PowerPC,MPC86xx') - - def test_ppc_7450(self): - self.require_accelerator("tcg") - self.set_machine('g3beige') - self.vm.set_console() - self.vm.add_args('-cpu', '7450') - self.vm.launch() - wait_for_console_pattern(self, '>> OpenBIOS') - wait_for_console_pattern(self, '>> CPU type PowerPC,G4') - - def test_ppc_7451(self): - self.require_accelerator("tcg") - self.set_machine('g3beige') - self.vm.set_console() - self.vm.add_args('-cpu', '7451') - self.vm.launch() - wait_for_console_pattern(self, '>> OpenBIOS') - wait_for_console_pattern(self, '>> CPU type PowerPC,G4') - - def test_ppc_7455(self): - self.require_accelerator("tcg") - self.set_machine('g3beige') - self.vm.set_console() - self.vm.add_args('-cpu', '7455') - self.vm.launch() - wait_for_console_pattern(self, '>> OpenBIOS') - wait_for_console_pattern(self, '>> CPU type PowerPC,G4') - - def test_ppc_7457(self): - self.require_accelerator("tcg") - self.set_machine('g3beige') - self.vm.set_console() - self.vm.add_args('-cpu', '7457') - self.vm.launch() - wait_for_console_pattern(self, '>> OpenBIOS') - wait_for_console_pattern(self, '>> CPU type PowerPC,G4') - - def test_ppc_7457a(self): - self.require_accelerator("tcg") - self.set_machine('g3beige') - self.vm.set_console() - self.vm.add_args('-cpu', '7457a') - self.vm.launch() - wait_for_console_pattern(self, '>> OpenBIOS') - wait_for_console_pattern(self, '>> CPU type PowerPC,G4') - -if __name__ == '__main__': - QemuSystemTest.main() diff --git a/tests/functional/test_ppc_amiga.py b/tests/functional/test_ppc_amiga.py deleted file mode 100755 index 8600e2e..0000000 --- a/tests/functional/test_ppc_amiga.py +++ /dev/null @@ -1,43 +0,0 @@ -#!/usr/bin/env python3 -# -# Test AmigaNG boards -# -# Copyright (c) 2023 BALATON Zoltan -# -# This work is licensed under the terms of the GNU GPL, version 2 or -# later. See the COPYING file in the top-level directory. - -import subprocess - -from qemu_test import QemuSystemTest, Asset -from qemu_test import wait_for_console_pattern - - -class AmigaOneMachine(QemuSystemTest): - - timeout = 90 - - ASSET_IMAGE = Asset( - ('https://www.hyperion-entertainment.com/index.php/' - 'downloads?view=download&format=raw&file=25'), - '8ff39330ba47d4f64de4ee8fd6809e9c010a9ef17fe51e95c3c1d53437cb481f') - - def test_ppc_amigaone(self): - self.require_accelerator("tcg") - self.set_machine('amigaone') - tar_name = 'A1Firmware_Floppy_05-Mar-2005.zip' - self.archive_extract(self.ASSET_IMAGE, format="zip") - bios = self.scratch_file("u-boot-amigaone.bin") - with open(bios, "wb") as bios_fh: - subprocess.run(['tail', '-c', '524288', - self.scratch_file("floppy_edition", - "updater.image")], - stdout=bios_fh) - - self.vm.set_console() - self.vm.add_args('-bios', bios) - self.vm.launch() - wait_for_console_pattern(self, 'FLASH:') - -if __name__ == '__main__': - QemuSystemTest.main() diff --git a/tests/functional/test_ppc_bamboo.py b/tests/functional/test_ppc_bamboo.py deleted file mode 100755 index c634ae7..0000000 --- a/tests/functional/test_ppc_bamboo.py +++ /dev/null @@ -1,48 +0,0 @@ -#!/usr/bin/env python3 -# -# Test that Linux kernel boots on the ppc bamboo board and check the console -# -# Copyright (c) 2021 Red Hat -# -# This work is licensed under the terms of the GNU GPL, version 2 or -# later. See the COPYING file in the top-level directory. - -from qemu_test import QemuSystemTest, Asset -from qemu_test import wait_for_console_pattern -from qemu_test import exec_command_and_wait_for_pattern - - -class BambooMachine(QemuSystemTest): - - timeout = 90 - - ASSET_KERNEL = Asset( - ('https://github.com/legoater/qemu-ppc-boot/raw/refs/heads/main/' - 'buildroot/qemu_ppc_bamboo-2023.11-8-gdcd9f0f6eb-20240105/vmlinux'), - 'a2e12eb45b73491ac62fc0bbeb68dead0dc5c0f22cf83146558389209b420ad1') - ASSET_INITRD = Asset( - ('https://github.com/legoater/qemu-ppc-boot/raw/refs/heads/main/' - 'buildroot/qemu_ppc_bamboo-2023.11-8-gdcd9f0f6eb-20240105/rootfs.cpio'), - 'd2a36bdb8763b389765dc8c29d4904cec2bd001c587f92e85ab9eb10d5ddda54') - - def test_ppc_bamboo(self): - self.set_machine('bamboo') - self.require_accelerator("tcg") - self.require_netdev('user') - - kernel = self.ASSET_KERNEL.fetch() - initrd = self.ASSET_INITRD.fetch() - - self.vm.set_console() - self.vm.add_args('-kernel', kernel, - '-initrd', initrd, - '-nic', 'user,model=virtio-net-pci,restrict=on') - self.vm.launch() - wait_for_console_pattern(self, 'buildroot login:') - exec_command_and_wait_for_pattern(self, 'root', '#') - exec_command_and_wait_for_pattern(self, 'ping -c1 10.0.2.2', - '1 packets transmitted, 1 packets received, 0% packet loss') - exec_command_and_wait_for_pattern(self, 'halt', 'System Halted') - -if __name__ == '__main__': - QemuSystemTest.main() diff --git a/tests/functional/test_ppc_mac.py b/tests/functional/test_ppc_mac.py deleted file mode 100755 index 9e4bc1a..0000000 --- a/tests/functional/test_ppc_mac.py +++ /dev/null @@ -1,36 +0,0 @@ -#!/usr/bin/env python3 -# -# Boot Linux kernel on a mac99 and g3beige ppc machine and check the console -# -# SPDX-License-Identifier: GPL-2.0-or-later - -from qemu_test import LinuxKernelTest, Asset - - -class MacTest(LinuxKernelTest): - - ASSET_DAY15 = Asset( - 'https://qemu-advcal.gitlab.io/qac-best-of-multiarch/download/day15.tar.xz', - '03e0757c131d2959decf293a3572d3b96c5a53587165bf05ce41b2818a2bccd5') - - def do_day15_test(self): - # mac99 also works with kvm_pr but we don't have a reliable way at - # the moment (e.g. by looking at /proc/modules) to detect whether - # we're running kvm_hv or kvm_pr. For now let's disable this test - # if we don't have TCG support. - self.require_accelerator("tcg") - self.archive_extract(self.ASSET_DAY15) - self.vm.add_args('-M', 'graphics=off') - self.launch_kernel(self.scratch_file('day15', 'invaders.elf'), - wait_for='QEMU advent calendar') - - def test_ppc_g3beige(self): - self.set_machine('g3beige') - self.do_day15_test() - - def test_ppc_mac99(self): - self.set_machine('mac99') - self.do_day15_test() - -if __name__ == '__main__': - LinuxKernelTest.main() diff --git a/tests/functional/test_ppc_migration.py b/tests/functional/test_ppc_migration.py deleted file mode 100755 index a869282..0000000 --- a/tests/functional/test_ppc_migration.py +++ /dev/null @@ -1,26 +0,0 @@ -#!/usr/bin/env python3 -# -# SPDX-License-Identifier: GPL-2.0-or-later -# -# ppc migration test - -from migration import MigrationTest - - -class PpcMigrationTest(MigrationTest): - - def test_migration_with_tcp_localhost(self): - self.set_machine('sam460ex') - self.migration_with_tcp_localhost() - - def test_migration_with_unix(self): - self.set_machine('sam460ex') - self.migration_with_unix() - - def test_migration_with_exec(self): - self.set_machine('sam460ex') - self.migration_with_exec() - - -if __name__ == '__main__': - MigrationTest.main() diff --git a/tests/functional/test_ppc_mpc8544ds.py b/tests/functional/test_ppc_mpc8544ds.py deleted file mode 100755 index 0715410..0000000 --- a/tests/functional/test_ppc_mpc8544ds.py +++ /dev/null @@ -1,37 +0,0 @@ -#!/usr/bin/env python3 -# -# Test that Linux kernel boots on ppc machines and check the console -# -# Copyright (c) 2018, 2020 Red Hat, Inc. -# -# This work is licensed under the terms of the GNU GPL, version 2 or -# later. See the COPYING file in the top-level directory. - -from qemu_test import QemuSystemTest, Asset -from qemu_test import wait_for_console_pattern - - -class Mpc8544dsMachine(QemuSystemTest): - - timeout = 90 - KERNEL_COMMON_COMMAND_LINE = 'printk.time=0 ' - panic_message = 'Kernel panic - not syncing' - - ASSET_IMAGE = Asset( - ('https://qemu-advcal.gitlab.io/qac-best-of-multiarch/download/' - 'day04.tar.xz'), - '88bc83f3c9f3d633bcfc108a6342d677abca247066a2fb8d4636744a0d319f94') - - def test_ppc_mpc8544ds(self): - self.require_accelerator("tcg") - self.set_machine('mpc8544ds') - kernel_file = self.archive_extract(self.ASSET_IMAGE, - member='creek/creek.bin') - self.vm.set_console() - self.vm.add_args('-kernel', kernel_file) - self.vm.launch() - wait_for_console_pattern(self, 'QEMU advent calendar 2020', - self.panic_message) - -if __name__ == '__main__': - QemuSystemTest.main() diff --git a/tests/functional/test_ppc_replay.py b/tests/functional/test_ppc_replay.py deleted file mode 100755 index 8382070..0000000 --- a/tests/functional/test_ppc_replay.py +++ /dev/null @@ -1,34 +0,0 @@ -#!/usr/bin/env python3 -# -# Replay tests for ppc machines -# -# SPDX-License-Identifier: GPL-2.0-or-later - -from qemu_test import Asset -from replay_kernel import ReplayKernelBase - - -class PpcReplay(ReplayKernelBase): - - ASSET_DAY15 = Asset( - 'https://qemu-advcal.gitlab.io/qac-best-of-multiarch/download/day15.tar.xz', - '03e0757c131d2959decf293a3572d3b96c5a53587165bf05ce41b2818a2bccd5') - - def do_day15_test(self): - self.require_accelerator("tcg") - kernel_path = self.archive_extract(self.ASSET_DAY15, - member='day15/invaders.elf') - self.run_rr(kernel_path, self.REPLAY_KERNEL_COMMAND_LINE, - 'QEMU advent calendar', args=('-M', 'graphics=off')) - - def test_g3beige(self): - self.set_machine('g3beige') - self.do_day15_test() - - def test_mac99(self): - self.set_machine('mac99') - self.do_day15_test() - - -if __name__ == '__main__': - ReplayKernelBase.main() diff --git a/tests/functional/test_ppc_sam460ex.py b/tests/functional/test_ppc_sam460ex.py deleted file mode 100644 index 31cf9dd..0000000 --- a/tests/functional/test_ppc_sam460ex.py +++ /dev/null @@ -1,38 +0,0 @@ -#!/usr/bin/env python3 -# -# Functional test that boots a sam460ex machine with a PPC 460EX CPU -# -# SPDX-License-Identifier: GPL-2.0-or-later - -from qemu_test import LinuxKernelTest, Asset -from qemu_test import exec_command_and_wait_for_pattern - - -class sam460exTest(LinuxKernelTest): - - ASSET_BR2_SAM460EX_LINUX = Asset( - 'https://github.com/legoater/qemu-ppc-boot/raw/refs/heads/main/buildroot/qemu_ppc_sam460ex-2023.11-8-gdcd9f0f6eb-20240105/vmlinux', - '6f46346f3e20e8b5fc050ff363f350f8b9d76a051b9e0bd7ea470cc680c14df2') - - def test_ppc_sam460ex_buildroot(self): - self.set_machine('sam460ex') - self.require_netdev('user') - - linux_path = self.ASSET_BR2_SAM460EX_LINUX.fetch() - - self.vm.set_console() - self.vm.add_args('-kernel', linux_path, - '-device', 'virtio-net-pci,netdev=net0', - '-netdev', 'user,id=net0') - self.vm.launch() - - self.wait_for_console_pattern('Linux version') - self.wait_for_console_pattern('Hardware name: amcc,canyonlands 460EX') - self.wait_for_console_pattern('/init as init process') - self.wait_for_console_pattern('lease of 10.0.2.15 obtained') - self.wait_for_console_pattern('buildroot login:') - exec_command_and_wait_for_pattern(self, 'root', '#') - exec_command_and_wait_for_pattern(self, 'poweroff', 'System Halted') - -if __name__ == '__main__': - LinuxKernelTest.main() diff --git a/tests/functional/test_ppc_tuxrun.py b/tests/functional/test_ppc_tuxrun.py deleted file mode 100755 index 5458a7f..0000000 --- a/tests/functional/test_ppc_tuxrun.py +++ /dev/null @@ -1,35 +0,0 @@ -#!/usr/bin/env python3 -# -# Functional test that boots known good tuxboot images the same way -# that tuxrun (www.tuxrun.org) does. This tool is used by things like -# the LKFT project to run regression tests on kernels. -# -# Copyright (c) 2023 Linaro Ltd. -# -# Author: -# Alex Bennée -# -# SPDX-License-Identifier: GPL-2.0-or-later - -from qemu_test import Asset -from qemu_test.tuxruntest import TuxRunBaselineTest - -class TuxRunPPC32Test(TuxRunBaselineTest): - - ASSET_PPC32_KERNEL = Asset( - 'https://storage.tuxboot.com/buildroot/20241119/ppc32/uImage', - 'aa5d81deabdb255a318c4bc5ffd6fdd2b5da1ef39f1955dcc35b671d258b68e9') - ASSET_PPC32_ROOTFS = Asset( - 'https://storage.tuxboot.com/buildroot/20241119/ppc32/rootfs.ext4.zst', - '67554f830269d6bf53b67c7dd206bcc821e463993d526b1644066fea8117019b') - - def test_ppc32(self): - self.set_machine('ppce500') - self.cpu='e500mc' - self.wait_for_shutdown=False - self.common_tuxrun(kernel_asset=self.ASSET_PPC32_KERNEL, - rootfs_asset=self.ASSET_PPC32_ROOTFS, - drive="virtio-blk-pci") - -if __name__ == '__main__': - TuxRunBaselineTest.main() diff --git a/tests/functional/test_ppc_virtex_ml507.py b/tests/functional/test_ppc_virtex_ml507.py deleted file mode 100755 index 8fe4354..0000000 --- a/tests/functional/test_ppc_virtex_ml507.py +++ /dev/null @@ -1,39 +0,0 @@ -#!/usr/bin/env python3 -# -# Test that Linux kernel boots on ppc machines and check the console -# -# Copyright (c) 2018, 2020 Red Hat, Inc. -# -# This work is licensed under the terms of the GNU GPL, version 2 or -# later. See the COPYING file in the top-level directory. - -from qemu_test import QemuSystemTest, Asset -from qemu_test import wait_for_console_pattern - - -class VirtexMl507Machine(QemuSystemTest): - - timeout = 90 - KERNEL_COMMON_COMMAND_LINE = 'printk.time=0 ' - panic_message = 'Kernel panic - not syncing' - - ASSET_IMAGE = Asset( - ('https://qemu-advcal.gitlab.io/qac-best-of-multiarch/download/' - 'day08.tar.xz'), - 'cefe5b8aeb5e9d2d1d4fd22dcf48d917d68d5a765132bf2ddd6332dc393b824c') - - def test_ppc_virtex_ml507(self): - self.require_accelerator("tcg") - self.set_machine('virtex-ml507') - self.archive_extract(self.ASSET_IMAGE) - self.vm.set_console() - self.vm.add_args('-kernel', self.scratch_file('hippo', 'hippo.linux'), - '-dtb', self.scratch_file('hippo', - 'virtex440-ml507.dtb'), - '-m', '512') - self.vm.launch() - wait_for_console_pattern(self, 'QEMU advent calendar 2020', - self.panic_message) - -if __name__ == '__main__': - QemuSystemTest.main() -- cgit v1.1 From e1a8572a8d7a11627db22366d356d0daf0f6d559 Mon Sep 17 00:00:00 2001 From: Thomas Huth Date: Tue, 19 Aug 2025 13:23:54 +0200 Subject: tests/functional: Move riscv32/riscv64 tests into target-specific folders MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The opensbi test is used for both, riscv32 and riscv64. Copy the main test to the riscv64 folder and add a simple wrapper to the riscv32 folder to be able to run it for that target, too. Reviewed-by: Pierrick Bouvier Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Thomas Huth Message-ID: <20250819112403.432587-18-thuth@redhat.com> --- tests/functional/meson.build | 25 +----------- tests/functional/riscv32/meson.build | 10 +++++ tests/functional/riscv32/test_migration.py | 26 ++++++++++++ tests/functional/riscv32/test_opensbi.py | 10 +++++ tests/functional/riscv32/test_tuxrun.py | 38 ++++++++++++++++++ tests/functional/riscv64/meson.build | 15 +++++++ tests/functional/riscv64/test_migration.py | 26 ++++++++++++ tests/functional/riscv64/test_opensbi.py | 36 +++++++++++++++++ tests/functional/riscv64/test_sifive_u.py | 63 ++++++++++++++++++++++++++++++ tests/functional/riscv64/test_tuxrun.py | 51 ++++++++++++++++++++++++ tests/functional/test_riscv32_migration.py | 26 ------------ tests/functional/test_riscv32_tuxrun.py | 38 ------------------ tests/functional/test_riscv64_migration.py | 26 ------------ tests/functional/test_riscv64_sifive_u.py | 63 ------------------------------ tests/functional/test_riscv64_tuxrun.py | 51 ------------------------ tests/functional/test_riscv_opensbi.py | 36 ----------------- 16 files changed, 277 insertions(+), 263 deletions(-) create mode 100644 tests/functional/riscv32/meson.build create mode 100755 tests/functional/riscv32/test_migration.py create mode 100755 tests/functional/riscv32/test_opensbi.py create mode 100755 tests/functional/riscv32/test_tuxrun.py create mode 100644 tests/functional/riscv64/meson.build create mode 100755 tests/functional/riscv64/test_migration.py create mode 100755 tests/functional/riscv64/test_opensbi.py create mode 100755 tests/functional/riscv64/test_sifive_u.py create mode 100755 tests/functional/riscv64/test_tuxrun.py delete mode 100755 tests/functional/test_riscv32_migration.py delete mode 100755 tests/functional/test_riscv32_tuxrun.py delete mode 100755 tests/functional/test_riscv64_migration.py delete mode 100755 tests/functional/test_riscv64_sifive_u.py delete mode 100755 tests/functional/test_riscv64_tuxrun.py delete mode 100755 tests/functional/test_riscv_opensbi.py (limited to 'tests') diff --git a/tests/functional/meson.build b/tests/functional/meson.build index 3caeea5..2d8f67f 100644 --- a/tests/functional/meson.build +++ b/tests/functional/meson.build @@ -26,10 +26,8 @@ subdir('mips64el') subdir('or1k') subdir('ppc') subdir('ppc64') - -test_riscv64_timeouts = { - 'riscv64_tuxrun' : 120, -} +subdir('riscv32') +subdir('riscv64') test_s390x_timeouts = { 's390x_ccw_virtio' : 420, @@ -60,25 +58,6 @@ tests_generic_linuxuser = [ tests_generic_bsduser = [ ] -tests_riscv32_system_quick = [ - 'riscv32_migration', - 'riscv_opensbi', -] - -tests_riscv32_system_thorough = [ - 'riscv32_tuxrun', -] - -tests_riscv64_system_quick = [ - 'riscv64_migration', - 'riscv_opensbi', -] - -tests_riscv64_system_thorough = [ - 'riscv64_sifive_u', - 'riscv64_tuxrun', -] - tests_rx_system_thorough = [ 'rx_gdbsim', ] diff --git a/tests/functional/riscv32/meson.build b/tests/functional/riscv32/meson.build new file mode 100644 index 0000000..f3ebbb8 --- /dev/null +++ b/tests/functional/riscv32/meson.build @@ -0,0 +1,10 @@ +# SPDX-License-Identifier: GPL-2.0-or-later + +tests_riscv32_system_quick = [ + 'migration', + 'opensbi', +] + +tests_riscv32_system_thorough = [ + 'tuxrun', +] diff --git a/tests/functional/riscv32/test_migration.py b/tests/functional/riscv32/test_migration.py new file mode 100755 index 0000000..30acbbe --- /dev/null +++ b/tests/functional/riscv32/test_migration.py @@ -0,0 +1,26 @@ +#!/usr/bin/env python3 +# +# SPDX-License-Identifier: GPL-2.0-or-later +# +# riscv32 migration test + +from migration import MigrationTest + + +class Rv32MigrationTest(MigrationTest): + + def test_migration_with_tcp_localhost(self): + self.set_machine('spike') + self.migration_with_tcp_localhost() + + def test_migration_with_unix(self): + self.set_machine('virt') + self.migration_with_unix() + + def test_migration_with_exec(self): + self.set_machine('spike') + self.migration_with_exec() + + +if __name__ == '__main__': + MigrationTest.main() diff --git a/tests/functional/riscv32/test_opensbi.py b/tests/functional/riscv32/test_opensbi.py new file mode 100755 index 0000000..d1ac706 --- /dev/null +++ b/tests/functional/riscv32/test_opensbi.py @@ -0,0 +1,10 @@ +#!/usr/bin/env python3 +# +# SPDX-License-Identifier: GPL-2.0-or-later +# +# Reuse the 64-bit OpenSBI test for RISC-V 32-bit machines + +from riscv64.test_opensbi import RiscvOpenSBI + +if __name__ == '__main__': + RiscvOpenSBI.main() diff --git a/tests/functional/riscv32/test_tuxrun.py b/tests/functional/riscv32/test_tuxrun.py new file mode 100755 index 0000000..3c57020 --- /dev/null +++ b/tests/functional/riscv32/test_tuxrun.py @@ -0,0 +1,38 @@ +#!/usr/bin/env python3 +# +# Functional test that boots known good tuxboot images the same way +# that tuxrun (www.tuxrun.org) does. This tool is used by things like +# the LKFT project to run regression tests on kernels. +# +# Copyright (c) 2023 Linaro Ltd. +# +# Author: +# Alex Bennée +# +# SPDX-License-Identifier: GPL-2.0-or-later + +from qemu_test import Asset +from qemu_test.tuxruntest import TuxRunBaselineTest + +class TuxRunRiscV32Test(TuxRunBaselineTest): + + ASSET_RISCV32_KERNEL = Asset( + 'https://storage.tuxboot.com/buildroot/20241119/riscv32/Image', + '872bc8f8e0d4661825d5f47f7bec64988e9d0a8bd5db8917d57e16f66d83b329') + ASSET_RISCV32_ROOTFS = Asset( + 'https://storage.tuxboot.com/buildroot/20241119/riscv32/rootfs.ext4.zst', + '511ad34e63222db08d6c1da16fad224970de36517a784110956ba6a24a0ee5f6') + + def test_riscv32(self): + self.set_machine('virt') + self.common_tuxrun(kernel_asset=self.ASSET_RISCV32_KERNEL, + rootfs_asset=self.ASSET_RISCV32_ROOTFS) + + def test_riscv32_maxcpu(self): + self.set_machine('virt') + self.cpu='max' + self.common_tuxrun(kernel_asset=self.ASSET_RISCV32_KERNEL, + rootfs_asset=self.ASSET_RISCV32_ROOTFS) + +if __name__ == '__main__': + TuxRunBaselineTest.main() diff --git a/tests/functional/riscv64/meson.build b/tests/functional/riscv64/meson.build new file mode 100644 index 0000000..c1704d9 --- /dev/null +++ b/tests/functional/riscv64/meson.build @@ -0,0 +1,15 @@ +# SPDX-License-Identifier: GPL-2.0-or-later + +test_riscv64_timeouts = { + 'tuxrun' : 120, +} + +tests_riscv64_system_quick = [ + 'migration', + 'opensbi', +] + +tests_riscv64_system_thorough = [ + 'sifive_u', + 'tuxrun', +] diff --git a/tests/functional/riscv64/test_migration.py b/tests/functional/riscv64/test_migration.py new file mode 100755 index 0000000..2d613a2 --- /dev/null +++ b/tests/functional/riscv64/test_migration.py @@ -0,0 +1,26 @@ +#!/usr/bin/env python3 +# +# SPDX-License-Identifier: GPL-2.0-or-later +# +# riscv64 migration test + +from migration import MigrationTest + + +class Rv64MigrationTest(MigrationTest): + + def test_migration_with_tcp_localhost(self): + self.set_machine('virt') + self.migration_with_tcp_localhost() + + def test_migration_with_unix(self): + self.set_machine('spike') + self.migration_with_unix() + + def test_migration_with_exec(self): + self.set_machine('virt') + self.migration_with_exec() + + +if __name__ == '__main__': + MigrationTest.main() diff --git a/tests/functional/riscv64/test_opensbi.py b/tests/functional/riscv64/test_opensbi.py new file mode 100755 index 0000000..d077e40 --- /dev/null +++ b/tests/functional/riscv64/test_opensbi.py @@ -0,0 +1,36 @@ +#!/usr/bin/env python3 +# +# OpenSBI boot test for RISC-V machines +# +# Copyright (c) 2022, Ventana Micro +# +# This work is licensed under the terms of the GNU GPL, version 2 or +# later. See the COPYING file in the top-level directory. + +from qemu_test import QemuSystemTest +from qemu_test import wait_for_console_pattern + +class RiscvOpenSBI(QemuSystemTest): + + timeout = 5 + + def boot_opensbi(self): + self.vm.set_console() + self.vm.launch() + wait_for_console_pattern(self, 'Platform Name') + wait_for_console_pattern(self, 'Boot HART MEDELEG') + + def test_riscv_spike(self): + self.set_machine('spike') + self.boot_opensbi() + + def test_riscv_sifive_u(self): + self.set_machine('sifive_u') + self.boot_opensbi() + + def test_riscv_virt(self): + self.set_machine('virt') + self.boot_opensbi() + +if __name__ == '__main__': + QemuSystemTest.main() diff --git a/tests/functional/riscv64/test_sifive_u.py b/tests/functional/riscv64/test_sifive_u.py new file mode 100755 index 0000000..358ff0d --- /dev/null +++ b/tests/functional/riscv64/test_sifive_u.py @@ -0,0 +1,63 @@ +#!/usr/bin/env python3 +# +# Functional test that boots a Linux kernel on a Sifive U machine +# and checks the console +# +# Copyright (c) Linaro Ltd. +# +# Author: +# Philippe Mathieu-Daudé +# +# SPDX-License-Identifier: GPL-2.0-or-later + +import os + +from qemu_test import Asset, LinuxKernelTest +from qemu_test import skipIfMissingCommands + + +class SifiveU(LinuxKernelTest): + + ASSET_KERNEL = Asset( + 'https://storage.tuxboot.com/buildroot/20241119/riscv64/Image', + '2bd8132a3bf21570290042324fff48c987f42f2a00c08de979f43f0662ebadba') + ASSET_ROOTFS = Asset( + ('https://github.com/groeck/linux-build-test/raw/' + '9819da19e6eef291686fdd7b029ea00e764dc62f/rootfs/riscv64/' + 'rootfs.ext2.gz'), + 'b6ed95610310b7956f9bf20c4c9c0c05fea647900df441da9dfe767d24e8b28b') + + def do_test_riscv64_sifive_u_mmc_spi(self, connect_card): + self.set_machine('sifive_u') + kernel_path = self.ASSET_KERNEL.fetch() + rootfs_path = self.uncompress(self.ASSET_ROOTFS) + + self.vm.set_console() + kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE + + 'earlycon=sbi console=ttySIF0 ' + 'root=/dev/mmcblk0 ') + self.vm.add_args('-kernel', kernel_path, + '-append', kernel_command_line, + '-no-reboot') + if connect_card: + kernel_command_line += 'panic=-1 noreboot rootwait ' + self.vm.add_args('-drive', f'file={rootfs_path},if=sd,format=raw') + pattern = 'Boot successful.' + else: + kernel_command_line += 'panic=0 noreboot ' + pattern = 'Cannot open root device "mmcblk0" or unknown-block(0,0)' + + self.vm.launch() + self.wait_for_console_pattern(pattern) + + os.remove(rootfs_path) + + def test_riscv64_sifive_u_nommc_spi(self): + self.do_test_riscv64_sifive_u_mmc_spi(False) + + def test_riscv64_sifive_u_mmc_spi(self): + self.do_test_riscv64_sifive_u_mmc_spi(True) + + +if __name__ == '__main__': + LinuxKernelTest.main() diff --git a/tests/functional/riscv64/test_tuxrun.py b/tests/functional/riscv64/test_tuxrun.py new file mode 100755 index 0000000..0d8de36 --- /dev/null +++ b/tests/functional/riscv64/test_tuxrun.py @@ -0,0 +1,51 @@ +#!/usr/bin/env python3 +# +# Functional test that boots known good tuxboot images the same way +# that tuxrun (www.tuxrun.org) does. This tool is used by things like +# the LKFT project to run regression tests on kernels. +# +# Copyright (c) 2023 Linaro Ltd. +# +# Author: +# Alex Bennée +# +# SPDX-License-Identifier: GPL-2.0-or-later + +from qemu_test import Asset +from qemu_test.tuxruntest import TuxRunBaselineTest + +class TuxRunRiscV64Test(TuxRunBaselineTest): + + ASSET_RISCV64_KERNEL = Asset( + 'https://storage.tuxboot.com/buildroot/20241119/riscv64/Image', + '2bd8132a3bf21570290042324fff48c987f42f2a00c08de979f43f0662ebadba') + ASSET_RISCV64_ROOTFS = Asset( + 'https://storage.tuxboot.com/buildroot/20241119/riscv64/rootfs.ext4.zst', + 'aa4736a9872651dfc0d95e709465eedf1134fd19d42b8cb305bfd776f9801004') + + ASSET_RISCV32_KERNEL = Asset( + 'https://storage.tuxboot.com/buildroot/20241119/riscv32/Image', + '872bc8f8e0d4661825d5f47f7bec64988e9d0a8bd5db8917d57e16f66d83b329') + ASSET_RISCV32_ROOTFS = Asset( + 'https://storage.tuxboot.com/buildroot/20241119/riscv32/rootfs.ext4.zst', + '511ad34e63222db08d6c1da16fad224970de36517a784110956ba6a24a0ee5f6') + + def test_riscv64(self): + self.set_machine('virt') + self.common_tuxrun(kernel_asset=self.ASSET_RISCV64_KERNEL, + rootfs_asset=self.ASSET_RISCV64_ROOTFS) + + def test_riscv64_maxcpu(self): + self.set_machine('virt') + self.cpu='max' + self.common_tuxrun(kernel_asset=self.ASSET_RISCV64_KERNEL, + rootfs_asset=self.ASSET_RISCV64_ROOTFS) + + def test_riscv64_rv32(self): + self.set_machine('virt') + self.cpu='rv32' + self.common_tuxrun(kernel_asset=self.ASSET_RISCV32_KERNEL, + rootfs_asset=self.ASSET_RISCV32_ROOTFS) + +if __name__ == '__main__': + TuxRunBaselineTest.main() diff --git a/tests/functional/test_riscv32_migration.py b/tests/functional/test_riscv32_migration.py deleted file mode 100755 index 30acbbe..0000000 --- a/tests/functional/test_riscv32_migration.py +++ /dev/null @@ -1,26 +0,0 @@ -#!/usr/bin/env python3 -# -# SPDX-License-Identifier: GPL-2.0-or-later -# -# riscv32 migration test - -from migration import MigrationTest - - -class Rv32MigrationTest(MigrationTest): - - def test_migration_with_tcp_localhost(self): - self.set_machine('spike') - self.migration_with_tcp_localhost() - - def test_migration_with_unix(self): - self.set_machine('virt') - self.migration_with_unix() - - def test_migration_with_exec(self): - self.set_machine('spike') - self.migration_with_exec() - - -if __name__ == '__main__': - MigrationTest.main() diff --git a/tests/functional/test_riscv32_tuxrun.py b/tests/functional/test_riscv32_tuxrun.py deleted file mode 100755 index 3c57020..0000000 --- a/tests/functional/test_riscv32_tuxrun.py +++ /dev/null @@ -1,38 +0,0 @@ -#!/usr/bin/env python3 -# -# Functional test that boots known good tuxboot images the same way -# that tuxrun (www.tuxrun.org) does. This tool is used by things like -# the LKFT project to run regression tests on kernels. -# -# Copyright (c) 2023 Linaro Ltd. -# -# Author: -# Alex Bennée -# -# SPDX-License-Identifier: GPL-2.0-or-later - -from qemu_test import Asset -from qemu_test.tuxruntest import TuxRunBaselineTest - -class TuxRunRiscV32Test(TuxRunBaselineTest): - - ASSET_RISCV32_KERNEL = Asset( - 'https://storage.tuxboot.com/buildroot/20241119/riscv32/Image', - '872bc8f8e0d4661825d5f47f7bec64988e9d0a8bd5db8917d57e16f66d83b329') - ASSET_RISCV32_ROOTFS = Asset( - 'https://storage.tuxboot.com/buildroot/20241119/riscv32/rootfs.ext4.zst', - '511ad34e63222db08d6c1da16fad224970de36517a784110956ba6a24a0ee5f6') - - def test_riscv32(self): - self.set_machine('virt') - self.common_tuxrun(kernel_asset=self.ASSET_RISCV32_KERNEL, - rootfs_asset=self.ASSET_RISCV32_ROOTFS) - - def test_riscv32_maxcpu(self): - self.set_machine('virt') - self.cpu='max' - self.common_tuxrun(kernel_asset=self.ASSET_RISCV32_KERNEL, - rootfs_asset=self.ASSET_RISCV32_ROOTFS) - -if __name__ == '__main__': - TuxRunBaselineTest.main() diff --git a/tests/functional/test_riscv64_migration.py b/tests/functional/test_riscv64_migration.py deleted file mode 100755 index 2d613a2..0000000 --- a/tests/functional/test_riscv64_migration.py +++ /dev/null @@ -1,26 +0,0 @@ -#!/usr/bin/env python3 -# -# SPDX-License-Identifier: GPL-2.0-or-later -# -# riscv64 migration test - -from migration import MigrationTest - - -class Rv64MigrationTest(MigrationTest): - - def test_migration_with_tcp_localhost(self): - self.set_machine('virt') - self.migration_with_tcp_localhost() - - def test_migration_with_unix(self): - self.set_machine('spike') - self.migration_with_unix() - - def test_migration_with_exec(self): - self.set_machine('virt') - self.migration_with_exec() - - -if __name__ == '__main__': - MigrationTest.main() diff --git a/tests/functional/test_riscv64_sifive_u.py b/tests/functional/test_riscv64_sifive_u.py deleted file mode 100755 index 358ff0d..0000000 --- a/tests/functional/test_riscv64_sifive_u.py +++ /dev/null @@ -1,63 +0,0 @@ -#!/usr/bin/env python3 -# -# Functional test that boots a Linux kernel on a Sifive U machine -# and checks the console -# -# Copyright (c) Linaro Ltd. -# -# Author: -# Philippe Mathieu-Daudé -# -# SPDX-License-Identifier: GPL-2.0-or-later - -import os - -from qemu_test import Asset, LinuxKernelTest -from qemu_test import skipIfMissingCommands - - -class SifiveU(LinuxKernelTest): - - ASSET_KERNEL = Asset( - 'https://storage.tuxboot.com/buildroot/20241119/riscv64/Image', - '2bd8132a3bf21570290042324fff48c987f42f2a00c08de979f43f0662ebadba') - ASSET_ROOTFS = Asset( - ('https://github.com/groeck/linux-build-test/raw/' - '9819da19e6eef291686fdd7b029ea00e764dc62f/rootfs/riscv64/' - 'rootfs.ext2.gz'), - 'b6ed95610310b7956f9bf20c4c9c0c05fea647900df441da9dfe767d24e8b28b') - - def do_test_riscv64_sifive_u_mmc_spi(self, connect_card): - self.set_machine('sifive_u') - kernel_path = self.ASSET_KERNEL.fetch() - rootfs_path = self.uncompress(self.ASSET_ROOTFS) - - self.vm.set_console() - kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE + - 'earlycon=sbi console=ttySIF0 ' - 'root=/dev/mmcblk0 ') - self.vm.add_args('-kernel', kernel_path, - '-append', kernel_command_line, - '-no-reboot') - if connect_card: - kernel_command_line += 'panic=-1 noreboot rootwait ' - self.vm.add_args('-drive', f'file={rootfs_path},if=sd,format=raw') - pattern = 'Boot successful.' - else: - kernel_command_line += 'panic=0 noreboot ' - pattern = 'Cannot open root device "mmcblk0" or unknown-block(0,0)' - - self.vm.launch() - self.wait_for_console_pattern(pattern) - - os.remove(rootfs_path) - - def test_riscv64_sifive_u_nommc_spi(self): - self.do_test_riscv64_sifive_u_mmc_spi(False) - - def test_riscv64_sifive_u_mmc_spi(self): - self.do_test_riscv64_sifive_u_mmc_spi(True) - - -if __name__ == '__main__': - LinuxKernelTest.main() diff --git a/tests/functional/test_riscv64_tuxrun.py b/tests/functional/test_riscv64_tuxrun.py deleted file mode 100755 index 0d8de36..0000000 --- a/tests/functional/test_riscv64_tuxrun.py +++ /dev/null @@ -1,51 +0,0 @@ -#!/usr/bin/env python3 -# -# Functional test that boots known good tuxboot images the same way -# that tuxrun (www.tuxrun.org) does. This tool is used by things like -# the LKFT project to run regression tests on kernels. -# -# Copyright (c) 2023 Linaro Ltd. -# -# Author: -# Alex Bennée -# -# SPDX-License-Identifier: GPL-2.0-or-later - -from qemu_test import Asset -from qemu_test.tuxruntest import TuxRunBaselineTest - -class TuxRunRiscV64Test(TuxRunBaselineTest): - - ASSET_RISCV64_KERNEL = Asset( - 'https://storage.tuxboot.com/buildroot/20241119/riscv64/Image', - '2bd8132a3bf21570290042324fff48c987f42f2a00c08de979f43f0662ebadba') - ASSET_RISCV64_ROOTFS = Asset( - 'https://storage.tuxboot.com/buildroot/20241119/riscv64/rootfs.ext4.zst', - 'aa4736a9872651dfc0d95e709465eedf1134fd19d42b8cb305bfd776f9801004') - - ASSET_RISCV32_KERNEL = Asset( - 'https://storage.tuxboot.com/buildroot/20241119/riscv32/Image', - '872bc8f8e0d4661825d5f47f7bec64988e9d0a8bd5db8917d57e16f66d83b329') - ASSET_RISCV32_ROOTFS = Asset( - 'https://storage.tuxboot.com/buildroot/20241119/riscv32/rootfs.ext4.zst', - '511ad34e63222db08d6c1da16fad224970de36517a784110956ba6a24a0ee5f6') - - def test_riscv64(self): - self.set_machine('virt') - self.common_tuxrun(kernel_asset=self.ASSET_RISCV64_KERNEL, - rootfs_asset=self.ASSET_RISCV64_ROOTFS) - - def test_riscv64_maxcpu(self): - self.set_machine('virt') - self.cpu='max' - self.common_tuxrun(kernel_asset=self.ASSET_RISCV64_KERNEL, - rootfs_asset=self.ASSET_RISCV64_ROOTFS) - - def test_riscv64_rv32(self): - self.set_machine('virt') - self.cpu='rv32' - self.common_tuxrun(kernel_asset=self.ASSET_RISCV32_KERNEL, - rootfs_asset=self.ASSET_RISCV32_ROOTFS) - -if __name__ == '__main__': - TuxRunBaselineTest.main() diff --git a/tests/functional/test_riscv_opensbi.py b/tests/functional/test_riscv_opensbi.py deleted file mode 100755 index d077e40..0000000 --- a/tests/functional/test_riscv_opensbi.py +++ /dev/null @@ -1,36 +0,0 @@ -#!/usr/bin/env python3 -# -# OpenSBI boot test for RISC-V machines -# -# Copyright (c) 2022, Ventana Micro -# -# This work is licensed under the terms of the GNU GPL, version 2 or -# later. See the COPYING file in the top-level directory. - -from qemu_test import QemuSystemTest -from qemu_test import wait_for_console_pattern - -class RiscvOpenSBI(QemuSystemTest): - - timeout = 5 - - def boot_opensbi(self): - self.vm.set_console() - self.vm.launch() - wait_for_console_pattern(self, 'Platform Name') - wait_for_console_pattern(self, 'Boot HART MEDELEG') - - def test_riscv_spike(self): - self.set_machine('spike') - self.boot_opensbi() - - def test_riscv_sifive_u(self): - self.set_machine('sifive_u') - self.boot_opensbi() - - def test_riscv_virt(self): - self.set_machine('virt') - self.boot_opensbi() - -if __name__ == '__main__': - QemuSystemTest.main() -- cgit v1.1 From bbb43ea3be12f09c284954b7b51ae8fea85ebe33 Mon Sep 17 00:00:00 2001 From: Thomas Huth Date: Tue, 19 Aug 2025 13:23:55 +0200 Subject: tests/functional: Move rx test into target-specific folders MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Move the architecture specific test into an architecture specific subdirectory. Reviewed-by: Pierrick Bouvier Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Thomas Huth Message-ID: <20250819112403.432587-19-thuth@redhat.com> --- tests/functional/meson.build | 5 +-- tests/functional/rx/meson.build | 5 +++ tests/functional/rx/test_gdbsim.py | 76 ++++++++++++++++++++++++++++++++++++++ tests/functional/test_rx_gdbsim.py | 76 -------------------------------------- 4 files changed, 82 insertions(+), 80 deletions(-) create mode 100644 tests/functional/rx/meson.build create mode 100755 tests/functional/rx/test_gdbsim.py delete mode 100755 tests/functional/test_rx_gdbsim.py (limited to 'tests') diff --git a/tests/functional/meson.build b/tests/functional/meson.build index 2d8f67f..7e7a6aa 100644 --- a/tests/functional/meson.build +++ b/tests/functional/meson.build @@ -28,6 +28,7 @@ subdir('ppc') subdir('ppc64') subdir('riscv32') subdir('riscv64') +subdir('rx') test_s390x_timeouts = { 's390x_ccw_virtio' : 420, @@ -58,10 +59,6 @@ tests_generic_linuxuser = [ tests_generic_bsduser = [ ] -tests_rx_system_thorough = [ - 'rx_gdbsim', -] - tests_s390x_system_thorough = [ 's390x_ccw_virtio', 's390x_pxelinux', diff --git a/tests/functional/rx/meson.build b/tests/functional/rx/meson.build new file mode 100644 index 0000000..6af83a9 --- /dev/null +++ b/tests/functional/rx/meson.build @@ -0,0 +1,5 @@ +# SPDX-License-Identifier: GPL-2.0-or-later + +tests_rx_system_thorough = [ + 'gdbsim', +] diff --git a/tests/functional/rx/test_gdbsim.py b/tests/functional/rx/test_gdbsim.py new file mode 100755 index 0000000..4924579 --- /dev/null +++ b/tests/functional/rx/test_gdbsim.py @@ -0,0 +1,76 @@ +#!/usr/bin/env python3 +# +# Functional test that boots a Linux kernel and checks the console +# +# Copyright (c) 2018 Red Hat, Inc. +# +# Author: +# Cleber Rosa +# +# This work is licensed under the terms of the GNU GPL, version 2 or +# later. See the COPYING file in the top-level directory. + +from qemu_test import QemuSystemTest, Asset +from qemu_test import exec_command_and_wait_for_pattern +from qemu_test import wait_for_console_pattern, skipFlakyTest + + +class RxGdbSimMachine(QemuSystemTest): + + timeout = 30 + KERNEL_COMMON_COMMAND_LINE = 'printk.time=0 ' + + ASSET_UBOOT = Asset( + ('https://github.com/philmd/qemu-testing-blob/raw/rx-gdbsim/rx/gdbsim/' + 'u-boot.bin'), + 'dd7dd4220cccf7aeb32227b26233bf39600db05c3f8e26005bcc2bf6c927207d') + ASSET_DTB = Asset( + ('https://github.com/philmd/qemu-testing-blob/raw/rx-gdbsim/rx/gdbsim/' + 'rx-gdbsim.dtb'), + 'aa278d9c1907a4501741d7ee57e7f65c02dd1b3e0323b33c6d4247f1b32cf29a') + ASSET_KERNEL = Asset( + ('https://github.com/philmd/qemu-testing-blob/raw/rx-gdbsim/rx/gdbsim/' + 'zImage'), + 'baa43205e74a7220ed8482188c5e9ce497226712abb7f4e7e4f825ce19ff9656') + + def test_uboot(self): + """ + U-Boot and checks that the console is operational. + """ + self.set_machine('gdbsim-r5f562n8') + + uboot_path = self.ASSET_UBOOT.fetch() + + self.vm.set_console() + self.vm.add_args('-bios', uboot_path, + '-no-reboot') + self.vm.launch() + uboot_version = 'U-Boot 2016.05-rc3-23705-ga1ef3c71cb-dirty' + wait_for_console_pattern(self, uboot_version) + gcc_version = 'rx-unknown-linux-gcc (GCC) 9.0.0 20181105 (experimental)' + # FIXME limit baudrate on chardev, else we type too fast + # https://gitlab.com/qemu-project/qemu/-/issues/2691 + #exec_command_and_wait_for_pattern(self, 'version', gcc_version) + + @skipFlakyTest(bug_url="https://gitlab.com/qemu-project/qemu/-/issues/2691") + def test_linux_sash(self): + """ + Boots a Linux kernel and checks that the console is operational. + """ + self.set_machine('gdbsim-r5f562n7') + + dtb_path = self.ASSET_DTB.fetch() + kernel_path = self.ASSET_KERNEL.fetch() + + self.vm.set_console() + kernel_command_line = self.KERNEL_COMMON_COMMAND_LINE + 'earlycon' + self.vm.add_args('-kernel', kernel_path, + '-dtb', dtb_path, + '-no-reboot') + self.vm.launch() + wait_for_console_pattern(self, 'Sash command shell (version 1.1.1)', + failure_message='Kernel panic - not syncing') + exec_command_and_wait_for_pattern(self, 'printenv', 'TERM=linux') + +if __name__ == '__main__': + QemuSystemTest.main() diff --git a/tests/functional/test_rx_gdbsim.py b/tests/functional/test_rx_gdbsim.py deleted file mode 100755 index 4924579..0000000 --- a/tests/functional/test_rx_gdbsim.py +++ /dev/null @@ -1,76 +0,0 @@ -#!/usr/bin/env python3 -# -# Functional test that boots a Linux kernel and checks the console -# -# Copyright (c) 2018 Red Hat, Inc. -# -# Author: -# Cleber Rosa -# -# This work is licensed under the terms of the GNU GPL, version 2 or -# later. See the COPYING file in the top-level directory. - -from qemu_test import QemuSystemTest, Asset -from qemu_test import exec_command_and_wait_for_pattern -from qemu_test import wait_for_console_pattern, skipFlakyTest - - -class RxGdbSimMachine(QemuSystemTest): - - timeout = 30 - KERNEL_COMMON_COMMAND_LINE = 'printk.time=0 ' - - ASSET_UBOOT = Asset( - ('https://github.com/philmd/qemu-testing-blob/raw/rx-gdbsim/rx/gdbsim/' - 'u-boot.bin'), - 'dd7dd4220cccf7aeb32227b26233bf39600db05c3f8e26005bcc2bf6c927207d') - ASSET_DTB = Asset( - ('https://github.com/philmd/qemu-testing-blob/raw/rx-gdbsim/rx/gdbsim/' - 'rx-gdbsim.dtb'), - 'aa278d9c1907a4501741d7ee57e7f65c02dd1b3e0323b33c6d4247f1b32cf29a') - ASSET_KERNEL = Asset( - ('https://github.com/philmd/qemu-testing-blob/raw/rx-gdbsim/rx/gdbsim/' - 'zImage'), - 'baa43205e74a7220ed8482188c5e9ce497226712abb7f4e7e4f825ce19ff9656') - - def test_uboot(self): - """ - U-Boot and checks that the console is operational. - """ - self.set_machine('gdbsim-r5f562n8') - - uboot_path = self.ASSET_UBOOT.fetch() - - self.vm.set_console() - self.vm.add_args('-bios', uboot_path, - '-no-reboot') - self.vm.launch() - uboot_version = 'U-Boot 2016.05-rc3-23705-ga1ef3c71cb-dirty' - wait_for_console_pattern(self, uboot_version) - gcc_version = 'rx-unknown-linux-gcc (GCC) 9.0.0 20181105 (experimental)' - # FIXME limit baudrate on chardev, else we type too fast - # https://gitlab.com/qemu-project/qemu/-/issues/2691 - #exec_command_and_wait_for_pattern(self, 'version', gcc_version) - - @skipFlakyTest(bug_url="https://gitlab.com/qemu-project/qemu/-/issues/2691") - def test_linux_sash(self): - """ - Boots a Linux kernel and checks that the console is operational. - """ - self.set_machine('gdbsim-r5f562n7') - - dtb_path = self.ASSET_DTB.fetch() - kernel_path = self.ASSET_KERNEL.fetch() - - self.vm.set_console() - kernel_command_line = self.KERNEL_COMMON_COMMAND_LINE + 'earlycon' - self.vm.add_args('-kernel', kernel_path, - '-dtb', dtb_path, - '-no-reboot') - self.vm.launch() - wait_for_console_pattern(self, 'Sash command shell (version 1.1.1)', - failure_message='Kernel panic - not syncing') - exec_command_and_wait_for_pattern(self, 'printenv', 'TERM=linux') - -if __name__ == '__main__': - QemuSystemTest.main() -- cgit v1.1 From 5e50a3c9c0f31daf53962914855accdc97a3109b Mon Sep 17 00:00:00 2001 From: Thomas Huth Date: Tue, 19 Aug 2025 13:23:56 +0200 Subject: tests/functional: Move s390x tests into target-specific folders MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The tests/functional folder has become quite crowded, thus move the s390x tests into a target-specific subfolder. Reviewed-by: Pierrick Bouvier Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Thomas Huth Message-ID: <20250819112403.432587-20-thuth@redhat.com> --- tests/functional/meson.build | 13 +- tests/functional/s390x/meson.build | 13 + tests/functional/s390x/test_ccw_virtio.py | 274 ++++++++++++++++++++ tests/functional/s390x/test_pxelinux.py | 119 +++++++++ tests/functional/s390x/test_replay.py | 28 ++ tests/functional/s390x/test_topology.py | 415 ++++++++++++++++++++++++++++++ tests/functional/s390x/test_tuxrun.py | 35 +++ tests/functional/test_s390x_ccw_virtio.py | 274 -------------------- tests/functional/test_s390x_pxelinux.py | 119 --------- tests/functional/test_s390x_replay.py | 28 -- tests/functional/test_s390x_topology.py | 415 ------------------------------ tests/functional/test_s390x_tuxrun.py | 35 --- 12 files changed, 885 insertions(+), 883 deletions(-) create mode 100644 tests/functional/s390x/meson.build create mode 100755 tests/functional/s390x/test_ccw_virtio.py create mode 100755 tests/functional/s390x/test_pxelinux.py create mode 100755 tests/functional/s390x/test_replay.py create mode 100755 tests/functional/s390x/test_topology.py create mode 100755 tests/functional/s390x/test_tuxrun.py delete mode 100755 tests/functional/test_s390x_ccw_virtio.py delete mode 100755 tests/functional/test_s390x_pxelinux.py delete mode 100755 tests/functional/test_s390x_replay.py delete mode 100755 tests/functional/test_s390x_topology.py delete mode 100755 tests/functional/test_s390x_tuxrun.py (limited to 'tests') diff --git a/tests/functional/meson.build b/tests/functional/meson.build index 7e7a6aa..abaa4e0 100644 --- a/tests/functional/meson.build +++ b/tests/functional/meson.build @@ -29,10 +29,7 @@ subdir('ppc64') subdir('riscv32') subdir('riscv64') subdir('rx') - -test_s390x_timeouts = { - 's390x_ccw_virtio' : 420, -} +subdir('s390x') test_sh4_timeouts = { 'sh4_tuxrun' : 240, @@ -59,14 +56,6 @@ tests_generic_linuxuser = [ tests_generic_bsduser = [ ] -tests_s390x_system_thorough = [ - 's390x_ccw_virtio', - 's390x_pxelinux', - 's390x_replay', - 's390x_topology', - 's390x_tuxrun', -] - tests_sh4_system_thorough = [ 'sh4_r2d', 'sh4_tuxrun', diff --git a/tests/functional/s390x/meson.build b/tests/functional/s390x/meson.build new file mode 100644 index 0000000..030b116 --- /dev/null +++ b/tests/functional/s390x/meson.build @@ -0,0 +1,13 @@ +# SPDX-License-Identifier: GPL-2.0-or-later + +test_s390x_timeouts = { + 'ccw_virtio' : 420, +} + +tests_s390x_system_thorough = [ + 'ccw_virtio', + 'pxelinux', + 'replay', + 'topology', + 'tuxrun', +] diff --git a/tests/functional/s390x/test_ccw_virtio.py b/tests/functional/s390x/test_ccw_virtio.py new file mode 100755 index 0000000..453711a --- /dev/null +++ b/tests/functional/s390x/test_ccw_virtio.py @@ -0,0 +1,274 @@ +#!/usr/bin/env python3 +# +# Functional test that boots an s390x Linux guest with ccw and PCI devices +# attached and checks whether the devices are recognized by Linux +# +# Copyright (c) 2020 Red Hat, Inc. +# +# Author: +# Cornelia Huck +# +# This work is licensed under the terms of the GNU GPL, version 2 or +# later. See the COPYING file in the top-level directory. + +import os +import tempfile + +from qemu_test import QemuSystemTest, Asset +from qemu_test import exec_command_and_wait_for_pattern +from qemu_test import wait_for_console_pattern + + +class S390CCWVirtioMachine(QemuSystemTest): + KERNEL_COMMON_COMMAND_LINE = 'printk.time=0 ' + + timeout = 120 + + ASSET_BUSTER_KERNEL = Asset( + ('https://snapshot.debian.org/archive/debian/' + '20201126T092837Z/dists/buster/main/installer-s390x/' + '20190702+deb10u6/images/generic/kernel.debian'), + 'd411d17c39ae7ad38d27534376cbe88b68b403c325739364122c2e6f1537e818') + ASSET_BUSTER_INITRD = Asset( + ('https://snapshot.debian.org/archive/debian/' + '20201126T092837Z/dists/buster/main/installer-s390x/' + '20190702+deb10u6/images/generic/initrd.debian'), + '836bbd0fe6a5ca81274c28c2b063ea315ce1868660866e9b60180c575fef9fd5') + + ASSET_F31_KERNEL = Asset( + ('https://archives.fedoraproject.org/pub/archive' + '/fedora-secondary/releases/31/Server/s390x/os' + '/images/kernel.img'), + '480859574f3f44caa6cd35c62d70e1ac0609134e22ce2a954bbed9b110c06e0b') + ASSET_F31_INITRD = Asset( + ('https://archives.fedoraproject.org/pub/archive' + '/fedora-secondary/releases/31/Server/s390x/os' + '/images/initrd.img'), + '04c46095b2c49020b1c2327158898b7db747e4892ae319726192fb949716aa9c') + + def wait_for_console_pattern(self, success_message, vm=None): + wait_for_console_pattern(self, success_message, + failure_message='Kernel panic - not syncing', + vm=vm) + + def wait_for_crw_reports(self): + exec_command_and_wait_for_pattern(self, + 'while ! (dmesg -c | grep CRW) ; do sleep 1 ; done', + 'CRW reports') + + dmesg_clear_count = 1 + def clear_guest_dmesg(self): + exec_command_and_wait_for_pattern(self, 'dmesg -c > /dev/null; ' + r'echo dm_clear\ ' + str(self.dmesg_clear_count), + r'dm_clear ' + str(self.dmesg_clear_count)) + self.dmesg_clear_count += 1 + + def test_s390x_devices(self): + self.set_machine('s390-ccw-virtio') + + kernel_path = self.ASSET_BUSTER_KERNEL.fetch() + initrd_path = self.ASSET_BUSTER_INITRD.fetch() + + self.vm.set_console() + kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE + + 'console=sclp0 root=/dev/ram0 BOOT_DEBUG=3') + self.vm.add_args('-nographic', + '-kernel', kernel_path, + '-initrd', initrd_path, + '-append', kernel_command_line, + '-cpu', 'max,prno-trng=off', + '-device', 'virtio-net-ccw,devno=fe.1.1111', + '-device', + 'virtio-rng-ccw,devno=fe.2.0000,max_revision=0,id=rn1', + '-device', + 'virtio-rng-ccw,devno=fe.3.1234,max_revision=2,id=rn2', + '-device', 'zpci,uid=5,target=zzz', + '-device', 'virtio-net-pci,id=zzz', + '-device', 'zpci,uid=0xa,fid=12,target=serial', + '-device', 'virtio-serial-pci,id=serial', + '-device', 'virtio-balloon-ccw') + self.vm.launch() + + shell_ready = "sh: can't access tty; job control turned off" + self.wait_for_console_pattern(shell_ready) + # first debug shell is too early, we need to wait for device detection + exec_command_and_wait_for_pattern(self, 'exit', shell_ready) + + ccw_bus_ids="0.1.1111 0.2.0000 0.3.1234" + pci_bus_ids="0005:00:00.0 000a:00:00.0" + exec_command_and_wait_for_pattern(self, 'ls /sys/bus/ccw/devices/', + ccw_bus_ids) + exec_command_and_wait_for_pattern(self, 'ls /sys/bus/pci/devices/', + pci_bus_ids) + # check that the device at 0.2.0000 is in legacy mode, while the + # device at 0.3.1234 has the virtio-1 feature bit set + virtio_rng_features="00000000000000000000000000001100" + \ + "10000000000000000000000000000000" + virtio_rng_features_legacy="00000000000000000000000000001100" + \ + "00000000000000000000000000000000" + exec_command_and_wait_for_pattern(self, + 'cat /sys/bus/ccw/devices/0.2.0000/virtio?/features', + virtio_rng_features_legacy) + exec_command_and_wait_for_pattern(self, + 'cat /sys/bus/ccw/devices/0.3.1234/virtio?/features', + virtio_rng_features) + # check that /dev/hwrng works - and that it's gone after ejecting + exec_command_and_wait_for_pattern(self, + 'dd if=/dev/hwrng of=/dev/null bs=1k count=10', + '10+0 records out') + self.clear_guest_dmesg() + self.vm.cmd('device_del', id='rn1') + self.wait_for_crw_reports() + self.clear_guest_dmesg() + self.vm.cmd('device_del', id='rn2') + self.wait_for_crw_reports() + exec_command_and_wait_for_pattern(self, + 'dd if=/dev/hwrng of=/dev/null bs=1k count=10', + 'dd: /dev/hwrng: No such device') + # verify that we indeed have virtio-net devices (without having the + # virtio-net driver handy) + exec_command_and_wait_for_pattern(self, + 'cat /sys/bus/ccw/devices/0.1.1111/cutype', + '3832/01') + exec_command_and_wait_for_pattern(self, + r'cat /sys/bus/pci/devices/0005\:00\:00.0/subsystem_vendor', + r'0x1af4') + exec_command_and_wait_for_pattern(self, + r'cat /sys/bus/pci/devices/0005\:00\:00.0/subsystem_device', + r'0x0001') + # check fid propagation + exec_command_and_wait_for_pattern(self, + r'cat /sys/bus/pci/devices/000a\:00\:00.0/function_id', + r'0x0000000c') + # add another device + self.clear_guest_dmesg() + self.vm.cmd('device_add', driver='virtio-net-ccw', + devno='fe.0.4711', id='net_4711') + self.wait_for_crw_reports() + exec_command_and_wait_for_pattern(self, 'for i in 1 2 3 4 5 6 7 ; do ' + 'if [ -e /sys/bus/ccw/devices/*4711 ]; then break; fi ;' + 'sleep 1 ; done ; ls /sys/bus/ccw/devices/', + '0.0.4711') + # and detach it again + self.clear_guest_dmesg() + self.vm.cmd('device_del', id='net_4711') + self.vm.event_wait(name='DEVICE_DELETED', + match={'data': {'device': 'net_4711'}}) + self.wait_for_crw_reports() + exec_command_and_wait_for_pattern(self, + 'ls /sys/bus/ccw/devices/0.0.4711', + 'No such file or directory') + # test the virtio-balloon device + exec_command_and_wait_for_pattern(self, 'head -n 1 /proc/meminfo', + 'MemTotal: 115640 kB') + self.vm.cmd('human-monitor-command', command_line='balloon 96') + exec_command_and_wait_for_pattern(self, 'head -n 1 /proc/meminfo', + 'MemTotal: 82872 kB') + self.vm.cmd('human-monitor-command', command_line='balloon 128') + exec_command_and_wait_for_pattern(self, 'head -n 1 /proc/meminfo', + 'MemTotal: 115640 kB') + + + def test_s390x_fedora(self): + self.set_machine('s390-ccw-virtio') + + kernel_path = self.ASSET_F31_KERNEL.fetch() + + initrd_path = self.uncompress(self.ASSET_F31_INITRD, format="xz") + + self.vm.set_console() + kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE + ' audit=0 ' + 'rd.plymouth=0 plymouth.enable=0 rd.rescue') + self.vm.add_args('-nographic', + '-smp', '4', + '-m', '512', + '-name', 'Some Guest Name', + '-uuid', '30de4fd9-b4d5-409e-86a5-09b387f70bfa', + '-kernel', kernel_path, + '-initrd', initrd_path, + '-append', kernel_command_line, + '-device', 'zpci,uid=7,target=n', + '-device', 'virtio-net-pci,id=n,mac=02:ca:fe:fa:ce:12', + '-device', 'virtio-rng-ccw,devno=fe.1.9876', + '-device', 'virtio-gpu-ccw,devno=fe.2.5432') + self.vm.launch() + self.wait_for_console_pattern('Kernel command line: %s' + % kernel_command_line) + self.wait_for_console_pattern('Entering emergency mode') + + # Some tests to see whether the CLI options have been considered: + self.log.info("Test whether QEMU CLI options have been considered") + exec_command_and_wait_for_pattern(self, + 'while ! (dmesg | grep enP7p0s0) ; do sleep 1 ; done', + 'virtio_net virtio0 enP7p0s0: renamed') + exec_command_and_wait_for_pattern(self, 'lspci', + '0007:00:00.0 Class 0200: Device 1af4:1000') + exec_command_and_wait_for_pattern(self, + 'cat /sys/class/net/enP7p0s0/address', + '02:ca:fe:fa:ce:12') + exec_command_and_wait_for_pattern(self, 'lscss', '0.1.9876') + exec_command_and_wait_for_pattern(self, 'lscss', '0.2.5432') + exec_command_and_wait_for_pattern(self, 'cat /proc/cpuinfo', + 'processors : 4') + exec_command_and_wait_for_pattern(self, 'grep MemTotal /proc/meminfo', + 'MemTotal: 499848 kB') + exec_command_and_wait_for_pattern(self, 'grep Name /proc/sysinfo', + 'Extended Name: Some Guest Name') + exec_command_and_wait_for_pattern(self, 'grep UUID /proc/sysinfo', + '30de4fd9-b4d5-409e-86a5-09b387f70bfa') + + # Disable blinking cursor, then write some stuff into the framebuffer. + # QEMU's PPM screendumps contain uncompressed 24-bit values, while the + # framebuffer uses 32-bit, so we pad our text with some spaces when + # writing to the framebuffer. Since the PPM is uncompressed, we then + # can simply read the written "magic bytes" back from the PPM file to + # check whether the framebuffer is working as expected. + # Unfortunately, this test is flaky, so we don't run it by default + if os.getenv('QEMU_TEST_FLAKY_TESTS'): + self.log.info("Test screendump of virtio-gpu device") + exec_command_and_wait_for_pattern(self, + 'while ! (dmesg | grep gpudrmfb) ; do sleep 1 ; done', + 'virtio_gpudrmfb frame buffer device') + exec_command_and_wait_for_pattern(self, + r'echo -e "\e[?25l" > /dev/tty0', ':/#') + exec_command_and_wait_for_pattern(self, 'for ((i=0;i<250;i++)); do ' + 'echo " The qu ick fo x j ump s o ver a laz y d og" >> fox.txt;' + 'done', + ':/#') + exec_command_and_wait_for_pattern(self, + 'dd if=fox.txt of=/dev/fb0 bs=1000 oflag=sync,nocache ; rm fox.txt', + '12+0 records out') + with tempfile.NamedTemporaryFile(suffix='.ppm', + prefix='qemu-scrdump-') as ppmfile: + self.vm.cmd('screendump', filename=ppmfile.name) + ppmfile.seek(0) + line = ppmfile.readline() + self.assertEqual(line, b"P6\n") + line = ppmfile.readline() + self.assertEqual(line, b"1280 800\n") + line = ppmfile.readline() + self.assertEqual(line, b"255\n") + line = ppmfile.readline(256) + self.assertEqual(line, b"The quick fox jumps over a lazy dog\n") + else: + self.log.info("Skipped flaky screendump of virtio-gpu device test") + + # Hot-plug a virtio-crypto device and see whether it gets accepted + self.log.info("Test hot-plug virtio-crypto device") + self.clear_guest_dmesg() + self.vm.cmd('object-add', qom_type='cryptodev-backend-builtin', + id='cbe0') + self.vm.cmd('device_add', driver='virtio-crypto-ccw', id='crypdev0', + cryptodev='cbe0', devno='fe.0.2342') + exec_command_and_wait_for_pattern(self, + 'while ! (dmesg -c | grep Accelerator.device) ; do' + ' sleep 1 ; done', 'Accelerator device is ready') + exec_command_and_wait_for_pattern(self, 'lscss', '0.0.2342') + self.vm.cmd('device_del', id='crypdev0') + self.vm.cmd('object-del', id='cbe0') + exec_command_and_wait_for_pattern(self, + 'while ! (dmesg -c | grep Start.virtcrypto_remove) ; do' + ' sleep 1 ; done', 'Start virtcrypto_remove.') + +if __name__ == '__main__': + QemuSystemTest.main() diff --git a/tests/functional/s390x/test_pxelinux.py b/tests/functional/s390x/test_pxelinux.py new file mode 100755 index 0000000..4fc33b8 --- /dev/null +++ b/tests/functional/s390x/test_pxelinux.py @@ -0,0 +1,119 @@ +#!/usr/bin/env python3 +# +# SPDX-License-Identifier: GPL-2.0-or-later +# +# Functional test that checks the pxelinux.cfg network booting of a s390x VM +# (TFTP booting without config file is already tested by the pxe qtest, so +# we don't repeat that here). + +import os +import shutil + +from qemu_test import QemuSystemTest, Asset, wait_for_console_pattern + + +pxelinux_cfg_contents='''# pxelinux.cfg style config file +default Debian +label Nonexisting +kernel kernel.notavailable +initrd initrd.notavailable +label Debian +kernel kernel.debian +initrd initrd.debian +append testoption=teststring +label Fedora +kernel kernel.fedora +''' + +class S390PxeLinux(QemuSystemTest): + + ASSET_DEBIAN_KERNEL = Asset( + ('https://snapshot.debian.org/archive/debian/' + '20201126T092837Z/dists/buster/main/installer-s390x/' + '20190702+deb10u6/images/generic/kernel.debian'), + 'd411d17c39ae7ad38d27534376cbe88b68b403c325739364122c2e6f1537e818') + + ASSET_DEBIAN_INITRD = Asset( + ('https://snapshot.debian.org/archive/debian/' + '20201126T092837Z/dists/buster/main/installer-s390x/' + '20190702+deb10u6/images/generic/initrd.debian'), + '836bbd0fe6a5ca81274c28c2b063ea315ce1868660866e9b60180c575fef9fd5') + + ASSET_FEDORA_KERNEL = Asset( + ('https://archives.fedoraproject.org/pub/archive' + '/fedora-secondary/releases/31/Server/s390x/os' + '/images/kernel.img'), + '480859574f3f44caa6cd35c62d70e1ac0609134e22ce2a954bbed9b110c06e0b') + + def pxelinux_launch(self, pl_name='default', extra_opts=None): + self.require_netdev('user') + self.set_machine('s390-ccw-virtio') + + debian_kernel = self.ASSET_DEBIAN_KERNEL.fetch() + debian_initrd = self.ASSET_DEBIAN_INITRD.fetch() + fedora_kernel = self.ASSET_FEDORA_KERNEL.fetch() + + # Prepare a folder for the TFTP "server": + tftpdir = self.scratch_file('tftp') + shutil.rmtree(tftpdir, ignore_errors=True) # Remove stale stuff + os.mkdir(tftpdir) + shutil.copy(debian_kernel, os.path.join(tftpdir, 'kernel.debian')) + shutil.copy(debian_initrd, os.path.join(tftpdir, 'initrd.debian')) + shutil.copy(fedora_kernel, os.path.join(tftpdir, 'kernel.fedora')) + + pxelinuxdir = self.scratch_file('tftp', 'pxelinux.cfg') + os.mkdir(pxelinuxdir) + + cfg_fname = self.scratch_file('tftp', 'pxelinux.cfg', pl_name) + with open(cfg_fname, 'w', encoding='utf-8') as f: + f.write(pxelinux_cfg_contents) + + virtio_net_dev = 'virtio-net-ccw,netdev=n1,bootindex=1' + if extra_opts: + virtio_net_dev += ',' + extra_opts + + self.vm.add_args('-m', '384', + '-netdev', f'user,id=n1,tftp={tftpdir}', + '-device', virtio_net_dev) + self.vm.set_console() + self.vm.launch() + + + def test_default(self): + self.pxelinux_launch() + # The kernel prints its arguments to the console, so we can use + # this to check whether the kernel parameters are correctly handled: + wait_for_console_pattern(self, 'testoption=teststring') + # Now also check that we've successfully loaded the initrd: + wait_for_console_pattern(self, 'Unpacking initramfs...') + wait_for_console_pattern(self, 'Run /init as init process') + + def test_mac(self): + self.pxelinux_launch(pl_name='01-02-ca-fe-ba-be-42', + extra_opts='mac=02:ca:fe:ba:be:42,loadparm=3') + wait_for_console_pattern(self, 'Linux version 5.3.7-301.fc31.s390x') + + def test_uuid(self): + # Also add a non-bootable disk to check the fallback to network boot: + self.vm.add_args('-blockdev', 'null-co,size=65536,node-name=d1', + '-device', 'virtio-blk,drive=d1,bootindex=0,loadparm=1', + '-uuid', '550e8400-e29b-11d4-a716-446655441234') + self.pxelinux_launch(pl_name='550e8400-e29b-11d4-a716-446655441234') + wait_for_console_pattern(self, 'Debian 4.19.146-1 (2020-09-17)') + + def test_ip(self): + self.vm.add_args('-M', 'loadparm=3') + self.pxelinux_launch(pl_name='0A00020F') + wait_for_console_pattern(self, 'Linux version 5.3.7-301.fc31.s390x') + + def test_menu(self): + self.vm.add_args('-boot', 'menu=on,splash-time=10') + self.pxelinux_launch(pl_name='0A00') + wait_for_console_pattern(self, '[1] Nonexisting') + wait_for_console_pattern(self, '[2] Debian') + wait_for_console_pattern(self, '[3] Fedora') + wait_for_console_pattern(self, 'Debian 4.19.146-1 (2020-09-17)') + + +if __name__ == '__main__': + QemuSystemTest.main() diff --git a/tests/functional/s390x/test_replay.py b/tests/functional/s390x/test_replay.py new file mode 100755 index 0000000..33b5843 --- /dev/null +++ b/tests/functional/s390x/test_replay.py @@ -0,0 +1,28 @@ +#!/usr/bin/env python3 +# +# Replay test that boots a Linux kernel on an s390x machine +# and checks the console +# +# SPDX-License-Identifier: GPL-2.0-or-later + +from qemu_test import Asset +from replay_kernel import ReplayKernelBase + + +class S390xReplay(ReplayKernelBase): + + ASSET_KERNEL = Asset( + ('https://archives.fedoraproject.org/pub/archive/fedora-secondary/' + 'releases/29/Everything/s390x/os/images/kernel.img'), + 'dace03b8ae0c9f670ebb9b8d6ce5eb24b62987f346de8f1300a439bb00bb99e7') + + def test_s390_ccw_virtio(self): + self.set_machine('s390-ccw-virtio') + kernel_path = self.ASSET_KERNEL.fetch() + kernel_command_line = self.KERNEL_COMMON_COMMAND_LINE + 'console=sclp0' + console_pattern = 'Kernel command line: %s' % kernel_command_line + self.run_rr(kernel_path, kernel_command_line, console_pattern, shift=9) + + +if __name__ == '__main__': + ReplayKernelBase.main() diff --git a/tests/functional/s390x/test_topology.py b/tests/functional/s390x/test_topology.py new file mode 100755 index 0000000..1b5dc65 --- /dev/null +++ b/tests/functional/s390x/test_topology.py @@ -0,0 +1,415 @@ +#!/usr/bin/env python3 +# +# Functional test that boots a Linux kernel and checks the console +# +# Copyright IBM Corp. 2023 +# +# Author: +# Pierre Morel +# +# This work is licensed under the terms of the GNU GPL, version 2 or +# later. See the COPYING file in the top-level directory. + +from qemu_test import QemuSystemTest, Asset +from qemu_test import exec_command +from qemu_test import exec_command_and_wait_for_pattern +from qemu_test import wait_for_console_pattern + + +class S390CPUTopology(QemuSystemTest): + """ + S390x CPU topology consists of 4 topology layers, from bottom to top, + the cores, sockets, books and drawers and 2 modifiers attributes, + the entitlement and the dedication. + See: docs/system/s390x/cpu-topology.rst. + + S390x CPU topology is setup in different ways: + - implicitly from the '-smp' argument by completing each topology + level one after the other beginning with drawer 0, book 0 and + socket 0. + - explicitly from the '-device' argument on the QEMU command line + - explicitly by hotplug of a new CPU using QMP or HMP + - it is modified by using QMP 'set-cpu-topology' + + The S390x modifier attribute entitlement depends on the machine + polarization, which can be horizontal or vertical. + The polarization is changed on a request from the guest. + """ + timeout = 90 + event_timeout = 10 + + KERNEL_COMMON_COMMAND_LINE = ('printk.time=0 ' + 'root=/dev/ram ' + 'selinux=0 ' + 'rdinit=/bin/sh') + ASSET_F35_KERNEL = Asset( + ('https://archives.fedoraproject.org/pub/archive' + '/fedora-secondary/releases/35/Server/s390x/os' + '/images/kernel.img'), + '1f2dddfd11bb1393dd2eb2e784036fbf6fc11057a6d7d27f9eb12d3edc67ef73') + + ASSET_F35_INITRD = Asset( + ('https://archives.fedoraproject.org/pub/archive' + '/fedora-secondary/releases/35/Server/s390x/os' + '/images/initrd.img'), + '1100145fbca00240c8c372ae4b89b48c99844bc189b3dfbc3f481dc60055ca46') + + def wait_until_booted(self): + wait_for_console_pattern(self, 'no job control', + failure_message='Kernel panic - not syncing', + vm=None) + + def check_topology(self, c, s, b, d, e, t): + res = self.vm.qmp('query-cpus-fast') + cpus = res['return'] + for cpu in cpus: + core = cpu['props']['core-id'] + socket = cpu['props']['socket-id'] + book = cpu['props']['book-id'] + drawer = cpu['props']['drawer-id'] + entitlement = cpu.get('entitlement') + dedicated = cpu.get('dedicated') + if core == c: + self.assertEqual(drawer, d) + self.assertEqual(book, b) + self.assertEqual(socket, s) + self.assertEqual(entitlement, e) + self.assertEqual(dedicated, t) + + def kernel_init(self): + """ + We need a VM that supports CPU topology, + currently this only the case when using KVM, not TCG. + We need a kernel supporting the CPU topology. + We need a minimal root filesystem with a shell. + """ + self.require_accelerator("kvm") + kernel_path = self.ASSET_F35_KERNEL.fetch() + initrd_path = self.uncompress(self.ASSET_F35_INITRD, format="xz") + + self.vm.set_console() + kernel_command_line = self.KERNEL_COMMON_COMMAND_LINE + self.vm.add_args('-nographic', + '-enable-kvm', + '-cpu', 'max,ctop=on', + '-m', '512', + '-kernel', kernel_path, + '-initrd', initrd_path, + '-append', kernel_command_line) + + def system_init(self): + self.log.info("System init") + exec_command_and_wait_for_pattern(self, + """ mount proc -t proc /proc; + mount sys -t sysfs /sys; + cat /sys/devices/system/cpu/dispatching """, + '0') + + def test_single(self): + """ + This test checks the simplest topology with a single CPU. + """ + self.set_machine('s390-ccw-virtio') + self.kernel_init() + self.vm.launch() + self.wait_until_booted() + self.check_topology(0, 0, 0, 0, 'medium', False) + + def test_default(self): + """ + This test checks the implicit topology. + """ + self.set_machine('s390-ccw-virtio') + self.kernel_init() + self.vm.add_args('-smp', + '13,drawers=2,books=2,sockets=3,cores=2,maxcpus=24') + self.vm.launch() + self.wait_until_booted() + self.check_topology(0, 0, 0, 0, 'medium', False) + self.check_topology(1, 0, 0, 0, 'medium', False) + self.check_topology(2, 1, 0, 0, 'medium', False) + self.check_topology(3, 1, 0, 0, 'medium', False) + self.check_topology(4, 2, 0, 0, 'medium', False) + self.check_topology(5, 2, 0, 0, 'medium', False) + self.check_topology(6, 0, 1, 0, 'medium', False) + self.check_topology(7, 0, 1, 0, 'medium', False) + self.check_topology(8, 1, 1, 0, 'medium', False) + self.check_topology(9, 1, 1, 0, 'medium', False) + self.check_topology(10, 2, 1, 0, 'medium', False) + self.check_topology(11, 2, 1, 0, 'medium', False) + self.check_topology(12, 0, 0, 1, 'medium', False) + + def test_move(self): + """ + This test checks the topology modification by moving a CPU + to another socket: CPU 0 is moved from socket 0 to socket 2. + """ + self.set_machine('s390-ccw-virtio') + self.kernel_init() + self.vm.add_args('-smp', + '1,drawers=2,books=2,sockets=3,cores=2,maxcpus=24') + self.vm.launch() + self.wait_until_booted() + + self.check_topology(0, 0, 0, 0, 'medium', False) + res = self.vm.qmp('set-cpu-topology', + {'core-id': 0, 'socket-id': 2, 'entitlement': 'low'}) + self.assertEqual(res['return'], {}) + self.check_topology(0, 2, 0, 0, 'low', False) + + def test_dash_device(self): + """ + This test verifies that a CPU defined with the '-device' + command line option finds its right place inside the topology. + """ + self.set_machine('s390-ccw-virtio') + self.kernel_init() + self.vm.add_args('-smp', + '1,drawers=2,books=2,sockets=3,cores=2,maxcpus=24') + self.vm.add_args('-device', 'max-s390x-cpu,core-id=10') + self.vm.add_args('-device', + 'max-s390x-cpu,' + 'core-id=1,socket-id=0,book-id=1,drawer-id=1,entitlement=low') + self.vm.add_args('-device', + 'max-s390x-cpu,' + 'core-id=2,socket-id=0,book-id=1,drawer-id=1,entitlement=medium') + self.vm.add_args('-device', + 'max-s390x-cpu,' + 'core-id=3,socket-id=1,book-id=1,drawer-id=1,entitlement=high') + self.vm.add_args('-device', + 'max-s390x-cpu,' + 'core-id=4,socket-id=1,book-id=1,drawer-id=1') + self.vm.add_args('-device', + 'max-s390x-cpu,' + 'core-id=5,socket-id=2,book-id=1,drawer-id=1,dedicated=true') + + self.vm.launch() + self.wait_until_booted() + + self.check_topology(10, 2, 1, 0, 'medium', False) + self.check_topology(1, 0, 1, 1, 'low', False) + self.check_topology(2, 0, 1, 1, 'medium', False) + self.check_topology(3, 1, 1, 1, 'high', False) + self.check_topology(4, 1, 1, 1, 'medium', False) + self.check_topology(5, 2, 1, 1, 'high', True) + + + def guest_set_dispatching(self, dispatching): + exec_command(self, + f'echo {dispatching} > /sys/devices/system/cpu/dispatching') + self.vm.event_wait('CPU_POLARIZATION_CHANGE', self.event_timeout) + exec_command_and_wait_for_pattern(self, + 'cat /sys/devices/system/cpu/dispatching', dispatching) + + + def test_polarization(self): + """ + This test verifies that QEMU modifies the entitlement change after + several guest polarization change requests. + """ + self.set_machine('s390-ccw-virtio') + self.kernel_init() + self.vm.launch() + self.wait_until_booted() + + self.system_init() + res = self.vm.qmp('query-s390x-cpu-polarization') + self.assertEqual(res['return']['polarization'], 'horizontal') + self.check_topology(0, 0, 0, 0, 'medium', False) + + self.guest_set_dispatching('1') + res = self.vm.qmp('query-s390x-cpu-polarization') + self.assertEqual(res['return']['polarization'], 'vertical') + self.check_topology(0, 0, 0, 0, 'medium', False) + + self.guest_set_dispatching('0') + res = self.vm.qmp('query-s390x-cpu-polarization') + self.assertEqual(res['return']['polarization'], 'horizontal') + self.check_topology(0, 0, 0, 0, 'medium', False) + + + def check_polarization(self, polarization): + #We need to wait for the change to have been propagated to the kernel + exec_command_and_wait_for_pattern(self, + "\n".join([ + "timeout 1 sh -c 'while true", + 'do', + ' syspath="/sys/devices/system/cpu/cpu0/polarization"', + ' polarization="$(cat "$syspath")" || exit', + f' if [ "$polarization" = "{polarization}" ]; then', + ' exit 0', + ' fi', + ' sleep 0.01', + #searched for strings mustn't show up in command, '' to obfuscate + "done' && echo succ''ess || echo fail''ure", + ]), + "success", "failure") + + + def test_entitlement(self): + """ + This test verifies that QEMU modifies the entitlement + after a guest request and that the guest sees the change. + """ + self.set_machine('s390-ccw-virtio') + self.kernel_init() + self.vm.launch() + self.wait_until_booted() + + self.system_init() + + self.check_polarization('horizontal') + self.check_topology(0, 0, 0, 0, 'medium', False) + + self.guest_set_dispatching('1') + self.check_polarization('vertical:medium') + self.check_topology(0, 0, 0, 0, 'medium', False) + + res = self.vm.qmp('set-cpu-topology', + {'core-id': 0, 'entitlement': 'low'}) + self.assertEqual(res['return'], {}) + self.check_polarization('vertical:low') + self.check_topology(0, 0, 0, 0, 'low', False) + + res = self.vm.qmp('set-cpu-topology', + {'core-id': 0, 'entitlement': 'medium'}) + self.assertEqual(res['return'], {}) + self.check_polarization('vertical:medium') + self.check_topology(0, 0, 0, 0, 'medium', False) + + res = self.vm.qmp('set-cpu-topology', + {'core-id': 0, 'entitlement': 'high'}) + self.assertEqual(res['return'], {}) + self.check_polarization('vertical:high') + self.check_topology(0, 0, 0, 0, 'high', False) + + self.guest_set_dispatching('0') + self.check_polarization("horizontal") + self.check_topology(0, 0, 0, 0, 'high', False) + + + def test_dedicated(self): + """ + This test verifies that QEMU adjusts the entitlement correctly when a + CPU is made dedicated. + QEMU retains the entitlement value when horizontal polarization is in effect. + For the guest, the field shows the effective value of the entitlement. + """ + self.set_machine('s390-ccw-virtio') + self.kernel_init() + self.vm.launch() + self.wait_until_booted() + + self.system_init() + + self.check_polarization("horizontal") + + res = self.vm.qmp('set-cpu-topology', + {'core-id': 0, 'dedicated': True}) + self.assertEqual(res['return'], {}) + self.check_topology(0, 0, 0, 0, 'high', True) + self.check_polarization("horizontal") + + self.guest_set_dispatching('1') + self.check_topology(0, 0, 0, 0, 'high', True) + self.check_polarization("vertical:high") + + self.guest_set_dispatching('0') + self.check_topology(0, 0, 0, 0, 'high', True) + self.check_polarization("horizontal") + + + def test_socket_full(self): + """ + This test verifies that QEMU does not accept to overload a socket. + The socket-id 0 on book-id 0 already contains CPUs 0 and 1 and can + not accept any new CPU while socket-id 0 on book-id 1 is free. + """ + self.set_machine('s390-ccw-virtio') + self.kernel_init() + self.vm.add_args('-smp', + '3,drawers=2,books=2,sockets=3,cores=2,maxcpus=24') + self.vm.launch() + self.wait_until_booted() + + self.system_init() + + res = self.vm.qmp('set-cpu-topology', + {'core-id': 2, 'socket-id': 0, 'book-id': 0}) + self.assertEqual(res['error']['class'], 'GenericError') + + res = self.vm.qmp('set-cpu-topology', + {'core-id': 2, 'socket-id': 0, 'book-id': 1}) + self.assertEqual(res['return'], {}) + + def test_dedicated_error(self): + """ + This test verifies that QEMU refuses to lower the entitlement + of a dedicated CPU + """ + self.set_machine('s390-ccw-virtio') + self.kernel_init() + self.vm.launch() + self.wait_until_booted() + + self.system_init() + + res = self.vm.qmp('set-cpu-topology', + {'core-id': 0, 'dedicated': True}) + self.assertEqual(res['return'], {}) + + self.check_topology(0, 0, 0, 0, 'high', True) + + self.guest_set_dispatching('1') + + self.check_topology(0, 0, 0, 0, 'high', True) + + res = self.vm.qmp('set-cpu-topology', + {'core-id': 0, 'entitlement': 'low', 'dedicated': True}) + self.assertEqual(res['error']['class'], 'GenericError') + + res = self.vm.qmp('set-cpu-topology', + {'core-id': 0, 'entitlement': 'low'}) + self.assertEqual(res['error']['class'], 'GenericError') + + res = self.vm.qmp('set-cpu-topology', + {'core-id': 0, 'entitlement': 'medium', 'dedicated': True}) + self.assertEqual(res['error']['class'], 'GenericError') + + res = self.vm.qmp('set-cpu-topology', + {'core-id': 0, 'entitlement': 'medium'}) + self.assertEqual(res['error']['class'], 'GenericError') + + res = self.vm.qmp('set-cpu-topology', + {'core-id': 0, 'entitlement': 'low', 'dedicated': False}) + self.assertEqual(res['return'], {}) + + res = self.vm.qmp('set-cpu-topology', + {'core-id': 0, 'entitlement': 'medium', 'dedicated': False}) + self.assertEqual(res['return'], {}) + + def test_move_error(self): + """ + This test verifies that QEMU refuses to move a CPU to an + nonexistent location + """ + self.set_machine('s390-ccw-virtio') + self.kernel_init() + self.vm.launch() + self.wait_until_booted() + + self.system_init() + + res = self.vm.qmp('set-cpu-topology', {'core-id': 0, 'drawer-id': 1}) + self.assertEqual(res['error']['class'], 'GenericError') + + res = self.vm.qmp('set-cpu-topology', {'core-id': 0, 'book-id': 1}) + self.assertEqual(res['error']['class'], 'GenericError') + + res = self.vm.qmp('set-cpu-topology', {'core-id': 0, 'socket-id': 1}) + self.assertEqual(res['error']['class'], 'GenericError') + + self.check_topology(0, 0, 0, 0, 'medium', False) + +if __name__ == '__main__': + QemuSystemTest.main() diff --git a/tests/functional/s390x/test_tuxrun.py b/tests/functional/s390x/test_tuxrun.py new file mode 100755 index 0000000..8df3c68 --- /dev/null +++ b/tests/functional/s390x/test_tuxrun.py @@ -0,0 +1,35 @@ +#!/usr/bin/env python3 +# +# Functional test that boots known good tuxboot images the same way +# that tuxrun (www.tuxrun.org) does. This tool is used by things like +# the LKFT project to run regression tests on kernels. +# +# Copyright (c) 2023 Linaro Ltd. +# +# Author: +# Alex Bennée +# +# SPDX-License-Identifier: GPL-2.0-or-later + +from qemu_test import Asset +from qemu_test.tuxruntest import TuxRunBaselineTest + +class TuxRunS390xTest(TuxRunBaselineTest): + + ASSET_S390X_KERNEL = Asset( + 'https://storage.tuxboot.com/buildroot/20241119/s390/bzImage', + 'ee67e91db52a2aed104a7c72b2a08987c678f8179c029626789c35d6dd0fedf1') + ASSET_S390X_ROOTFS = Asset( + 'https://storage.tuxboot.com/buildroot/20241119/s390/rootfs.ext4.zst', + 'bff7971fc2fef56372d98afe4557b82fd0a785a241e44c29b058e577ad1bbb44') + + def test_s390(self): + self.set_machine('s390-ccw-virtio') + self.wait_for_shutdown=False + self.common_tuxrun(kernel_asset=self.ASSET_S390X_KERNEL, + rootfs_asset=self.ASSET_S390X_ROOTFS, + drive="virtio-blk-ccw", + haltmsg="Requesting system halt") + +if __name__ == '__main__': + TuxRunBaselineTest.main() diff --git a/tests/functional/test_s390x_ccw_virtio.py b/tests/functional/test_s390x_ccw_virtio.py deleted file mode 100755 index 453711a..0000000 --- a/tests/functional/test_s390x_ccw_virtio.py +++ /dev/null @@ -1,274 +0,0 @@ -#!/usr/bin/env python3 -# -# Functional test that boots an s390x Linux guest with ccw and PCI devices -# attached and checks whether the devices are recognized by Linux -# -# Copyright (c) 2020 Red Hat, Inc. -# -# Author: -# Cornelia Huck -# -# This work is licensed under the terms of the GNU GPL, version 2 or -# later. See the COPYING file in the top-level directory. - -import os -import tempfile - -from qemu_test import QemuSystemTest, Asset -from qemu_test import exec_command_and_wait_for_pattern -from qemu_test import wait_for_console_pattern - - -class S390CCWVirtioMachine(QemuSystemTest): - KERNEL_COMMON_COMMAND_LINE = 'printk.time=0 ' - - timeout = 120 - - ASSET_BUSTER_KERNEL = Asset( - ('https://snapshot.debian.org/archive/debian/' - '20201126T092837Z/dists/buster/main/installer-s390x/' - '20190702+deb10u6/images/generic/kernel.debian'), - 'd411d17c39ae7ad38d27534376cbe88b68b403c325739364122c2e6f1537e818') - ASSET_BUSTER_INITRD = Asset( - ('https://snapshot.debian.org/archive/debian/' - '20201126T092837Z/dists/buster/main/installer-s390x/' - '20190702+deb10u6/images/generic/initrd.debian'), - '836bbd0fe6a5ca81274c28c2b063ea315ce1868660866e9b60180c575fef9fd5') - - ASSET_F31_KERNEL = Asset( - ('https://archives.fedoraproject.org/pub/archive' - '/fedora-secondary/releases/31/Server/s390x/os' - '/images/kernel.img'), - '480859574f3f44caa6cd35c62d70e1ac0609134e22ce2a954bbed9b110c06e0b') - ASSET_F31_INITRD = Asset( - ('https://archives.fedoraproject.org/pub/archive' - '/fedora-secondary/releases/31/Server/s390x/os' - '/images/initrd.img'), - '04c46095b2c49020b1c2327158898b7db747e4892ae319726192fb949716aa9c') - - def wait_for_console_pattern(self, success_message, vm=None): - wait_for_console_pattern(self, success_message, - failure_message='Kernel panic - not syncing', - vm=vm) - - def wait_for_crw_reports(self): - exec_command_and_wait_for_pattern(self, - 'while ! (dmesg -c | grep CRW) ; do sleep 1 ; done', - 'CRW reports') - - dmesg_clear_count = 1 - def clear_guest_dmesg(self): - exec_command_and_wait_for_pattern(self, 'dmesg -c > /dev/null; ' - r'echo dm_clear\ ' + str(self.dmesg_clear_count), - r'dm_clear ' + str(self.dmesg_clear_count)) - self.dmesg_clear_count += 1 - - def test_s390x_devices(self): - self.set_machine('s390-ccw-virtio') - - kernel_path = self.ASSET_BUSTER_KERNEL.fetch() - initrd_path = self.ASSET_BUSTER_INITRD.fetch() - - self.vm.set_console() - kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE + - 'console=sclp0 root=/dev/ram0 BOOT_DEBUG=3') - self.vm.add_args('-nographic', - '-kernel', kernel_path, - '-initrd', initrd_path, - '-append', kernel_command_line, - '-cpu', 'max,prno-trng=off', - '-device', 'virtio-net-ccw,devno=fe.1.1111', - '-device', - 'virtio-rng-ccw,devno=fe.2.0000,max_revision=0,id=rn1', - '-device', - 'virtio-rng-ccw,devno=fe.3.1234,max_revision=2,id=rn2', - '-device', 'zpci,uid=5,target=zzz', - '-device', 'virtio-net-pci,id=zzz', - '-device', 'zpci,uid=0xa,fid=12,target=serial', - '-device', 'virtio-serial-pci,id=serial', - '-device', 'virtio-balloon-ccw') - self.vm.launch() - - shell_ready = "sh: can't access tty; job control turned off" - self.wait_for_console_pattern(shell_ready) - # first debug shell is too early, we need to wait for device detection - exec_command_and_wait_for_pattern(self, 'exit', shell_ready) - - ccw_bus_ids="0.1.1111 0.2.0000 0.3.1234" - pci_bus_ids="0005:00:00.0 000a:00:00.0" - exec_command_and_wait_for_pattern(self, 'ls /sys/bus/ccw/devices/', - ccw_bus_ids) - exec_command_and_wait_for_pattern(self, 'ls /sys/bus/pci/devices/', - pci_bus_ids) - # check that the device at 0.2.0000 is in legacy mode, while the - # device at 0.3.1234 has the virtio-1 feature bit set - virtio_rng_features="00000000000000000000000000001100" + \ - "10000000000000000000000000000000" - virtio_rng_features_legacy="00000000000000000000000000001100" + \ - "00000000000000000000000000000000" - exec_command_and_wait_for_pattern(self, - 'cat /sys/bus/ccw/devices/0.2.0000/virtio?/features', - virtio_rng_features_legacy) - exec_command_and_wait_for_pattern(self, - 'cat /sys/bus/ccw/devices/0.3.1234/virtio?/features', - virtio_rng_features) - # check that /dev/hwrng works - and that it's gone after ejecting - exec_command_and_wait_for_pattern(self, - 'dd if=/dev/hwrng of=/dev/null bs=1k count=10', - '10+0 records out') - self.clear_guest_dmesg() - self.vm.cmd('device_del', id='rn1') - self.wait_for_crw_reports() - self.clear_guest_dmesg() - self.vm.cmd('device_del', id='rn2') - self.wait_for_crw_reports() - exec_command_and_wait_for_pattern(self, - 'dd if=/dev/hwrng of=/dev/null bs=1k count=10', - 'dd: /dev/hwrng: No such device') - # verify that we indeed have virtio-net devices (without having the - # virtio-net driver handy) - exec_command_and_wait_for_pattern(self, - 'cat /sys/bus/ccw/devices/0.1.1111/cutype', - '3832/01') - exec_command_and_wait_for_pattern(self, - r'cat /sys/bus/pci/devices/0005\:00\:00.0/subsystem_vendor', - r'0x1af4') - exec_command_and_wait_for_pattern(self, - r'cat /sys/bus/pci/devices/0005\:00\:00.0/subsystem_device', - r'0x0001') - # check fid propagation - exec_command_and_wait_for_pattern(self, - r'cat /sys/bus/pci/devices/000a\:00\:00.0/function_id', - r'0x0000000c') - # add another device - self.clear_guest_dmesg() - self.vm.cmd('device_add', driver='virtio-net-ccw', - devno='fe.0.4711', id='net_4711') - self.wait_for_crw_reports() - exec_command_and_wait_for_pattern(self, 'for i in 1 2 3 4 5 6 7 ; do ' - 'if [ -e /sys/bus/ccw/devices/*4711 ]; then break; fi ;' - 'sleep 1 ; done ; ls /sys/bus/ccw/devices/', - '0.0.4711') - # and detach it again - self.clear_guest_dmesg() - self.vm.cmd('device_del', id='net_4711') - self.vm.event_wait(name='DEVICE_DELETED', - match={'data': {'device': 'net_4711'}}) - self.wait_for_crw_reports() - exec_command_and_wait_for_pattern(self, - 'ls /sys/bus/ccw/devices/0.0.4711', - 'No such file or directory') - # test the virtio-balloon device - exec_command_and_wait_for_pattern(self, 'head -n 1 /proc/meminfo', - 'MemTotal: 115640 kB') - self.vm.cmd('human-monitor-command', command_line='balloon 96') - exec_command_and_wait_for_pattern(self, 'head -n 1 /proc/meminfo', - 'MemTotal: 82872 kB') - self.vm.cmd('human-monitor-command', command_line='balloon 128') - exec_command_and_wait_for_pattern(self, 'head -n 1 /proc/meminfo', - 'MemTotal: 115640 kB') - - - def test_s390x_fedora(self): - self.set_machine('s390-ccw-virtio') - - kernel_path = self.ASSET_F31_KERNEL.fetch() - - initrd_path = self.uncompress(self.ASSET_F31_INITRD, format="xz") - - self.vm.set_console() - kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE + ' audit=0 ' - 'rd.plymouth=0 plymouth.enable=0 rd.rescue') - self.vm.add_args('-nographic', - '-smp', '4', - '-m', '512', - '-name', 'Some Guest Name', - '-uuid', '30de4fd9-b4d5-409e-86a5-09b387f70bfa', - '-kernel', kernel_path, - '-initrd', initrd_path, - '-append', kernel_command_line, - '-device', 'zpci,uid=7,target=n', - '-device', 'virtio-net-pci,id=n,mac=02:ca:fe:fa:ce:12', - '-device', 'virtio-rng-ccw,devno=fe.1.9876', - '-device', 'virtio-gpu-ccw,devno=fe.2.5432') - self.vm.launch() - self.wait_for_console_pattern('Kernel command line: %s' - % kernel_command_line) - self.wait_for_console_pattern('Entering emergency mode') - - # Some tests to see whether the CLI options have been considered: - self.log.info("Test whether QEMU CLI options have been considered") - exec_command_and_wait_for_pattern(self, - 'while ! (dmesg | grep enP7p0s0) ; do sleep 1 ; done', - 'virtio_net virtio0 enP7p0s0: renamed') - exec_command_and_wait_for_pattern(self, 'lspci', - '0007:00:00.0 Class 0200: Device 1af4:1000') - exec_command_and_wait_for_pattern(self, - 'cat /sys/class/net/enP7p0s0/address', - '02:ca:fe:fa:ce:12') - exec_command_and_wait_for_pattern(self, 'lscss', '0.1.9876') - exec_command_and_wait_for_pattern(self, 'lscss', '0.2.5432') - exec_command_and_wait_for_pattern(self, 'cat /proc/cpuinfo', - 'processors : 4') - exec_command_and_wait_for_pattern(self, 'grep MemTotal /proc/meminfo', - 'MemTotal: 499848 kB') - exec_command_and_wait_for_pattern(self, 'grep Name /proc/sysinfo', - 'Extended Name: Some Guest Name') - exec_command_and_wait_for_pattern(self, 'grep UUID /proc/sysinfo', - '30de4fd9-b4d5-409e-86a5-09b387f70bfa') - - # Disable blinking cursor, then write some stuff into the framebuffer. - # QEMU's PPM screendumps contain uncompressed 24-bit values, while the - # framebuffer uses 32-bit, so we pad our text with some spaces when - # writing to the framebuffer. Since the PPM is uncompressed, we then - # can simply read the written "magic bytes" back from the PPM file to - # check whether the framebuffer is working as expected. - # Unfortunately, this test is flaky, so we don't run it by default - if os.getenv('QEMU_TEST_FLAKY_TESTS'): - self.log.info("Test screendump of virtio-gpu device") - exec_command_and_wait_for_pattern(self, - 'while ! (dmesg | grep gpudrmfb) ; do sleep 1 ; done', - 'virtio_gpudrmfb frame buffer device') - exec_command_and_wait_for_pattern(self, - r'echo -e "\e[?25l" > /dev/tty0', ':/#') - exec_command_and_wait_for_pattern(self, 'for ((i=0;i<250;i++)); do ' - 'echo " The qu ick fo x j ump s o ver a laz y d og" >> fox.txt;' - 'done', - ':/#') - exec_command_and_wait_for_pattern(self, - 'dd if=fox.txt of=/dev/fb0 bs=1000 oflag=sync,nocache ; rm fox.txt', - '12+0 records out') - with tempfile.NamedTemporaryFile(suffix='.ppm', - prefix='qemu-scrdump-') as ppmfile: - self.vm.cmd('screendump', filename=ppmfile.name) - ppmfile.seek(0) - line = ppmfile.readline() - self.assertEqual(line, b"P6\n") - line = ppmfile.readline() - self.assertEqual(line, b"1280 800\n") - line = ppmfile.readline() - self.assertEqual(line, b"255\n") - line = ppmfile.readline(256) - self.assertEqual(line, b"The quick fox jumps over a lazy dog\n") - else: - self.log.info("Skipped flaky screendump of virtio-gpu device test") - - # Hot-plug a virtio-crypto device and see whether it gets accepted - self.log.info("Test hot-plug virtio-crypto device") - self.clear_guest_dmesg() - self.vm.cmd('object-add', qom_type='cryptodev-backend-builtin', - id='cbe0') - self.vm.cmd('device_add', driver='virtio-crypto-ccw', id='crypdev0', - cryptodev='cbe0', devno='fe.0.2342') - exec_command_and_wait_for_pattern(self, - 'while ! (dmesg -c | grep Accelerator.device) ; do' - ' sleep 1 ; done', 'Accelerator device is ready') - exec_command_and_wait_for_pattern(self, 'lscss', '0.0.2342') - self.vm.cmd('device_del', id='crypdev0') - self.vm.cmd('object-del', id='cbe0') - exec_command_and_wait_for_pattern(self, - 'while ! (dmesg -c | grep Start.virtcrypto_remove) ; do' - ' sleep 1 ; done', 'Start virtcrypto_remove.') - -if __name__ == '__main__': - QemuSystemTest.main() diff --git a/tests/functional/test_s390x_pxelinux.py b/tests/functional/test_s390x_pxelinux.py deleted file mode 100755 index 4fc33b8..0000000 --- a/tests/functional/test_s390x_pxelinux.py +++ /dev/null @@ -1,119 +0,0 @@ -#!/usr/bin/env python3 -# -# SPDX-License-Identifier: GPL-2.0-or-later -# -# Functional test that checks the pxelinux.cfg network booting of a s390x VM -# (TFTP booting without config file is already tested by the pxe qtest, so -# we don't repeat that here). - -import os -import shutil - -from qemu_test import QemuSystemTest, Asset, wait_for_console_pattern - - -pxelinux_cfg_contents='''# pxelinux.cfg style config file -default Debian -label Nonexisting -kernel kernel.notavailable -initrd initrd.notavailable -label Debian -kernel kernel.debian -initrd initrd.debian -append testoption=teststring -label Fedora -kernel kernel.fedora -''' - -class S390PxeLinux(QemuSystemTest): - - ASSET_DEBIAN_KERNEL = Asset( - ('https://snapshot.debian.org/archive/debian/' - '20201126T092837Z/dists/buster/main/installer-s390x/' - '20190702+deb10u6/images/generic/kernel.debian'), - 'd411d17c39ae7ad38d27534376cbe88b68b403c325739364122c2e6f1537e818') - - ASSET_DEBIAN_INITRD = Asset( - ('https://snapshot.debian.org/archive/debian/' - '20201126T092837Z/dists/buster/main/installer-s390x/' - '20190702+deb10u6/images/generic/initrd.debian'), - '836bbd0fe6a5ca81274c28c2b063ea315ce1868660866e9b60180c575fef9fd5') - - ASSET_FEDORA_KERNEL = Asset( - ('https://archives.fedoraproject.org/pub/archive' - '/fedora-secondary/releases/31/Server/s390x/os' - '/images/kernel.img'), - '480859574f3f44caa6cd35c62d70e1ac0609134e22ce2a954bbed9b110c06e0b') - - def pxelinux_launch(self, pl_name='default', extra_opts=None): - self.require_netdev('user') - self.set_machine('s390-ccw-virtio') - - debian_kernel = self.ASSET_DEBIAN_KERNEL.fetch() - debian_initrd = self.ASSET_DEBIAN_INITRD.fetch() - fedora_kernel = self.ASSET_FEDORA_KERNEL.fetch() - - # Prepare a folder for the TFTP "server": - tftpdir = self.scratch_file('tftp') - shutil.rmtree(tftpdir, ignore_errors=True) # Remove stale stuff - os.mkdir(tftpdir) - shutil.copy(debian_kernel, os.path.join(tftpdir, 'kernel.debian')) - shutil.copy(debian_initrd, os.path.join(tftpdir, 'initrd.debian')) - shutil.copy(fedora_kernel, os.path.join(tftpdir, 'kernel.fedora')) - - pxelinuxdir = self.scratch_file('tftp', 'pxelinux.cfg') - os.mkdir(pxelinuxdir) - - cfg_fname = self.scratch_file('tftp', 'pxelinux.cfg', pl_name) - with open(cfg_fname, 'w', encoding='utf-8') as f: - f.write(pxelinux_cfg_contents) - - virtio_net_dev = 'virtio-net-ccw,netdev=n1,bootindex=1' - if extra_opts: - virtio_net_dev += ',' + extra_opts - - self.vm.add_args('-m', '384', - '-netdev', f'user,id=n1,tftp={tftpdir}', - '-device', virtio_net_dev) - self.vm.set_console() - self.vm.launch() - - - def test_default(self): - self.pxelinux_launch() - # The kernel prints its arguments to the console, so we can use - # this to check whether the kernel parameters are correctly handled: - wait_for_console_pattern(self, 'testoption=teststring') - # Now also check that we've successfully loaded the initrd: - wait_for_console_pattern(self, 'Unpacking initramfs...') - wait_for_console_pattern(self, 'Run /init as init process') - - def test_mac(self): - self.pxelinux_launch(pl_name='01-02-ca-fe-ba-be-42', - extra_opts='mac=02:ca:fe:ba:be:42,loadparm=3') - wait_for_console_pattern(self, 'Linux version 5.3.7-301.fc31.s390x') - - def test_uuid(self): - # Also add a non-bootable disk to check the fallback to network boot: - self.vm.add_args('-blockdev', 'null-co,size=65536,node-name=d1', - '-device', 'virtio-blk,drive=d1,bootindex=0,loadparm=1', - '-uuid', '550e8400-e29b-11d4-a716-446655441234') - self.pxelinux_launch(pl_name='550e8400-e29b-11d4-a716-446655441234') - wait_for_console_pattern(self, 'Debian 4.19.146-1 (2020-09-17)') - - def test_ip(self): - self.vm.add_args('-M', 'loadparm=3') - self.pxelinux_launch(pl_name='0A00020F') - wait_for_console_pattern(self, 'Linux version 5.3.7-301.fc31.s390x') - - def test_menu(self): - self.vm.add_args('-boot', 'menu=on,splash-time=10') - self.pxelinux_launch(pl_name='0A00') - wait_for_console_pattern(self, '[1] Nonexisting') - wait_for_console_pattern(self, '[2] Debian') - wait_for_console_pattern(self, '[3] Fedora') - wait_for_console_pattern(self, 'Debian 4.19.146-1 (2020-09-17)') - - -if __name__ == '__main__': - QemuSystemTest.main() diff --git a/tests/functional/test_s390x_replay.py b/tests/functional/test_s390x_replay.py deleted file mode 100755 index 33b5843..0000000 --- a/tests/functional/test_s390x_replay.py +++ /dev/null @@ -1,28 +0,0 @@ -#!/usr/bin/env python3 -# -# Replay test that boots a Linux kernel on an s390x machine -# and checks the console -# -# SPDX-License-Identifier: GPL-2.0-or-later - -from qemu_test import Asset -from replay_kernel import ReplayKernelBase - - -class S390xReplay(ReplayKernelBase): - - ASSET_KERNEL = Asset( - ('https://archives.fedoraproject.org/pub/archive/fedora-secondary/' - 'releases/29/Everything/s390x/os/images/kernel.img'), - 'dace03b8ae0c9f670ebb9b8d6ce5eb24b62987f346de8f1300a439bb00bb99e7') - - def test_s390_ccw_virtio(self): - self.set_machine('s390-ccw-virtio') - kernel_path = self.ASSET_KERNEL.fetch() - kernel_command_line = self.KERNEL_COMMON_COMMAND_LINE + 'console=sclp0' - console_pattern = 'Kernel command line: %s' % kernel_command_line - self.run_rr(kernel_path, kernel_command_line, console_pattern, shift=9) - - -if __name__ == '__main__': - ReplayKernelBase.main() diff --git a/tests/functional/test_s390x_topology.py b/tests/functional/test_s390x_topology.py deleted file mode 100755 index 1b5dc65..0000000 --- a/tests/functional/test_s390x_topology.py +++ /dev/null @@ -1,415 +0,0 @@ -#!/usr/bin/env python3 -# -# Functional test that boots a Linux kernel and checks the console -# -# Copyright IBM Corp. 2023 -# -# Author: -# Pierre Morel -# -# This work is licensed under the terms of the GNU GPL, version 2 or -# later. See the COPYING file in the top-level directory. - -from qemu_test import QemuSystemTest, Asset -from qemu_test import exec_command -from qemu_test import exec_command_and_wait_for_pattern -from qemu_test import wait_for_console_pattern - - -class S390CPUTopology(QemuSystemTest): - """ - S390x CPU topology consists of 4 topology layers, from bottom to top, - the cores, sockets, books and drawers and 2 modifiers attributes, - the entitlement and the dedication. - See: docs/system/s390x/cpu-topology.rst. - - S390x CPU topology is setup in different ways: - - implicitly from the '-smp' argument by completing each topology - level one after the other beginning with drawer 0, book 0 and - socket 0. - - explicitly from the '-device' argument on the QEMU command line - - explicitly by hotplug of a new CPU using QMP or HMP - - it is modified by using QMP 'set-cpu-topology' - - The S390x modifier attribute entitlement depends on the machine - polarization, which can be horizontal or vertical. - The polarization is changed on a request from the guest. - """ - timeout = 90 - event_timeout = 10 - - KERNEL_COMMON_COMMAND_LINE = ('printk.time=0 ' - 'root=/dev/ram ' - 'selinux=0 ' - 'rdinit=/bin/sh') - ASSET_F35_KERNEL = Asset( - ('https://archives.fedoraproject.org/pub/archive' - '/fedora-secondary/releases/35/Server/s390x/os' - '/images/kernel.img'), - '1f2dddfd11bb1393dd2eb2e784036fbf6fc11057a6d7d27f9eb12d3edc67ef73') - - ASSET_F35_INITRD = Asset( - ('https://archives.fedoraproject.org/pub/archive' - '/fedora-secondary/releases/35/Server/s390x/os' - '/images/initrd.img'), - '1100145fbca00240c8c372ae4b89b48c99844bc189b3dfbc3f481dc60055ca46') - - def wait_until_booted(self): - wait_for_console_pattern(self, 'no job control', - failure_message='Kernel panic - not syncing', - vm=None) - - def check_topology(self, c, s, b, d, e, t): - res = self.vm.qmp('query-cpus-fast') - cpus = res['return'] - for cpu in cpus: - core = cpu['props']['core-id'] - socket = cpu['props']['socket-id'] - book = cpu['props']['book-id'] - drawer = cpu['props']['drawer-id'] - entitlement = cpu.get('entitlement') - dedicated = cpu.get('dedicated') - if core == c: - self.assertEqual(drawer, d) - self.assertEqual(book, b) - self.assertEqual(socket, s) - self.assertEqual(entitlement, e) - self.assertEqual(dedicated, t) - - def kernel_init(self): - """ - We need a VM that supports CPU topology, - currently this only the case when using KVM, not TCG. - We need a kernel supporting the CPU topology. - We need a minimal root filesystem with a shell. - """ - self.require_accelerator("kvm") - kernel_path = self.ASSET_F35_KERNEL.fetch() - initrd_path = self.uncompress(self.ASSET_F35_INITRD, format="xz") - - self.vm.set_console() - kernel_command_line = self.KERNEL_COMMON_COMMAND_LINE - self.vm.add_args('-nographic', - '-enable-kvm', - '-cpu', 'max,ctop=on', - '-m', '512', - '-kernel', kernel_path, - '-initrd', initrd_path, - '-append', kernel_command_line) - - def system_init(self): - self.log.info("System init") - exec_command_and_wait_for_pattern(self, - """ mount proc -t proc /proc; - mount sys -t sysfs /sys; - cat /sys/devices/system/cpu/dispatching """, - '0') - - def test_single(self): - """ - This test checks the simplest topology with a single CPU. - """ - self.set_machine('s390-ccw-virtio') - self.kernel_init() - self.vm.launch() - self.wait_until_booted() - self.check_topology(0, 0, 0, 0, 'medium', False) - - def test_default(self): - """ - This test checks the implicit topology. - """ - self.set_machine('s390-ccw-virtio') - self.kernel_init() - self.vm.add_args('-smp', - '13,drawers=2,books=2,sockets=3,cores=2,maxcpus=24') - self.vm.launch() - self.wait_until_booted() - self.check_topology(0, 0, 0, 0, 'medium', False) - self.check_topology(1, 0, 0, 0, 'medium', False) - self.check_topology(2, 1, 0, 0, 'medium', False) - self.check_topology(3, 1, 0, 0, 'medium', False) - self.check_topology(4, 2, 0, 0, 'medium', False) - self.check_topology(5, 2, 0, 0, 'medium', False) - self.check_topology(6, 0, 1, 0, 'medium', False) - self.check_topology(7, 0, 1, 0, 'medium', False) - self.check_topology(8, 1, 1, 0, 'medium', False) - self.check_topology(9, 1, 1, 0, 'medium', False) - self.check_topology(10, 2, 1, 0, 'medium', False) - self.check_topology(11, 2, 1, 0, 'medium', False) - self.check_topology(12, 0, 0, 1, 'medium', False) - - def test_move(self): - """ - This test checks the topology modification by moving a CPU - to another socket: CPU 0 is moved from socket 0 to socket 2. - """ - self.set_machine('s390-ccw-virtio') - self.kernel_init() - self.vm.add_args('-smp', - '1,drawers=2,books=2,sockets=3,cores=2,maxcpus=24') - self.vm.launch() - self.wait_until_booted() - - self.check_topology(0, 0, 0, 0, 'medium', False) - res = self.vm.qmp('set-cpu-topology', - {'core-id': 0, 'socket-id': 2, 'entitlement': 'low'}) - self.assertEqual(res['return'], {}) - self.check_topology(0, 2, 0, 0, 'low', False) - - def test_dash_device(self): - """ - This test verifies that a CPU defined with the '-device' - command line option finds its right place inside the topology. - """ - self.set_machine('s390-ccw-virtio') - self.kernel_init() - self.vm.add_args('-smp', - '1,drawers=2,books=2,sockets=3,cores=2,maxcpus=24') - self.vm.add_args('-device', 'max-s390x-cpu,core-id=10') - self.vm.add_args('-device', - 'max-s390x-cpu,' - 'core-id=1,socket-id=0,book-id=1,drawer-id=1,entitlement=low') - self.vm.add_args('-device', - 'max-s390x-cpu,' - 'core-id=2,socket-id=0,book-id=1,drawer-id=1,entitlement=medium') - self.vm.add_args('-device', - 'max-s390x-cpu,' - 'core-id=3,socket-id=1,book-id=1,drawer-id=1,entitlement=high') - self.vm.add_args('-device', - 'max-s390x-cpu,' - 'core-id=4,socket-id=1,book-id=1,drawer-id=1') - self.vm.add_args('-device', - 'max-s390x-cpu,' - 'core-id=5,socket-id=2,book-id=1,drawer-id=1,dedicated=true') - - self.vm.launch() - self.wait_until_booted() - - self.check_topology(10, 2, 1, 0, 'medium', False) - self.check_topology(1, 0, 1, 1, 'low', False) - self.check_topology(2, 0, 1, 1, 'medium', False) - self.check_topology(3, 1, 1, 1, 'high', False) - self.check_topology(4, 1, 1, 1, 'medium', False) - self.check_topology(5, 2, 1, 1, 'high', True) - - - def guest_set_dispatching(self, dispatching): - exec_command(self, - f'echo {dispatching} > /sys/devices/system/cpu/dispatching') - self.vm.event_wait('CPU_POLARIZATION_CHANGE', self.event_timeout) - exec_command_and_wait_for_pattern(self, - 'cat /sys/devices/system/cpu/dispatching', dispatching) - - - def test_polarization(self): - """ - This test verifies that QEMU modifies the entitlement change after - several guest polarization change requests. - """ - self.set_machine('s390-ccw-virtio') - self.kernel_init() - self.vm.launch() - self.wait_until_booted() - - self.system_init() - res = self.vm.qmp('query-s390x-cpu-polarization') - self.assertEqual(res['return']['polarization'], 'horizontal') - self.check_topology(0, 0, 0, 0, 'medium', False) - - self.guest_set_dispatching('1') - res = self.vm.qmp('query-s390x-cpu-polarization') - self.assertEqual(res['return']['polarization'], 'vertical') - self.check_topology(0, 0, 0, 0, 'medium', False) - - self.guest_set_dispatching('0') - res = self.vm.qmp('query-s390x-cpu-polarization') - self.assertEqual(res['return']['polarization'], 'horizontal') - self.check_topology(0, 0, 0, 0, 'medium', False) - - - def check_polarization(self, polarization): - #We need to wait for the change to have been propagated to the kernel - exec_command_and_wait_for_pattern(self, - "\n".join([ - "timeout 1 sh -c 'while true", - 'do', - ' syspath="/sys/devices/system/cpu/cpu0/polarization"', - ' polarization="$(cat "$syspath")" || exit', - f' if [ "$polarization" = "{polarization}" ]; then', - ' exit 0', - ' fi', - ' sleep 0.01', - #searched for strings mustn't show up in command, '' to obfuscate - "done' && echo succ''ess || echo fail''ure", - ]), - "success", "failure") - - - def test_entitlement(self): - """ - This test verifies that QEMU modifies the entitlement - after a guest request and that the guest sees the change. - """ - self.set_machine('s390-ccw-virtio') - self.kernel_init() - self.vm.launch() - self.wait_until_booted() - - self.system_init() - - self.check_polarization('horizontal') - self.check_topology(0, 0, 0, 0, 'medium', False) - - self.guest_set_dispatching('1') - self.check_polarization('vertical:medium') - self.check_topology(0, 0, 0, 0, 'medium', False) - - res = self.vm.qmp('set-cpu-topology', - {'core-id': 0, 'entitlement': 'low'}) - self.assertEqual(res['return'], {}) - self.check_polarization('vertical:low') - self.check_topology(0, 0, 0, 0, 'low', False) - - res = self.vm.qmp('set-cpu-topology', - {'core-id': 0, 'entitlement': 'medium'}) - self.assertEqual(res['return'], {}) - self.check_polarization('vertical:medium') - self.check_topology(0, 0, 0, 0, 'medium', False) - - res = self.vm.qmp('set-cpu-topology', - {'core-id': 0, 'entitlement': 'high'}) - self.assertEqual(res['return'], {}) - self.check_polarization('vertical:high') - self.check_topology(0, 0, 0, 0, 'high', False) - - self.guest_set_dispatching('0') - self.check_polarization("horizontal") - self.check_topology(0, 0, 0, 0, 'high', False) - - - def test_dedicated(self): - """ - This test verifies that QEMU adjusts the entitlement correctly when a - CPU is made dedicated. - QEMU retains the entitlement value when horizontal polarization is in effect. - For the guest, the field shows the effective value of the entitlement. - """ - self.set_machine('s390-ccw-virtio') - self.kernel_init() - self.vm.launch() - self.wait_until_booted() - - self.system_init() - - self.check_polarization("horizontal") - - res = self.vm.qmp('set-cpu-topology', - {'core-id': 0, 'dedicated': True}) - self.assertEqual(res['return'], {}) - self.check_topology(0, 0, 0, 0, 'high', True) - self.check_polarization("horizontal") - - self.guest_set_dispatching('1') - self.check_topology(0, 0, 0, 0, 'high', True) - self.check_polarization("vertical:high") - - self.guest_set_dispatching('0') - self.check_topology(0, 0, 0, 0, 'high', True) - self.check_polarization("horizontal") - - - def test_socket_full(self): - """ - This test verifies that QEMU does not accept to overload a socket. - The socket-id 0 on book-id 0 already contains CPUs 0 and 1 and can - not accept any new CPU while socket-id 0 on book-id 1 is free. - """ - self.set_machine('s390-ccw-virtio') - self.kernel_init() - self.vm.add_args('-smp', - '3,drawers=2,books=2,sockets=3,cores=2,maxcpus=24') - self.vm.launch() - self.wait_until_booted() - - self.system_init() - - res = self.vm.qmp('set-cpu-topology', - {'core-id': 2, 'socket-id': 0, 'book-id': 0}) - self.assertEqual(res['error']['class'], 'GenericError') - - res = self.vm.qmp('set-cpu-topology', - {'core-id': 2, 'socket-id': 0, 'book-id': 1}) - self.assertEqual(res['return'], {}) - - def test_dedicated_error(self): - """ - This test verifies that QEMU refuses to lower the entitlement - of a dedicated CPU - """ - self.set_machine('s390-ccw-virtio') - self.kernel_init() - self.vm.launch() - self.wait_until_booted() - - self.system_init() - - res = self.vm.qmp('set-cpu-topology', - {'core-id': 0, 'dedicated': True}) - self.assertEqual(res['return'], {}) - - self.check_topology(0, 0, 0, 0, 'high', True) - - self.guest_set_dispatching('1') - - self.check_topology(0, 0, 0, 0, 'high', True) - - res = self.vm.qmp('set-cpu-topology', - {'core-id': 0, 'entitlement': 'low', 'dedicated': True}) - self.assertEqual(res['error']['class'], 'GenericError') - - res = self.vm.qmp('set-cpu-topology', - {'core-id': 0, 'entitlement': 'low'}) - self.assertEqual(res['error']['class'], 'GenericError') - - res = self.vm.qmp('set-cpu-topology', - {'core-id': 0, 'entitlement': 'medium', 'dedicated': True}) - self.assertEqual(res['error']['class'], 'GenericError') - - res = self.vm.qmp('set-cpu-topology', - {'core-id': 0, 'entitlement': 'medium'}) - self.assertEqual(res['error']['class'], 'GenericError') - - res = self.vm.qmp('set-cpu-topology', - {'core-id': 0, 'entitlement': 'low', 'dedicated': False}) - self.assertEqual(res['return'], {}) - - res = self.vm.qmp('set-cpu-topology', - {'core-id': 0, 'entitlement': 'medium', 'dedicated': False}) - self.assertEqual(res['return'], {}) - - def test_move_error(self): - """ - This test verifies that QEMU refuses to move a CPU to an - nonexistent location - """ - self.set_machine('s390-ccw-virtio') - self.kernel_init() - self.vm.launch() - self.wait_until_booted() - - self.system_init() - - res = self.vm.qmp('set-cpu-topology', {'core-id': 0, 'drawer-id': 1}) - self.assertEqual(res['error']['class'], 'GenericError') - - res = self.vm.qmp('set-cpu-topology', {'core-id': 0, 'book-id': 1}) - self.assertEqual(res['error']['class'], 'GenericError') - - res = self.vm.qmp('set-cpu-topology', {'core-id': 0, 'socket-id': 1}) - self.assertEqual(res['error']['class'], 'GenericError') - - self.check_topology(0, 0, 0, 0, 'medium', False) - -if __name__ == '__main__': - QemuSystemTest.main() diff --git a/tests/functional/test_s390x_tuxrun.py b/tests/functional/test_s390x_tuxrun.py deleted file mode 100755 index 8df3c68..0000000 --- a/tests/functional/test_s390x_tuxrun.py +++ /dev/null @@ -1,35 +0,0 @@ -#!/usr/bin/env python3 -# -# Functional test that boots known good tuxboot images the same way -# that tuxrun (www.tuxrun.org) does. This tool is used by things like -# the LKFT project to run regression tests on kernels. -# -# Copyright (c) 2023 Linaro Ltd. -# -# Author: -# Alex Bennée -# -# SPDX-License-Identifier: GPL-2.0-or-later - -from qemu_test import Asset -from qemu_test.tuxruntest import TuxRunBaselineTest - -class TuxRunS390xTest(TuxRunBaselineTest): - - ASSET_S390X_KERNEL = Asset( - 'https://storage.tuxboot.com/buildroot/20241119/s390/bzImage', - 'ee67e91db52a2aed104a7c72b2a08987c678f8179c029626789c35d6dd0fedf1') - ASSET_S390X_ROOTFS = Asset( - 'https://storage.tuxboot.com/buildroot/20241119/s390/rootfs.ext4.zst', - 'bff7971fc2fef56372d98afe4557b82fd0a785a241e44c29b058e577ad1bbb44') - - def test_s390(self): - self.set_machine('s390-ccw-virtio') - self.wait_for_shutdown=False - self.common_tuxrun(kernel_asset=self.ASSET_S390X_KERNEL, - rootfs_asset=self.ASSET_S390X_ROOTFS, - drive="virtio-blk-ccw", - haltmsg="Requesting system halt") - -if __name__ == '__main__': - TuxRunBaselineTest.main() -- cgit v1.1 From 58e95a05dec8bb0c739a2b7192b6d0a96d1a99a5 Mon Sep 17 00:00:00 2001 From: Thomas Huth Date: Tue, 19 Aug 2025 13:23:57 +0200 Subject: tests/functional: Move sh4/sh4eb tests into target-specific folders MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The tests/functional folder has become quite crowded, thus move the sh4 tests into a target-specific subfolder. Reviewed-by: Pierrick Bouvier Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Thomas Huth Message-ID: <20250819112403.432587-21-thuth@redhat.com> --- tests/functional/meson.build | 15 ++---------- tests/functional/sh4/meson.build | 10 ++++++++ tests/functional/sh4/test_r2d.py | 29 ++++++++++++++++++++++ tests/functional/sh4/test_tuxrun.py | 49 +++++++++++++++++++++++++++++++++++++ tests/functional/sh4eb/meson.build | 5 ++++ tests/functional/sh4eb/test_r2d.py | 28 +++++++++++++++++++++ tests/functional/test_sh4_r2d.py | 29 ---------------------- tests/functional/test_sh4_tuxrun.py | 49 ------------------------------------- tests/functional/test_sh4eb_r2d.py | 28 --------------------- 9 files changed, 123 insertions(+), 119 deletions(-) create mode 100644 tests/functional/sh4/meson.build create mode 100755 tests/functional/sh4/test_r2d.py create mode 100755 tests/functional/sh4/test_tuxrun.py create mode 100644 tests/functional/sh4eb/meson.build create mode 100755 tests/functional/sh4eb/test_r2d.py delete mode 100755 tests/functional/test_sh4_r2d.py delete mode 100755 tests/functional/test_sh4_tuxrun.py delete mode 100755 tests/functional/test_sh4eb_r2d.py (limited to 'tests') diff --git a/tests/functional/meson.build b/tests/functional/meson.build index abaa4e0..ce71350 100644 --- a/tests/functional/meson.build +++ b/tests/functional/meson.build @@ -30,10 +30,8 @@ subdir('riscv32') subdir('riscv64') subdir('rx') subdir('s390x') - -test_sh4_timeouts = { - 'sh4_tuxrun' : 240, -} +subdir('sh4') +subdir('sh4eb') test_x86_64_timeouts = { 'acpi_bits' : 420, @@ -56,15 +54,6 @@ tests_generic_linuxuser = [ tests_generic_bsduser = [ ] -tests_sh4_system_thorough = [ - 'sh4_r2d', - 'sh4_tuxrun', -] - -tests_sh4eb_system_thorough = [ - 'sh4eb_r2d', -] - tests_sparc_system_quick = [ 'sparc_migration', ] diff --git a/tests/functional/sh4/meson.build b/tests/functional/sh4/meson.build new file mode 100644 index 0000000..56f824e --- /dev/null +++ b/tests/functional/sh4/meson.build @@ -0,0 +1,10 @@ +# SPDX-License-Identifier: GPL-2.0-or-later + +test_sh4_timeouts = { + 'tuxrun' : 240, +} + +tests_sh4_system_thorough = [ + 'r2d', + 'tuxrun', +] diff --git a/tests/functional/sh4/test_r2d.py b/tests/functional/sh4/test_r2d.py new file mode 100755 index 0000000..03a64837 --- /dev/null +++ b/tests/functional/sh4/test_r2d.py @@ -0,0 +1,29 @@ +#!/usr/bin/env python3 +# +# Boot a Linux kernel on a r2d sh4 machine and check the console +# +# SPDX-License-Identifier: GPL-2.0-or-later + +from qemu_test import LinuxKernelTest, Asset, skipFlakyTest + + +class R2dTest(LinuxKernelTest): + + ASSET_DAY09 = Asset( + 'https://qemu-advcal.gitlab.io/qac-best-of-multiarch/download/day09.tar.xz', + 'a61b44d2630a739d1380cc4ff4b80981d47ccfd5992f1484ccf48322c35f09ac') + + # This test has a 6-10% failure rate on various hosts that look + # like issues with a buggy kernel. + # XXX file tracking bug + @skipFlakyTest(bug_url=None) + def test_r2d(self): + self.set_machine('r2d') + self.archive_extract(self.ASSET_DAY09) + self.vm.add_args('-append', 'console=ttySC1') + self.launch_kernel(self.scratch_file('day09', 'zImage'), + console_index=1, + wait_for='QEMU advent calendar') + +if __name__ == '__main__': + LinuxKernelTest.main() diff --git a/tests/functional/sh4/test_tuxrun.py b/tests/functional/sh4/test_tuxrun.py new file mode 100755 index 0000000..1748f8c --- /dev/null +++ b/tests/functional/sh4/test_tuxrun.py @@ -0,0 +1,49 @@ +#!/usr/bin/env python3 +# +# Functional test that boots known good tuxboot images the same way +# that tuxrun (www.tuxrun.org) does. This tool is used by things like +# the LKFT project to run regression tests on kernels. +# +# Copyright (c) 2023 Linaro Ltd. +# +# Author: +# Alex Bennée +# +# SPDX-License-Identifier: GPL-2.0-or-later + +from qemu_test import Asset, exec_command_and_wait_for_pattern +from qemu_test.tuxruntest import TuxRunBaselineTest + +class TuxRunSh4Test(TuxRunBaselineTest): + + ASSET_SH4_KERNEL = Asset( + 'https://storage.tuxboot.com/20230331/sh4/zImage', + '29d9b2aba604a0f53a5dc3b5d0f2b8e35d497de1129f8ee5139eb6fdf0db692f') + ASSET_SH4_ROOTFS = Asset( + 'https://storage.tuxboot.com/20230331/sh4/rootfs.ext4.zst', + '3592a7a3d5a641e8b9821449e77bc43c9904a56c30d45da0694349cfd86743fd') + + def test_sh4(self): + self.set_machine('r2d') + self.cpu='sh7785' + self.root='sda' + self.console='ttySC1' + + # The test is currently too unstable to do much in userspace + # so we skip common_tuxrun and do a minimal boot and shutdown. + (kernel, disk, dtb) = self.fetch_tuxrun_assets(self.ASSET_SH4_KERNEL, + self.ASSET_SH4_ROOTFS) + + # the console comes on the second serial port + self.prepare_run(kernel, disk, + "driver=ide-hd,bus=ide.0,unit=0", + console_index=1) + self.vm.launch() + + self.wait_for_console_pattern("tuxtest login:") + exec_command_and_wait_for_pattern(self, 'root', 'root@tuxtest:~#') + exec_command_and_wait_for_pattern(self, 'halt', + "reboot: System halted") + +if __name__ == '__main__': + TuxRunBaselineTest.main() diff --git a/tests/functional/sh4eb/meson.build b/tests/functional/sh4eb/meson.build new file mode 100644 index 0000000..25e9a6e --- /dev/null +++ b/tests/functional/sh4eb/meson.build @@ -0,0 +1,5 @@ +# SPDX-License-Identifier: GPL-2.0-or-later + +tests_sh4eb_system_thorough = [ + 'r2d', +] diff --git a/tests/functional/sh4eb/test_r2d.py b/tests/functional/sh4eb/test_r2d.py new file mode 100755 index 0000000..473093b --- /dev/null +++ b/tests/functional/sh4eb/test_r2d.py @@ -0,0 +1,28 @@ +#!/usr/bin/env python3 +# +# Boot a Linux kernel on a r2d sh4eb machine and check the console +# +# SPDX-License-Identifier: GPL-2.0-or-later + +from qemu_test import LinuxKernelTest, Asset +from qemu_test import exec_command_and_wait_for_pattern + + +class R2dEBTest(LinuxKernelTest): + + ASSET_TGZ = Asset( + 'https://landley.net/bin/mkroot/0.8.11/sh4eb.tgz', + 'be8c6cb5aef8406899dc5aa5e22b6aa45840eb886cdd3ced51555c10577ada2c') + + def test_sh4eb_r2d(self): + self.set_machine('r2d') + self.archive_extract(self.ASSET_TGZ) + self.vm.add_args('-append', 'console=ttySC1 noiotrap') + self.launch_kernel(self.scratch_file('sh4eb', 'linux-kernel'), + initrd=self.scratch_file('sh4eb', + 'initramfs.cpio.gz'), + console_index=1, wait_for='Type exit when done') + exec_command_and_wait_for_pattern(self, 'exit', 'Restarting system') + +if __name__ == '__main__': + LinuxKernelTest.main() diff --git a/tests/functional/test_sh4_r2d.py b/tests/functional/test_sh4_r2d.py deleted file mode 100755 index 03a64837..0000000 --- a/tests/functional/test_sh4_r2d.py +++ /dev/null @@ -1,29 +0,0 @@ -#!/usr/bin/env python3 -# -# Boot a Linux kernel on a r2d sh4 machine and check the console -# -# SPDX-License-Identifier: GPL-2.0-or-later - -from qemu_test import LinuxKernelTest, Asset, skipFlakyTest - - -class R2dTest(LinuxKernelTest): - - ASSET_DAY09 = Asset( - 'https://qemu-advcal.gitlab.io/qac-best-of-multiarch/download/day09.tar.xz', - 'a61b44d2630a739d1380cc4ff4b80981d47ccfd5992f1484ccf48322c35f09ac') - - # This test has a 6-10% failure rate on various hosts that look - # like issues with a buggy kernel. - # XXX file tracking bug - @skipFlakyTest(bug_url=None) - def test_r2d(self): - self.set_machine('r2d') - self.archive_extract(self.ASSET_DAY09) - self.vm.add_args('-append', 'console=ttySC1') - self.launch_kernel(self.scratch_file('day09', 'zImage'), - console_index=1, - wait_for='QEMU advent calendar') - -if __name__ == '__main__': - LinuxKernelTest.main() diff --git a/tests/functional/test_sh4_tuxrun.py b/tests/functional/test_sh4_tuxrun.py deleted file mode 100755 index 1748f8c..0000000 --- a/tests/functional/test_sh4_tuxrun.py +++ /dev/null @@ -1,49 +0,0 @@ -#!/usr/bin/env python3 -# -# Functional test that boots known good tuxboot images the same way -# that tuxrun (www.tuxrun.org) does. This tool is used by things like -# the LKFT project to run regression tests on kernels. -# -# Copyright (c) 2023 Linaro Ltd. -# -# Author: -# Alex Bennée -# -# SPDX-License-Identifier: GPL-2.0-or-later - -from qemu_test import Asset, exec_command_and_wait_for_pattern -from qemu_test.tuxruntest import TuxRunBaselineTest - -class TuxRunSh4Test(TuxRunBaselineTest): - - ASSET_SH4_KERNEL = Asset( - 'https://storage.tuxboot.com/20230331/sh4/zImage', - '29d9b2aba604a0f53a5dc3b5d0f2b8e35d497de1129f8ee5139eb6fdf0db692f') - ASSET_SH4_ROOTFS = Asset( - 'https://storage.tuxboot.com/20230331/sh4/rootfs.ext4.zst', - '3592a7a3d5a641e8b9821449e77bc43c9904a56c30d45da0694349cfd86743fd') - - def test_sh4(self): - self.set_machine('r2d') - self.cpu='sh7785' - self.root='sda' - self.console='ttySC1' - - # The test is currently too unstable to do much in userspace - # so we skip common_tuxrun and do a minimal boot and shutdown. - (kernel, disk, dtb) = self.fetch_tuxrun_assets(self.ASSET_SH4_KERNEL, - self.ASSET_SH4_ROOTFS) - - # the console comes on the second serial port - self.prepare_run(kernel, disk, - "driver=ide-hd,bus=ide.0,unit=0", - console_index=1) - self.vm.launch() - - self.wait_for_console_pattern("tuxtest login:") - exec_command_and_wait_for_pattern(self, 'root', 'root@tuxtest:~#') - exec_command_and_wait_for_pattern(self, 'halt', - "reboot: System halted") - -if __name__ == '__main__': - TuxRunBaselineTest.main() diff --git a/tests/functional/test_sh4eb_r2d.py b/tests/functional/test_sh4eb_r2d.py deleted file mode 100755 index 473093b..0000000 --- a/tests/functional/test_sh4eb_r2d.py +++ /dev/null @@ -1,28 +0,0 @@ -#!/usr/bin/env python3 -# -# Boot a Linux kernel on a r2d sh4eb machine and check the console -# -# SPDX-License-Identifier: GPL-2.0-or-later - -from qemu_test import LinuxKernelTest, Asset -from qemu_test import exec_command_and_wait_for_pattern - - -class R2dEBTest(LinuxKernelTest): - - ASSET_TGZ = Asset( - 'https://landley.net/bin/mkroot/0.8.11/sh4eb.tgz', - 'be8c6cb5aef8406899dc5aa5e22b6aa45840eb886cdd3ced51555c10577ada2c') - - def test_sh4eb_r2d(self): - self.set_machine('r2d') - self.archive_extract(self.ASSET_TGZ) - self.vm.add_args('-append', 'console=ttySC1 noiotrap') - self.launch_kernel(self.scratch_file('sh4eb', 'linux-kernel'), - initrd=self.scratch_file('sh4eb', - 'initramfs.cpio.gz'), - console_index=1, wait_for='Type exit when done') - exec_command_and_wait_for_pattern(self, 'exit', 'Restarting system') - -if __name__ == '__main__': - LinuxKernelTest.main() -- cgit v1.1 From e76291a65457b1fe18b6bf7a90b1d022fa15bf9d Mon Sep 17 00:00:00 2001 From: Thomas Huth Date: Tue, 19 Aug 2025 13:23:58 +0200 Subject: tests/functional: Move sparc/sparc64 tests into target-specific folders MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The tests/functional folder has become quite crowded, thus move the sparc tests into a target-specific subfolder. Reviewed-by: Pierrick Bouvier Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Thomas Huth Message-ID: <20250819112403.432587-22-thuth@redhat.com> --- tests/functional/meson.build | 20 ++-------------- tests/functional/sparc/meson.build | 10 ++++++++ tests/functional/sparc/test_migration.py | 26 ++++++++++++++++++++ tests/functional/sparc/test_replay.py | 27 +++++++++++++++++++++ tests/functional/sparc/test_sun4m.py | 24 +++++++++++++++++++ tests/functional/sparc64/meson.build | 10 ++++++++ tests/functional/sparc64/test_migration.py | 26 ++++++++++++++++++++ tests/functional/sparc64/test_sun4u.py | 38 ++++++++++++++++++++++++++++++ tests/functional/sparc64/test_tuxrun.py | 35 +++++++++++++++++++++++++++ tests/functional/test_sparc64_migration.py | 26 -------------------- tests/functional/test_sparc64_sun4u.py | 38 ------------------------------ tests/functional/test_sparc64_tuxrun.py | 35 --------------------------- tests/functional/test_sparc_migration.py | 26 -------------------- tests/functional/test_sparc_replay.py | 27 --------------------- tests/functional/test_sparc_sun4m.py | 24 ------------------- 15 files changed, 198 insertions(+), 194 deletions(-) create mode 100644 tests/functional/sparc/meson.build create mode 100755 tests/functional/sparc/test_migration.py create mode 100755 tests/functional/sparc/test_replay.py create mode 100755 tests/functional/sparc/test_sun4m.py create mode 100644 tests/functional/sparc64/meson.build create mode 100755 tests/functional/sparc64/test_migration.py create mode 100755 tests/functional/sparc64/test_sun4u.py create mode 100755 tests/functional/sparc64/test_tuxrun.py delete mode 100755 tests/functional/test_sparc64_migration.py delete mode 100755 tests/functional/test_sparc64_sun4u.py delete mode 100755 tests/functional/test_sparc64_tuxrun.py delete mode 100755 tests/functional/test_sparc_migration.py delete mode 100755 tests/functional/test_sparc_replay.py delete mode 100755 tests/functional/test_sparc_sun4m.py (limited to 'tests') diff --git a/tests/functional/meson.build b/tests/functional/meson.build index ce71350..00d18db 100644 --- a/tests/functional/meson.build +++ b/tests/functional/meson.build @@ -32,6 +32,8 @@ subdir('rx') subdir('s390x') subdir('sh4') subdir('sh4eb') +subdir('sparc') +subdir('sparc64') test_x86_64_timeouts = { 'acpi_bits' : 420, @@ -54,24 +56,6 @@ tests_generic_linuxuser = [ tests_generic_bsduser = [ ] -tests_sparc_system_quick = [ - 'sparc_migration', -] - -tests_sparc_system_thorough = [ - 'sparc_replay', - 'sparc_sun4m', -] - -tests_sparc64_system_quick = [ - 'sparc64_migration', -] - -tests_sparc64_system_thorough = [ - 'sparc64_sun4u', - 'sparc64_tuxrun', -] - tests_x86_64_system_quick = [ 'cpu_queries', 'mem_addr_space', diff --git a/tests/functional/sparc/meson.build b/tests/functional/sparc/meson.build new file mode 100644 index 0000000..88732be --- /dev/null +++ b/tests/functional/sparc/meson.build @@ -0,0 +1,10 @@ +# SPDX-License-Identifier: GPL-2.0-or-later + +tests_sparc_system_quick = [ + 'migration', +] + +tests_sparc_system_thorough = [ + 'replay', + 'sun4m', +] diff --git a/tests/functional/sparc/test_migration.py b/tests/functional/sparc/test_migration.py new file mode 100755 index 0000000..dd6d578 --- /dev/null +++ b/tests/functional/sparc/test_migration.py @@ -0,0 +1,26 @@ +#!/usr/bin/env python3 +# +# SPDX-License-Identifier: GPL-2.0-or-later +# +# Sparc migration test + +from migration import MigrationTest + + +class SparcMigrationTest(MigrationTest): + + def test_migration_with_tcp_localhost(self): + self.set_machine('SS-4') + self.migration_with_tcp_localhost() + + def test_migration_with_unix(self): + self.set_machine('SS-5') + self.migration_with_unix() + + def test_migration_with_exec(self): + self.set_machine('SS-4') + self.migration_with_exec() + + +if __name__ == '__main__': + MigrationTest.main() diff --git a/tests/functional/sparc/test_replay.py b/tests/functional/sparc/test_replay.py new file mode 100755 index 0000000..865d648 --- /dev/null +++ b/tests/functional/sparc/test_replay.py @@ -0,0 +1,27 @@ +#!/usr/bin/env python3 +# +# Replay test that boots a Linux kernel on a sparc sun4m machine +# and checks the console +# +# SPDX-License-Identifier: GPL-2.0-or-later + +from qemu_test import Asset +from replay_kernel import ReplayKernelBase + + +class SparcReplay(ReplayKernelBase): + + ASSET_DAY11 = Asset( + 'https://qemu-advcal.gitlab.io/qac-best-of-multiarch/download/day11.tar.xz', + 'c776533ba756bf4dd3f1fc4c024fb50ef0d853e05c5f5ddf0900a32d1eaa49e0') + + def test_replay(self): + self.set_machine('SS-10') + kernel_path = self.archive_extract(self.ASSET_DAY11, + member="day11/zImage.elf") + self.run_rr(kernel_path, self.REPLAY_KERNEL_COMMAND_LINE, + 'QEMU advent calendar') + + +if __name__ == '__main__': + ReplayKernelBase.main() diff --git a/tests/functional/sparc/test_sun4m.py b/tests/functional/sparc/test_sun4m.py new file mode 100755 index 0000000..7cd28eb --- /dev/null +++ b/tests/functional/sparc/test_sun4m.py @@ -0,0 +1,24 @@ +#!/usr/bin/env python3 +# +# Functional test that boots a Linux kernel on a sparc sun4m machine +# and checks the console +# +# SPDX-License-Identifier: GPL-2.0-or-later + +from qemu_test import LinuxKernelTest, Asset + + +class Sun4mTest(LinuxKernelTest): + + ASSET_DAY11 = Asset( + 'https://qemu-advcal.gitlab.io/qac-best-of-multiarch/download/day11.tar.xz', + 'c776533ba756bf4dd3f1fc4c024fb50ef0d853e05c5f5ddf0900a32d1eaa49e0') + + def test_sparc_ss20(self): + self.set_machine('SS-20') + self.archive_extract(self.ASSET_DAY11) + self.launch_kernel(self.scratch_file('day11', 'zImage.elf'), + wait_for='QEMU advent calendar') + +if __name__ == '__main__': + LinuxKernelTest.main() diff --git a/tests/functional/sparc64/meson.build b/tests/functional/sparc64/meson.build new file mode 100644 index 0000000..2e04e7d --- /dev/null +++ b/tests/functional/sparc64/meson.build @@ -0,0 +1,10 @@ +# SPDX-License-Identifier: GPL-2.0-or-later + +tests_sparc64_system_quick = [ + 'migration', +] + +tests_sparc64_system_thorough = [ + 'sun4u', + 'tuxrun', +] diff --git a/tests/functional/sparc64/test_migration.py b/tests/functional/sparc64/test_migration.py new file mode 100755 index 0000000..a8a6c73 --- /dev/null +++ b/tests/functional/sparc64/test_migration.py @@ -0,0 +1,26 @@ +#!/usr/bin/env python3 +# +# SPDX-License-Identifier: GPL-2.0-or-later +# +# Sparc64 migration test + +from migration import MigrationTest + + +class Sparc64MigrationTest(MigrationTest): + + def test_migration_with_tcp_localhost(self): + self.set_machine('sun4u') + self.migration_with_tcp_localhost() + + def test_migration_with_unix(self): + self.set_machine('sun4u') + self.migration_with_unix() + + def test_migration_with_exec(self): + self.set_machine('sun4u') + self.migration_with_exec() + + +if __name__ == '__main__': + MigrationTest.main() diff --git a/tests/functional/sparc64/test_sun4u.py b/tests/functional/sparc64/test_sun4u.py new file mode 100755 index 0000000..27ac289 --- /dev/null +++ b/tests/functional/sparc64/test_sun4u.py @@ -0,0 +1,38 @@ +#!/usr/bin/env python3 +# +# Functional test that boots a Linux kernel and checks the console +# +# Copyright (c) 2020 Red Hat, Inc. +# +# Author: +# Thomas Huth +# +# This work is licensed under the terms of the GNU GPL, version 2 or +# later. See the COPYING file in the top-level directory. + +from qemu_test import QemuSystemTest, Asset +from qemu_test import wait_for_console_pattern + + +class Sun4uMachine(QemuSystemTest): + """Boots the Linux kernel and checks that the console is operational""" + + timeout = 90 + + ASSET_IMAGE = Asset( + ('https://qemu-advcal.gitlab.io/qac-best-of-multiarch/download/' + 'day23.tar.xz'), + 'a3ed92450704af244178351afd0e769776e7decb298e95a63abfd9a6e3f6c854') + + def test_sparc64_sun4u(self): + self.set_machine('sun4u') + kernel_file = self.archive_extract(self.ASSET_IMAGE, + member='day23/vmlinux') + self.vm.set_console() + self.vm.add_args('-kernel', kernel_file, + '-append', 'printk.time=0') + self.vm.launch() + wait_for_console_pattern(self, 'Starting logging: OK') + +if __name__ == '__main__': + QemuSystemTest.main() diff --git a/tests/functional/sparc64/test_tuxrun.py b/tests/functional/sparc64/test_tuxrun.py new file mode 100755 index 0000000..0d7b43d --- /dev/null +++ b/tests/functional/sparc64/test_tuxrun.py @@ -0,0 +1,35 @@ +#!/usr/bin/env python3 +# +# Functional test that boots known good tuxboot images the same way +# that tuxrun (www.tuxrun.org) does. This tool is used by things like +# the LKFT project to run regression tests on kernels. +# +# Copyright (c) 2023 Linaro Ltd. +# +# Author: +# Alex Bennée +# +# SPDX-License-Identifier: GPL-2.0-or-later + +from qemu_test import Asset +from qemu_test.tuxruntest import TuxRunBaselineTest + +class TuxRunSparc64Test(TuxRunBaselineTest): + + ASSET_SPARC64_KERNEL = Asset( + 'https://storage.tuxboot.com/buildroot/20241119/sparc64/vmlinux', + 'a04cfb2e70a264051d161fdd93aabf4b2a9472f2e435c14ed18c5848c5fed261') + ASSET_SPARC64_ROOTFS = Asset( + 'https://storage.tuxboot.com/buildroot/20241119/sparc64/rootfs.ext4.zst', + '479c3dc104c82b68be55e2c0c5c38cd473d0b37ad4badccde4775bb88ce34611') + + def test_sparc64(self): + self.set_machine('sun4u') + self.root='sda' + self.wait_for_shutdown=False + self.common_tuxrun(kernel_asset=self.ASSET_SPARC64_KERNEL, + rootfs_asset=self.ASSET_SPARC64_ROOTFS, + drive="driver=ide-hd,bus=ide.0,unit=0") + +if __name__ == '__main__': + TuxRunBaselineTest.main() diff --git a/tests/functional/test_sparc64_migration.py b/tests/functional/test_sparc64_migration.py deleted file mode 100755 index a8a6c73..0000000 --- a/tests/functional/test_sparc64_migration.py +++ /dev/null @@ -1,26 +0,0 @@ -#!/usr/bin/env python3 -# -# SPDX-License-Identifier: GPL-2.0-or-later -# -# Sparc64 migration test - -from migration import MigrationTest - - -class Sparc64MigrationTest(MigrationTest): - - def test_migration_with_tcp_localhost(self): - self.set_machine('sun4u') - self.migration_with_tcp_localhost() - - def test_migration_with_unix(self): - self.set_machine('sun4u') - self.migration_with_unix() - - def test_migration_with_exec(self): - self.set_machine('sun4u') - self.migration_with_exec() - - -if __name__ == '__main__': - MigrationTest.main() diff --git a/tests/functional/test_sparc64_sun4u.py b/tests/functional/test_sparc64_sun4u.py deleted file mode 100755 index 27ac289..0000000 --- a/tests/functional/test_sparc64_sun4u.py +++ /dev/null @@ -1,38 +0,0 @@ -#!/usr/bin/env python3 -# -# Functional test that boots a Linux kernel and checks the console -# -# Copyright (c) 2020 Red Hat, Inc. -# -# Author: -# Thomas Huth -# -# This work is licensed under the terms of the GNU GPL, version 2 or -# later. See the COPYING file in the top-level directory. - -from qemu_test import QemuSystemTest, Asset -from qemu_test import wait_for_console_pattern - - -class Sun4uMachine(QemuSystemTest): - """Boots the Linux kernel and checks that the console is operational""" - - timeout = 90 - - ASSET_IMAGE = Asset( - ('https://qemu-advcal.gitlab.io/qac-best-of-multiarch/download/' - 'day23.tar.xz'), - 'a3ed92450704af244178351afd0e769776e7decb298e95a63abfd9a6e3f6c854') - - def test_sparc64_sun4u(self): - self.set_machine('sun4u') - kernel_file = self.archive_extract(self.ASSET_IMAGE, - member='day23/vmlinux') - self.vm.set_console() - self.vm.add_args('-kernel', kernel_file, - '-append', 'printk.time=0') - self.vm.launch() - wait_for_console_pattern(self, 'Starting logging: OK') - -if __name__ == '__main__': - QemuSystemTest.main() diff --git a/tests/functional/test_sparc64_tuxrun.py b/tests/functional/test_sparc64_tuxrun.py deleted file mode 100755 index 0d7b43d..0000000 --- a/tests/functional/test_sparc64_tuxrun.py +++ /dev/null @@ -1,35 +0,0 @@ -#!/usr/bin/env python3 -# -# Functional test that boots known good tuxboot images the same way -# that tuxrun (www.tuxrun.org) does. This tool is used by things like -# the LKFT project to run regression tests on kernels. -# -# Copyright (c) 2023 Linaro Ltd. -# -# Author: -# Alex Bennée -# -# SPDX-License-Identifier: GPL-2.0-or-later - -from qemu_test import Asset -from qemu_test.tuxruntest import TuxRunBaselineTest - -class TuxRunSparc64Test(TuxRunBaselineTest): - - ASSET_SPARC64_KERNEL = Asset( - 'https://storage.tuxboot.com/buildroot/20241119/sparc64/vmlinux', - 'a04cfb2e70a264051d161fdd93aabf4b2a9472f2e435c14ed18c5848c5fed261') - ASSET_SPARC64_ROOTFS = Asset( - 'https://storage.tuxboot.com/buildroot/20241119/sparc64/rootfs.ext4.zst', - '479c3dc104c82b68be55e2c0c5c38cd473d0b37ad4badccde4775bb88ce34611') - - def test_sparc64(self): - self.set_machine('sun4u') - self.root='sda' - self.wait_for_shutdown=False - self.common_tuxrun(kernel_asset=self.ASSET_SPARC64_KERNEL, - rootfs_asset=self.ASSET_SPARC64_ROOTFS, - drive="driver=ide-hd,bus=ide.0,unit=0") - -if __name__ == '__main__': - TuxRunBaselineTest.main() diff --git a/tests/functional/test_sparc_migration.py b/tests/functional/test_sparc_migration.py deleted file mode 100755 index dd6d578..0000000 --- a/tests/functional/test_sparc_migration.py +++ /dev/null @@ -1,26 +0,0 @@ -#!/usr/bin/env python3 -# -# SPDX-License-Identifier: GPL-2.0-or-later -# -# Sparc migration test - -from migration import MigrationTest - - -class SparcMigrationTest(MigrationTest): - - def test_migration_with_tcp_localhost(self): - self.set_machine('SS-4') - self.migration_with_tcp_localhost() - - def test_migration_with_unix(self): - self.set_machine('SS-5') - self.migration_with_unix() - - def test_migration_with_exec(self): - self.set_machine('SS-4') - self.migration_with_exec() - - -if __name__ == '__main__': - MigrationTest.main() diff --git a/tests/functional/test_sparc_replay.py b/tests/functional/test_sparc_replay.py deleted file mode 100755 index 865d648..0000000 --- a/tests/functional/test_sparc_replay.py +++ /dev/null @@ -1,27 +0,0 @@ -#!/usr/bin/env python3 -# -# Replay test that boots a Linux kernel on a sparc sun4m machine -# and checks the console -# -# SPDX-License-Identifier: GPL-2.0-or-later - -from qemu_test import Asset -from replay_kernel import ReplayKernelBase - - -class SparcReplay(ReplayKernelBase): - - ASSET_DAY11 = Asset( - 'https://qemu-advcal.gitlab.io/qac-best-of-multiarch/download/day11.tar.xz', - 'c776533ba756bf4dd3f1fc4c024fb50ef0d853e05c5f5ddf0900a32d1eaa49e0') - - def test_replay(self): - self.set_machine('SS-10') - kernel_path = self.archive_extract(self.ASSET_DAY11, - member="day11/zImage.elf") - self.run_rr(kernel_path, self.REPLAY_KERNEL_COMMAND_LINE, - 'QEMU advent calendar') - - -if __name__ == '__main__': - ReplayKernelBase.main() diff --git a/tests/functional/test_sparc_sun4m.py b/tests/functional/test_sparc_sun4m.py deleted file mode 100755 index 7cd28eb..0000000 --- a/tests/functional/test_sparc_sun4m.py +++ /dev/null @@ -1,24 +0,0 @@ -#!/usr/bin/env python3 -# -# Functional test that boots a Linux kernel on a sparc sun4m machine -# and checks the console -# -# SPDX-License-Identifier: GPL-2.0-or-later - -from qemu_test import LinuxKernelTest, Asset - - -class Sun4mTest(LinuxKernelTest): - - ASSET_DAY11 = Asset( - 'https://qemu-advcal.gitlab.io/qac-best-of-multiarch/download/day11.tar.xz', - 'c776533ba756bf4dd3f1fc4c024fb50ef0d853e05c5f5ddf0900a32d1eaa49e0') - - def test_sparc_ss20(self): - self.set_machine('SS-20') - self.archive_extract(self.ASSET_DAY11) - self.launch_kernel(self.scratch_file('day11', 'zImage.elf'), - wait_for='QEMU advent calendar') - -if __name__ == '__main__': - LinuxKernelTest.main() -- cgit v1.1 From 1917d47dd78adbd30abd462712458d0a0b583308 Mon Sep 17 00:00:00 2001 From: Thomas Huth Date: Tue, 19 Aug 2025 13:23:59 +0200 Subject: tests/functional: Move x86_64 tests into target-specific folder The tests/functional folder has become quite crowded, thus move the x86_64 tests into a target-specific subfolder. Reviewed-by: Pierrick Bouvier Signed-off-by: Thomas Huth Message-ID: <20250819112403.432587-23-thuth@redhat.com> --- tests/functional/meson.build | 37 +-- tests/functional/test_acpi_bits.py | 340 -------------------- tests/functional/test_cpu_queries.py | 37 --- tests/functional/test_intel_iommu.py | 155 --------- tests/functional/test_linux_initrd.py | 95 ------ tests/functional/test_mem_addr_space.py | 349 --------------------- tests/functional/test_memlock.py | 79 ----- tests/functional/test_netdev_ethtool.py | 88 ------ tests/functional/test_pc_cpu_hotplug_props.py | 37 --- tests/functional/test_virtio_balloon.py | 178 ----------- tests/functional/test_virtio_gpu.py | 144 --------- tests/functional/test_virtio_version.py | 177 ----------- tests/functional/test_x86_64_hotplug_blk.py | 85 ----- tests/functional/test_x86_64_hotplug_cpu.py | 71 ----- tests/functional/test_x86_64_kvm_xen.py | 157 --------- tests/functional/test_x86_64_migration.py | 26 -- tests/functional/test_x86_64_multiprocess.py | 31 -- tests/functional/test_x86_64_replay.py | 58 ---- tests/functional/test_x86_64_reverse_debug.py | 36 --- tests/functional/test_x86_64_tuxrun.py | 36 --- tests/functional/test_x86_cpu_model_versions.py | 249 --------------- tests/functional/x86_64/meson.build | 37 +++ tests/functional/x86_64/test_acpi_bits.py | 340 ++++++++++++++++++++ tests/functional/x86_64/test_cpu_model_versions.py | 249 +++++++++++++++ tests/functional/x86_64/test_cpu_queries.py | 37 +++ tests/functional/x86_64/test_hotplug_blk.py | 85 +++++ tests/functional/x86_64/test_hotplug_cpu.py | 71 +++++ tests/functional/x86_64/test_intel_iommu.py | 155 +++++++++ tests/functional/x86_64/test_kvm_xen.py | 157 +++++++++ tests/functional/x86_64/test_linux_initrd.py | 95 ++++++ tests/functional/x86_64/test_mem_addr_space.py | 349 +++++++++++++++++++++ tests/functional/x86_64/test_memlock.py | 79 +++++ tests/functional/x86_64/test_migration.py | 26 ++ tests/functional/x86_64/test_multiprocess.py | 31 ++ tests/functional/x86_64/test_netdev_ethtool.py | 88 ++++++ .../functional/x86_64/test_pc_cpu_hotplug_props.py | 37 +++ tests/functional/x86_64/test_replay.py | 58 ++++ tests/functional/x86_64/test_reverse_debug.py | 36 +++ tests/functional/x86_64/test_tuxrun.py | 36 +++ tests/functional/x86_64/test_virtio_balloon.py | 178 +++++++++++ tests/functional/x86_64/test_virtio_gpu.py | 144 +++++++++ tests/functional/x86_64/test_virtio_version.py | 177 +++++++++++ 42 files changed, 2466 insertions(+), 2464 deletions(-) delete mode 100755 tests/functional/test_acpi_bits.py delete mode 100755 tests/functional/test_cpu_queries.py delete mode 100755 tests/functional/test_intel_iommu.py delete mode 100755 tests/functional/test_linux_initrd.py delete mode 100755 tests/functional/test_mem_addr_space.py delete mode 100755 tests/functional/test_memlock.py delete mode 100755 tests/functional/test_netdev_ethtool.py delete mode 100755 tests/functional/test_pc_cpu_hotplug_props.py delete mode 100755 tests/functional/test_virtio_balloon.py delete mode 100755 tests/functional/test_virtio_gpu.py delete mode 100755 tests/functional/test_virtio_version.py delete mode 100755 tests/functional/test_x86_64_hotplug_blk.py delete mode 100755 tests/functional/test_x86_64_hotplug_cpu.py delete mode 100755 tests/functional/test_x86_64_kvm_xen.py delete mode 100755 tests/functional/test_x86_64_migration.py delete mode 100755 tests/functional/test_x86_64_multiprocess.py delete mode 100755 tests/functional/test_x86_64_replay.py delete mode 100755 tests/functional/test_x86_64_reverse_debug.py delete mode 100755 tests/functional/test_x86_64_tuxrun.py delete mode 100755 tests/functional/test_x86_cpu_model_versions.py create mode 100644 tests/functional/x86_64/meson.build create mode 100755 tests/functional/x86_64/test_acpi_bits.py create mode 100755 tests/functional/x86_64/test_cpu_model_versions.py create mode 100755 tests/functional/x86_64/test_cpu_queries.py create mode 100755 tests/functional/x86_64/test_hotplug_blk.py create mode 100755 tests/functional/x86_64/test_hotplug_cpu.py create mode 100755 tests/functional/x86_64/test_intel_iommu.py create mode 100755 tests/functional/x86_64/test_kvm_xen.py create mode 100755 tests/functional/x86_64/test_linux_initrd.py create mode 100755 tests/functional/x86_64/test_mem_addr_space.py create mode 100755 tests/functional/x86_64/test_memlock.py create mode 100755 tests/functional/x86_64/test_migration.py create mode 100755 tests/functional/x86_64/test_multiprocess.py create mode 100755 tests/functional/x86_64/test_netdev_ethtool.py create mode 100755 tests/functional/x86_64/test_pc_cpu_hotplug_props.py create mode 100755 tests/functional/x86_64/test_replay.py create mode 100755 tests/functional/x86_64/test_reverse_debug.py create mode 100755 tests/functional/x86_64/test_tuxrun.py create mode 100755 tests/functional/x86_64/test_virtio_balloon.py create mode 100755 tests/functional/x86_64/test_virtio_gpu.py create mode 100755 tests/functional/x86_64/test_virtio_version.py (limited to 'tests') diff --git a/tests/functional/meson.build b/tests/functional/meson.build index 00d18db..34e3023 100644 --- a/tests/functional/meson.build +++ b/tests/functional/meson.build @@ -34,15 +34,7 @@ subdir('sh4') subdir('sh4eb') subdir('sparc') subdir('sparc64') - -test_x86_64_timeouts = { - 'acpi_bits' : 420, - 'intel_iommu': 300, - 'netdev_ethtool' : 180, - 'virtio_balloon': 120, - 'x86_64_kvm_xen' : 180, - 'x86_64_replay' : 480, -} +subdir('x86_64') tests_generic_system = [ 'empty_cpu_model', @@ -56,33 +48,6 @@ tests_generic_linuxuser = [ tests_generic_bsduser = [ ] -tests_x86_64_system_quick = [ - 'cpu_queries', - 'mem_addr_space', - 'x86_64_migration', - 'pc_cpu_hotplug_props', - 'virtio_version', - 'x86_cpu_model_versions', - 'vnc', - 'memlock', -] - -tests_x86_64_system_thorough = [ - 'acpi_bits', - 'intel_iommu', - 'linux_initrd', - 'x86_64_multiprocess', - 'netdev_ethtool', - 'virtio_balloon', - 'virtio_gpu', - 'x86_64_hotplug_blk', - 'x86_64_hotplug_cpu', - 'x86_64_kvm_xen', - 'x86_64_replay', - 'x86_64_reverse_debug', - 'x86_64_tuxrun', -] - tests_xtensa_system_thorough = [ 'xtensa_lx60', 'xtensa_replay', diff --git a/tests/functional/test_acpi_bits.py b/tests/functional/test_acpi_bits.py deleted file mode 100755 index 8e0563a..0000000 --- a/tests/functional/test_acpi_bits.py +++ /dev/null @@ -1,340 +0,0 @@ -#!/usr/bin/env python3 -# -# Exercise QEMU generated ACPI/SMBIOS tables using biosbits, -# https://biosbits.org/ -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . -# -# -# Author: -# Ani Sinha - -# pylint: disable=invalid-name -# pylint: disable=consider-using-f-string - -""" -This is QEMU ACPI/SMBIOS functional tests using biosbits. -Biosbits is available originally at https://biosbits.org/. -This test uses a fork of the upstream bits and has numerous fixes -including an upgraded acpica. The fork is located here: -https://gitlab.com/qemu-project/biosbits-bits . -""" - -import os -import re -import shutil -import subprocess - -from typing import ( - List, - Optional, - Sequence, -) -from qemu.machine import QEMUMachine -from qemu_test import (QemuSystemTest, Asset, skipIfMissingCommands, - skipIfNotMachine) - - -# default timeout of 120 secs is sometimes not enough for bits test. -BITS_TIMEOUT = 200 - -class QEMUBitsMachine(QEMUMachine): # pylint: disable=too-few-public-methods - """ - A QEMU VM, with isa-debugcon enabled and bits iso passed - using -cdrom to QEMU commandline. - - """ - def __init__(self, - binary: str, - args: Sequence[str] = (), - wrapper: Sequence[str] = (), - name: Optional[str] = None, - base_temp_dir: str = "/var/tmp", - debugcon_log: str = "debugcon-log.txt", - debugcon_addr: str = "0x403", - qmp_timer: Optional[float] = None): - # pylint: disable=too-many-arguments - - if name is None: - name = "qemu-bits-%d" % os.getpid() - super().__init__(binary, args, wrapper=wrapper, name=name, - base_temp_dir=base_temp_dir, - qmp_timer=qmp_timer) - self.debugcon_log = debugcon_log - self.debugcon_addr = debugcon_addr - self.base_temp_dir = base_temp_dir - - @property - def _base_args(self) -> List[str]: - args = super()._base_args - args.extend([ - '-chardev', - 'file,path=%s,id=debugcon' %os.path.join(self.base_temp_dir, - self.debugcon_log), - '-device', - 'isa-debugcon,iobase=%s,chardev=debugcon' %self.debugcon_addr, - ]) - return args - - def base_args(self): - """return the base argument to QEMU binary""" - return self._base_args - -@skipIfMissingCommands("xorriso", "mformat") -@skipIfNotMachine("x86_64") -class AcpiBitsTest(QemuSystemTest): #pylint: disable=too-many-instance-attributes - """ - ACPI and SMBIOS tests using biosbits. - """ - # in slower systems the test can take as long as 3 minutes to complete. - timeout = BITS_TIMEOUT - - # following are some standard configuration constants - # gitlab CI does shallow clones of depth 20 - BITS_INTERNAL_VER = 2020 - # commit hash must match the artifact tag below - BITS_COMMIT_HASH = 'c7920d2b' - # this is the latest bits release as of today. - BITS_TAG = "qemu-bits-10262023" - - ASSET_BITS = Asset(("https://gitlab.com/qemu-project/" - "biosbits-bits/-/jobs/artifacts/%s/" - "download?job=qemu-bits-build" % BITS_TAG), - '1b8dd612c6831a6b491716a77acc486666aaa867051cdc34f7ce169c2e25f487') - - def __init__(self, *args, **kwargs): - super().__init__(*args, **kwargs) - self._vm = None - - self._debugcon_addr = '0x403' - self._debugcon_log = 'debugcon-log.txt' - - def _print_log(self, log): - self.logger.info('\nlogs from biosbits follows:') - self.logger.info('==========================================\n') - self.logger.info(log) - self.logger.info('==========================================\n') - - def copy_bits_config(self): - """ copies the bios bits config file into bits. - """ - bits_config_file = self.data_file('acpi-bits', - 'bits-config', - 'bits-cfg.txt') - target_config_dir = self.scratch_file('bits-%d' % - self.BITS_INTERNAL_VER, - 'boot') - self.assertTrue(os.path.exists(bits_config_file)) - self.assertTrue(os.path.exists(target_config_dir)) - shutil.copy2(bits_config_file, target_config_dir) - self.logger.info('copied config file %s to %s', - bits_config_file, target_config_dir) - - def copy_test_scripts(self): - """copies the python test scripts into bits. """ - - bits_test_dir = self.data_file('acpi-bits', 'bits-tests') - target_test_dir = self.scratch_file('bits-%d' % self.BITS_INTERNAL_VER, - 'boot', 'python') - - self.assertTrue(os.path.exists(bits_test_dir)) - self.assertTrue(os.path.exists(target_test_dir)) - - for filename in os.listdir(bits_test_dir): - if os.path.isfile(os.path.join(bits_test_dir, filename)) and \ - filename.endswith('.py2'): - # All test scripts are named with extension .py2 so that - # they are not run by accident. - # - # These scripts are intended to run inside the test VM - # and are written for python 2.7 not python 3, hence - # would cause syntax errors if loaded ouside the VM. - newfilename = os.path.splitext(filename)[0] + '.py' - shutil.copy2(os.path.join(bits_test_dir, filename), - os.path.join(target_test_dir, newfilename)) - self.logger.info('copied test file %s to %s', - filename, target_test_dir) - - # now remove the pyc test file if it exists, otherwise the - # changes in the python test script won't be executed. - testfile_pyc = os.path.splitext(filename)[0] + '.pyc' - if os.access(os.path.join(target_test_dir, testfile_pyc), - os.F_OK): - os.remove(os.path.join(target_test_dir, testfile_pyc)) - self.logger.info('removed compiled file %s', - os.path.join(target_test_dir, - testfile_pyc)) - - def fix_mkrescue(self, mkrescue): - """ grub-mkrescue is a bash script with two variables, 'prefix' and - 'libdir'. They must be pointed to the right location so that the - iso can be generated appropriately. We point the two variables to - the directory where we have extracted our pre-built bits grub - tarball. - """ - grub_x86_64_mods = self.scratch_file('grub-inst-x86_64-efi') - grub_i386_mods = self.scratch_file('grub-inst') - - self.assertTrue(os.path.exists(grub_x86_64_mods)) - self.assertTrue(os.path.exists(grub_i386_mods)) - - new_script = "" - with open(mkrescue, 'r', encoding='utf-8') as filehandle: - orig_script = filehandle.read() - new_script = re.sub('(^prefix=)(.*)', - r'\1"%s"' %grub_x86_64_mods, - orig_script, flags=re.M) - new_script = re.sub('(^libdir=)(.*)', r'\1"%s/lib"' %grub_i386_mods, - new_script, flags=re.M) - - with open(mkrescue, 'w', encoding='utf-8') as filehandle: - filehandle.write(new_script) - - def generate_bits_iso(self): - """ Uses grub-mkrescue to generate a fresh bits iso with the python - test scripts - """ - bits_dir = self.scratch_file('bits-%d' % self.BITS_INTERNAL_VER) - iso_file = self.scratch_file('bits-%d.iso' % self.BITS_INTERNAL_VER) - mkrescue_script = self.scratch_file('grub-inst-x86_64-efi', - 'bin', - 'grub-mkrescue') - - self.assertTrue(os.access(mkrescue_script, - os.R_OK | os.W_OK | os.X_OK)) - - self.fix_mkrescue(mkrescue_script) - - self.logger.info('using grub-mkrescue for generating biosbits iso ...') - - try: - if os.getenv('V') or os.getenv('BITS_DEBUG'): - proc = subprocess.run([mkrescue_script, '-o', iso_file, - bits_dir], - stdout=subprocess.PIPE, - stderr=subprocess.STDOUT, - check=True) - self.logger.info("grub-mkrescue output %s" % proc.stdout) - else: - subprocess.check_call([mkrescue_script, '-o', - iso_file, bits_dir], - stderr=subprocess.DEVNULL, - stdout=subprocess.DEVNULL) - except Exception as e: # pylint: disable=broad-except - self.skipTest("Error while generating the bits iso. " - "Pass V=1 in the environment to get more details. " - + str(e)) - - self.assertTrue(os.access(iso_file, os.R_OK)) - - self.logger.info('iso file %s successfully generated.', iso_file) - - def setUp(self): # pylint: disable=arguments-differ - super().setUp() - self.logger = self.log - - prebuiltDir = self.scratch_file('prebuilt') - if not os.path.isdir(prebuiltDir): - os.mkdir(prebuiltDir, mode=0o775) - - bits_zip_file = self.scratch_file('prebuilt', - 'bits-%d-%s.zip' - %(self.BITS_INTERNAL_VER, - self.BITS_COMMIT_HASH)) - grub_tar_file = self.scratch_file('prebuilt', - 'bits-%d-%s-grub.tar.gz' - %(self.BITS_INTERNAL_VER, - self.BITS_COMMIT_HASH)) - - # extract the bits artifact in the temp working directory - self.archive_extract(self.ASSET_BITS, sub_dir='prebuilt', format='zip') - - # extract the bits software in the temp working directory - self.archive_extract(bits_zip_file) - self.archive_extract(grub_tar_file) - - self.copy_test_scripts() - self.copy_bits_config() - self.generate_bits_iso() - - def parse_log(self): - """parse the log generated by running bits tests and - check for failures. - """ - debugconf = self.scratch_file(self._debugcon_log) - log = "" - with open(debugconf, 'r', encoding='utf-8') as filehandle: - log = filehandle.read() - - matchiter = re.finditer(r'(.*Summary: )(\d+ passed), (\d+ failed).*', - log) - for match in matchiter: - # verify that no test cases failed. - try: - self.assertEqual(match.group(3).split()[0], '0', - 'Some bits tests seems to have failed. ' \ - 'Please check the test logs for more info.') - except AssertionError as e: - self._print_log(log) - raise e - else: - if os.getenv('V') or os.getenv('BITS_DEBUG'): - self._print_log(log) - - def tearDown(self): - """ - Lets do some cleanups. - """ - if self._vm: - self.assertFalse(not self._vm.is_running) - super().tearDown() - - def test_acpi_smbios_bits(self): - """The main test case implementation.""" - - self.set_machine('pc') - iso_file = self.scratch_file('bits-%d.iso' % self.BITS_INTERNAL_VER) - - self.assertTrue(os.access(iso_file, os.R_OK)) - - self._vm = QEMUBitsMachine(binary=self.qemu_bin, - base_temp_dir=self.workdir, - debugcon_log=self._debugcon_log, - debugcon_addr=self._debugcon_addr) - - self._vm.add_args('-cdrom', '%s' %iso_file) - # the vm needs to be run under icount so that TCG emulation is - # consistent in terms of timing. smilatency tests have consistent - # timing requirements. - self._vm.add_args('-icount', 'auto') - # currently there is no support in bits for recognizing 64-bit SMBIOS - # entry points. QEMU defaults to 64-bit entry points since the - # upstream commit bf376f3020 ("hw/i386/pc: Default to use SMBIOS 3.0 - # for newer machine models"). Therefore, enforce 32-bit entry point. - self._vm.add_args('-machine', 'smbios-entry-point-type=32') - - # enable console logging - self._vm.set_console() - self._vm.launch() - - - # biosbits has been configured to run all the specified test suites - # in batch mode and then automatically initiate a vm shutdown. - self._vm.event_wait('SHUTDOWN', timeout=BITS_TIMEOUT) - self._vm.wait(timeout=None) - self.logger.debug("Checking console output ...") - self.parse_log() - -if __name__ == '__main__': - QemuSystemTest.main() diff --git a/tests/functional/test_cpu_queries.py b/tests/functional/test_cpu_queries.py deleted file mode 100755 index b1122a0..0000000 --- a/tests/functional/test_cpu_queries.py +++ /dev/null @@ -1,37 +0,0 @@ -#!/usr/bin/env python3 -# -# Sanity check of query-cpu-* results -# -# Copyright (c) 2019 Red Hat, Inc. -# -# Author: -# Eduardo Habkost -# -# This work is licensed under the terms of the GNU GPL, version 2 or -# later. See the COPYING file in the top-level directory. - -from qemu_test import QemuSystemTest - -class QueryCPUModelExpansion(QemuSystemTest): - """ - Run query-cpu-model-expansion for each CPU model, and validate results - """ - - def test(self): - self.set_machine('none') - self.vm.add_args('-S') - self.vm.launch() - - cpus = self.vm.cmd('query-cpu-definitions') - for c in cpus: - self.log.info("Checking CPU: %s", c) - self.assertNotIn('', c['unavailable-features'], c['name']) - - for c in cpus: - model = {'name': c['name']} - e = self.vm.cmd('query-cpu-model-expansion', model=model, - type='full') - self.assertEqual(e['model']['name'], c['name']) - -if __name__ == '__main__': - QemuSystemTest.main() diff --git a/tests/functional/test_intel_iommu.py b/tests/functional/test_intel_iommu.py deleted file mode 100755 index 62268d6..0000000 --- a/tests/functional/test_intel_iommu.py +++ /dev/null @@ -1,155 +0,0 @@ -#!/usr/bin/env python3 -# -# INTEL_IOMMU Functional tests -# -# Copyright (c) 2021 Red Hat, Inc. -# -# Author: -# Eric Auger -# -# This work is licensed under the terms of the GNU GPL, version 2 or -# later. See the COPYING file in the top-level directory. - -from qemu_test import LinuxKernelTest, Asset, exec_command_and_wait_for_pattern - - -class IntelIOMMU(LinuxKernelTest): - - ASSET_KERNEL = Asset( - ('https://archives.fedoraproject.org/pub/archive/fedora/linux/releases' - '/31/Server/x86_64/os/images/pxeboot/vmlinuz'), - 'd4738d03dbbe083ca610d0821d0a8f1488bebbdccef54ce33e3adb35fda00129') - - ASSET_INITRD = Asset( - ('https://archives.fedoraproject.org/pub/archive/fedora/linux/releases' - '/31/Server/x86_64/os/images/pxeboot/initrd.img'), - '277cd6c7adf77c7e63d73bbb2cded8ef9e2d3a2f100000e92ff1f8396513cd8b') - - ASSET_DISKIMAGE = Asset( - ('https://archives.fedoraproject.org/pub/archive/fedora/linux/releases' - '/31/Cloud/x86_64/images/Fedora-Cloud-Base-31-1.9.x86_64.qcow2'), - 'e3c1b309d9203604922d6e255c2c5d098a309c2d46215d8fc026954f3c5c27a0') - - DEFAULT_KERNEL_PARAMS = ('root=/dev/vda1 console=ttyS0 net.ifnames=0 ' - 'quiet rd.rescue ') - GUEST_PORT = 8080 - IOMMU_ADDON = ',iommu_platform=on,disable-modern=off,disable-legacy=on' - kernel_path = None - initrd_path = None - kernel_params = None - - def add_common_args(self, path): - self.vm.add_args('-drive', f'file={path},if=none,id=drv0,snapshot=on') - self.vm.add_args('-device', 'virtio-blk-pci,bus=pcie.0,' + - 'drive=drv0,id=virtio-disk0,bootindex=1,' - 'werror=stop,rerror=stop' + self.IOMMU_ADDON) - self.vm.add_args('-device', 'virtio-gpu-pci' + self.IOMMU_ADDON) - - self.vm.add_args('-netdev', - 'user,id=n1,hostfwd=tcp:127.0.0.1:0-:%d' % - self.GUEST_PORT) - self.vm.add_args('-device', - 'virtio-net-pci,netdev=n1' + self.IOMMU_ADDON) - - self.vm.add_args('-device', 'virtio-rng-pci,rng=rng0') - self.vm.add_args('-object', - 'rng-random,id=rng0,filename=/dev/urandom') - self.vm.add_args("-m", "1G") - self.vm.add_args("-accel", "kvm") - - def common_vm_setup(self): - self.set_machine('q35') - self.require_accelerator("kvm") - self.require_netdev('user') - - self.kernel_path = self.ASSET_KERNEL.fetch() - self.initrd_path = self.ASSET_INITRD.fetch() - image_path = self.ASSET_DISKIMAGE.fetch() - self.add_common_args(image_path) - self.kernel_params = self.DEFAULT_KERNEL_PARAMS - - def run_and_check(self): - if self.kernel_path: - self.vm.add_args('-kernel', self.kernel_path, - '-append', self.kernel_params, - '-initrd', self.initrd_path) - self.vm.set_console() - self.vm.launch() - self.wait_for_console_pattern('Entering emergency mode.') - prompt = '# ' - self.wait_for_console_pattern(prompt) - - # Copy a file (checked later), umount afterwards to drop disk cache: - exec_command_and_wait_for_pattern(self, 'mount /dev/vda1 /sysroot', - prompt) - filename = '/boot/initramfs-5.3.7-301.fc31.x86_64.img' - exec_command_and_wait_for_pattern(self, (f'cp /sysroot{filename}' - ' /sysroot/root/data'), - prompt) - exec_command_and_wait_for_pattern(self, 'umount /sysroot', prompt) - - # Switch from initrd to the cloud image filesystem: - exec_command_and_wait_for_pattern(self, 'mount /dev/vda1 /sysroot', - prompt) - exec_command_and_wait_for_pattern(self, - ('for d in dev proc sys run ; do ' - 'mount -o bind /$d /sysroot/$d ; done'), prompt) - exec_command_and_wait_for_pattern(self, 'chroot /sysroot', prompt) - - # Checking for IOMMU enablement: - self.log.info("Checking whether IOMMU has been enabled...") - exec_command_and_wait_for_pattern(self, 'cat /proc/cmdline', - 'intel_iommu=on') - self.wait_for_console_pattern(prompt) - exec_command_and_wait_for_pattern(self, 'dmesg | grep DMAR:', - 'IOMMU enabled') - self.wait_for_console_pattern(prompt) - exec_command_and_wait_for_pattern(self, - 'find /sys/kernel/iommu_groups/ -type l', - 'devices/0000:00:') - self.wait_for_console_pattern(prompt) - - # Check hard disk device via sha256sum: - self.log.info("Checking hard disk...") - hashsum = '0dc7472f879be70b2f3daae279e3ae47175ffe249691e7d97f47222b65b8a720' - exec_command_and_wait_for_pattern(self, 'sha256sum ' + filename, - hashsum) - self.wait_for_console_pattern(prompt) - exec_command_and_wait_for_pattern(self, 'sha256sum /root/data', - hashsum) - self.wait_for_console_pattern(prompt) - - # Check virtio-net via HTTP: - exec_command_and_wait_for_pattern(self, 'dhclient eth0', prompt) - self.check_http_download(filename, hashsum, self.GUEST_PORT) - - def test_intel_iommu(self): - self.common_vm_setup() - self.vm.add_args('-device', 'intel-iommu,intremap=on') - self.vm.add_args('-machine', 'kernel_irqchip=split') - self.kernel_params += 'intel_iommu=on' - self.run_and_check() - - def test_intel_iommu_strict(self): - self.common_vm_setup() - self.vm.add_args('-device', 'intel-iommu,intremap=on') - self.vm.add_args('-machine', 'kernel_irqchip=split') - self.kernel_params += 'intel_iommu=on,strict' - self.run_and_check() - - def test_intel_iommu_strict_cm(self): - self.common_vm_setup() - self.vm.add_args('-device', 'intel-iommu,intremap=on,caching-mode=on') - self.vm.add_args('-machine', 'kernel_irqchip=split') - self.kernel_params += 'intel_iommu=on,strict' - self.run_and_check() - - def test_intel_iommu_pt(self): - self.common_vm_setup() - self.vm.add_args('-device', 'intel-iommu,intremap=on') - self.vm.add_args('-machine', 'kernel_irqchip=split') - self.kernel_params += 'intel_iommu=on iommu=pt' - self.run_and_check() - -if __name__ == '__main__': - LinuxKernelTest.main() diff --git a/tests/functional/test_linux_initrd.py b/tests/functional/test_linux_initrd.py deleted file mode 100755 index 2207f83..0000000 --- a/tests/functional/test_linux_initrd.py +++ /dev/null @@ -1,95 +0,0 @@ -#!/usr/bin/env python3 -# -# Linux initrd integration test. -# -# Copyright (c) 2018 Red Hat, Inc. -# -# Author: -# Wainer dos Santos Moschetta -# -# This work is licensed under the terms of the GNU GPL, version 2 or -# later. See the COPYING file in the top-level directory. - -import logging -import tempfile - -from qemu_test import QemuSystemTest, Asset, skipFlakyTest - - -class LinuxInitrd(QemuSystemTest): - """ - Checks QEMU evaluates correctly the initrd file passed as -initrd option. - """ - - timeout = 300 - - ASSET_F18_KERNEL = Asset( - ('https://archives.fedoraproject.org/pub/archive/fedora/linux/' - 'releases/18/Fedora/x86_64/os/images/pxeboot/vmlinuz'), - '1a27cb42559ce29237ac186699d063556ad69c8349d732bb1bd8d614e5a8cc2e') - - ASSET_F28_KERNEL = Asset( - ('https://archives.fedoraproject.org/pub/archive/fedora/linux/' - 'releases/28/Everything/x86_64/os/images/pxeboot/vmlinuz'), - 'd05909c9d4a742a6fcc84dcc0361009e4611769619cc187a07107579a035f24e') - - def test_with_2gib_file_should_exit_error_msg_with_linux_v3_6(self): - """ - Pretends to boot QEMU with an initrd file with size of 2GiB - and expect it exits with error message. - Fedora-18 shipped with linux-3.6 which have not supported xloadflags - cannot support more than 2GiB initrd. - """ - self.set_machine('pc') - kernel_path = self.ASSET_F18_KERNEL.fetch() - max_size = 2 * (1024 ** 3) - 1 - - with tempfile.NamedTemporaryFile() as initrd: - initrd.seek(max_size) - initrd.write(b'\0') - initrd.flush() - self.vm.add_args('-kernel', kernel_path, '-initrd', initrd.name, - '-m', '4096') - self.vm.set_qmp_monitor(enabled=False) - self.vm.launch() - self.vm.wait() - self.assertEqual(self.vm.exitcode(), 1) - expected_msg = r'.*initrd is too large.*max: \d+, need %s.*' % ( - max_size + 1) - self.assertRegex(self.vm.get_log(), expected_msg) - - # XXX file tracking bug - @skipFlakyTest(bug_url=None) - def test_with_2gib_file_should_work_with_linux_v4_16(self): - """ - QEMU has supported up to 4 GiB initrd for recent kernel - Expect guest can reach 'Unpacking initramfs...' - """ - self.set_machine('pc') - kernel_path = self.ASSET_F28_KERNEL.fetch() - max_size = 2 * (1024 ** 3) + 1 - - with tempfile.NamedTemporaryFile() as initrd: - initrd.seek(max_size) - initrd.write(b'\0') - initrd.flush() - - self.vm.set_console() - kernel_command_line = 'console=ttyS0' - self.vm.add_args('-kernel', kernel_path, - '-append', kernel_command_line, - '-initrd', initrd.name, - '-m', '5120') - self.vm.launch() - console = self.vm.console_socket.makefile() - console_logger = logging.getLogger('console') - while True: - msg = console.readline() - console_logger.debug(msg.strip()) - if 'Unpacking initramfs...' in msg: - break - if 'Kernel panic - not syncing' in msg: - self.fail("Kernel panic reached") - -if __name__ == '__main__': - QemuSystemTest.main() diff --git a/tests/functional/test_mem_addr_space.py b/tests/functional/test_mem_addr_space.py deleted file mode 100755 index 61b4a19..0000000 --- a/tests/functional/test_mem_addr_space.py +++ /dev/null @@ -1,349 +0,0 @@ -#!/usr/bin/env python3 -# -# Check for crash when using memory beyond the available guest processor -# address space. -# -# Copyright (c) 2023 Red Hat, Inc. -# -# Author: -# Ani Sinha -# -# SPDX-License-Identifier: GPL-2.0-or-later - -from qemu_test import QemuSystemTest -import time - -class MemAddrCheck(QemuSystemTest): - # after launch, in order to generate the logs from QEMU we need to - # wait for some time. Launching and then immediately shutting down - # the VM generates empty logs. A delay of 1 second is added for - # this reason. - DELAY_Q35_BOOT_SEQUENCE = 1 - - # This helper can go away when the 32-bit host deprecation - # turns into full & final removal of support. - def ensure_64bit_binary(self): - with open(self.qemu_bin, "rb") as fh: - ident = fh.read(4) - - # "\x7fELF" - if ident != bytes([0x7f, 0x45, 0x4C, 0x46]): - # Non-ELF file implies macOS or Windows which - # we already assume to be 64-bit only - return - - # bits == 1 -> 32-bit; bits == 2 -> 64-bit - bits = int.from_bytes(fh.read(1), byteorder='little') - if bits != 2: - # 32-bit ELF builds won't be able to address sufficient - # RAM to run the tests - self.skipTest("64-bit build host is required") - - # first, lets test some 32-bit processors. - # for all 32-bit cases, pci64_hole_size is 0. - def test_phybits_low_pse36(self): - """ - With pse36 feature ON, a processor has 36 bits of addressing. So it can - access up to a maximum of 64GiB of memory. Memory hotplug region begins - at 4 GiB boundary when "above_4g_mem_size" is 0 (this would be true when - we have 0.5 GiB of VM memory, see pc_q35_init()). This means total - hotpluggable memory size is 60 GiB. Per slot, we reserve 1 GiB of memory - for dimm alignment for all machines. That leaves total hotpluggable - actual memory size of 59 GiB. If the VM is started with 0.5 GiB of - memory, maxmem should be set to a maximum value of 59.5 GiB to ensure - that the processor can address all memory directly. - Note that 64-bit pci hole size is 0 in this case. If maxmem is set to - 59.6G, QEMU should fail to start with a message "phy-bits are too low". - If maxmem is set to 59.5G with all other QEMU parameters identical, QEMU - should start fine. - """ - self.ensure_64bit_binary() - self.set_machine('q35') - self.vm.add_args('-S', '-m', '512,slots=1,maxmem=59.6G', - '-cpu', 'pentium,pse36=on', '-display', 'none', - '-object', 'memory-backend-ram,id=mem1,size=1G', - '-device', 'pc-dimm,id=vm0,memdev=mem1') - self.vm.set_qmp_monitor(enabled=False) - self.vm.launch() - self.vm.wait() - self.assertEqual(self.vm.exitcode(), 1, "QEMU exit code should be 1") - self.assertRegex(self.vm.get_log(), r'phys-bits too low') - - def test_phybits_low_pae(self): - """ - With pae feature ON, a processor has 36 bits of addressing. So it can - access up to a maximum of 64GiB of memory. Rest is the same as the case - with pse36 above. - """ - self.ensure_64bit_binary() - self.set_machine('q35') - self.vm.add_args('-S', '-m', '512,slots=1,maxmem=59.6G', - '-cpu', 'pentium,pae=on', '-display', 'none', - '-object', 'memory-backend-ram,id=mem1,size=1G', - '-device', 'pc-dimm,id=vm0,memdev=mem1') - self.vm.set_qmp_monitor(enabled=False) - self.vm.launch() - self.vm.wait() - self.assertEqual(self.vm.exitcode(), 1, "QEMU exit code should be 1") - self.assertRegex(self.vm.get_log(), r'phys-bits too low') - - def test_phybits_ok_pentium_pse36(self): - """ - Setting maxmem to 59.5G and making sure that QEMU can start with the - same options as the failing case above with pse36 cpu feature. - """ - self.ensure_64bit_binary() - self.set_machine('q35') - self.vm.add_args('-m', '512,slots=1,maxmem=59.5G', - '-cpu', 'pentium,pse36=on', '-display', 'none', - '-object', 'memory-backend-ram,id=mem1,size=1G', - '-device', 'pc-dimm,id=vm0,memdev=mem1') - self.vm.set_qmp_monitor(enabled=False) - self.vm.launch() - time.sleep(self.DELAY_Q35_BOOT_SEQUENCE) - self.vm.shutdown() - self.assertNotRegex(self.vm.get_log(), r'phys-bits too low') - - def test_phybits_ok_pentium_pae(self): - """ - Test is same as above but now with pae cpu feature turned on. - Setting maxmem to 59.5G and making sure that QEMU can start fine - with the same options as the case above. - """ - self.ensure_64bit_binary() - self.set_machine('q35') - self.vm.add_args('-m', '512,slots=1,maxmem=59.5G', - '-cpu', 'pentium,pae=on', '-display', 'none', - '-object', 'memory-backend-ram,id=mem1,size=1G', - '-device', 'pc-dimm,id=vm0,memdev=mem1') - self.vm.set_qmp_monitor(enabled=False) - self.vm.launch() - time.sleep(self.DELAY_Q35_BOOT_SEQUENCE) - self.vm.shutdown() - self.assertNotRegex(self.vm.get_log(), r'phys-bits too low') - - def test_phybits_ok_pentium2(self): - """ - Pentium2 has 36 bits of addressing, so its same as pentium - with pse36 ON. - """ - self.ensure_64bit_binary() - self.set_machine('q35') - self.vm.add_args('-m', '512,slots=1,maxmem=59.5G', - '-cpu', 'pentium2', '-display', 'none', - '-object', 'memory-backend-ram,id=mem1,size=1G', - '-device', 'pc-dimm,id=vm0,memdev=mem1') - self.vm.set_qmp_monitor(enabled=False) - self.vm.launch() - time.sleep(self.DELAY_Q35_BOOT_SEQUENCE) - self.vm.shutdown() - self.assertNotRegex(self.vm.get_log(), r'phys-bits too low') - - def test_phybits_low_nonpse36(self): - """ - Pentium processor has 32 bits of addressing without pse36 or pae - so it can access physical address up to 4 GiB. Setting maxmem to - 4 GiB should make QEMU fail to start with "phys-bits too low" - message because the region for memory hotplug is always placed - above 4 GiB due to the PCI hole and simplicity. - """ - self.ensure_64bit_binary() - self.set_machine('q35') - self.vm.add_args('-S', '-m', '512,slots=1,maxmem=4G', - '-cpu', 'pentium', '-display', 'none', - '-object', 'memory-backend-ram,id=mem1,size=1G', - '-device', 'pc-dimm,id=vm0,memdev=mem1') - self.vm.set_qmp_monitor(enabled=False) - self.vm.launch() - self.vm.wait() - self.assertEqual(self.vm.exitcode(), 1, "QEMU exit code should be 1") - self.assertRegex(self.vm.get_log(), r'phys-bits too low') - - # now lets test some 64-bit CPU cases. - def test_phybits_low_tcg_q35_70_amd(self): - """ - For q35 7.1 machines and above, there is a HT window that starts at - 1024 GiB and ends at 1 TiB - 1. If the max GPA falls in this range, - "above_4G" memory is adjusted to start at 1 TiB boundary for AMD cpus - in the default case. Lets test without that case for machines 7.0. - For q35-7.0 machines, "above 4G" memory starts are 4G. - pci64_hole size is 32 GiB. Since TCG_PHYS_ADDR_BITS is defined to - be 40, TCG emulated CPUs have maximum of 1 TiB (1024 GiB) of - directly addressable memory. - Hence, maxmem value at most can be - 1024 GiB - 4 GiB - 1 GiB per slot for alignment - 32 GiB + 0.5 GiB - which is equal to 987.5 GiB. Setting the value to 988 GiB should - make QEMU fail with the error message. - """ - self.ensure_64bit_binary() - self.set_machine('pc-q35-7.0') - self.vm.add_args('-S', '-m', '512,slots=1,maxmem=988G', - '-display', 'none', - '-object', 'memory-backend-ram,id=mem1,size=1G', - '-device', 'pc-dimm,id=vm0,memdev=mem1') - self.vm.set_qmp_monitor(enabled=False) - self.vm.launch() - self.vm.wait() - self.assertEqual(self.vm.exitcode(), 1, "QEMU exit code should be 1") - self.assertRegex(self.vm.get_log(), r'phys-bits too low') - - def test_phybits_low_tcg_q35_71_amd(self): - """ - AMD_HT_START is defined to be at 1012 GiB. So for q35 machines - version > 7.0 and AMD cpus, instead of 1024 GiB limit for 40 bit - processor address space, it has to be 1012 GiB , that is 12 GiB - less than the case above in order to accommodate HT hole. - Make sure QEMU fails when maxmem size is 976 GiB (12 GiB less - than 988 GiB). - """ - self.ensure_64bit_binary() - self.set_machine('pc-q35-7.1') - self.vm.add_args('-S', '-m', '512,slots=1,maxmem=976G', - '-display', 'none', - '-object', 'memory-backend-ram,id=mem1,size=1G', - '-device', 'pc-dimm,id=vm0,memdev=mem1') - self.vm.set_qmp_monitor(enabled=False) - self.vm.launch() - self.vm.wait() - self.assertEqual(self.vm.exitcode(), 1, "QEMU exit code should be 1") - self.assertRegex(self.vm.get_log(), r'phys-bits too low') - - def test_phybits_ok_tcg_q35_70_amd(self): - """ - Same as q35-7.0 AMD case except that here we check that QEMU can - successfully start when maxmem is < 988G. - """ - self.ensure_64bit_binary() - self.set_machine('pc-q35-7.0') - self.vm.add_args('-S', '-m', '512,slots=1,maxmem=987.5G', - '-display', 'none', - '-object', 'memory-backend-ram,id=mem1,size=1G', - '-device', 'pc-dimm,id=vm0,memdev=mem1') - self.vm.set_qmp_monitor(enabled=False) - self.vm.launch() - time.sleep(self.DELAY_Q35_BOOT_SEQUENCE) - self.vm.shutdown() - self.assertNotRegex(self.vm.get_log(), r'phys-bits too low') - - def test_phybits_ok_tcg_q35_71_amd(self): - """ - Same as q35-7.1 AMD case except that here we check that QEMU can - successfully start when maxmem is < 976G. - """ - self.ensure_64bit_binary() - self.set_machine('pc-q35-7.1') - self.vm.add_args('-S', '-m', '512,slots=1,maxmem=975.5G', - '-display', 'none', - '-object', 'memory-backend-ram,id=mem1,size=1G', - '-device', 'pc-dimm,id=vm0,memdev=mem1') - self.vm.set_qmp_monitor(enabled=False) - self.vm.launch() - time.sleep(self.DELAY_Q35_BOOT_SEQUENCE) - self.vm.shutdown() - self.assertNotRegex(self.vm.get_log(), r'phys-bits too low') - - def test_phybits_ok_tcg_q35_71_intel(self): - """ - Same parameters as test_phybits_low_tcg_q35_71_amd() but use - Intel cpu instead. QEMU should start fine in this case as - "above_4G" memory starts at 4G. - """ - self.ensure_64bit_binary() - self.set_machine('pc-q35-7.1') - self.vm.add_args('-S', '-cpu', 'Skylake-Server', - '-m', '512,slots=1,maxmem=976G', - '-display', 'none', - '-object', 'memory-backend-ram,id=mem1,size=1G', - '-device', 'pc-dimm,id=vm0,memdev=mem1') - self.vm.set_qmp_monitor(enabled=False) - self.vm.launch() - time.sleep(self.DELAY_Q35_BOOT_SEQUENCE) - self.vm.shutdown() - self.assertNotRegex(self.vm.get_log(), r'phys-bits too low') - - def test_phybits_low_tcg_q35_71_amd_41bits(self): - """ - AMD processor with 41 bits. Max cpu hw address = 2 TiB. - By setting maxram above 1012 GiB - 32 GiB - 4 GiB = 976 GiB, we can - force "above_4G" memory to start at 1 TiB for q35-7.1 machines - (max GPA will be above AMD_HT_START which is defined as 1012 GiB). - - With pci_64_hole size at 32 GiB, in this case, maxmem should be 991.5 - GiB with 1 GiB per slot for alignment and 0.5 GiB as non-hotplug - memory for the VM (1024 - 32 - 1 + 0.5). With 992 GiB, QEMU should - fail to start. - """ - self.ensure_64bit_binary() - self.set_machine('pc-q35-7.1') - self.vm.add_args('-S', '-cpu', 'EPYC-v4,phys-bits=41', - '-m', '512,slots=1,maxmem=992G', - '-display', 'none', - '-object', 'memory-backend-ram,id=mem1,size=1G', - '-device', 'pc-dimm,id=vm0,memdev=mem1') - self.vm.set_qmp_monitor(enabled=False) - self.vm.launch() - self.vm.wait() - self.assertEqual(self.vm.exitcode(), 1, "QEMU exit code should be 1") - self.assertRegex(self.vm.get_log(), r'phys-bits too low') - - def test_phybits_ok_tcg_q35_71_amd_41bits(self): - """ - AMD processor with 41 bits. Max cpu hw address = 2 TiB. - Same as above but by setting maxram between 976 GiB and 992 Gib, - QEMU should start fine. - """ - self.ensure_64bit_binary() - self.set_machine('pc-q35-7.1') - self.vm.add_args('-S', '-cpu', 'EPYC-v4,phys-bits=41', - '-m', '512,slots=1,maxmem=990G', - '-display', 'none', - '-object', 'memory-backend-ram,id=mem1,size=1G', - '-device', 'pc-dimm,id=vm0,memdev=mem1') - self.vm.set_qmp_monitor(enabled=False) - self.vm.launch() - time.sleep(self.DELAY_Q35_BOOT_SEQUENCE) - self.vm.shutdown() - self.assertNotRegex(self.vm.get_log(), r'phys-bits too low') - - def test_phybits_low_tcg_q35_intel_cxl(self): - """ - cxl memory window starts after memory device range. Here, we use 1 GiB - of cxl window memory. 4G_mem end aligns at 4G. pci64_hole is 32 GiB and - starts after the cxl memory window. - So maxmem here should be at most 986 GiB considering all memory boundary - alignment constraints with 40 bits (1 TiB) of processor physical bits. - """ - self.ensure_64bit_binary() - self.set_machine('q35') - self.vm.add_args('-S', '-cpu', 'Skylake-Server,phys-bits=40', - '-m', '512,slots=1,maxmem=987G', - '-display', 'none', - '-device', 'pxb-cxl,bus_nr=12,bus=pcie.0,id=cxl.1', - '-M', 'cxl=on,cxl-fmw.0.targets.0=cxl.1,cxl-fmw.0.size=1G') - self.vm.set_qmp_monitor(enabled=False) - self.vm.launch() - self.vm.wait() - self.assertEqual(self.vm.exitcode(), 1, "QEMU exit code should be 1") - self.assertRegex(self.vm.get_log(), r'phys-bits too low') - - def test_phybits_ok_tcg_q35_intel_cxl(self): - """ - Same as above but here we do not reserve any cxl memory window. Hence, - with the exact same parameters as above, QEMU should start fine even - with cxl enabled. - """ - self.ensure_64bit_binary() - self.set_machine('q35') - self.vm.add_args('-S', '-cpu', 'Skylake-Server,phys-bits=40', - '-machine', 'cxl=on', - '-m', '512,slots=1,maxmem=987G', - '-display', 'none', - '-device', 'pxb-cxl,bus_nr=12,bus=pcie.0,id=cxl.1') - self.vm.set_qmp_monitor(enabled=False) - self.vm.launch() - time.sleep(self.DELAY_Q35_BOOT_SEQUENCE) - self.vm.shutdown() - self.assertNotRegex(self.vm.get_log(), r'phys-bits too low') - -if __name__ == '__main__': - QemuSystemTest.main() diff --git a/tests/functional/test_memlock.py b/tests/functional/test_memlock.py deleted file mode 100755 index 2b515ff..0000000 --- a/tests/functional/test_memlock.py +++ /dev/null @@ -1,79 +0,0 @@ -#!/usr/bin/env python3 -# -# Functional test that check overcommit memlock options -# -# Copyright (c) Yandex Technologies LLC, 2025 -# -# Author: -# Alexandr Moshkov -# -# SPDX-License-Identifier: GPL-2.0-or-later - -import re - -from typing import Dict - -from qemu_test import QemuSystemTest -from qemu_test import skipLockedMemoryTest - - -STATUS_VALUE_PATTERN = re.compile(r'^(\w+):\s+(\d+) kB', re.MULTILINE) - - -@skipLockedMemoryTest(2_097_152) # 2GB -class MemlockTest(QemuSystemTest): - """ - Runs a guest with memlock options. - Then verify, that this options is working correctly - by checking the status file of the QEMU process. - """ - - def common_vm_setup_with_memlock(self, memlock): - self.vm.add_args('-overcommit', f'mem-lock={memlock}') - self.vm.launch() - - def test_memlock_off(self): - self.common_vm_setup_with_memlock('off') - - status = self.get_process_status_values(self.vm.get_pid()) - - self.assertTrue(status['VmLck'] == 0) - - def test_memlock_on(self): - self.common_vm_setup_with_memlock('on') - - status = self.get_process_status_values(self.vm.get_pid()) - - # VmLck > 0 kB and almost all memory is resident - self.assertTrue(status['VmLck'] > 0) - self.assertTrue(status['VmRSS'] >= status['VmSize'] * 0.70) - - def test_memlock_onfault(self): - self.common_vm_setup_with_memlock('on-fault') - - status = self.get_process_status_values(self.vm.get_pid()) - - # VmLck > 0 kB and only few memory is resident - self.assertTrue(status['VmLck'] > 0) - self.assertTrue(status['VmRSS'] <= status['VmSize'] * 0.30) - - def get_process_status_values(self, pid: int) -> Dict[str, int]: - result = {} - raw_status = self._get_raw_process_status(pid) - - for line in raw_status.split('\n'): - if m := STATUS_VALUE_PATTERN.match(line): - result[m.group(1)] = int(m.group(2)) - - return result - - def _get_raw_process_status(self, pid: int) -> str: - try: - with open(f'/proc/{pid}/status', 'r') as f: - return f.read() - except FileNotFoundError: - self.skipTest("Can't open status file of the process") - - -if __name__ == '__main__': - MemlockTest.main() diff --git a/tests/functional/test_netdev_ethtool.py b/tests/functional/test_netdev_ethtool.py deleted file mode 100755 index ee1a397..0000000 --- a/tests/functional/test_netdev_ethtool.py +++ /dev/null @@ -1,88 +0,0 @@ -#!/usr/bin/env python3 -# -# ethtool tests for emulated network devices -# -# This test leverages ethtool's --test sequence to validate network -# device behaviour. -# -# SPDX-License-Identifier: GPL-2.0-or-later - -from unittest import skip -from qemu_test import QemuSystemTest, Asset -from qemu_test import wait_for_console_pattern - -class NetDevEthtool(QemuSystemTest): - - # Runs in about 17s under KVM, 19s under TCG, 25s under GCOV - timeout = 45 - - # Fetch assets from the netdev-ethtool subdir of my shared test - # images directory on fileserver.linaro.org. - ASSET_BASEURL = ('https://fileserver.linaro.org/s/kE4nCFLdQcoBF9t/' - 'download?path=%2Fnetdev-ethtool&files=') - ASSET_BZIMAGE = Asset( - ASSET_BASEURL + "bzImage", - "ed62ee06ea620b1035747f3f66a5e9fc5d3096b29f75562ada888b04cd1c4baf") - ASSET_ROOTFS = Asset( - ASSET_BASEURL + "rootfs.squashfs", - "8f0207e3c4d40832ae73c1a927e42ca30ccb1e71f047acb6ddb161ba422934e6") - - def common_test_code(self, netdev, extra_args=None): - self.set_machine('q35') - - # This custom kernel has drivers for all the supported network - # devices we can emulate in QEMU - kernel = self.ASSET_BZIMAGE.fetch() - rootfs = self.ASSET_ROOTFS.fetch() - - append = 'printk.time=0 console=ttyS0 ' - append += 'root=/dev/sr0 rootfstype=squashfs ' - - # any additional kernel tweaks for the test - if extra_args: - append += extra_args - - # finally invoke ethtool directly - append += ' init=/usr/sbin/ethtool -- -t eth1 offline' - - # add the rootfs via a readonly cdrom image - drive = f"file={rootfs},if=ide,index=0,media=cdrom" - - self.vm.add_args('-kernel', kernel, - '-append', append, - '-drive', drive, - '-device', netdev) - - self.vm.set_console(console_index=0) - self.vm.launch() - - wait_for_console_pattern(self, - "The test result is PASS", - "The test result is FAIL", - vm=None) - # no need to gracefully shutdown, just finish - self.vm.kill() - - def test_igb(self): - self.common_test_code("igb") - - def test_igb_nomsi(self): - self.common_test_code("igb", "pci=nomsi") - - # It seems the other popular cards we model in QEMU currently fail - # the pattern test with: - # - # pattern test failed (reg 0x00178): got 0x00000000 expected 0x00005A5A - # - # So for now we skip them. - - @skip("Incomplete reg 0x00178 support") - def test_e1000(self): - self.common_test_code("e1000") - - @skip("Incomplete reg 0x00178 support") - def test_i82550(self): - self.common_test_code("i82550") - -if __name__ == '__main__': - QemuSystemTest.main() diff --git a/tests/functional/test_pc_cpu_hotplug_props.py b/tests/functional/test_pc_cpu_hotplug_props.py deleted file mode 100755 index 2bed8ad..0000000 --- a/tests/functional/test_pc_cpu_hotplug_props.py +++ /dev/null @@ -1,37 +0,0 @@ -#!/usr/bin/env python3 -# -# Ensure CPU die-id can be omitted on -device -# -# Copyright (c) 2019 Red Hat Inc -# -# Author: -# Eduardo Habkost -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2.1 of the License, or (at your option) any later version. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, see . -# - -from qemu_test import QemuSystemTest - -class OmittedCPUProps(QemuSystemTest): - - def test_no_die_id(self): - self.set_machine('pc') - self.vm.add_args('-nodefaults', '-S') - self.vm.add_args('-smp', '1,sockets=2,cores=2,threads=2,maxcpus=8') - self.vm.add_args('-device', 'qemu64-x86_64-cpu,socket-id=1,core-id=0,thread-id=0') - self.vm.launch() - self.assertEqual(len(self.vm.cmd('query-cpus-fast')), 2) - -if __name__ == '__main__': - QemuSystemTest.main() diff --git a/tests/functional/test_virtio_balloon.py b/tests/functional/test_virtio_balloon.py deleted file mode 100755 index 5877b6c..0000000 --- a/tests/functional/test_virtio_balloon.py +++ /dev/null @@ -1,178 +0,0 @@ -#!/usr/bin/env python3 -# -# virtio-balloon tests -# -# This work is licensed under the terms of the GNU GPL, version 2 or -# later. See the COPYING file in the top-level directory. - -import time - -from qemu_test import QemuSystemTest, Asset -from qemu_test import wait_for_console_pattern -from qemu_test import exec_command_and_wait_for_pattern - -UNSET_STATS_VALUE = 18446744073709551615 - - -class VirtioBalloonx86(QemuSystemTest): - - ASSET_KERNEL = Asset( - ('https://archives.fedoraproject.org/pub/archive/fedora/linux/releases' - '/31/Server/x86_64/os/images/pxeboot/vmlinuz'), - 'd4738d03dbbe083ca610d0821d0a8f1488bebbdccef54ce33e3adb35fda00129') - - ASSET_INITRD = Asset( - ('https://archives.fedoraproject.org/pub/archive/fedora/linux/releases' - '/31/Server/x86_64/os/images/pxeboot/initrd.img'), - '277cd6c7adf77c7e63d73bbb2cded8ef9e2d3a2f100000e92ff1f8396513cd8b') - - ASSET_DISKIMAGE = Asset( - ('https://archives.fedoraproject.org/pub/archive/fedora/linux/releases' - '/31/Cloud/x86_64/images/Fedora-Cloud-Base-31-1.9.x86_64.qcow2'), - 'e3c1b309d9203604922d6e255c2c5d098a309c2d46215d8fc026954f3c5c27a0') - - DEFAULT_KERNEL_PARAMS = ('root=/dev/vda1 console=ttyS0 net.ifnames=0 ' - 'rd.rescue quiet') - - def wait_for_console_pattern(self, success_message, vm=None): - wait_for_console_pattern( - self, - success_message, - failure_message="Kernel panic - not syncing", - vm=vm, - ) - - def mount_root(self): - self.wait_for_console_pattern('Entering emergency mode.') - prompt = '# ' - self.wait_for_console_pattern(prompt) - - # Synchronize on virtio-block driver creating the root device - exec_command_and_wait_for_pattern(self, - "while ! (dmesg -c | grep vda:) ; do sleep 1 ; done", - "vda1") - - exec_command_and_wait_for_pattern(self, 'mount /dev/vda1 /sysroot', - prompt) - exec_command_and_wait_for_pattern(self, 'chroot /sysroot', - prompt) - exec_command_and_wait_for_pattern(self, "modprobe virtio-balloon", - prompt) - - def assert_initial_stats(self): - ret = self.vm.qmp('qom-get', - {'path': '/machine/peripheral/balloon', - 'property': 'guest-stats'})['return'] - when = ret.get('last-update') - assert when == 0 - stats = ret.get('stats') - for name, val in stats.items(): - assert val == UNSET_STATS_VALUE - - def assert_running_stats(self, then): - # We told the QEMU to refresh stats every 100ms, but - # there can be a delay between virtio-ballon driver - # being modprobed and seeing the first stats refresh - # Retry a few times for robustness under heavy load - retries = 10 - when = 0 - while when == 0 and retries: - ret = self.vm.qmp('qom-get', - {'path': '/machine/peripheral/balloon', - 'property': 'guest-stats'})['return'] - when = ret.get('last-update') - if when == 0: - retries = retries - 1 - time.sleep(0.5) - - now = time.time() - - assert when > then and when < now - stats = ret.get('stats') - # Stat we expect this particular Kernel to have set - expectData = [ - "stat-available-memory", - "stat-disk-caches", - "stat-free-memory", - "stat-htlb-pgalloc", - "stat-htlb-pgfail", - "stat-major-faults", - "stat-minor-faults", - "stat-swap-in", - "stat-swap-out", - "stat-total-memory", - ] - for name, val in stats.items(): - if name in expectData: - assert val != UNSET_STATS_VALUE - else: - assert val == UNSET_STATS_VALUE - - def test_virtio_balloon_stats(self): - self.set_machine('q35') - self.require_accelerator("kvm") - kernel_path = self.ASSET_KERNEL.fetch() - initrd_path = self.ASSET_INITRD.fetch() - diskimage_path = self.ASSET_DISKIMAGE.fetch() - - self.vm.set_console() - self.vm.add_args("-S") - self.vm.add_args("-cpu", "max") - self.vm.add_args("-m", "2G") - # Slow down BIOS phase with boot menu, so that after a system - # reset, we can reliably catch the clean stats again in BIOS - # phase before the guest OS launches - self.vm.add_args("-boot", "menu=on") - self.vm.add_args("-accel", "kvm") - self.vm.add_args("-device", "virtio-balloon,id=balloon") - self.vm.add_args('-drive', - f'file={diskimage_path},if=none,id=drv0,snapshot=on') - self.vm.add_args('-device', 'virtio-blk-pci,bus=pcie.0,' + - 'drive=drv0,id=virtio-disk0,bootindex=1') - - self.vm.add_args( - "-kernel", - kernel_path, - "-initrd", - initrd_path, - "-append", - self.DEFAULT_KERNEL_PARAMS - ) - self.vm.launch() - - # Poll stats at 100ms - self.vm.qmp('qom-set', - {'path': '/machine/peripheral/balloon', - 'property': 'guest-stats-polling-interval', - 'value': 100 }) - - # We've not run any guest code yet, neither BIOS or guest, - # so stats should be all default values - self.assert_initial_stats() - - self.vm.qmp('cont') - - then = time.time() - self.mount_root() - self.assert_running_stats(then) - - # Race window between these two commands, where we - # rely on '-boot menu=on' to (hopefully) ensure we're - # still executing the BIOS when QEMU processes the - # 'stop', and thus have not loaded the virtio-balloon - # driver in the guest - self.vm.qmp('system_reset') - self.vm.qmp('stop') - - # If the above assumption held, we're in BIOS now and - # stats should be all back at their default values - self.assert_initial_stats() - self.vm.qmp('cont') - - then = time.time() - self.mount_root() - self.assert_running_stats(then) - - -if __name__ == '__main__': - QemuSystemTest.main() diff --git a/tests/functional/test_virtio_gpu.py b/tests/functional/test_virtio_gpu.py deleted file mode 100755 index be96de2..0000000 --- a/tests/functional/test_virtio_gpu.py +++ /dev/null @@ -1,144 +0,0 @@ -#!/usr/bin/env python3 -# -# virtio-gpu tests -# -# This work is licensed under the terms of the GNU GPL, version 2 or -# later. See the COPYING file in the top-level directory. - - -from qemu_test import QemuSystemTest, Asset -from qemu_test import wait_for_console_pattern -from qemu_test import exec_command_and_wait_for_pattern -from qemu_test import is_readable_executable_file - - -import os -import socket -import subprocess - - -def pick_default_vug_bin(test): - bld_dir_path = test.build_file("contrib", "vhost-user-gpu", "vhost-user-gpu") - if is_readable_executable_file(bld_dir_path): - return bld_dir_path - - -class VirtioGPUx86(QemuSystemTest): - - KERNEL_COMMAND_LINE = "printk.time=0 console=ttyS0 rdinit=/bin/bash" - ASSET_KERNEL = Asset( - ("https://archives.fedoraproject.org/pub/archive/fedora" - "/linux/releases/33/Everything/x86_64/os/images" - "/pxeboot/vmlinuz"), - '2dc5fb5cfe9ac278fa45640f3602d9b7a08cc189ed63fd9b162b07073e4df397') - ASSET_INITRD = Asset( - ("https://archives.fedoraproject.org/pub/archive/fedora" - "/linux/releases/33/Everything/x86_64/os/images" - "/pxeboot/initrd.img"), - 'c49b97f893a5349e4883452178763e402bdc5caa8845b226a2d1329b5f356045') - - def wait_for_console_pattern(self, success_message, vm=None): - wait_for_console_pattern( - self, - success_message, - failure_message="Kernel panic - not syncing", - vm=vm, - ) - - def test_virtio_vga_virgl(self): - # FIXME: should check presence of virtio, virgl etc - self.require_accelerator('kvm') - - kernel_path = self.ASSET_KERNEL.fetch() - initrd_path = self.ASSET_INITRD.fetch() - - self.vm.set_console() - self.vm.add_args("-cpu", "host") - self.vm.add_args("-m", "2G") - self.vm.add_args("-machine", "pc,accel=kvm") - self.vm.add_args("-device", "virtio-vga-gl") - self.vm.add_args("-display", "egl-headless") - self.vm.add_args( - "-kernel", - kernel_path, - "-initrd", - initrd_path, - "-append", - self.KERNEL_COMMAND_LINE, - ) - try: - self.vm.launch() - except: - # TODO: probably fails because we are missing the VirGL features - self.skipTest("VirGL not enabled?") - - self.wait_for_console_pattern("as init process") - exec_command_and_wait_for_pattern( - self, "/usr/sbin/modprobe virtio_gpu", "features: +virgl +edid" - ) - - def test_vhost_user_vga_virgl(self): - # FIXME: should check presence of vhost-user-gpu, virgl, memfd etc - self.require_accelerator('kvm') - - vug = pick_default_vug_bin(self) - if not vug: - self.skipTest("Could not find vhost-user-gpu") - - kernel_path = self.ASSET_KERNEL.fetch() - initrd_path = self.ASSET_INITRD.fetch() - - # Create socketpair to connect proxy and remote processes - qemu_sock, vug_sock = socket.socketpair( - socket.AF_UNIX, socket.SOCK_STREAM - ) - os.set_inheritable(qemu_sock.fileno(), True) - os.set_inheritable(vug_sock.fileno(), True) - - self._vug_log_path = self.log_file("vhost-user-gpu.log") - self._vug_log_file = open(self._vug_log_path, "wb") - self.log.info('Complete vhost-user-gpu.log file can be ' - 'found at %s', self._vug_log_path) - - vugp = subprocess.Popen( - [vug, "--virgl", "--fd=%d" % vug_sock.fileno()], - stdin=subprocess.DEVNULL, - stdout=self._vug_log_file, - stderr=subprocess.STDOUT, - shell=False, - close_fds=False, - ) - self._vug_log_file.close() - - self.vm.set_console() - self.vm.add_args("-cpu", "host") - self.vm.add_args("-m", "2G") - self.vm.add_args("-object", "memory-backend-memfd,id=mem,size=2G") - self.vm.add_args("-machine", "pc,memory-backend=mem,accel=kvm") - self.vm.add_args("-chardev", "socket,id=vug,fd=%d" % qemu_sock.fileno()) - self.vm.add_args("-device", "vhost-user-vga,chardev=vug") - self.vm.add_args("-display", "egl-headless") - self.vm.add_args( - "-kernel", - kernel_path, - "-initrd", - initrd_path, - "-append", - self.KERNEL_COMMAND_LINE, - ) - try: - self.vm.launch() - except: - # TODO: probably fails because we are missing the VirGL features - self.skipTest("VirGL not enabled?") - self.wait_for_console_pattern("as init process") - exec_command_and_wait_for_pattern(self, "/usr/sbin/modprobe virtio_gpu", - "features: +virgl +edid") - self.vm.shutdown() - qemu_sock.close() - vug_sock.close() - vugp.terminate() - vugp.wait() - -if __name__ == '__main__': - QemuSystemTest.main() diff --git a/tests/functional/test_virtio_version.py b/tests/functional/test_virtio_version.py deleted file mode 100755 index a5ea732..0000000 --- a/tests/functional/test_virtio_version.py +++ /dev/null @@ -1,177 +0,0 @@ -#!/usr/bin/env python3 -""" -Check compatibility of virtio device types -""" -# Copyright (c) 2018 Red Hat, Inc. -# -# Author: -# Eduardo Habkost -# -# This work is licensed under the terms of the GNU GPL, version 2 or -# later. See the COPYING file in the top-level directory. - -from qemu.machine import QEMUMachine -from qemu_test import QemuSystemTest - -# Virtio Device IDs: -VIRTIO_NET = 1 -VIRTIO_BLOCK = 2 -VIRTIO_CONSOLE = 3 -VIRTIO_RNG = 4 -VIRTIO_BALLOON = 5 -VIRTIO_RPMSG = 7 -VIRTIO_SCSI = 8 -VIRTIO_9P = 9 -VIRTIO_RPROC_SERIAL = 11 -VIRTIO_CAIF = 12 -VIRTIO_GPU = 16 -VIRTIO_INPUT = 18 -VIRTIO_VSOCK = 19 -VIRTIO_CRYPTO = 20 - -PCI_VENDOR_ID_REDHAT_QUMRANET = 0x1af4 - -# Device IDs for legacy/transitional devices: -PCI_LEGACY_DEVICE_IDS = { - VIRTIO_NET: 0x1000, - VIRTIO_BLOCK: 0x1001, - VIRTIO_BALLOON: 0x1002, - VIRTIO_CONSOLE: 0x1003, - VIRTIO_SCSI: 0x1004, - VIRTIO_RNG: 0x1005, - VIRTIO_9P: 0x1009, - VIRTIO_VSOCK: 0x1012, -} - -def pci_modern_device_id(virtio_devid): - return virtio_devid + 0x1040 - -def devtype_implements(vm, devtype, implements): - return devtype in [d['name'] for d in - vm.cmd('qom-list-types', implements=implements)] - -def get_pci_interfaces(vm, devtype): - interfaces = ('pci-express-device', 'conventional-pci-device') - return [i for i in interfaces if devtype_implements(vm, devtype, i)] - -class VirtioVersionCheck(QemuSystemTest): - """ - Check if virtio-version-specific device types result in the - same device tree created by `disable-modern` and - `disable-legacy`. - """ - - # just in case there are failures, show larger diff: - maxDiff = 4096 - - def run_device(self, devtype, opts=None, machine='pc'): - """ - Run QEMU with `-device DEVTYPE`, return device info from `query-pci` - """ - with QEMUMachine(self.qemu_bin) as vm: - vm.set_machine(machine) - if opts: - devtype += ',' + opts - vm.add_args('-device', '%s,id=devfortest' % (devtype)) - vm.add_args('-S') - vm.launch() - - pcibuses = vm.cmd('query-pci') - alldevs = [dev for bus in pcibuses for dev in bus['devices']] - devfortest = [dev for dev in alldevs - if dev['qdev_id'] == 'devfortest'] - return devfortest[0], get_pci_interfaces(vm, devtype) - - - def assert_devids(self, dev, devid, non_transitional=False): - self.assertEqual(dev['id']['vendor'], PCI_VENDOR_ID_REDHAT_QUMRANET) - self.assertEqual(dev['id']['device'], devid) - if non_transitional: - self.assertTrue(0x1040 <= dev['id']['device'] <= 0x107f) - self.assertGreaterEqual(dev['id']['subsystem'], 0x40) - - def check_all_variants(self, qemu_devtype, virtio_devid): - """Check if a virtio device type and its variants behave as expected""" - # Force modern mode: - dev_modern, _ = self.run_device(qemu_devtype, - 'disable-modern=off,disable-legacy=on') - self.assert_devids(dev_modern, pci_modern_device_id(virtio_devid), - non_transitional=True) - - # -non-transitional device types should be 100% equivalent to - # ,disable-modern=off,disable-legacy=on - dev_1_0, nt_ifaces = self.run_device('%s-non-transitional' % (qemu_devtype)) - self.assertEqual(dev_modern, dev_1_0) - - # Force transitional mode: - dev_trans, _ = self.run_device(qemu_devtype, - 'disable-modern=off,disable-legacy=off') - self.assert_devids(dev_trans, PCI_LEGACY_DEVICE_IDS[virtio_devid]) - - # Force legacy mode: - dev_legacy, _ = self.run_device(qemu_devtype, - 'disable-modern=on,disable-legacy=off') - self.assert_devids(dev_legacy, PCI_LEGACY_DEVICE_IDS[virtio_devid]) - - # No options: default to transitional on PC machine-type: - no_opts_pc, generic_ifaces = self.run_device(qemu_devtype) - self.assertEqual(dev_trans, no_opts_pc) - - #TODO: check if plugging on a PCI Express bus will make the - # device non-transitional - #no_opts_q35 = self.run_device(qemu_devtype, machine='q35') - #self.assertEqual(dev_modern, no_opts_q35) - - # -transitional device types should be 100% equivalent to - # ,disable-modern=off,disable-legacy=off - dev_trans, trans_ifaces = self.run_device('%s-transitional' % (qemu_devtype)) - self.assertEqual(dev_trans, dev_trans) - - # ensure the interface information is correct: - self.assertIn('conventional-pci-device', generic_ifaces) - self.assertIn('pci-express-device', generic_ifaces) - - self.assertIn('conventional-pci-device', nt_ifaces) - self.assertIn('pci-express-device', nt_ifaces) - - self.assertIn('conventional-pci-device', trans_ifaces) - self.assertNotIn('pci-express-device', trans_ifaces) - - - def test_conventional_devs(self): - self.set_machine('pc') - self.check_all_variants('virtio-net-pci', VIRTIO_NET) - # virtio-blk requires 'driver' parameter - #self.check_all_variants('virtio-blk-pci', VIRTIO_BLOCK) - self.check_all_variants('virtio-serial-pci', VIRTIO_CONSOLE) - self.check_all_variants('virtio-rng-pci', VIRTIO_RNG) - self.check_all_variants('virtio-balloon-pci', VIRTIO_BALLOON) - self.check_all_variants('virtio-scsi-pci', VIRTIO_SCSI) - # virtio-9p requires 'fsdev' parameter - #self.check_all_variants('virtio-9p-pci', VIRTIO_9P) - - def check_modern_only(self, qemu_devtype, virtio_devid): - """Check if a modern-only virtio device type behaves as expected""" - # Force modern mode: - dev_modern, _ = self.run_device(qemu_devtype, - 'disable-modern=off,disable-legacy=on') - self.assert_devids(dev_modern, pci_modern_device_id(virtio_devid), - non_transitional=True) - - # No options: should be modern anyway - dev_no_opts, ifaces = self.run_device(qemu_devtype) - self.assertEqual(dev_modern, dev_no_opts) - - self.assertIn('conventional-pci-device', ifaces) - self.assertIn('pci-express-device', ifaces) - - def test_modern_only_devs(self): - self.set_machine('pc') - self.check_modern_only('virtio-vga', VIRTIO_GPU) - self.check_modern_only('virtio-gpu-pci', VIRTIO_GPU) - self.check_modern_only('virtio-mouse-pci', VIRTIO_INPUT) - self.check_modern_only('virtio-tablet-pci', VIRTIO_INPUT) - self.check_modern_only('virtio-keyboard-pci', VIRTIO_INPUT) - -if __name__ == '__main__': - QemuSystemTest.main() diff --git a/tests/functional/test_x86_64_hotplug_blk.py b/tests/functional/test_x86_64_hotplug_blk.py deleted file mode 100755 index 7ddbfef..0000000 --- a/tests/functional/test_x86_64_hotplug_blk.py +++ /dev/null @@ -1,85 +0,0 @@ -#!/usr/bin/env python3 -# -# Functional test that hotplugs a virtio blk disk and checks it on a Linux -# guest -# -# Copyright (c) 2021 Red Hat, Inc. -# Copyright (c) Yandex -# -# This work is licensed under the terms of the GNU GPL, version 2 or -# later. See the COPYING file in the top-level directory. - -from qemu_test import LinuxKernelTest, Asset, exec_command_and_wait_for_pattern - - -class HotPlugBlk(LinuxKernelTest): - - ASSET_KERNEL = Asset( - ('https://archives.fedoraproject.org/pub/archive/fedora/linux/releases' - '/31/Server/x86_64/os/images/pxeboot/vmlinuz'), - 'd4738d03dbbe083ca610d0821d0a8f1488bebbdccef54ce33e3adb35fda00129') - - ASSET_INITRD = Asset( - ('https://archives.fedoraproject.org/pub/archive/fedora/linux/releases' - '/31/Server/x86_64/os/images/pxeboot/initrd.img'), - '277cd6c7adf77c7e63d73bbb2cded8ef9e2d3a2f100000e92ff1f8396513cd8b') - - def blockdev_add(self) -> None: - self.vm.cmd('blockdev-add', **{ - 'driver': 'null-co', - 'size': 1073741824, - 'node-name': 'disk' - }) - - def assert_vda(self) -> None: - exec_command_and_wait_for_pattern(self, 'while ! test -e /sys/block/vda ;' - ' do sleep 0.2 ; done', '# ') - - def assert_no_vda(self) -> None: - exec_command_and_wait_for_pattern(self, 'while test -e /sys/block/vda ;' - ' do sleep 0.2 ; done', '# ') - - def plug(self) -> None: - args = { - 'driver': 'virtio-blk-pci', - 'drive': 'disk', - 'id': 'virtio-disk0', - 'bus': 'pci.1', - 'addr': '1', - } - - self.assert_no_vda() - self.vm.cmd('device_add', args) - self.wait_for_console_pattern('virtio_blk virtio0: [vda]') - self.assert_vda() - - def unplug(self) -> None: - self.vm.cmd('device_del', id='virtio-disk0') - - self.vm.event_wait('DEVICE_DELETED', 1.0, - match={'data': {'device': 'virtio-disk0'}}) - - self.assert_no_vda() - - def test(self) -> None: - self.require_accelerator('kvm') - self.set_machine('q35') - - self.vm.add_args('-accel', 'kvm') - self.vm.add_args('-device', 'pcie-pci-bridge,id=pci.1,bus=pcie.0') - self.vm.add_args('-m', '1G') - self.vm.add_args('-append', 'console=ttyS0 rd.rescue') - - self.launch_kernel(self.ASSET_KERNEL.fetch(), - self.ASSET_INITRD.fetch(), - wait_for='Entering emergency mode.') - self.wait_for_console_pattern('# ') - - self.blockdev_add() - - self.plug() - self.unplug() - - -if __name__ == '__main__': - LinuxKernelTest.main() diff --git a/tests/functional/test_x86_64_hotplug_cpu.py b/tests/functional/test_x86_64_hotplug_cpu.py deleted file mode 100755 index 7b9200a..0000000 --- a/tests/functional/test_x86_64_hotplug_cpu.py +++ /dev/null @@ -1,71 +0,0 @@ -#!/usr/bin/env python3 -# -# Functional test that hotplugs a CPU and checks it on a Linux guest -# -# Copyright (c) 2021 Red Hat, Inc. -# -# Author: -# Cleber Rosa -# -# This work is licensed under the terms of the GNU GPL, version 2 or -# later. See the COPYING file in the top-level directory. - -from qemu_test import LinuxKernelTest, Asset, exec_command_and_wait_for_pattern - - -class HotPlugCPU(LinuxKernelTest): - - ASSET_KERNEL = Asset( - ('https://archives.fedoraproject.org/pub/archive/fedora/linux/releases' - '/31/Server/x86_64/os/images/pxeboot/vmlinuz'), - 'd4738d03dbbe083ca610d0821d0a8f1488bebbdccef54ce33e3adb35fda00129') - - ASSET_INITRD = Asset( - ('https://archives.fedoraproject.org/pub/archive/fedora/linux/releases' - '/31/Server/x86_64/os/images/pxeboot/initrd.img'), - '277cd6c7adf77c7e63d73bbb2cded8ef9e2d3a2f100000e92ff1f8396513cd8b') - - def test_hotplug(self): - - self.require_accelerator('kvm') - self.vm.add_args('-accel', 'kvm') - self.vm.add_args('-cpu', 'Haswell') - self.vm.add_args('-smp', '1,sockets=1,cores=2,threads=1,maxcpus=2') - self.vm.add_args('-m', '1G') - self.vm.add_args('-append', 'console=ttyS0 rd.rescue') - - self.launch_kernel(self.ASSET_KERNEL.fetch(), - self.ASSET_INITRD.fetch(), - wait_for='Entering emergency mode.') - prompt = '# ' - self.wait_for_console_pattern(prompt) - - exec_command_and_wait_for_pattern(self, - 'cd /sys/devices/system/cpu/cpu0', - 'cpu0#') - exec_command_and_wait_for_pattern(self, - 'cd /sys/devices/system/cpu/cpu1', - 'No such file or directory') - - self.vm.cmd('device_add', - driver='Haswell-x86_64-cpu', - id='c1', - socket_id=0, - core_id=1, - thread_id=0) - self.wait_for_console_pattern('CPU1 has been hot-added') - - exec_command_and_wait_for_pattern(self, - 'cd /sys/devices/system/cpu/cpu1', - 'cpu1#') - - exec_command_and_wait_for_pattern(self, 'cd ..', prompt) - self.vm.cmd('device_del', id='c1') - - exec_command_and_wait_for_pattern(self, - 'while cd /sys/devices/system/cpu/cpu1 ;' - ' do sleep 0.2 ; done', - 'No such file or directory') - -if __name__ == '__main__': - LinuxKernelTest.main() diff --git a/tests/functional/test_x86_64_kvm_xen.py b/tests/functional/test_x86_64_kvm_xen.py deleted file mode 100755 index a5d4450..0000000 --- a/tests/functional/test_x86_64_kvm_xen.py +++ /dev/null @@ -1,157 +0,0 @@ -#!/usr/bin/env python3 -# -# KVM Xen guest functional tests -# -# Copyright © 2021 Red Hat, Inc. -# Copyright © 2023 Amazon.com, Inc. or its affiliates. All Rights Reserved. -# -# Author: -# David Woodhouse -# Alex Bennée -# -# SPDX-License-Identifier: GPL-2.0-or-later - -from qemu.machine import machine - -from qemu_test import QemuSystemTest, Asset, exec_command_and_wait_for_pattern -from qemu_test import wait_for_console_pattern - -class KVMXenGuest(QemuSystemTest): - - KERNEL_DEFAULT = 'printk.time=0 root=/dev/xvda console=ttyS0 quiet' - - kernel_path = None - kernel_params = None - - # Fetch assets from the kvm-xen-guest subdir of my shared test - # images directory on fileserver.linaro.org where you can find - # build instructions for how they where assembled. - ASSET_KERNEL = Asset( - ('https://fileserver.linaro.org/s/kE4nCFLdQcoBF9t/download?' - 'path=%2Fkvm-xen-guest&files=bzImage'), - 'ec0ad7bb8c33c5982baee0a75505fe7dbf29d3ff5d44258204d6307c6fe0132a') - - ASSET_ROOTFS = Asset( - ('https://fileserver.linaro.org/s/kE4nCFLdQcoBF9t/download?' - 'path=%2Fkvm-xen-guest&files=rootfs.ext4'), - 'b11045d649006c649c184e93339aaa41a8fe20a1a86620af70323252eb29e40b') - - def common_vm_setup(self): - # We also catch lack of KVM_XEN support if we fail to launch - self.require_accelerator("kvm") - self.require_netdev('user') - - self.vm.set_console() - - self.vm.add_args("-accel", "kvm,xen-version=0x4000a,kernel-irqchip=split") - self.vm.add_args("-smp", "2") - - self.kernel_path = self.ASSET_KERNEL.fetch() - self.rootfs = self.ASSET_ROOTFS.fetch() - - def run_and_check(self): - self.vm.add_args('-kernel', self.kernel_path, - '-append', self.kernel_params, - '-drive', f"file={self.rootfs},if=none,snapshot=on,format=raw,id=drv0", - '-device', 'xen-disk,drive=drv0,vdev=xvda', - '-device', 'virtio-net-pci,netdev=unet', - '-netdev', 'user,id=unet,hostfwd=:127.0.0.1:0-:22') - - try: - self.vm.launch() - except machine.VMLaunchFailure as e: - if "Xen HVM guest support not present" in e.output: - self.skipTest("KVM Xen support is not present " - "(need v5.12+ kernel with CONFIG_KVM_XEN)") - elif "Property 'kvm-accel.xen-version' not found" in e.output: - self.skipTest("QEMU not built with CONFIG_XEN_EMU support") - else: - raise e - - self.log.info('VM launched, waiting for sshd') - console_pattern = 'Starting dropbear sshd: OK' - wait_for_console_pattern(self, console_pattern, 'Oops') - self.log.info('sshd ready') - - exec_command_and_wait_for_pattern(self, 'cat /proc/cmdline', 'xen') - exec_command_and_wait_for_pattern(self, 'dmesg | grep "Grant table"', - 'Grant table initialized') - wait_for_console_pattern(self, '#', 'Oops') - - def test_kvm_xen_guest(self): - self.common_vm_setup() - - self.kernel_params = (self.KERNEL_DEFAULT + - ' xen_emul_unplug=ide-disks') - self.run_and_check() - exec_command_and_wait_for_pattern(self, - 'grep xen-pirq.*msi /proc/interrupts', - 'virtio0-output') - - def test_kvm_xen_guest_nomsi(self): - self.common_vm_setup() - - self.kernel_params = (self.KERNEL_DEFAULT + - ' xen_emul_unplug=ide-disks pci=nomsi') - self.run_and_check() - exec_command_and_wait_for_pattern(self, - 'grep xen-pirq.* /proc/interrupts', - 'virtio0') - - def test_kvm_xen_guest_noapic_nomsi(self): - self.common_vm_setup() - - self.kernel_params = (self.KERNEL_DEFAULT + - ' xen_emul_unplug=ide-disks noapic pci=nomsi') - self.run_and_check() - exec_command_and_wait_for_pattern(self, - 'grep xen-pirq /proc/interrupts', - 'virtio0') - - def test_kvm_xen_guest_vapic(self): - self.common_vm_setup() - self.vm.add_args('-cpu', 'host,+xen-vapic') - self.kernel_params = (self.KERNEL_DEFAULT + - ' xen_emul_unplug=ide-disks') - self.run_and_check() - exec_command_and_wait_for_pattern(self, - 'grep xen-pirq /proc/interrupts', - 'acpi') - wait_for_console_pattern(self, '#') - exec_command_and_wait_for_pattern(self, - 'grep PCI-MSI /proc/interrupts', - 'virtio0-output') - - def test_kvm_xen_guest_novector(self): - self.common_vm_setup() - self.kernel_params = (self.KERNEL_DEFAULT + - ' xen_emul_unplug=ide-disks' + - ' xen_no_vector_callback') - self.run_and_check() - exec_command_and_wait_for_pattern(self, - 'grep xen-platform-pci /proc/interrupts', - 'fasteoi') - - def test_kvm_xen_guest_novector_nomsi(self): - self.common_vm_setup() - - self.kernel_params = (self.KERNEL_DEFAULT + - ' xen_emul_unplug=ide-disks pci=nomsi' + - ' xen_no_vector_callback') - self.run_and_check() - exec_command_and_wait_for_pattern(self, - 'grep xen-platform-pci /proc/interrupts', - 'IO-APIC') - - def test_kvm_xen_guest_novector_noapic(self): - self.common_vm_setup() - self.kernel_params = (self.KERNEL_DEFAULT + - ' xen_emul_unplug=ide-disks' + - ' xen_no_vector_callback noapic') - self.run_and_check() - exec_command_and_wait_for_pattern(self, - 'grep xen-platform-pci /proc/interrupts', - 'XT-PIC') - -if __name__ == '__main__': - QemuSystemTest.main() diff --git a/tests/functional/test_x86_64_migration.py b/tests/functional/test_x86_64_migration.py deleted file mode 100755 index f3a517a..0000000 --- a/tests/functional/test_x86_64_migration.py +++ /dev/null @@ -1,26 +0,0 @@ -#!/usr/bin/env python3 -# -# SPDX-License-Identifier: GPL-2.0-or-later -# -# x86_64 migration test - -from migration import MigrationTest - - -class X8664MigrationTest(MigrationTest): - - def test_migration_with_tcp_localhost(self): - self.set_machine('microvm') - self.migration_with_tcp_localhost() - - def test_migration_with_unix(self): - self.set_machine('microvm') - self.migration_with_unix() - - def test_migration_with_exec(self): - self.set_machine('microvm') - self.migration_with_exec() - - -if __name__ == '__main__': - MigrationTest.main() diff --git a/tests/functional/test_x86_64_multiprocess.py b/tests/functional/test_x86_64_multiprocess.py deleted file mode 100755 index 756629d..0000000 --- a/tests/functional/test_x86_64_multiprocess.py +++ /dev/null @@ -1,31 +0,0 @@ -#!/usr/bin/env python3 -# -# SPDX-License-Identifier: GPL-2.0-or-later -# -# Test for multiprocess qemu on x86 - -from multiprocess import Multiprocess -from qemu_test import Asset - - -class X86Multiprocess(Multiprocess): - - ASSET_KERNEL_X86 = Asset( - ('https://archives.fedoraproject.org/pub/archive/fedora/linux' - '/releases/31/Everything/x86_64/os/images/pxeboot/vmlinuz'), - 'd4738d03dbbe083ca610d0821d0a8f1488bebbdccef54ce33e3adb35fda00129') - - ASSET_INITRD_X86 = Asset( - ('https://archives.fedoraproject.org/pub/archive/fedora/linux' - '/releases/31/Everything/x86_64/os/images/pxeboot/initrd.img'), - '3b6cb5c91a14c42e2f61520f1689264d865e772a1f0069e660a800d31dd61fb9') - - def test_multiprocess(self): - kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE + - 'console=ttyS0 rdinit=/bin/bash') - self.do_test(self.ASSET_KERNEL_X86, self.ASSET_INITRD_X86, - kernel_command_line, 'pc') - - -if __name__ == '__main__': - Multiprocess.main() diff --git a/tests/functional/test_x86_64_replay.py b/tests/functional/test_x86_64_replay.py deleted file mode 100755 index 27287d4..0000000 --- a/tests/functional/test_x86_64_replay.py +++ /dev/null @@ -1,58 +0,0 @@ -#!/usr/bin/env python3 -# -# Replay test that boots a Linux kernel on x86_64 machines -# and checks the console -# -# SPDX-License-Identifier: GPL-2.0-or-later - -from subprocess import check_call, DEVNULL - -from qemu_test import Asset, skipFlakyTest, get_qemu_img -from replay_kernel import ReplayKernelBase - - -class X86Replay(ReplayKernelBase): - - ASSET_KERNEL = Asset( - 'https://storage.tuxboot.com/buildroot/20241119/x86_64/bzImage', - 'f57bfc6553bcd6e0a54aab86095bf642b33b5571d14e3af1731b18c87ed5aef8') - - ASSET_ROOTFS = Asset( - 'https://storage.tuxboot.com/buildroot/20241119/x86_64/rootfs.ext4.zst', - '4b8b2a99117519c5290e1202cb36eb6c7aaba92b357b5160f5970cf5fb78a751') - - def do_test_x86(self, machine, blkdevice, devroot): - self.require_netdev('user') - self.set_machine(machine) - self.cpu="Nehalem" - kernel_path = self.ASSET_KERNEL.fetch() - - raw_disk = self.uncompress(self.ASSET_ROOTFS) - disk = self.scratch_file('scratch.qcow2') - qemu_img = get_qemu_img(self) - check_call([qemu_img, 'create', '-f', 'qcow2', '-b', raw_disk, - '-F', 'raw', disk], stdout=DEVNULL, stderr=DEVNULL) - - args = ('-drive', 'file=%s,snapshot=on,id=hd0,if=none' % disk, - '-drive', 'driver=blkreplay,id=hd0-rr,if=none,image=hd0', - '-device', '%s,drive=hd0-rr' % blkdevice, - '-netdev', 'user,id=vnet,hostfwd=:127.0.0.1:0-:22', - '-device', 'virtio-net,netdev=vnet', - '-object', 'filter-replay,id=replay,netdev=vnet') - - kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE + - f"console=ttyS0 root=/dev/{devroot}") - console_pattern = 'Welcome to TuxTest' - self.run_rr(kernel_path, kernel_command_line, console_pattern, shift=5, - args=args) - - @skipFlakyTest('https://gitlab.com/qemu-project/qemu/-/issues/2094') - def test_pc(self): - self.do_test_x86('pc', 'virtio-blk', 'vda') - - def test_q35(self): - self.do_test_x86('q35', 'ide-hd', 'sda') - - -if __name__ == '__main__': - ReplayKernelBase.main() diff --git a/tests/functional/test_x86_64_reverse_debug.py b/tests/functional/test_x86_64_reverse_debug.py deleted file mode 100755 index d713e91..0000000 --- a/tests/functional/test_x86_64_reverse_debug.py +++ /dev/null @@ -1,36 +0,0 @@ -#!/usr/bin/env python3 -# -# SPDX-License-Identifier: GPL-2.0-or-later -# -# Reverse debugging test -# -# Copyright (c) 2020 ISP RAS -# -# Author: -# Pavel Dovgalyuk -# -# This work is licensed under the terms of the GNU GPL, version 2 or -# later. See the COPYING file in the top-level directory. - -from qemu_test import skipIfMissingImports, skipFlakyTest -from reverse_debugging import ReverseDebugging - - -@skipIfMissingImports('avocado.utils') -class ReverseDebugging_X86_64(ReverseDebugging): - - REG_PC = 0x10 - REG_CS = 0x12 - def get_pc(self, g): - return self.get_reg_le(g, self.REG_PC) \ - + self.get_reg_le(g, self.REG_CS) * 0x10 - - @skipFlakyTest("https://gitlab.com/qemu-project/qemu/-/issues/2922") - def test_x86_64_pc(self): - self.set_machine('pc') - # start with BIOS only - self.reverse_debugging() - - -if __name__ == '__main__': - ReverseDebugging.main() diff --git a/tests/functional/test_x86_64_tuxrun.py b/tests/functional/test_x86_64_tuxrun.py deleted file mode 100755 index fcbc62b..0000000 --- a/tests/functional/test_x86_64_tuxrun.py +++ /dev/null @@ -1,36 +0,0 @@ -#!/usr/bin/env python3 -# -# Functional test that boots known good tuxboot images the same way -# that tuxrun (www.tuxrun.org) does. This tool is used by things like -# the LKFT project to run regression tests on kernels. -# -# Copyright (c) 2023 Linaro Ltd. -# -# Author: -# Alex Bennée -# -# SPDX-License-Identifier: GPL-2.0-or-later - -from qemu_test import Asset -from qemu_test.tuxruntest import TuxRunBaselineTest - -class TuxRunX86Test(TuxRunBaselineTest): - - ASSET_X86_64_KERNEL = Asset( - 'https://storage.tuxboot.com/buildroot/20241119/x86_64/bzImage', - 'f57bfc6553bcd6e0a54aab86095bf642b33b5571d14e3af1731b18c87ed5aef8') - ASSET_X86_64_ROOTFS = Asset( - 'https://storage.tuxboot.com/buildroot/20241119/x86_64/rootfs.ext4.zst', - '4b8b2a99117519c5290e1202cb36eb6c7aaba92b357b5160f5970cf5fb78a751') - - def test_x86_64(self): - self.set_machine('q35') - self.cpu="Nehalem" - self.root='sda' - self.wait_for_shutdown=False - self.common_tuxrun(kernel_asset=self.ASSET_X86_64_KERNEL, - rootfs_asset=self.ASSET_X86_64_ROOTFS, - drive="driver=ide-hd,bus=ide.0,unit=0") - -if __name__ == '__main__': - TuxRunBaselineTest.main() diff --git a/tests/functional/test_x86_cpu_model_versions.py b/tests/functional/test_x86_cpu_model_versions.py deleted file mode 100755 index 36c968f..0000000 --- a/tests/functional/test_x86_cpu_model_versions.py +++ /dev/null @@ -1,249 +0,0 @@ -#!/usr/bin/env python3 -# -# Basic validation of x86 versioned CPU models and CPU model aliases -# -# Copyright (c) 2019 Red Hat Inc -# -# Author: -# Eduardo Habkost -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2.1 of the License, or (at your option) any later version. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, see . -# - -import re - -from qemu_test import QemuSystemTest - -class X86CPUModelAliases(QemuSystemTest): - """ - Validation of PC CPU model versions and CPU model aliases - """ - def validate_aliases(self, cpus): - for c in cpus.values(): - if 'alias-of' in c: - # all aliases must point to a valid CPU model name: - self.assertIn(c['alias-of'], cpus, - '%s.alias-of (%s) is not a valid CPU model name' % (c['name'], c['alias-of'])) - # aliases must not point to aliases - self.assertNotIn('alias-of', cpus[c['alias-of']], - '%s.alias-of (%s) points to another alias' % (c['name'], c['alias-of'])) - - # aliases must not be static - self.assertFalse(c['static']) - - def validate_variant_aliases(self, cpus): - # -noTSX, -IBRS and -IBPB variants of CPU models are special: - # they shouldn't have their own versions: - self.assertNotIn("Haswell-noTSX-v1", cpus, - "Haswell-noTSX shouldn't be versioned") - self.assertNotIn("Broadwell-noTSX-v1", cpus, - "Broadwell-noTSX shouldn't be versioned") - self.assertNotIn("Nehalem-IBRS-v1", cpus, - "Nehalem-IBRS shouldn't be versioned") - self.assertNotIn("Westmere-IBRS-v1", cpus, - "Westmere-IBRS shouldn't be versioned") - self.assertNotIn("SandyBridge-IBRS-v1", cpus, - "SandyBridge-IBRS shouldn't be versioned") - self.assertNotIn("IvyBridge-IBRS-v1", cpus, - "IvyBridge-IBRS shouldn't be versioned") - self.assertNotIn("Haswell-noTSX-IBRS-v1", cpus, - "Haswell-noTSX-IBRS shouldn't be versioned") - self.assertNotIn("Haswell-IBRS-v1", cpus, - "Haswell-IBRS shouldn't be versioned") - self.assertNotIn("Broadwell-noTSX-IBRS-v1", cpus, - "Broadwell-noTSX-IBRS shouldn't be versioned") - self.assertNotIn("Broadwell-IBRS-v1", cpus, - "Broadwell-IBRS shouldn't be versioned") - self.assertNotIn("Skylake-Client-IBRS-v1", cpus, - "Skylake-Client-IBRS shouldn't be versioned") - self.assertNotIn("Skylake-Server-IBRS-v1", cpus, - "Skylake-Server-IBRS shouldn't be versioned") - self.assertNotIn("EPYC-IBPB-v1", cpus, - "EPYC-IBPB shouldn't be versioned") - - def test_unversioned_alias(self): - """ - Check if unversioned CPU model is an alias pointing to right version - """ - self.set_machine('pc') - self.vm.add_args('-S') - self.vm.launch() - - cpus = dict((m['name'], m) for m in - self.vm.cmd('query-cpu-definitions')) - - self.assertFalse(cpus['Cascadelake-Server']['static'], - 'unversioned Cascadelake-Server CPU model must not be static') - self.assertEqual(cpus['Cascadelake-Server'].get('alias-of'), - 'Cascadelake-Server-v1', - 'Cascadelake-Server must be an alias of Cascadelake-Server-v1') - self.assertNotIn('alias-of', cpus['Cascadelake-Server-v1'], - 'Cascadelake-Server-v1 must not be an alias') - - self.assertFalse(cpus['qemu64']['static'], - 'unversioned qemu64 CPU model must not be static') - self.assertEqual(cpus['qemu64'].get('alias-of'), 'qemu64-v1', - 'qemu64 must be an alias of qemu64-v1') - self.assertNotIn('alias-of', cpus['qemu64-v1'], - 'qemu64-v1 must not be an alias') - - self.validate_variant_aliases(cpus) - - # On recent PC machines, -noTSX and -IBRS models should be aliases: - self.assertEqual(cpus["Haswell"].get('alias-of'), - "Haswell-v1", - "Haswell must be an alias") - self.assertEqual(cpus["Haswell-noTSX"].get('alias-of'), - "Haswell-v2", - "Haswell-noTSX must be an alias") - self.assertEqual(cpus["Haswell-IBRS"].get('alias-of'), - "Haswell-v3", - "Haswell-IBRS must be an alias") - self.assertEqual(cpus["Haswell-noTSX-IBRS"].get('alias-of'), - "Haswell-v4", - "Haswell-noTSX-IBRS must be an alias") - - self.assertEqual(cpus["Broadwell"].get('alias-of'), - "Broadwell-v1", - "Broadwell must be an alias") - self.assertEqual(cpus["Broadwell-noTSX"].get('alias-of'), - "Broadwell-v2", - "Broadwell-noTSX must be an alias") - self.assertEqual(cpus["Broadwell-IBRS"].get('alias-of'), - "Broadwell-v3", - "Broadwell-IBRS must be an alias") - self.assertEqual(cpus["Broadwell-noTSX-IBRS"].get('alias-of'), - "Broadwell-v4", - "Broadwell-noTSX-IBRS must be an alias") - - self.assertEqual(cpus["Nehalem"].get('alias-of'), - "Nehalem-v1", - "Nehalem must be an alias") - self.assertEqual(cpus["Nehalem-IBRS"].get('alias-of'), - "Nehalem-v2", - "Nehalem-IBRS must be an alias") - - self.assertEqual(cpus["Westmere"].get('alias-of'), - "Westmere-v1", - "Westmere must be an alias") - self.assertEqual(cpus["Westmere-IBRS"].get('alias-of'), - "Westmere-v2", - "Westmere-IBRS must be an alias") - - self.assertEqual(cpus["SandyBridge"].get('alias-of'), - "SandyBridge-v1", - "SandyBridge must be an alias") - self.assertEqual(cpus["SandyBridge-IBRS"].get('alias-of'), - "SandyBridge-v2", - "SandyBridge-IBRS must be an alias") - - self.assertEqual(cpus["IvyBridge"].get('alias-of'), - "IvyBridge-v1", - "IvyBridge must be an alias") - self.assertEqual(cpus["IvyBridge-IBRS"].get('alias-of'), - "IvyBridge-v2", - "IvyBridge-IBRS must be an alias") - - self.assertEqual(cpus["Skylake-Client"].get('alias-of'), - "Skylake-Client-v1", - "Skylake-Client must be an alias") - self.assertEqual(cpus["Skylake-Client-IBRS"].get('alias-of'), - "Skylake-Client-v2", - "Skylake-Client-IBRS must be an alias") - - self.assertEqual(cpus["Skylake-Server"].get('alias-of'), - "Skylake-Server-v1", - "Skylake-Server must be an alias") - self.assertEqual(cpus["Skylake-Server-IBRS"].get('alias-of'), - "Skylake-Server-v2", - "Skylake-Server-IBRS must be an alias") - - self.assertEqual(cpus["EPYC"].get('alias-of'), - "EPYC-v1", - "EPYC must be an alias") - self.assertEqual(cpus["EPYC-IBPB"].get('alias-of'), - "EPYC-v2", - "EPYC-IBPB must be an alias") - - self.validate_aliases(cpus) - - def test_none_alias(self): - """ - Check if unversioned CPU model is an alias pointing to some version - """ - self.set_machine('none') - self.vm.add_args('-S') - self.vm.launch() - - cpus = dict((m['name'], m) for m in - self.vm.cmd('query-cpu-definitions')) - - self.assertFalse(cpus['Cascadelake-Server']['static'], - 'unversioned Cascadelake-Server CPU model must not be static') - self.assertTrue(re.match('Cascadelake-Server-v[0-9]+', cpus['Cascadelake-Server']['alias-of']), - 'Cascadelake-Server must be an alias of versioned CPU model') - self.assertNotIn('alias-of', cpus['Cascadelake-Server-v1'], - 'Cascadelake-Server-v1 must not be an alias') - - self.assertFalse(cpus['qemu64']['static'], - 'unversioned qemu64 CPU model must not be static') - self.assertTrue(re.match('qemu64-v[0-9]+', cpus['qemu64']['alias-of']), - 'qemu64 must be an alias of versioned CPU model') - self.assertNotIn('alias-of', cpus['qemu64-v1'], - 'qemu64-v1 must not be an alias') - - self.validate_aliases(cpus) - - -class CascadelakeArchCapabilities(QemuSystemTest): - """ - Validation of Cascadelake arch-capabilities - """ - def get_cpu_prop(self, prop): - cpu_path = self.vm.cmd('query-cpus-fast')[0].get('qom-path') - return self.vm.cmd('qom-get', path=cpu_path, property=prop) - - def test(self): - self.set_machine('pc') - # machine-type only: - self.vm.add_args('-S') - self.set_vm_arg('-cpu', - 'Cascadelake-Server,x-force-features=on,check=off,' - 'enforce=off') - self.vm.launch() - self.assertFalse(self.get_cpu_prop('arch-capabilities'), - 'pc + Cascadelake-Server should not have arch-capabilities') - - def test_unset(self): - self.set_machine('pc') - self.vm.add_args('-S') - self.set_vm_arg('-cpu', - 'Cascadelake-Server,x-force-features=on,check=off,' - 'enforce=off,-arch-capabilities') - self.vm.launch() - self.assertFalse(self.get_cpu_prop('arch-capabilities'), - 'pc + Cascadelake-Server,-arch-capabilities should not have arch-capabilities') - - def test_v2_unset(self): - self.set_machine('pc') - self.vm.add_args('-S') - self.set_vm_arg('-cpu', - 'Cascadelake-Server-v2,x-force-features=on,check=off,' - 'enforce=off,-arch-capabilities') - self.vm.launch() - self.assertFalse(self.get_cpu_prop('arch-capabilities'), - 'pc + Cascadelake-Server-v2,-arch-capabilities should not have arch-capabilities') - -if __name__ == '__main__': - QemuSystemTest.main() diff --git a/tests/functional/x86_64/meson.build b/tests/functional/x86_64/meson.build new file mode 100644 index 0000000..696a9ec --- /dev/null +++ b/tests/functional/x86_64/meson.build @@ -0,0 +1,37 @@ +# SPDX-License-Identifier: GPL-2.0-or-later + +test_x86_64_timeouts = { + 'acpi_bits' : 420, + 'intel_iommu': 300, + 'kvm_xen' : 180, + 'netdev_ethtool' : 180, + 'replay' : 480, + 'virtio_balloon': 120, +} + +tests_x86_64_system_quick = [ + 'cpu_model_versions', + 'cpu_queries', + 'mem_addr_space', + 'migration', + 'pc_cpu_hotplug_props', + 'virtio_version', + 'vnc', + 'memlock', +] + +tests_x86_64_system_thorough = [ + 'acpi_bits', + 'hotplug_blk', + 'hotplug_cpu', + 'intel_iommu', + 'kvm_xen', + 'linux_initrd', + 'multiprocess', + 'netdev_ethtool', + 'replay', + 'reverse_debug', + 'tuxrun', + 'virtio_balloon', + 'virtio_gpu', +] diff --git a/tests/functional/x86_64/test_acpi_bits.py b/tests/functional/x86_64/test_acpi_bits.py new file mode 100755 index 0000000..8e0563a --- /dev/null +++ b/tests/functional/x86_64/test_acpi_bits.py @@ -0,0 +1,340 @@ +#!/usr/bin/env python3 +# +# Exercise QEMU generated ACPI/SMBIOS tables using biosbits, +# https://biosbits.org/ +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# +# +# Author: +# Ani Sinha + +# pylint: disable=invalid-name +# pylint: disable=consider-using-f-string + +""" +This is QEMU ACPI/SMBIOS functional tests using biosbits. +Biosbits is available originally at https://biosbits.org/. +This test uses a fork of the upstream bits and has numerous fixes +including an upgraded acpica. The fork is located here: +https://gitlab.com/qemu-project/biosbits-bits . +""" + +import os +import re +import shutil +import subprocess + +from typing import ( + List, + Optional, + Sequence, +) +from qemu.machine import QEMUMachine +from qemu_test import (QemuSystemTest, Asset, skipIfMissingCommands, + skipIfNotMachine) + + +# default timeout of 120 secs is sometimes not enough for bits test. +BITS_TIMEOUT = 200 + +class QEMUBitsMachine(QEMUMachine): # pylint: disable=too-few-public-methods + """ + A QEMU VM, with isa-debugcon enabled and bits iso passed + using -cdrom to QEMU commandline. + + """ + def __init__(self, + binary: str, + args: Sequence[str] = (), + wrapper: Sequence[str] = (), + name: Optional[str] = None, + base_temp_dir: str = "/var/tmp", + debugcon_log: str = "debugcon-log.txt", + debugcon_addr: str = "0x403", + qmp_timer: Optional[float] = None): + # pylint: disable=too-many-arguments + + if name is None: + name = "qemu-bits-%d" % os.getpid() + super().__init__(binary, args, wrapper=wrapper, name=name, + base_temp_dir=base_temp_dir, + qmp_timer=qmp_timer) + self.debugcon_log = debugcon_log + self.debugcon_addr = debugcon_addr + self.base_temp_dir = base_temp_dir + + @property + def _base_args(self) -> List[str]: + args = super()._base_args + args.extend([ + '-chardev', + 'file,path=%s,id=debugcon' %os.path.join(self.base_temp_dir, + self.debugcon_log), + '-device', + 'isa-debugcon,iobase=%s,chardev=debugcon' %self.debugcon_addr, + ]) + return args + + def base_args(self): + """return the base argument to QEMU binary""" + return self._base_args + +@skipIfMissingCommands("xorriso", "mformat") +@skipIfNotMachine("x86_64") +class AcpiBitsTest(QemuSystemTest): #pylint: disable=too-many-instance-attributes + """ + ACPI and SMBIOS tests using biosbits. + """ + # in slower systems the test can take as long as 3 minutes to complete. + timeout = BITS_TIMEOUT + + # following are some standard configuration constants + # gitlab CI does shallow clones of depth 20 + BITS_INTERNAL_VER = 2020 + # commit hash must match the artifact tag below + BITS_COMMIT_HASH = 'c7920d2b' + # this is the latest bits release as of today. + BITS_TAG = "qemu-bits-10262023" + + ASSET_BITS = Asset(("https://gitlab.com/qemu-project/" + "biosbits-bits/-/jobs/artifacts/%s/" + "download?job=qemu-bits-build" % BITS_TAG), + '1b8dd612c6831a6b491716a77acc486666aaa867051cdc34f7ce169c2e25f487') + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + self._vm = None + + self._debugcon_addr = '0x403' + self._debugcon_log = 'debugcon-log.txt' + + def _print_log(self, log): + self.logger.info('\nlogs from biosbits follows:') + self.logger.info('==========================================\n') + self.logger.info(log) + self.logger.info('==========================================\n') + + def copy_bits_config(self): + """ copies the bios bits config file into bits. + """ + bits_config_file = self.data_file('acpi-bits', + 'bits-config', + 'bits-cfg.txt') + target_config_dir = self.scratch_file('bits-%d' % + self.BITS_INTERNAL_VER, + 'boot') + self.assertTrue(os.path.exists(bits_config_file)) + self.assertTrue(os.path.exists(target_config_dir)) + shutil.copy2(bits_config_file, target_config_dir) + self.logger.info('copied config file %s to %s', + bits_config_file, target_config_dir) + + def copy_test_scripts(self): + """copies the python test scripts into bits. """ + + bits_test_dir = self.data_file('acpi-bits', 'bits-tests') + target_test_dir = self.scratch_file('bits-%d' % self.BITS_INTERNAL_VER, + 'boot', 'python') + + self.assertTrue(os.path.exists(bits_test_dir)) + self.assertTrue(os.path.exists(target_test_dir)) + + for filename in os.listdir(bits_test_dir): + if os.path.isfile(os.path.join(bits_test_dir, filename)) and \ + filename.endswith('.py2'): + # All test scripts are named with extension .py2 so that + # they are not run by accident. + # + # These scripts are intended to run inside the test VM + # and are written for python 2.7 not python 3, hence + # would cause syntax errors if loaded ouside the VM. + newfilename = os.path.splitext(filename)[0] + '.py' + shutil.copy2(os.path.join(bits_test_dir, filename), + os.path.join(target_test_dir, newfilename)) + self.logger.info('copied test file %s to %s', + filename, target_test_dir) + + # now remove the pyc test file if it exists, otherwise the + # changes in the python test script won't be executed. + testfile_pyc = os.path.splitext(filename)[0] + '.pyc' + if os.access(os.path.join(target_test_dir, testfile_pyc), + os.F_OK): + os.remove(os.path.join(target_test_dir, testfile_pyc)) + self.logger.info('removed compiled file %s', + os.path.join(target_test_dir, + testfile_pyc)) + + def fix_mkrescue(self, mkrescue): + """ grub-mkrescue is a bash script with two variables, 'prefix' and + 'libdir'. They must be pointed to the right location so that the + iso can be generated appropriately. We point the two variables to + the directory where we have extracted our pre-built bits grub + tarball. + """ + grub_x86_64_mods = self.scratch_file('grub-inst-x86_64-efi') + grub_i386_mods = self.scratch_file('grub-inst') + + self.assertTrue(os.path.exists(grub_x86_64_mods)) + self.assertTrue(os.path.exists(grub_i386_mods)) + + new_script = "" + with open(mkrescue, 'r', encoding='utf-8') as filehandle: + orig_script = filehandle.read() + new_script = re.sub('(^prefix=)(.*)', + r'\1"%s"' %grub_x86_64_mods, + orig_script, flags=re.M) + new_script = re.sub('(^libdir=)(.*)', r'\1"%s/lib"' %grub_i386_mods, + new_script, flags=re.M) + + with open(mkrescue, 'w', encoding='utf-8') as filehandle: + filehandle.write(new_script) + + def generate_bits_iso(self): + """ Uses grub-mkrescue to generate a fresh bits iso with the python + test scripts + """ + bits_dir = self.scratch_file('bits-%d' % self.BITS_INTERNAL_VER) + iso_file = self.scratch_file('bits-%d.iso' % self.BITS_INTERNAL_VER) + mkrescue_script = self.scratch_file('grub-inst-x86_64-efi', + 'bin', + 'grub-mkrescue') + + self.assertTrue(os.access(mkrescue_script, + os.R_OK | os.W_OK | os.X_OK)) + + self.fix_mkrescue(mkrescue_script) + + self.logger.info('using grub-mkrescue for generating biosbits iso ...') + + try: + if os.getenv('V') or os.getenv('BITS_DEBUG'): + proc = subprocess.run([mkrescue_script, '-o', iso_file, + bits_dir], + stdout=subprocess.PIPE, + stderr=subprocess.STDOUT, + check=True) + self.logger.info("grub-mkrescue output %s" % proc.stdout) + else: + subprocess.check_call([mkrescue_script, '-o', + iso_file, bits_dir], + stderr=subprocess.DEVNULL, + stdout=subprocess.DEVNULL) + except Exception as e: # pylint: disable=broad-except + self.skipTest("Error while generating the bits iso. " + "Pass V=1 in the environment to get more details. " + + str(e)) + + self.assertTrue(os.access(iso_file, os.R_OK)) + + self.logger.info('iso file %s successfully generated.', iso_file) + + def setUp(self): # pylint: disable=arguments-differ + super().setUp() + self.logger = self.log + + prebuiltDir = self.scratch_file('prebuilt') + if not os.path.isdir(prebuiltDir): + os.mkdir(prebuiltDir, mode=0o775) + + bits_zip_file = self.scratch_file('prebuilt', + 'bits-%d-%s.zip' + %(self.BITS_INTERNAL_VER, + self.BITS_COMMIT_HASH)) + grub_tar_file = self.scratch_file('prebuilt', + 'bits-%d-%s-grub.tar.gz' + %(self.BITS_INTERNAL_VER, + self.BITS_COMMIT_HASH)) + + # extract the bits artifact in the temp working directory + self.archive_extract(self.ASSET_BITS, sub_dir='prebuilt', format='zip') + + # extract the bits software in the temp working directory + self.archive_extract(bits_zip_file) + self.archive_extract(grub_tar_file) + + self.copy_test_scripts() + self.copy_bits_config() + self.generate_bits_iso() + + def parse_log(self): + """parse the log generated by running bits tests and + check for failures. + """ + debugconf = self.scratch_file(self._debugcon_log) + log = "" + with open(debugconf, 'r', encoding='utf-8') as filehandle: + log = filehandle.read() + + matchiter = re.finditer(r'(.*Summary: )(\d+ passed), (\d+ failed).*', + log) + for match in matchiter: + # verify that no test cases failed. + try: + self.assertEqual(match.group(3).split()[0], '0', + 'Some bits tests seems to have failed. ' \ + 'Please check the test logs for more info.') + except AssertionError as e: + self._print_log(log) + raise e + else: + if os.getenv('V') or os.getenv('BITS_DEBUG'): + self._print_log(log) + + def tearDown(self): + """ + Lets do some cleanups. + """ + if self._vm: + self.assertFalse(not self._vm.is_running) + super().tearDown() + + def test_acpi_smbios_bits(self): + """The main test case implementation.""" + + self.set_machine('pc') + iso_file = self.scratch_file('bits-%d.iso' % self.BITS_INTERNAL_VER) + + self.assertTrue(os.access(iso_file, os.R_OK)) + + self._vm = QEMUBitsMachine(binary=self.qemu_bin, + base_temp_dir=self.workdir, + debugcon_log=self._debugcon_log, + debugcon_addr=self._debugcon_addr) + + self._vm.add_args('-cdrom', '%s' %iso_file) + # the vm needs to be run under icount so that TCG emulation is + # consistent in terms of timing. smilatency tests have consistent + # timing requirements. + self._vm.add_args('-icount', 'auto') + # currently there is no support in bits for recognizing 64-bit SMBIOS + # entry points. QEMU defaults to 64-bit entry points since the + # upstream commit bf376f3020 ("hw/i386/pc: Default to use SMBIOS 3.0 + # for newer machine models"). Therefore, enforce 32-bit entry point. + self._vm.add_args('-machine', 'smbios-entry-point-type=32') + + # enable console logging + self._vm.set_console() + self._vm.launch() + + + # biosbits has been configured to run all the specified test suites + # in batch mode and then automatically initiate a vm shutdown. + self._vm.event_wait('SHUTDOWN', timeout=BITS_TIMEOUT) + self._vm.wait(timeout=None) + self.logger.debug("Checking console output ...") + self.parse_log() + +if __name__ == '__main__': + QemuSystemTest.main() diff --git a/tests/functional/x86_64/test_cpu_model_versions.py b/tests/functional/x86_64/test_cpu_model_versions.py new file mode 100755 index 0000000..36c968f --- /dev/null +++ b/tests/functional/x86_64/test_cpu_model_versions.py @@ -0,0 +1,249 @@ +#!/usr/bin/env python3 +# +# Basic validation of x86 versioned CPU models and CPU model aliases +# +# Copyright (c) 2019 Red Hat Inc +# +# Author: +# Eduardo Habkost +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, see . +# + +import re + +from qemu_test import QemuSystemTest + +class X86CPUModelAliases(QemuSystemTest): + """ + Validation of PC CPU model versions and CPU model aliases + """ + def validate_aliases(self, cpus): + for c in cpus.values(): + if 'alias-of' in c: + # all aliases must point to a valid CPU model name: + self.assertIn(c['alias-of'], cpus, + '%s.alias-of (%s) is not a valid CPU model name' % (c['name'], c['alias-of'])) + # aliases must not point to aliases + self.assertNotIn('alias-of', cpus[c['alias-of']], + '%s.alias-of (%s) points to another alias' % (c['name'], c['alias-of'])) + + # aliases must not be static + self.assertFalse(c['static']) + + def validate_variant_aliases(self, cpus): + # -noTSX, -IBRS and -IBPB variants of CPU models are special: + # they shouldn't have their own versions: + self.assertNotIn("Haswell-noTSX-v1", cpus, + "Haswell-noTSX shouldn't be versioned") + self.assertNotIn("Broadwell-noTSX-v1", cpus, + "Broadwell-noTSX shouldn't be versioned") + self.assertNotIn("Nehalem-IBRS-v1", cpus, + "Nehalem-IBRS shouldn't be versioned") + self.assertNotIn("Westmere-IBRS-v1", cpus, + "Westmere-IBRS shouldn't be versioned") + self.assertNotIn("SandyBridge-IBRS-v1", cpus, + "SandyBridge-IBRS shouldn't be versioned") + self.assertNotIn("IvyBridge-IBRS-v1", cpus, + "IvyBridge-IBRS shouldn't be versioned") + self.assertNotIn("Haswell-noTSX-IBRS-v1", cpus, + "Haswell-noTSX-IBRS shouldn't be versioned") + self.assertNotIn("Haswell-IBRS-v1", cpus, + "Haswell-IBRS shouldn't be versioned") + self.assertNotIn("Broadwell-noTSX-IBRS-v1", cpus, + "Broadwell-noTSX-IBRS shouldn't be versioned") + self.assertNotIn("Broadwell-IBRS-v1", cpus, + "Broadwell-IBRS shouldn't be versioned") + self.assertNotIn("Skylake-Client-IBRS-v1", cpus, + "Skylake-Client-IBRS shouldn't be versioned") + self.assertNotIn("Skylake-Server-IBRS-v1", cpus, + "Skylake-Server-IBRS shouldn't be versioned") + self.assertNotIn("EPYC-IBPB-v1", cpus, + "EPYC-IBPB shouldn't be versioned") + + def test_unversioned_alias(self): + """ + Check if unversioned CPU model is an alias pointing to right version + """ + self.set_machine('pc') + self.vm.add_args('-S') + self.vm.launch() + + cpus = dict((m['name'], m) for m in + self.vm.cmd('query-cpu-definitions')) + + self.assertFalse(cpus['Cascadelake-Server']['static'], + 'unversioned Cascadelake-Server CPU model must not be static') + self.assertEqual(cpus['Cascadelake-Server'].get('alias-of'), + 'Cascadelake-Server-v1', + 'Cascadelake-Server must be an alias of Cascadelake-Server-v1') + self.assertNotIn('alias-of', cpus['Cascadelake-Server-v1'], + 'Cascadelake-Server-v1 must not be an alias') + + self.assertFalse(cpus['qemu64']['static'], + 'unversioned qemu64 CPU model must not be static') + self.assertEqual(cpus['qemu64'].get('alias-of'), 'qemu64-v1', + 'qemu64 must be an alias of qemu64-v1') + self.assertNotIn('alias-of', cpus['qemu64-v1'], + 'qemu64-v1 must not be an alias') + + self.validate_variant_aliases(cpus) + + # On recent PC machines, -noTSX and -IBRS models should be aliases: + self.assertEqual(cpus["Haswell"].get('alias-of'), + "Haswell-v1", + "Haswell must be an alias") + self.assertEqual(cpus["Haswell-noTSX"].get('alias-of'), + "Haswell-v2", + "Haswell-noTSX must be an alias") + self.assertEqual(cpus["Haswell-IBRS"].get('alias-of'), + "Haswell-v3", + "Haswell-IBRS must be an alias") + self.assertEqual(cpus["Haswell-noTSX-IBRS"].get('alias-of'), + "Haswell-v4", + "Haswell-noTSX-IBRS must be an alias") + + self.assertEqual(cpus["Broadwell"].get('alias-of'), + "Broadwell-v1", + "Broadwell must be an alias") + self.assertEqual(cpus["Broadwell-noTSX"].get('alias-of'), + "Broadwell-v2", + "Broadwell-noTSX must be an alias") + self.assertEqual(cpus["Broadwell-IBRS"].get('alias-of'), + "Broadwell-v3", + "Broadwell-IBRS must be an alias") + self.assertEqual(cpus["Broadwell-noTSX-IBRS"].get('alias-of'), + "Broadwell-v4", + "Broadwell-noTSX-IBRS must be an alias") + + self.assertEqual(cpus["Nehalem"].get('alias-of'), + "Nehalem-v1", + "Nehalem must be an alias") + self.assertEqual(cpus["Nehalem-IBRS"].get('alias-of'), + "Nehalem-v2", + "Nehalem-IBRS must be an alias") + + self.assertEqual(cpus["Westmere"].get('alias-of'), + "Westmere-v1", + "Westmere must be an alias") + self.assertEqual(cpus["Westmere-IBRS"].get('alias-of'), + "Westmere-v2", + "Westmere-IBRS must be an alias") + + self.assertEqual(cpus["SandyBridge"].get('alias-of'), + "SandyBridge-v1", + "SandyBridge must be an alias") + self.assertEqual(cpus["SandyBridge-IBRS"].get('alias-of'), + "SandyBridge-v2", + "SandyBridge-IBRS must be an alias") + + self.assertEqual(cpus["IvyBridge"].get('alias-of'), + "IvyBridge-v1", + "IvyBridge must be an alias") + self.assertEqual(cpus["IvyBridge-IBRS"].get('alias-of'), + "IvyBridge-v2", + "IvyBridge-IBRS must be an alias") + + self.assertEqual(cpus["Skylake-Client"].get('alias-of'), + "Skylake-Client-v1", + "Skylake-Client must be an alias") + self.assertEqual(cpus["Skylake-Client-IBRS"].get('alias-of'), + "Skylake-Client-v2", + "Skylake-Client-IBRS must be an alias") + + self.assertEqual(cpus["Skylake-Server"].get('alias-of'), + "Skylake-Server-v1", + "Skylake-Server must be an alias") + self.assertEqual(cpus["Skylake-Server-IBRS"].get('alias-of'), + "Skylake-Server-v2", + "Skylake-Server-IBRS must be an alias") + + self.assertEqual(cpus["EPYC"].get('alias-of'), + "EPYC-v1", + "EPYC must be an alias") + self.assertEqual(cpus["EPYC-IBPB"].get('alias-of'), + "EPYC-v2", + "EPYC-IBPB must be an alias") + + self.validate_aliases(cpus) + + def test_none_alias(self): + """ + Check if unversioned CPU model is an alias pointing to some version + """ + self.set_machine('none') + self.vm.add_args('-S') + self.vm.launch() + + cpus = dict((m['name'], m) for m in + self.vm.cmd('query-cpu-definitions')) + + self.assertFalse(cpus['Cascadelake-Server']['static'], + 'unversioned Cascadelake-Server CPU model must not be static') + self.assertTrue(re.match('Cascadelake-Server-v[0-9]+', cpus['Cascadelake-Server']['alias-of']), + 'Cascadelake-Server must be an alias of versioned CPU model') + self.assertNotIn('alias-of', cpus['Cascadelake-Server-v1'], + 'Cascadelake-Server-v1 must not be an alias') + + self.assertFalse(cpus['qemu64']['static'], + 'unversioned qemu64 CPU model must not be static') + self.assertTrue(re.match('qemu64-v[0-9]+', cpus['qemu64']['alias-of']), + 'qemu64 must be an alias of versioned CPU model') + self.assertNotIn('alias-of', cpus['qemu64-v1'], + 'qemu64-v1 must not be an alias') + + self.validate_aliases(cpus) + + +class CascadelakeArchCapabilities(QemuSystemTest): + """ + Validation of Cascadelake arch-capabilities + """ + def get_cpu_prop(self, prop): + cpu_path = self.vm.cmd('query-cpus-fast')[0].get('qom-path') + return self.vm.cmd('qom-get', path=cpu_path, property=prop) + + def test(self): + self.set_machine('pc') + # machine-type only: + self.vm.add_args('-S') + self.set_vm_arg('-cpu', + 'Cascadelake-Server,x-force-features=on,check=off,' + 'enforce=off') + self.vm.launch() + self.assertFalse(self.get_cpu_prop('arch-capabilities'), + 'pc + Cascadelake-Server should not have arch-capabilities') + + def test_unset(self): + self.set_machine('pc') + self.vm.add_args('-S') + self.set_vm_arg('-cpu', + 'Cascadelake-Server,x-force-features=on,check=off,' + 'enforce=off,-arch-capabilities') + self.vm.launch() + self.assertFalse(self.get_cpu_prop('arch-capabilities'), + 'pc + Cascadelake-Server,-arch-capabilities should not have arch-capabilities') + + def test_v2_unset(self): + self.set_machine('pc') + self.vm.add_args('-S') + self.set_vm_arg('-cpu', + 'Cascadelake-Server-v2,x-force-features=on,check=off,' + 'enforce=off,-arch-capabilities') + self.vm.launch() + self.assertFalse(self.get_cpu_prop('arch-capabilities'), + 'pc + Cascadelake-Server-v2,-arch-capabilities should not have arch-capabilities') + +if __name__ == '__main__': + QemuSystemTest.main() diff --git a/tests/functional/x86_64/test_cpu_queries.py b/tests/functional/x86_64/test_cpu_queries.py new file mode 100755 index 0000000..b1122a0 --- /dev/null +++ b/tests/functional/x86_64/test_cpu_queries.py @@ -0,0 +1,37 @@ +#!/usr/bin/env python3 +# +# Sanity check of query-cpu-* results +# +# Copyright (c) 2019 Red Hat, Inc. +# +# Author: +# Eduardo Habkost +# +# This work is licensed under the terms of the GNU GPL, version 2 or +# later. See the COPYING file in the top-level directory. + +from qemu_test import QemuSystemTest + +class QueryCPUModelExpansion(QemuSystemTest): + """ + Run query-cpu-model-expansion for each CPU model, and validate results + """ + + def test(self): + self.set_machine('none') + self.vm.add_args('-S') + self.vm.launch() + + cpus = self.vm.cmd('query-cpu-definitions') + for c in cpus: + self.log.info("Checking CPU: %s", c) + self.assertNotIn('', c['unavailable-features'], c['name']) + + for c in cpus: + model = {'name': c['name']} + e = self.vm.cmd('query-cpu-model-expansion', model=model, + type='full') + self.assertEqual(e['model']['name'], c['name']) + +if __name__ == '__main__': + QemuSystemTest.main() diff --git a/tests/functional/x86_64/test_hotplug_blk.py b/tests/functional/x86_64/test_hotplug_blk.py new file mode 100755 index 0000000..7ddbfef --- /dev/null +++ b/tests/functional/x86_64/test_hotplug_blk.py @@ -0,0 +1,85 @@ +#!/usr/bin/env python3 +# +# Functional test that hotplugs a virtio blk disk and checks it on a Linux +# guest +# +# Copyright (c) 2021 Red Hat, Inc. +# Copyright (c) Yandex +# +# This work is licensed under the terms of the GNU GPL, version 2 or +# later. See the COPYING file in the top-level directory. + +from qemu_test import LinuxKernelTest, Asset, exec_command_and_wait_for_pattern + + +class HotPlugBlk(LinuxKernelTest): + + ASSET_KERNEL = Asset( + ('https://archives.fedoraproject.org/pub/archive/fedora/linux/releases' + '/31/Server/x86_64/os/images/pxeboot/vmlinuz'), + 'd4738d03dbbe083ca610d0821d0a8f1488bebbdccef54ce33e3adb35fda00129') + + ASSET_INITRD = Asset( + ('https://archives.fedoraproject.org/pub/archive/fedora/linux/releases' + '/31/Server/x86_64/os/images/pxeboot/initrd.img'), + '277cd6c7adf77c7e63d73bbb2cded8ef9e2d3a2f100000e92ff1f8396513cd8b') + + def blockdev_add(self) -> None: + self.vm.cmd('blockdev-add', **{ + 'driver': 'null-co', + 'size': 1073741824, + 'node-name': 'disk' + }) + + def assert_vda(self) -> None: + exec_command_and_wait_for_pattern(self, 'while ! test -e /sys/block/vda ;' + ' do sleep 0.2 ; done', '# ') + + def assert_no_vda(self) -> None: + exec_command_and_wait_for_pattern(self, 'while test -e /sys/block/vda ;' + ' do sleep 0.2 ; done', '# ') + + def plug(self) -> None: + args = { + 'driver': 'virtio-blk-pci', + 'drive': 'disk', + 'id': 'virtio-disk0', + 'bus': 'pci.1', + 'addr': '1', + } + + self.assert_no_vda() + self.vm.cmd('device_add', args) + self.wait_for_console_pattern('virtio_blk virtio0: [vda]') + self.assert_vda() + + def unplug(self) -> None: + self.vm.cmd('device_del', id='virtio-disk0') + + self.vm.event_wait('DEVICE_DELETED', 1.0, + match={'data': {'device': 'virtio-disk0'}}) + + self.assert_no_vda() + + def test(self) -> None: + self.require_accelerator('kvm') + self.set_machine('q35') + + self.vm.add_args('-accel', 'kvm') + self.vm.add_args('-device', 'pcie-pci-bridge,id=pci.1,bus=pcie.0') + self.vm.add_args('-m', '1G') + self.vm.add_args('-append', 'console=ttyS0 rd.rescue') + + self.launch_kernel(self.ASSET_KERNEL.fetch(), + self.ASSET_INITRD.fetch(), + wait_for='Entering emergency mode.') + self.wait_for_console_pattern('# ') + + self.blockdev_add() + + self.plug() + self.unplug() + + +if __name__ == '__main__': + LinuxKernelTest.main() diff --git a/tests/functional/x86_64/test_hotplug_cpu.py b/tests/functional/x86_64/test_hotplug_cpu.py new file mode 100755 index 0000000..7b9200a --- /dev/null +++ b/tests/functional/x86_64/test_hotplug_cpu.py @@ -0,0 +1,71 @@ +#!/usr/bin/env python3 +# +# Functional test that hotplugs a CPU and checks it on a Linux guest +# +# Copyright (c) 2021 Red Hat, Inc. +# +# Author: +# Cleber Rosa +# +# This work is licensed under the terms of the GNU GPL, version 2 or +# later. See the COPYING file in the top-level directory. + +from qemu_test import LinuxKernelTest, Asset, exec_command_and_wait_for_pattern + + +class HotPlugCPU(LinuxKernelTest): + + ASSET_KERNEL = Asset( + ('https://archives.fedoraproject.org/pub/archive/fedora/linux/releases' + '/31/Server/x86_64/os/images/pxeboot/vmlinuz'), + 'd4738d03dbbe083ca610d0821d0a8f1488bebbdccef54ce33e3adb35fda00129') + + ASSET_INITRD = Asset( + ('https://archives.fedoraproject.org/pub/archive/fedora/linux/releases' + '/31/Server/x86_64/os/images/pxeboot/initrd.img'), + '277cd6c7adf77c7e63d73bbb2cded8ef9e2d3a2f100000e92ff1f8396513cd8b') + + def test_hotplug(self): + + self.require_accelerator('kvm') + self.vm.add_args('-accel', 'kvm') + self.vm.add_args('-cpu', 'Haswell') + self.vm.add_args('-smp', '1,sockets=1,cores=2,threads=1,maxcpus=2') + self.vm.add_args('-m', '1G') + self.vm.add_args('-append', 'console=ttyS0 rd.rescue') + + self.launch_kernel(self.ASSET_KERNEL.fetch(), + self.ASSET_INITRD.fetch(), + wait_for='Entering emergency mode.') + prompt = '# ' + self.wait_for_console_pattern(prompt) + + exec_command_and_wait_for_pattern(self, + 'cd /sys/devices/system/cpu/cpu0', + 'cpu0#') + exec_command_and_wait_for_pattern(self, + 'cd /sys/devices/system/cpu/cpu1', + 'No such file or directory') + + self.vm.cmd('device_add', + driver='Haswell-x86_64-cpu', + id='c1', + socket_id=0, + core_id=1, + thread_id=0) + self.wait_for_console_pattern('CPU1 has been hot-added') + + exec_command_and_wait_for_pattern(self, + 'cd /sys/devices/system/cpu/cpu1', + 'cpu1#') + + exec_command_and_wait_for_pattern(self, 'cd ..', prompt) + self.vm.cmd('device_del', id='c1') + + exec_command_and_wait_for_pattern(self, + 'while cd /sys/devices/system/cpu/cpu1 ;' + ' do sleep 0.2 ; done', + 'No such file or directory') + +if __name__ == '__main__': + LinuxKernelTest.main() diff --git a/tests/functional/x86_64/test_intel_iommu.py b/tests/functional/x86_64/test_intel_iommu.py new file mode 100755 index 0000000..62268d6 --- /dev/null +++ b/tests/functional/x86_64/test_intel_iommu.py @@ -0,0 +1,155 @@ +#!/usr/bin/env python3 +# +# INTEL_IOMMU Functional tests +# +# Copyright (c) 2021 Red Hat, Inc. +# +# Author: +# Eric Auger +# +# This work is licensed under the terms of the GNU GPL, version 2 or +# later. See the COPYING file in the top-level directory. + +from qemu_test import LinuxKernelTest, Asset, exec_command_and_wait_for_pattern + + +class IntelIOMMU(LinuxKernelTest): + + ASSET_KERNEL = Asset( + ('https://archives.fedoraproject.org/pub/archive/fedora/linux/releases' + '/31/Server/x86_64/os/images/pxeboot/vmlinuz'), + 'd4738d03dbbe083ca610d0821d0a8f1488bebbdccef54ce33e3adb35fda00129') + + ASSET_INITRD = Asset( + ('https://archives.fedoraproject.org/pub/archive/fedora/linux/releases' + '/31/Server/x86_64/os/images/pxeboot/initrd.img'), + '277cd6c7adf77c7e63d73bbb2cded8ef9e2d3a2f100000e92ff1f8396513cd8b') + + ASSET_DISKIMAGE = Asset( + ('https://archives.fedoraproject.org/pub/archive/fedora/linux/releases' + '/31/Cloud/x86_64/images/Fedora-Cloud-Base-31-1.9.x86_64.qcow2'), + 'e3c1b309d9203604922d6e255c2c5d098a309c2d46215d8fc026954f3c5c27a0') + + DEFAULT_KERNEL_PARAMS = ('root=/dev/vda1 console=ttyS0 net.ifnames=0 ' + 'quiet rd.rescue ') + GUEST_PORT = 8080 + IOMMU_ADDON = ',iommu_platform=on,disable-modern=off,disable-legacy=on' + kernel_path = None + initrd_path = None + kernel_params = None + + def add_common_args(self, path): + self.vm.add_args('-drive', f'file={path},if=none,id=drv0,snapshot=on') + self.vm.add_args('-device', 'virtio-blk-pci,bus=pcie.0,' + + 'drive=drv0,id=virtio-disk0,bootindex=1,' + 'werror=stop,rerror=stop' + self.IOMMU_ADDON) + self.vm.add_args('-device', 'virtio-gpu-pci' + self.IOMMU_ADDON) + + self.vm.add_args('-netdev', + 'user,id=n1,hostfwd=tcp:127.0.0.1:0-:%d' % + self.GUEST_PORT) + self.vm.add_args('-device', + 'virtio-net-pci,netdev=n1' + self.IOMMU_ADDON) + + self.vm.add_args('-device', 'virtio-rng-pci,rng=rng0') + self.vm.add_args('-object', + 'rng-random,id=rng0,filename=/dev/urandom') + self.vm.add_args("-m", "1G") + self.vm.add_args("-accel", "kvm") + + def common_vm_setup(self): + self.set_machine('q35') + self.require_accelerator("kvm") + self.require_netdev('user') + + self.kernel_path = self.ASSET_KERNEL.fetch() + self.initrd_path = self.ASSET_INITRD.fetch() + image_path = self.ASSET_DISKIMAGE.fetch() + self.add_common_args(image_path) + self.kernel_params = self.DEFAULT_KERNEL_PARAMS + + def run_and_check(self): + if self.kernel_path: + self.vm.add_args('-kernel', self.kernel_path, + '-append', self.kernel_params, + '-initrd', self.initrd_path) + self.vm.set_console() + self.vm.launch() + self.wait_for_console_pattern('Entering emergency mode.') + prompt = '# ' + self.wait_for_console_pattern(prompt) + + # Copy a file (checked later), umount afterwards to drop disk cache: + exec_command_and_wait_for_pattern(self, 'mount /dev/vda1 /sysroot', + prompt) + filename = '/boot/initramfs-5.3.7-301.fc31.x86_64.img' + exec_command_and_wait_for_pattern(self, (f'cp /sysroot{filename}' + ' /sysroot/root/data'), + prompt) + exec_command_and_wait_for_pattern(self, 'umount /sysroot', prompt) + + # Switch from initrd to the cloud image filesystem: + exec_command_and_wait_for_pattern(self, 'mount /dev/vda1 /sysroot', + prompt) + exec_command_and_wait_for_pattern(self, + ('for d in dev proc sys run ; do ' + 'mount -o bind /$d /sysroot/$d ; done'), prompt) + exec_command_and_wait_for_pattern(self, 'chroot /sysroot', prompt) + + # Checking for IOMMU enablement: + self.log.info("Checking whether IOMMU has been enabled...") + exec_command_and_wait_for_pattern(self, 'cat /proc/cmdline', + 'intel_iommu=on') + self.wait_for_console_pattern(prompt) + exec_command_and_wait_for_pattern(self, 'dmesg | grep DMAR:', + 'IOMMU enabled') + self.wait_for_console_pattern(prompt) + exec_command_and_wait_for_pattern(self, + 'find /sys/kernel/iommu_groups/ -type l', + 'devices/0000:00:') + self.wait_for_console_pattern(prompt) + + # Check hard disk device via sha256sum: + self.log.info("Checking hard disk...") + hashsum = '0dc7472f879be70b2f3daae279e3ae47175ffe249691e7d97f47222b65b8a720' + exec_command_and_wait_for_pattern(self, 'sha256sum ' + filename, + hashsum) + self.wait_for_console_pattern(prompt) + exec_command_and_wait_for_pattern(self, 'sha256sum /root/data', + hashsum) + self.wait_for_console_pattern(prompt) + + # Check virtio-net via HTTP: + exec_command_and_wait_for_pattern(self, 'dhclient eth0', prompt) + self.check_http_download(filename, hashsum, self.GUEST_PORT) + + def test_intel_iommu(self): + self.common_vm_setup() + self.vm.add_args('-device', 'intel-iommu,intremap=on') + self.vm.add_args('-machine', 'kernel_irqchip=split') + self.kernel_params += 'intel_iommu=on' + self.run_and_check() + + def test_intel_iommu_strict(self): + self.common_vm_setup() + self.vm.add_args('-device', 'intel-iommu,intremap=on') + self.vm.add_args('-machine', 'kernel_irqchip=split') + self.kernel_params += 'intel_iommu=on,strict' + self.run_and_check() + + def test_intel_iommu_strict_cm(self): + self.common_vm_setup() + self.vm.add_args('-device', 'intel-iommu,intremap=on,caching-mode=on') + self.vm.add_args('-machine', 'kernel_irqchip=split') + self.kernel_params += 'intel_iommu=on,strict' + self.run_and_check() + + def test_intel_iommu_pt(self): + self.common_vm_setup() + self.vm.add_args('-device', 'intel-iommu,intremap=on') + self.vm.add_args('-machine', 'kernel_irqchip=split') + self.kernel_params += 'intel_iommu=on iommu=pt' + self.run_and_check() + +if __name__ == '__main__': + LinuxKernelTest.main() diff --git a/tests/functional/x86_64/test_kvm_xen.py b/tests/functional/x86_64/test_kvm_xen.py new file mode 100755 index 0000000..a5d4450 --- /dev/null +++ b/tests/functional/x86_64/test_kvm_xen.py @@ -0,0 +1,157 @@ +#!/usr/bin/env python3 +# +# KVM Xen guest functional tests +# +# Copyright © 2021 Red Hat, Inc. +# Copyright © 2023 Amazon.com, Inc. or its affiliates. All Rights Reserved. +# +# Author: +# David Woodhouse +# Alex Bennée +# +# SPDX-License-Identifier: GPL-2.0-or-later + +from qemu.machine import machine + +from qemu_test import QemuSystemTest, Asset, exec_command_and_wait_for_pattern +from qemu_test import wait_for_console_pattern + +class KVMXenGuest(QemuSystemTest): + + KERNEL_DEFAULT = 'printk.time=0 root=/dev/xvda console=ttyS0 quiet' + + kernel_path = None + kernel_params = None + + # Fetch assets from the kvm-xen-guest subdir of my shared test + # images directory on fileserver.linaro.org where you can find + # build instructions for how they where assembled. + ASSET_KERNEL = Asset( + ('https://fileserver.linaro.org/s/kE4nCFLdQcoBF9t/download?' + 'path=%2Fkvm-xen-guest&files=bzImage'), + 'ec0ad7bb8c33c5982baee0a75505fe7dbf29d3ff5d44258204d6307c6fe0132a') + + ASSET_ROOTFS = Asset( + ('https://fileserver.linaro.org/s/kE4nCFLdQcoBF9t/download?' + 'path=%2Fkvm-xen-guest&files=rootfs.ext4'), + 'b11045d649006c649c184e93339aaa41a8fe20a1a86620af70323252eb29e40b') + + def common_vm_setup(self): + # We also catch lack of KVM_XEN support if we fail to launch + self.require_accelerator("kvm") + self.require_netdev('user') + + self.vm.set_console() + + self.vm.add_args("-accel", "kvm,xen-version=0x4000a,kernel-irqchip=split") + self.vm.add_args("-smp", "2") + + self.kernel_path = self.ASSET_KERNEL.fetch() + self.rootfs = self.ASSET_ROOTFS.fetch() + + def run_and_check(self): + self.vm.add_args('-kernel', self.kernel_path, + '-append', self.kernel_params, + '-drive', f"file={self.rootfs},if=none,snapshot=on,format=raw,id=drv0", + '-device', 'xen-disk,drive=drv0,vdev=xvda', + '-device', 'virtio-net-pci,netdev=unet', + '-netdev', 'user,id=unet,hostfwd=:127.0.0.1:0-:22') + + try: + self.vm.launch() + except machine.VMLaunchFailure as e: + if "Xen HVM guest support not present" in e.output: + self.skipTest("KVM Xen support is not present " + "(need v5.12+ kernel with CONFIG_KVM_XEN)") + elif "Property 'kvm-accel.xen-version' not found" in e.output: + self.skipTest("QEMU not built with CONFIG_XEN_EMU support") + else: + raise e + + self.log.info('VM launched, waiting for sshd') + console_pattern = 'Starting dropbear sshd: OK' + wait_for_console_pattern(self, console_pattern, 'Oops') + self.log.info('sshd ready') + + exec_command_and_wait_for_pattern(self, 'cat /proc/cmdline', 'xen') + exec_command_and_wait_for_pattern(self, 'dmesg | grep "Grant table"', + 'Grant table initialized') + wait_for_console_pattern(self, '#', 'Oops') + + def test_kvm_xen_guest(self): + self.common_vm_setup() + + self.kernel_params = (self.KERNEL_DEFAULT + + ' xen_emul_unplug=ide-disks') + self.run_and_check() + exec_command_and_wait_for_pattern(self, + 'grep xen-pirq.*msi /proc/interrupts', + 'virtio0-output') + + def test_kvm_xen_guest_nomsi(self): + self.common_vm_setup() + + self.kernel_params = (self.KERNEL_DEFAULT + + ' xen_emul_unplug=ide-disks pci=nomsi') + self.run_and_check() + exec_command_and_wait_for_pattern(self, + 'grep xen-pirq.* /proc/interrupts', + 'virtio0') + + def test_kvm_xen_guest_noapic_nomsi(self): + self.common_vm_setup() + + self.kernel_params = (self.KERNEL_DEFAULT + + ' xen_emul_unplug=ide-disks noapic pci=nomsi') + self.run_and_check() + exec_command_and_wait_for_pattern(self, + 'grep xen-pirq /proc/interrupts', + 'virtio0') + + def test_kvm_xen_guest_vapic(self): + self.common_vm_setup() + self.vm.add_args('-cpu', 'host,+xen-vapic') + self.kernel_params = (self.KERNEL_DEFAULT + + ' xen_emul_unplug=ide-disks') + self.run_and_check() + exec_command_and_wait_for_pattern(self, + 'grep xen-pirq /proc/interrupts', + 'acpi') + wait_for_console_pattern(self, '#') + exec_command_and_wait_for_pattern(self, + 'grep PCI-MSI /proc/interrupts', + 'virtio0-output') + + def test_kvm_xen_guest_novector(self): + self.common_vm_setup() + self.kernel_params = (self.KERNEL_DEFAULT + + ' xen_emul_unplug=ide-disks' + + ' xen_no_vector_callback') + self.run_and_check() + exec_command_and_wait_for_pattern(self, + 'grep xen-platform-pci /proc/interrupts', + 'fasteoi') + + def test_kvm_xen_guest_novector_nomsi(self): + self.common_vm_setup() + + self.kernel_params = (self.KERNEL_DEFAULT + + ' xen_emul_unplug=ide-disks pci=nomsi' + + ' xen_no_vector_callback') + self.run_and_check() + exec_command_and_wait_for_pattern(self, + 'grep xen-platform-pci /proc/interrupts', + 'IO-APIC') + + def test_kvm_xen_guest_novector_noapic(self): + self.common_vm_setup() + self.kernel_params = (self.KERNEL_DEFAULT + + ' xen_emul_unplug=ide-disks' + + ' xen_no_vector_callback noapic') + self.run_and_check() + exec_command_and_wait_for_pattern(self, + 'grep xen-platform-pci /proc/interrupts', + 'XT-PIC') + +if __name__ == '__main__': + QemuSystemTest.main() diff --git a/tests/functional/x86_64/test_linux_initrd.py b/tests/functional/x86_64/test_linux_initrd.py new file mode 100755 index 0000000..2207f83 --- /dev/null +++ b/tests/functional/x86_64/test_linux_initrd.py @@ -0,0 +1,95 @@ +#!/usr/bin/env python3 +# +# Linux initrd integration test. +# +# Copyright (c) 2018 Red Hat, Inc. +# +# Author: +# Wainer dos Santos Moschetta +# +# This work is licensed under the terms of the GNU GPL, version 2 or +# later. See the COPYING file in the top-level directory. + +import logging +import tempfile + +from qemu_test import QemuSystemTest, Asset, skipFlakyTest + + +class LinuxInitrd(QemuSystemTest): + """ + Checks QEMU evaluates correctly the initrd file passed as -initrd option. + """ + + timeout = 300 + + ASSET_F18_KERNEL = Asset( + ('https://archives.fedoraproject.org/pub/archive/fedora/linux/' + 'releases/18/Fedora/x86_64/os/images/pxeboot/vmlinuz'), + '1a27cb42559ce29237ac186699d063556ad69c8349d732bb1bd8d614e5a8cc2e') + + ASSET_F28_KERNEL = Asset( + ('https://archives.fedoraproject.org/pub/archive/fedora/linux/' + 'releases/28/Everything/x86_64/os/images/pxeboot/vmlinuz'), + 'd05909c9d4a742a6fcc84dcc0361009e4611769619cc187a07107579a035f24e') + + def test_with_2gib_file_should_exit_error_msg_with_linux_v3_6(self): + """ + Pretends to boot QEMU with an initrd file with size of 2GiB + and expect it exits with error message. + Fedora-18 shipped with linux-3.6 which have not supported xloadflags + cannot support more than 2GiB initrd. + """ + self.set_machine('pc') + kernel_path = self.ASSET_F18_KERNEL.fetch() + max_size = 2 * (1024 ** 3) - 1 + + with tempfile.NamedTemporaryFile() as initrd: + initrd.seek(max_size) + initrd.write(b'\0') + initrd.flush() + self.vm.add_args('-kernel', kernel_path, '-initrd', initrd.name, + '-m', '4096') + self.vm.set_qmp_monitor(enabled=False) + self.vm.launch() + self.vm.wait() + self.assertEqual(self.vm.exitcode(), 1) + expected_msg = r'.*initrd is too large.*max: \d+, need %s.*' % ( + max_size + 1) + self.assertRegex(self.vm.get_log(), expected_msg) + + # XXX file tracking bug + @skipFlakyTest(bug_url=None) + def test_with_2gib_file_should_work_with_linux_v4_16(self): + """ + QEMU has supported up to 4 GiB initrd for recent kernel + Expect guest can reach 'Unpacking initramfs...' + """ + self.set_machine('pc') + kernel_path = self.ASSET_F28_KERNEL.fetch() + max_size = 2 * (1024 ** 3) + 1 + + with tempfile.NamedTemporaryFile() as initrd: + initrd.seek(max_size) + initrd.write(b'\0') + initrd.flush() + + self.vm.set_console() + kernel_command_line = 'console=ttyS0' + self.vm.add_args('-kernel', kernel_path, + '-append', kernel_command_line, + '-initrd', initrd.name, + '-m', '5120') + self.vm.launch() + console = self.vm.console_socket.makefile() + console_logger = logging.getLogger('console') + while True: + msg = console.readline() + console_logger.debug(msg.strip()) + if 'Unpacking initramfs...' in msg: + break + if 'Kernel panic - not syncing' in msg: + self.fail("Kernel panic reached") + +if __name__ == '__main__': + QemuSystemTest.main() diff --git a/tests/functional/x86_64/test_mem_addr_space.py b/tests/functional/x86_64/test_mem_addr_space.py new file mode 100755 index 0000000..61b4a19 --- /dev/null +++ b/tests/functional/x86_64/test_mem_addr_space.py @@ -0,0 +1,349 @@ +#!/usr/bin/env python3 +# +# Check for crash when using memory beyond the available guest processor +# address space. +# +# Copyright (c) 2023 Red Hat, Inc. +# +# Author: +# Ani Sinha +# +# SPDX-License-Identifier: GPL-2.0-or-later + +from qemu_test import QemuSystemTest +import time + +class MemAddrCheck(QemuSystemTest): + # after launch, in order to generate the logs from QEMU we need to + # wait for some time. Launching and then immediately shutting down + # the VM generates empty logs. A delay of 1 second is added for + # this reason. + DELAY_Q35_BOOT_SEQUENCE = 1 + + # This helper can go away when the 32-bit host deprecation + # turns into full & final removal of support. + def ensure_64bit_binary(self): + with open(self.qemu_bin, "rb") as fh: + ident = fh.read(4) + + # "\x7fELF" + if ident != bytes([0x7f, 0x45, 0x4C, 0x46]): + # Non-ELF file implies macOS or Windows which + # we already assume to be 64-bit only + return + + # bits == 1 -> 32-bit; bits == 2 -> 64-bit + bits = int.from_bytes(fh.read(1), byteorder='little') + if bits != 2: + # 32-bit ELF builds won't be able to address sufficient + # RAM to run the tests + self.skipTest("64-bit build host is required") + + # first, lets test some 32-bit processors. + # for all 32-bit cases, pci64_hole_size is 0. + def test_phybits_low_pse36(self): + """ + With pse36 feature ON, a processor has 36 bits of addressing. So it can + access up to a maximum of 64GiB of memory. Memory hotplug region begins + at 4 GiB boundary when "above_4g_mem_size" is 0 (this would be true when + we have 0.5 GiB of VM memory, see pc_q35_init()). This means total + hotpluggable memory size is 60 GiB. Per slot, we reserve 1 GiB of memory + for dimm alignment for all machines. That leaves total hotpluggable + actual memory size of 59 GiB. If the VM is started with 0.5 GiB of + memory, maxmem should be set to a maximum value of 59.5 GiB to ensure + that the processor can address all memory directly. + Note that 64-bit pci hole size is 0 in this case. If maxmem is set to + 59.6G, QEMU should fail to start with a message "phy-bits are too low". + If maxmem is set to 59.5G with all other QEMU parameters identical, QEMU + should start fine. + """ + self.ensure_64bit_binary() + self.set_machine('q35') + self.vm.add_args('-S', '-m', '512,slots=1,maxmem=59.6G', + '-cpu', 'pentium,pse36=on', '-display', 'none', + '-object', 'memory-backend-ram,id=mem1,size=1G', + '-device', 'pc-dimm,id=vm0,memdev=mem1') + self.vm.set_qmp_monitor(enabled=False) + self.vm.launch() + self.vm.wait() + self.assertEqual(self.vm.exitcode(), 1, "QEMU exit code should be 1") + self.assertRegex(self.vm.get_log(), r'phys-bits too low') + + def test_phybits_low_pae(self): + """ + With pae feature ON, a processor has 36 bits of addressing. So it can + access up to a maximum of 64GiB of memory. Rest is the same as the case + with pse36 above. + """ + self.ensure_64bit_binary() + self.set_machine('q35') + self.vm.add_args('-S', '-m', '512,slots=1,maxmem=59.6G', + '-cpu', 'pentium,pae=on', '-display', 'none', + '-object', 'memory-backend-ram,id=mem1,size=1G', + '-device', 'pc-dimm,id=vm0,memdev=mem1') + self.vm.set_qmp_monitor(enabled=False) + self.vm.launch() + self.vm.wait() + self.assertEqual(self.vm.exitcode(), 1, "QEMU exit code should be 1") + self.assertRegex(self.vm.get_log(), r'phys-bits too low') + + def test_phybits_ok_pentium_pse36(self): + """ + Setting maxmem to 59.5G and making sure that QEMU can start with the + same options as the failing case above with pse36 cpu feature. + """ + self.ensure_64bit_binary() + self.set_machine('q35') + self.vm.add_args('-m', '512,slots=1,maxmem=59.5G', + '-cpu', 'pentium,pse36=on', '-display', 'none', + '-object', 'memory-backend-ram,id=mem1,size=1G', + '-device', 'pc-dimm,id=vm0,memdev=mem1') + self.vm.set_qmp_monitor(enabled=False) + self.vm.launch() + time.sleep(self.DELAY_Q35_BOOT_SEQUENCE) + self.vm.shutdown() + self.assertNotRegex(self.vm.get_log(), r'phys-bits too low') + + def test_phybits_ok_pentium_pae(self): + """ + Test is same as above but now with pae cpu feature turned on. + Setting maxmem to 59.5G and making sure that QEMU can start fine + with the same options as the case above. + """ + self.ensure_64bit_binary() + self.set_machine('q35') + self.vm.add_args('-m', '512,slots=1,maxmem=59.5G', + '-cpu', 'pentium,pae=on', '-display', 'none', + '-object', 'memory-backend-ram,id=mem1,size=1G', + '-device', 'pc-dimm,id=vm0,memdev=mem1') + self.vm.set_qmp_monitor(enabled=False) + self.vm.launch() + time.sleep(self.DELAY_Q35_BOOT_SEQUENCE) + self.vm.shutdown() + self.assertNotRegex(self.vm.get_log(), r'phys-bits too low') + + def test_phybits_ok_pentium2(self): + """ + Pentium2 has 36 bits of addressing, so its same as pentium + with pse36 ON. + """ + self.ensure_64bit_binary() + self.set_machine('q35') + self.vm.add_args('-m', '512,slots=1,maxmem=59.5G', + '-cpu', 'pentium2', '-display', 'none', + '-object', 'memory-backend-ram,id=mem1,size=1G', + '-device', 'pc-dimm,id=vm0,memdev=mem1') + self.vm.set_qmp_monitor(enabled=False) + self.vm.launch() + time.sleep(self.DELAY_Q35_BOOT_SEQUENCE) + self.vm.shutdown() + self.assertNotRegex(self.vm.get_log(), r'phys-bits too low') + + def test_phybits_low_nonpse36(self): + """ + Pentium processor has 32 bits of addressing without pse36 or pae + so it can access physical address up to 4 GiB. Setting maxmem to + 4 GiB should make QEMU fail to start with "phys-bits too low" + message because the region for memory hotplug is always placed + above 4 GiB due to the PCI hole and simplicity. + """ + self.ensure_64bit_binary() + self.set_machine('q35') + self.vm.add_args('-S', '-m', '512,slots=1,maxmem=4G', + '-cpu', 'pentium', '-display', 'none', + '-object', 'memory-backend-ram,id=mem1,size=1G', + '-device', 'pc-dimm,id=vm0,memdev=mem1') + self.vm.set_qmp_monitor(enabled=False) + self.vm.launch() + self.vm.wait() + self.assertEqual(self.vm.exitcode(), 1, "QEMU exit code should be 1") + self.assertRegex(self.vm.get_log(), r'phys-bits too low') + + # now lets test some 64-bit CPU cases. + def test_phybits_low_tcg_q35_70_amd(self): + """ + For q35 7.1 machines and above, there is a HT window that starts at + 1024 GiB and ends at 1 TiB - 1. If the max GPA falls in this range, + "above_4G" memory is adjusted to start at 1 TiB boundary for AMD cpus + in the default case. Lets test without that case for machines 7.0. + For q35-7.0 machines, "above 4G" memory starts are 4G. + pci64_hole size is 32 GiB. Since TCG_PHYS_ADDR_BITS is defined to + be 40, TCG emulated CPUs have maximum of 1 TiB (1024 GiB) of + directly addressable memory. + Hence, maxmem value at most can be + 1024 GiB - 4 GiB - 1 GiB per slot for alignment - 32 GiB + 0.5 GiB + which is equal to 987.5 GiB. Setting the value to 988 GiB should + make QEMU fail with the error message. + """ + self.ensure_64bit_binary() + self.set_machine('pc-q35-7.0') + self.vm.add_args('-S', '-m', '512,slots=1,maxmem=988G', + '-display', 'none', + '-object', 'memory-backend-ram,id=mem1,size=1G', + '-device', 'pc-dimm,id=vm0,memdev=mem1') + self.vm.set_qmp_monitor(enabled=False) + self.vm.launch() + self.vm.wait() + self.assertEqual(self.vm.exitcode(), 1, "QEMU exit code should be 1") + self.assertRegex(self.vm.get_log(), r'phys-bits too low') + + def test_phybits_low_tcg_q35_71_amd(self): + """ + AMD_HT_START is defined to be at 1012 GiB. So for q35 machines + version > 7.0 and AMD cpus, instead of 1024 GiB limit for 40 bit + processor address space, it has to be 1012 GiB , that is 12 GiB + less than the case above in order to accommodate HT hole. + Make sure QEMU fails when maxmem size is 976 GiB (12 GiB less + than 988 GiB). + """ + self.ensure_64bit_binary() + self.set_machine('pc-q35-7.1') + self.vm.add_args('-S', '-m', '512,slots=1,maxmem=976G', + '-display', 'none', + '-object', 'memory-backend-ram,id=mem1,size=1G', + '-device', 'pc-dimm,id=vm0,memdev=mem1') + self.vm.set_qmp_monitor(enabled=False) + self.vm.launch() + self.vm.wait() + self.assertEqual(self.vm.exitcode(), 1, "QEMU exit code should be 1") + self.assertRegex(self.vm.get_log(), r'phys-bits too low') + + def test_phybits_ok_tcg_q35_70_amd(self): + """ + Same as q35-7.0 AMD case except that here we check that QEMU can + successfully start when maxmem is < 988G. + """ + self.ensure_64bit_binary() + self.set_machine('pc-q35-7.0') + self.vm.add_args('-S', '-m', '512,slots=1,maxmem=987.5G', + '-display', 'none', + '-object', 'memory-backend-ram,id=mem1,size=1G', + '-device', 'pc-dimm,id=vm0,memdev=mem1') + self.vm.set_qmp_monitor(enabled=False) + self.vm.launch() + time.sleep(self.DELAY_Q35_BOOT_SEQUENCE) + self.vm.shutdown() + self.assertNotRegex(self.vm.get_log(), r'phys-bits too low') + + def test_phybits_ok_tcg_q35_71_amd(self): + """ + Same as q35-7.1 AMD case except that here we check that QEMU can + successfully start when maxmem is < 976G. + """ + self.ensure_64bit_binary() + self.set_machine('pc-q35-7.1') + self.vm.add_args('-S', '-m', '512,slots=1,maxmem=975.5G', + '-display', 'none', + '-object', 'memory-backend-ram,id=mem1,size=1G', + '-device', 'pc-dimm,id=vm0,memdev=mem1') + self.vm.set_qmp_monitor(enabled=False) + self.vm.launch() + time.sleep(self.DELAY_Q35_BOOT_SEQUENCE) + self.vm.shutdown() + self.assertNotRegex(self.vm.get_log(), r'phys-bits too low') + + def test_phybits_ok_tcg_q35_71_intel(self): + """ + Same parameters as test_phybits_low_tcg_q35_71_amd() but use + Intel cpu instead. QEMU should start fine in this case as + "above_4G" memory starts at 4G. + """ + self.ensure_64bit_binary() + self.set_machine('pc-q35-7.1') + self.vm.add_args('-S', '-cpu', 'Skylake-Server', + '-m', '512,slots=1,maxmem=976G', + '-display', 'none', + '-object', 'memory-backend-ram,id=mem1,size=1G', + '-device', 'pc-dimm,id=vm0,memdev=mem1') + self.vm.set_qmp_monitor(enabled=False) + self.vm.launch() + time.sleep(self.DELAY_Q35_BOOT_SEQUENCE) + self.vm.shutdown() + self.assertNotRegex(self.vm.get_log(), r'phys-bits too low') + + def test_phybits_low_tcg_q35_71_amd_41bits(self): + """ + AMD processor with 41 bits. Max cpu hw address = 2 TiB. + By setting maxram above 1012 GiB - 32 GiB - 4 GiB = 976 GiB, we can + force "above_4G" memory to start at 1 TiB for q35-7.1 machines + (max GPA will be above AMD_HT_START which is defined as 1012 GiB). + + With pci_64_hole size at 32 GiB, in this case, maxmem should be 991.5 + GiB with 1 GiB per slot for alignment and 0.5 GiB as non-hotplug + memory for the VM (1024 - 32 - 1 + 0.5). With 992 GiB, QEMU should + fail to start. + """ + self.ensure_64bit_binary() + self.set_machine('pc-q35-7.1') + self.vm.add_args('-S', '-cpu', 'EPYC-v4,phys-bits=41', + '-m', '512,slots=1,maxmem=992G', + '-display', 'none', + '-object', 'memory-backend-ram,id=mem1,size=1G', + '-device', 'pc-dimm,id=vm0,memdev=mem1') + self.vm.set_qmp_monitor(enabled=False) + self.vm.launch() + self.vm.wait() + self.assertEqual(self.vm.exitcode(), 1, "QEMU exit code should be 1") + self.assertRegex(self.vm.get_log(), r'phys-bits too low') + + def test_phybits_ok_tcg_q35_71_amd_41bits(self): + """ + AMD processor with 41 bits. Max cpu hw address = 2 TiB. + Same as above but by setting maxram between 976 GiB and 992 Gib, + QEMU should start fine. + """ + self.ensure_64bit_binary() + self.set_machine('pc-q35-7.1') + self.vm.add_args('-S', '-cpu', 'EPYC-v4,phys-bits=41', + '-m', '512,slots=1,maxmem=990G', + '-display', 'none', + '-object', 'memory-backend-ram,id=mem1,size=1G', + '-device', 'pc-dimm,id=vm0,memdev=mem1') + self.vm.set_qmp_monitor(enabled=False) + self.vm.launch() + time.sleep(self.DELAY_Q35_BOOT_SEQUENCE) + self.vm.shutdown() + self.assertNotRegex(self.vm.get_log(), r'phys-bits too low') + + def test_phybits_low_tcg_q35_intel_cxl(self): + """ + cxl memory window starts after memory device range. Here, we use 1 GiB + of cxl window memory. 4G_mem end aligns at 4G. pci64_hole is 32 GiB and + starts after the cxl memory window. + So maxmem here should be at most 986 GiB considering all memory boundary + alignment constraints with 40 bits (1 TiB) of processor physical bits. + """ + self.ensure_64bit_binary() + self.set_machine('q35') + self.vm.add_args('-S', '-cpu', 'Skylake-Server,phys-bits=40', + '-m', '512,slots=1,maxmem=987G', + '-display', 'none', + '-device', 'pxb-cxl,bus_nr=12,bus=pcie.0,id=cxl.1', + '-M', 'cxl=on,cxl-fmw.0.targets.0=cxl.1,cxl-fmw.0.size=1G') + self.vm.set_qmp_monitor(enabled=False) + self.vm.launch() + self.vm.wait() + self.assertEqual(self.vm.exitcode(), 1, "QEMU exit code should be 1") + self.assertRegex(self.vm.get_log(), r'phys-bits too low') + + def test_phybits_ok_tcg_q35_intel_cxl(self): + """ + Same as above but here we do not reserve any cxl memory window. Hence, + with the exact same parameters as above, QEMU should start fine even + with cxl enabled. + """ + self.ensure_64bit_binary() + self.set_machine('q35') + self.vm.add_args('-S', '-cpu', 'Skylake-Server,phys-bits=40', + '-machine', 'cxl=on', + '-m', '512,slots=1,maxmem=987G', + '-display', 'none', + '-device', 'pxb-cxl,bus_nr=12,bus=pcie.0,id=cxl.1') + self.vm.set_qmp_monitor(enabled=False) + self.vm.launch() + time.sleep(self.DELAY_Q35_BOOT_SEQUENCE) + self.vm.shutdown() + self.assertNotRegex(self.vm.get_log(), r'phys-bits too low') + +if __name__ == '__main__': + QemuSystemTest.main() diff --git a/tests/functional/x86_64/test_memlock.py b/tests/functional/x86_64/test_memlock.py new file mode 100755 index 0000000..2b515ff --- /dev/null +++ b/tests/functional/x86_64/test_memlock.py @@ -0,0 +1,79 @@ +#!/usr/bin/env python3 +# +# Functional test that check overcommit memlock options +# +# Copyright (c) Yandex Technologies LLC, 2025 +# +# Author: +# Alexandr Moshkov +# +# SPDX-License-Identifier: GPL-2.0-or-later + +import re + +from typing import Dict + +from qemu_test import QemuSystemTest +from qemu_test import skipLockedMemoryTest + + +STATUS_VALUE_PATTERN = re.compile(r'^(\w+):\s+(\d+) kB', re.MULTILINE) + + +@skipLockedMemoryTest(2_097_152) # 2GB +class MemlockTest(QemuSystemTest): + """ + Runs a guest with memlock options. + Then verify, that this options is working correctly + by checking the status file of the QEMU process. + """ + + def common_vm_setup_with_memlock(self, memlock): + self.vm.add_args('-overcommit', f'mem-lock={memlock}') + self.vm.launch() + + def test_memlock_off(self): + self.common_vm_setup_with_memlock('off') + + status = self.get_process_status_values(self.vm.get_pid()) + + self.assertTrue(status['VmLck'] == 0) + + def test_memlock_on(self): + self.common_vm_setup_with_memlock('on') + + status = self.get_process_status_values(self.vm.get_pid()) + + # VmLck > 0 kB and almost all memory is resident + self.assertTrue(status['VmLck'] > 0) + self.assertTrue(status['VmRSS'] >= status['VmSize'] * 0.70) + + def test_memlock_onfault(self): + self.common_vm_setup_with_memlock('on-fault') + + status = self.get_process_status_values(self.vm.get_pid()) + + # VmLck > 0 kB and only few memory is resident + self.assertTrue(status['VmLck'] > 0) + self.assertTrue(status['VmRSS'] <= status['VmSize'] * 0.30) + + def get_process_status_values(self, pid: int) -> Dict[str, int]: + result = {} + raw_status = self._get_raw_process_status(pid) + + for line in raw_status.split('\n'): + if m := STATUS_VALUE_PATTERN.match(line): + result[m.group(1)] = int(m.group(2)) + + return result + + def _get_raw_process_status(self, pid: int) -> str: + try: + with open(f'/proc/{pid}/status', 'r') as f: + return f.read() + except FileNotFoundError: + self.skipTest("Can't open status file of the process") + + +if __name__ == '__main__': + MemlockTest.main() diff --git a/tests/functional/x86_64/test_migration.py b/tests/functional/x86_64/test_migration.py new file mode 100755 index 0000000..f3a517a --- /dev/null +++ b/tests/functional/x86_64/test_migration.py @@ -0,0 +1,26 @@ +#!/usr/bin/env python3 +# +# SPDX-License-Identifier: GPL-2.0-or-later +# +# x86_64 migration test + +from migration import MigrationTest + + +class X8664MigrationTest(MigrationTest): + + def test_migration_with_tcp_localhost(self): + self.set_machine('microvm') + self.migration_with_tcp_localhost() + + def test_migration_with_unix(self): + self.set_machine('microvm') + self.migration_with_unix() + + def test_migration_with_exec(self): + self.set_machine('microvm') + self.migration_with_exec() + + +if __name__ == '__main__': + MigrationTest.main() diff --git a/tests/functional/x86_64/test_multiprocess.py b/tests/functional/x86_64/test_multiprocess.py new file mode 100755 index 0000000..756629d --- /dev/null +++ b/tests/functional/x86_64/test_multiprocess.py @@ -0,0 +1,31 @@ +#!/usr/bin/env python3 +# +# SPDX-License-Identifier: GPL-2.0-or-later +# +# Test for multiprocess qemu on x86 + +from multiprocess import Multiprocess +from qemu_test import Asset + + +class X86Multiprocess(Multiprocess): + + ASSET_KERNEL_X86 = Asset( + ('https://archives.fedoraproject.org/pub/archive/fedora/linux' + '/releases/31/Everything/x86_64/os/images/pxeboot/vmlinuz'), + 'd4738d03dbbe083ca610d0821d0a8f1488bebbdccef54ce33e3adb35fda00129') + + ASSET_INITRD_X86 = Asset( + ('https://archives.fedoraproject.org/pub/archive/fedora/linux' + '/releases/31/Everything/x86_64/os/images/pxeboot/initrd.img'), + '3b6cb5c91a14c42e2f61520f1689264d865e772a1f0069e660a800d31dd61fb9') + + def test_multiprocess(self): + kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE + + 'console=ttyS0 rdinit=/bin/bash') + self.do_test(self.ASSET_KERNEL_X86, self.ASSET_INITRD_X86, + kernel_command_line, 'pc') + + +if __name__ == '__main__': + Multiprocess.main() diff --git a/tests/functional/x86_64/test_netdev_ethtool.py b/tests/functional/x86_64/test_netdev_ethtool.py new file mode 100755 index 0000000..ee1a397 --- /dev/null +++ b/tests/functional/x86_64/test_netdev_ethtool.py @@ -0,0 +1,88 @@ +#!/usr/bin/env python3 +# +# ethtool tests for emulated network devices +# +# This test leverages ethtool's --test sequence to validate network +# device behaviour. +# +# SPDX-License-Identifier: GPL-2.0-or-later + +from unittest import skip +from qemu_test import QemuSystemTest, Asset +from qemu_test import wait_for_console_pattern + +class NetDevEthtool(QemuSystemTest): + + # Runs in about 17s under KVM, 19s under TCG, 25s under GCOV + timeout = 45 + + # Fetch assets from the netdev-ethtool subdir of my shared test + # images directory on fileserver.linaro.org. + ASSET_BASEURL = ('https://fileserver.linaro.org/s/kE4nCFLdQcoBF9t/' + 'download?path=%2Fnetdev-ethtool&files=') + ASSET_BZIMAGE = Asset( + ASSET_BASEURL + "bzImage", + "ed62ee06ea620b1035747f3f66a5e9fc5d3096b29f75562ada888b04cd1c4baf") + ASSET_ROOTFS = Asset( + ASSET_BASEURL + "rootfs.squashfs", + "8f0207e3c4d40832ae73c1a927e42ca30ccb1e71f047acb6ddb161ba422934e6") + + def common_test_code(self, netdev, extra_args=None): + self.set_machine('q35') + + # This custom kernel has drivers for all the supported network + # devices we can emulate in QEMU + kernel = self.ASSET_BZIMAGE.fetch() + rootfs = self.ASSET_ROOTFS.fetch() + + append = 'printk.time=0 console=ttyS0 ' + append += 'root=/dev/sr0 rootfstype=squashfs ' + + # any additional kernel tweaks for the test + if extra_args: + append += extra_args + + # finally invoke ethtool directly + append += ' init=/usr/sbin/ethtool -- -t eth1 offline' + + # add the rootfs via a readonly cdrom image + drive = f"file={rootfs},if=ide,index=0,media=cdrom" + + self.vm.add_args('-kernel', kernel, + '-append', append, + '-drive', drive, + '-device', netdev) + + self.vm.set_console(console_index=0) + self.vm.launch() + + wait_for_console_pattern(self, + "The test result is PASS", + "The test result is FAIL", + vm=None) + # no need to gracefully shutdown, just finish + self.vm.kill() + + def test_igb(self): + self.common_test_code("igb") + + def test_igb_nomsi(self): + self.common_test_code("igb", "pci=nomsi") + + # It seems the other popular cards we model in QEMU currently fail + # the pattern test with: + # + # pattern test failed (reg 0x00178): got 0x00000000 expected 0x00005A5A + # + # So for now we skip them. + + @skip("Incomplete reg 0x00178 support") + def test_e1000(self): + self.common_test_code("e1000") + + @skip("Incomplete reg 0x00178 support") + def test_i82550(self): + self.common_test_code("i82550") + +if __name__ == '__main__': + QemuSystemTest.main() diff --git a/tests/functional/x86_64/test_pc_cpu_hotplug_props.py b/tests/functional/x86_64/test_pc_cpu_hotplug_props.py new file mode 100755 index 0000000..2bed8ad --- /dev/null +++ b/tests/functional/x86_64/test_pc_cpu_hotplug_props.py @@ -0,0 +1,37 @@ +#!/usr/bin/env python3 +# +# Ensure CPU die-id can be omitted on -device +# +# Copyright (c) 2019 Red Hat Inc +# +# Author: +# Eduardo Habkost +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, see . +# + +from qemu_test import QemuSystemTest + +class OmittedCPUProps(QemuSystemTest): + + def test_no_die_id(self): + self.set_machine('pc') + self.vm.add_args('-nodefaults', '-S') + self.vm.add_args('-smp', '1,sockets=2,cores=2,threads=2,maxcpus=8') + self.vm.add_args('-device', 'qemu64-x86_64-cpu,socket-id=1,core-id=0,thread-id=0') + self.vm.launch() + self.assertEqual(len(self.vm.cmd('query-cpus-fast')), 2) + +if __name__ == '__main__': + QemuSystemTest.main() diff --git a/tests/functional/x86_64/test_replay.py b/tests/functional/x86_64/test_replay.py new file mode 100755 index 0000000..27287d4 --- /dev/null +++ b/tests/functional/x86_64/test_replay.py @@ -0,0 +1,58 @@ +#!/usr/bin/env python3 +# +# Replay test that boots a Linux kernel on x86_64 machines +# and checks the console +# +# SPDX-License-Identifier: GPL-2.0-or-later + +from subprocess import check_call, DEVNULL + +from qemu_test import Asset, skipFlakyTest, get_qemu_img +from replay_kernel import ReplayKernelBase + + +class X86Replay(ReplayKernelBase): + + ASSET_KERNEL = Asset( + 'https://storage.tuxboot.com/buildroot/20241119/x86_64/bzImage', + 'f57bfc6553bcd6e0a54aab86095bf642b33b5571d14e3af1731b18c87ed5aef8') + + ASSET_ROOTFS = Asset( + 'https://storage.tuxboot.com/buildroot/20241119/x86_64/rootfs.ext4.zst', + '4b8b2a99117519c5290e1202cb36eb6c7aaba92b357b5160f5970cf5fb78a751') + + def do_test_x86(self, machine, blkdevice, devroot): + self.require_netdev('user') + self.set_machine(machine) + self.cpu="Nehalem" + kernel_path = self.ASSET_KERNEL.fetch() + + raw_disk = self.uncompress(self.ASSET_ROOTFS) + disk = self.scratch_file('scratch.qcow2') + qemu_img = get_qemu_img(self) + check_call([qemu_img, 'create', '-f', 'qcow2', '-b', raw_disk, + '-F', 'raw', disk], stdout=DEVNULL, stderr=DEVNULL) + + args = ('-drive', 'file=%s,snapshot=on,id=hd0,if=none' % disk, + '-drive', 'driver=blkreplay,id=hd0-rr,if=none,image=hd0', + '-device', '%s,drive=hd0-rr' % blkdevice, + '-netdev', 'user,id=vnet,hostfwd=:127.0.0.1:0-:22', + '-device', 'virtio-net,netdev=vnet', + '-object', 'filter-replay,id=replay,netdev=vnet') + + kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE + + f"console=ttyS0 root=/dev/{devroot}") + console_pattern = 'Welcome to TuxTest' + self.run_rr(kernel_path, kernel_command_line, console_pattern, shift=5, + args=args) + + @skipFlakyTest('https://gitlab.com/qemu-project/qemu/-/issues/2094') + def test_pc(self): + self.do_test_x86('pc', 'virtio-blk', 'vda') + + def test_q35(self): + self.do_test_x86('q35', 'ide-hd', 'sda') + + +if __name__ == '__main__': + ReplayKernelBase.main() diff --git a/tests/functional/x86_64/test_reverse_debug.py b/tests/functional/x86_64/test_reverse_debug.py new file mode 100755 index 0000000..d713e91 --- /dev/null +++ b/tests/functional/x86_64/test_reverse_debug.py @@ -0,0 +1,36 @@ +#!/usr/bin/env python3 +# +# SPDX-License-Identifier: GPL-2.0-or-later +# +# Reverse debugging test +# +# Copyright (c) 2020 ISP RAS +# +# Author: +# Pavel Dovgalyuk +# +# This work is licensed under the terms of the GNU GPL, version 2 or +# later. See the COPYING file in the top-level directory. + +from qemu_test import skipIfMissingImports, skipFlakyTest +from reverse_debugging import ReverseDebugging + + +@skipIfMissingImports('avocado.utils') +class ReverseDebugging_X86_64(ReverseDebugging): + + REG_PC = 0x10 + REG_CS = 0x12 + def get_pc(self, g): + return self.get_reg_le(g, self.REG_PC) \ + + self.get_reg_le(g, self.REG_CS) * 0x10 + + @skipFlakyTest("https://gitlab.com/qemu-project/qemu/-/issues/2922") + def test_x86_64_pc(self): + self.set_machine('pc') + # start with BIOS only + self.reverse_debugging() + + +if __name__ == '__main__': + ReverseDebugging.main() diff --git a/tests/functional/x86_64/test_tuxrun.py b/tests/functional/x86_64/test_tuxrun.py new file mode 100755 index 0000000..fcbc62b --- /dev/null +++ b/tests/functional/x86_64/test_tuxrun.py @@ -0,0 +1,36 @@ +#!/usr/bin/env python3 +# +# Functional test that boots known good tuxboot images the same way +# that tuxrun (www.tuxrun.org) does. This tool is used by things like +# the LKFT project to run regression tests on kernels. +# +# Copyright (c) 2023 Linaro Ltd. +# +# Author: +# Alex Bennée +# +# SPDX-License-Identifier: GPL-2.0-or-later + +from qemu_test import Asset +from qemu_test.tuxruntest import TuxRunBaselineTest + +class TuxRunX86Test(TuxRunBaselineTest): + + ASSET_X86_64_KERNEL = Asset( + 'https://storage.tuxboot.com/buildroot/20241119/x86_64/bzImage', + 'f57bfc6553bcd6e0a54aab86095bf642b33b5571d14e3af1731b18c87ed5aef8') + ASSET_X86_64_ROOTFS = Asset( + 'https://storage.tuxboot.com/buildroot/20241119/x86_64/rootfs.ext4.zst', + '4b8b2a99117519c5290e1202cb36eb6c7aaba92b357b5160f5970cf5fb78a751') + + def test_x86_64(self): + self.set_machine('q35') + self.cpu="Nehalem" + self.root='sda' + self.wait_for_shutdown=False + self.common_tuxrun(kernel_asset=self.ASSET_X86_64_KERNEL, + rootfs_asset=self.ASSET_X86_64_ROOTFS, + drive="driver=ide-hd,bus=ide.0,unit=0") + +if __name__ == '__main__': + TuxRunBaselineTest.main() diff --git a/tests/functional/x86_64/test_virtio_balloon.py b/tests/functional/x86_64/test_virtio_balloon.py new file mode 100755 index 0000000..5877b6c --- /dev/null +++ b/tests/functional/x86_64/test_virtio_balloon.py @@ -0,0 +1,178 @@ +#!/usr/bin/env python3 +# +# virtio-balloon tests +# +# This work is licensed under the terms of the GNU GPL, version 2 or +# later. See the COPYING file in the top-level directory. + +import time + +from qemu_test import QemuSystemTest, Asset +from qemu_test import wait_for_console_pattern +from qemu_test import exec_command_and_wait_for_pattern + +UNSET_STATS_VALUE = 18446744073709551615 + + +class VirtioBalloonx86(QemuSystemTest): + + ASSET_KERNEL = Asset( + ('https://archives.fedoraproject.org/pub/archive/fedora/linux/releases' + '/31/Server/x86_64/os/images/pxeboot/vmlinuz'), + 'd4738d03dbbe083ca610d0821d0a8f1488bebbdccef54ce33e3adb35fda00129') + + ASSET_INITRD = Asset( + ('https://archives.fedoraproject.org/pub/archive/fedora/linux/releases' + '/31/Server/x86_64/os/images/pxeboot/initrd.img'), + '277cd6c7adf77c7e63d73bbb2cded8ef9e2d3a2f100000e92ff1f8396513cd8b') + + ASSET_DISKIMAGE = Asset( + ('https://archives.fedoraproject.org/pub/archive/fedora/linux/releases' + '/31/Cloud/x86_64/images/Fedora-Cloud-Base-31-1.9.x86_64.qcow2'), + 'e3c1b309d9203604922d6e255c2c5d098a309c2d46215d8fc026954f3c5c27a0') + + DEFAULT_KERNEL_PARAMS = ('root=/dev/vda1 console=ttyS0 net.ifnames=0 ' + 'rd.rescue quiet') + + def wait_for_console_pattern(self, success_message, vm=None): + wait_for_console_pattern( + self, + success_message, + failure_message="Kernel panic - not syncing", + vm=vm, + ) + + def mount_root(self): + self.wait_for_console_pattern('Entering emergency mode.') + prompt = '# ' + self.wait_for_console_pattern(prompt) + + # Synchronize on virtio-block driver creating the root device + exec_command_and_wait_for_pattern(self, + "while ! (dmesg -c | grep vda:) ; do sleep 1 ; done", + "vda1") + + exec_command_and_wait_for_pattern(self, 'mount /dev/vda1 /sysroot', + prompt) + exec_command_and_wait_for_pattern(self, 'chroot /sysroot', + prompt) + exec_command_and_wait_for_pattern(self, "modprobe virtio-balloon", + prompt) + + def assert_initial_stats(self): + ret = self.vm.qmp('qom-get', + {'path': '/machine/peripheral/balloon', + 'property': 'guest-stats'})['return'] + when = ret.get('last-update') + assert when == 0 + stats = ret.get('stats') + for name, val in stats.items(): + assert val == UNSET_STATS_VALUE + + def assert_running_stats(self, then): + # We told the QEMU to refresh stats every 100ms, but + # there can be a delay between virtio-ballon driver + # being modprobed and seeing the first stats refresh + # Retry a few times for robustness under heavy load + retries = 10 + when = 0 + while when == 0 and retries: + ret = self.vm.qmp('qom-get', + {'path': '/machine/peripheral/balloon', + 'property': 'guest-stats'})['return'] + when = ret.get('last-update') + if when == 0: + retries = retries - 1 + time.sleep(0.5) + + now = time.time() + + assert when > then and when < now + stats = ret.get('stats') + # Stat we expect this particular Kernel to have set + expectData = [ + "stat-available-memory", + "stat-disk-caches", + "stat-free-memory", + "stat-htlb-pgalloc", + "stat-htlb-pgfail", + "stat-major-faults", + "stat-minor-faults", + "stat-swap-in", + "stat-swap-out", + "stat-total-memory", + ] + for name, val in stats.items(): + if name in expectData: + assert val != UNSET_STATS_VALUE + else: + assert val == UNSET_STATS_VALUE + + def test_virtio_balloon_stats(self): + self.set_machine('q35') + self.require_accelerator("kvm") + kernel_path = self.ASSET_KERNEL.fetch() + initrd_path = self.ASSET_INITRD.fetch() + diskimage_path = self.ASSET_DISKIMAGE.fetch() + + self.vm.set_console() + self.vm.add_args("-S") + self.vm.add_args("-cpu", "max") + self.vm.add_args("-m", "2G") + # Slow down BIOS phase with boot menu, so that after a system + # reset, we can reliably catch the clean stats again in BIOS + # phase before the guest OS launches + self.vm.add_args("-boot", "menu=on") + self.vm.add_args("-accel", "kvm") + self.vm.add_args("-device", "virtio-balloon,id=balloon") + self.vm.add_args('-drive', + f'file={diskimage_path},if=none,id=drv0,snapshot=on') + self.vm.add_args('-device', 'virtio-blk-pci,bus=pcie.0,' + + 'drive=drv0,id=virtio-disk0,bootindex=1') + + self.vm.add_args( + "-kernel", + kernel_path, + "-initrd", + initrd_path, + "-append", + self.DEFAULT_KERNEL_PARAMS + ) + self.vm.launch() + + # Poll stats at 100ms + self.vm.qmp('qom-set', + {'path': '/machine/peripheral/balloon', + 'property': 'guest-stats-polling-interval', + 'value': 100 }) + + # We've not run any guest code yet, neither BIOS or guest, + # so stats should be all default values + self.assert_initial_stats() + + self.vm.qmp('cont') + + then = time.time() + self.mount_root() + self.assert_running_stats(then) + + # Race window between these two commands, where we + # rely on '-boot menu=on' to (hopefully) ensure we're + # still executing the BIOS when QEMU processes the + # 'stop', and thus have not loaded the virtio-balloon + # driver in the guest + self.vm.qmp('system_reset') + self.vm.qmp('stop') + + # If the above assumption held, we're in BIOS now and + # stats should be all back at their default values + self.assert_initial_stats() + self.vm.qmp('cont') + + then = time.time() + self.mount_root() + self.assert_running_stats(then) + + +if __name__ == '__main__': + QemuSystemTest.main() diff --git a/tests/functional/x86_64/test_virtio_gpu.py b/tests/functional/x86_64/test_virtio_gpu.py new file mode 100755 index 0000000..be96de2 --- /dev/null +++ b/tests/functional/x86_64/test_virtio_gpu.py @@ -0,0 +1,144 @@ +#!/usr/bin/env python3 +# +# virtio-gpu tests +# +# This work is licensed under the terms of the GNU GPL, version 2 or +# later. See the COPYING file in the top-level directory. + + +from qemu_test import QemuSystemTest, Asset +from qemu_test import wait_for_console_pattern +from qemu_test import exec_command_and_wait_for_pattern +from qemu_test import is_readable_executable_file + + +import os +import socket +import subprocess + + +def pick_default_vug_bin(test): + bld_dir_path = test.build_file("contrib", "vhost-user-gpu", "vhost-user-gpu") + if is_readable_executable_file(bld_dir_path): + return bld_dir_path + + +class VirtioGPUx86(QemuSystemTest): + + KERNEL_COMMAND_LINE = "printk.time=0 console=ttyS0 rdinit=/bin/bash" + ASSET_KERNEL = Asset( + ("https://archives.fedoraproject.org/pub/archive/fedora" + "/linux/releases/33/Everything/x86_64/os/images" + "/pxeboot/vmlinuz"), + '2dc5fb5cfe9ac278fa45640f3602d9b7a08cc189ed63fd9b162b07073e4df397') + ASSET_INITRD = Asset( + ("https://archives.fedoraproject.org/pub/archive/fedora" + "/linux/releases/33/Everything/x86_64/os/images" + "/pxeboot/initrd.img"), + 'c49b97f893a5349e4883452178763e402bdc5caa8845b226a2d1329b5f356045') + + def wait_for_console_pattern(self, success_message, vm=None): + wait_for_console_pattern( + self, + success_message, + failure_message="Kernel panic - not syncing", + vm=vm, + ) + + def test_virtio_vga_virgl(self): + # FIXME: should check presence of virtio, virgl etc + self.require_accelerator('kvm') + + kernel_path = self.ASSET_KERNEL.fetch() + initrd_path = self.ASSET_INITRD.fetch() + + self.vm.set_console() + self.vm.add_args("-cpu", "host") + self.vm.add_args("-m", "2G") + self.vm.add_args("-machine", "pc,accel=kvm") + self.vm.add_args("-device", "virtio-vga-gl") + self.vm.add_args("-display", "egl-headless") + self.vm.add_args( + "-kernel", + kernel_path, + "-initrd", + initrd_path, + "-append", + self.KERNEL_COMMAND_LINE, + ) + try: + self.vm.launch() + except: + # TODO: probably fails because we are missing the VirGL features + self.skipTest("VirGL not enabled?") + + self.wait_for_console_pattern("as init process") + exec_command_and_wait_for_pattern( + self, "/usr/sbin/modprobe virtio_gpu", "features: +virgl +edid" + ) + + def test_vhost_user_vga_virgl(self): + # FIXME: should check presence of vhost-user-gpu, virgl, memfd etc + self.require_accelerator('kvm') + + vug = pick_default_vug_bin(self) + if not vug: + self.skipTest("Could not find vhost-user-gpu") + + kernel_path = self.ASSET_KERNEL.fetch() + initrd_path = self.ASSET_INITRD.fetch() + + # Create socketpair to connect proxy and remote processes + qemu_sock, vug_sock = socket.socketpair( + socket.AF_UNIX, socket.SOCK_STREAM + ) + os.set_inheritable(qemu_sock.fileno(), True) + os.set_inheritable(vug_sock.fileno(), True) + + self._vug_log_path = self.log_file("vhost-user-gpu.log") + self._vug_log_file = open(self._vug_log_path, "wb") + self.log.info('Complete vhost-user-gpu.log file can be ' + 'found at %s', self._vug_log_path) + + vugp = subprocess.Popen( + [vug, "--virgl", "--fd=%d" % vug_sock.fileno()], + stdin=subprocess.DEVNULL, + stdout=self._vug_log_file, + stderr=subprocess.STDOUT, + shell=False, + close_fds=False, + ) + self._vug_log_file.close() + + self.vm.set_console() + self.vm.add_args("-cpu", "host") + self.vm.add_args("-m", "2G") + self.vm.add_args("-object", "memory-backend-memfd,id=mem,size=2G") + self.vm.add_args("-machine", "pc,memory-backend=mem,accel=kvm") + self.vm.add_args("-chardev", "socket,id=vug,fd=%d" % qemu_sock.fileno()) + self.vm.add_args("-device", "vhost-user-vga,chardev=vug") + self.vm.add_args("-display", "egl-headless") + self.vm.add_args( + "-kernel", + kernel_path, + "-initrd", + initrd_path, + "-append", + self.KERNEL_COMMAND_LINE, + ) + try: + self.vm.launch() + except: + # TODO: probably fails because we are missing the VirGL features + self.skipTest("VirGL not enabled?") + self.wait_for_console_pattern("as init process") + exec_command_and_wait_for_pattern(self, "/usr/sbin/modprobe virtio_gpu", + "features: +virgl +edid") + self.vm.shutdown() + qemu_sock.close() + vug_sock.close() + vugp.terminate() + vugp.wait() + +if __name__ == '__main__': + QemuSystemTest.main() diff --git a/tests/functional/x86_64/test_virtio_version.py b/tests/functional/x86_64/test_virtio_version.py new file mode 100755 index 0000000..a5ea732 --- /dev/null +++ b/tests/functional/x86_64/test_virtio_version.py @@ -0,0 +1,177 @@ +#!/usr/bin/env python3 +""" +Check compatibility of virtio device types +""" +# Copyright (c) 2018 Red Hat, Inc. +# +# Author: +# Eduardo Habkost +# +# This work is licensed under the terms of the GNU GPL, version 2 or +# later. See the COPYING file in the top-level directory. + +from qemu.machine import QEMUMachine +from qemu_test import QemuSystemTest + +# Virtio Device IDs: +VIRTIO_NET = 1 +VIRTIO_BLOCK = 2 +VIRTIO_CONSOLE = 3 +VIRTIO_RNG = 4 +VIRTIO_BALLOON = 5 +VIRTIO_RPMSG = 7 +VIRTIO_SCSI = 8 +VIRTIO_9P = 9 +VIRTIO_RPROC_SERIAL = 11 +VIRTIO_CAIF = 12 +VIRTIO_GPU = 16 +VIRTIO_INPUT = 18 +VIRTIO_VSOCK = 19 +VIRTIO_CRYPTO = 20 + +PCI_VENDOR_ID_REDHAT_QUMRANET = 0x1af4 + +# Device IDs for legacy/transitional devices: +PCI_LEGACY_DEVICE_IDS = { + VIRTIO_NET: 0x1000, + VIRTIO_BLOCK: 0x1001, + VIRTIO_BALLOON: 0x1002, + VIRTIO_CONSOLE: 0x1003, + VIRTIO_SCSI: 0x1004, + VIRTIO_RNG: 0x1005, + VIRTIO_9P: 0x1009, + VIRTIO_VSOCK: 0x1012, +} + +def pci_modern_device_id(virtio_devid): + return virtio_devid + 0x1040 + +def devtype_implements(vm, devtype, implements): + return devtype in [d['name'] for d in + vm.cmd('qom-list-types', implements=implements)] + +def get_pci_interfaces(vm, devtype): + interfaces = ('pci-express-device', 'conventional-pci-device') + return [i for i in interfaces if devtype_implements(vm, devtype, i)] + +class VirtioVersionCheck(QemuSystemTest): + """ + Check if virtio-version-specific device types result in the + same device tree created by `disable-modern` and + `disable-legacy`. + """ + + # just in case there are failures, show larger diff: + maxDiff = 4096 + + def run_device(self, devtype, opts=None, machine='pc'): + """ + Run QEMU with `-device DEVTYPE`, return device info from `query-pci` + """ + with QEMUMachine(self.qemu_bin) as vm: + vm.set_machine(machine) + if opts: + devtype += ',' + opts + vm.add_args('-device', '%s,id=devfortest' % (devtype)) + vm.add_args('-S') + vm.launch() + + pcibuses = vm.cmd('query-pci') + alldevs = [dev for bus in pcibuses for dev in bus['devices']] + devfortest = [dev for dev in alldevs + if dev['qdev_id'] == 'devfortest'] + return devfortest[0], get_pci_interfaces(vm, devtype) + + + def assert_devids(self, dev, devid, non_transitional=False): + self.assertEqual(dev['id']['vendor'], PCI_VENDOR_ID_REDHAT_QUMRANET) + self.assertEqual(dev['id']['device'], devid) + if non_transitional: + self.assertTrue(0x1040 <= dev['id']['device'] <= 0x107f) + self.assertGreaterEqual(dev['id']['subsystem'], 0x40) + + def check_all_variants(self, qemu_devtype, virtio_devid): + """Check if a virtio device type and its variants behave as expected""" + # Force modern mode: + dev_modern, _ = self.run_device(qemu_devtype, + 'disable-modern=off,disable-legacy=on') + self.assert_devids(dev_modern, pci_modern_device_id(virtio_devid), + non_transitional=True) + + # -non-transitional device types should be 100% equivalent to + # ,disable-modern=off,disable-legacy=on + dev_1_0, nt_ifaces = self.run_device('%s-non-transitional' % (qemu_devtype)) + self.assertEqual(dev_modern, dev_1_0) + + # Force transitional mode: + dev_trans, _ = self.run_device(qemu_devtype, + 'disable-modern=off,disable-legacy=off') + self.assert_devids(dev_trans, PCI_LEGACY_DEVICE_IDS[virtio_devid]) + + # Force legacy mode: + dev_legacy, _ = self.run_device(qemu_devtype, + 'disable-modern=on,disable-legacy=off') + self.assert_devids(dev_legacy, PCI_LEGACY_DEVICE_IDS[virtio_devid]) + + # No options: default to transitional on PC machine-type: + no_opts_pc, generic_ifaces = self.run_device(qemu_devtype) + self.assertEqual(dev_trans, no_opts_pc) + + #TODO: check if plugging on a PCI Express bus will make the + # device non-transitional + #no_opts_q35 = self.run_device(qemu_devtype, machine='q35') + #self.assertEqual(dev_modern, no_opts_q35) + + # -transitional device types should be 100% equivalent to + # ,disable-modern=off,disable-legacy=off + dev_trans, trans_ifaces = self.run_device('%s-transitional' % (qemu_devtype)) + self.assertEqual(dev_trans, dev_trans) + + # ensure the interface information is correct: + self.assertIn('conventional-pci-device', generic_ifaces) + self.assertIn('pci-express-device', generic_ifaces) + + self.assertIn('conventional-pci-device', nt_ifaces) + self.assertIn('pci-express-device', nt_ifaces) + + self.assertIn('conventional-pci-device', trans_ifaces) + self.assertNotIn('pci-express-device', trans_ifaces) + + + def test_conventional_devs(self): + self.set_machine('pc') + self.check_all_variants('virtio-net-pci', VIRTIO_NET) + # virtio-blk requires 'driver' parameter + #self.check_all_variants('virtio-blk-pci', VIRTIO_BLOCK) + self.check_all_variants('virtio-serial-pci', VIRTIO_CONSOLE) + self.check_all_variants('virtio-rng-pci', VIRTIO_RNG) + self.check_all_variants('virtio-balloon-pci', VIRTIO_BALLOON) + self.check_all_variants('virtio-scsi-pci', VIRTIO_SCSI) + # virtio-9p requires 'fsdev' parameter + #self.check_all_variants('virtio-9p-pci', VIRTIO_9P) + + def check_modern_only(self, qemu_devtype, virtio_devid): + """Check if a modern-only virtio device type behaves as expected""" + # Force modern mode: + dev_modern, _ = self.run_device(qemu_devtype, + 'disable-modern=off,disable-legacy=on') + self.assert_devids(dev_modern, pci_modern_device_id(virtio_devid), + non_transitional=True) + + # No options: should be modern anyway + dev_no_opts, ifaces = self.run_device(qemu_devtype) + self.assertEqual(dev_modern, dev_no_opts) + + self.assertIn('conventional-pci-device', ifaces) + self.assertIn('pci-express-device', ifaces) + + def test_modern_only_devs(self): + self.set_machine('pc') + self.check_modern_only('virtio-vga', VIRTIO_GPU) + self.check_modern_only('virtio-gpu-pci', VIRTIO_GPU) + self.check_modern_only('virtio-mouse-pci', VIRTIO_INPUT) + self.check_modern_only('virtio-tablet-pci', VIRTIO_INPUT) + self.check_modern_only('virtio-keyboard-pci', VIRTIO_INPUT) + +if __name__ == '__main__': + QemuSystemTest.main() -- cgit v1.1 From e365d26e42281aae3dcb47aa63c862892efadb0c Mon Sep 17 00:00:00 2001 From: Thomas Huth Date: Tue, 19 Aug 2025 13:24:00 +0200 Subject: tests/functional: Move xtensa tests into target-specific folder MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The tests/functional folder has become quite crowded, thus move the xtensa tests into a target-specific subfolder. Reviewed-by: Pierrick Bouvier Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Thomas Huth Message-ID: <20250819112403.432587-24-thuth@redhat.com> --- tests/functional/meson.build | 6 +----- tests/functional/test_xtensa_lx60.py | 26 -------------------------- tests/functional/test_xtensa_replay.py | 28 ---------------------------- tests/functional/xtensa/meson.build | 6 ++++++ tests/functional/xtensa/test_lx60.py | 26 ++++++++++++++++++++++++++ tests/functional/xtensa/test_replay.py | 28 ++++++++++++++++++++++++++++ 6 files changed, 61 insertions(+), 59 deletions(-) delete mode 100755 tests/functional/test_xtensa_lx60.py delete mode 100755 tests/functional/test_xtensa_replay.py create mode 100644 tests/functional/xtensa/meson.build create mode 100755 tests/functional/xtensa/test_lx60.py create mode 100755 tests/functional/xtensa/test_replay.py (limited to 'tests') diff --git a/tests/functional/meson.build b/tests/functional/meson.build index 34e3023..b1eec16 100644 --- a/tests/functional/meson.build +++ b/tests/functional/meson.build @@ -35,6 +35,7 @@ subdir('sh4eb') subdir('sparc') subdir('sparc64') subdir('x86_64') +subdir('xtensa') tests_generic_system = [ 'empty_cpu_model', @@ -48,11 +49,6 @@ tests_generic_linuxuser = [ tests_generic_bsduser = [ ] -tests_xtensa_system_thorough = [ - 'xtensa_lx60', - 'xtensa_replay', -] - precache_all = [] foreach speed : ['quick', 'thorough'] foreach dir : target_dirs diff --git a/tests/functional/test_xtensa_lx60.py b/tests/functional/test_xtensa_lx60.py deleted file mode 100755 index 147c920..0000000 --- a/tests/functional/test_xtensa_lx60.py +++ /dev/null @@ -1,26 +0,0 @@ -#!/usr/bin/env python3 -# -# Functional test that boots a Linux kernel on an xtensa lx650 machine -# and checks the console -# -# SPDX-License-Identifier: GPL-2.0-or-later - -from qemu_test import LinuxKernelTest, Asset - - -class XTensaLX60Test(LinuxKernelTest): - - ASSET_DAY02 = Asset( - 'https://qemu-advcal.gitlab.io/qac-best-of-multiarch/download/day02.tar.xz', - '68ff07f9b3fd3df36d015eb46299ba44748e94bfbb2d5295fddc1a8d4a9fd324') - - def test_xtensa_lx60(self): - self.set_machine('lx60') - self.cpu = 'dc233c' - self.archive_extract(self.ASSET_DAY02) - self.launch_kernel(self.scratch_file('day02', - 'santas-sleigh-ride.elf'), - wait_for='QEMU advent calendar') - -if __name__ == '__main__': - LinuxKernelTest.main() diff --git a/tests/functional/test_xtensa_replay.py b/tests/functional/test_xtensa_replay.py deleted file mode 100755 index eb00a3b..0000000 --- a/tests/functional/test_xtensa_replay.py +++ /dev/null @@ -1,28 +0,0 @@ -#!/usr/bin/env python3 -# -# Replay test that boots a Linux kernel on an xtensa lx650 machine -# and checks the console -# -# SPDX-License-Identifier: GPL-2.0-or-later - -from qemu_test import Asset -from replay_kernel import ReplayKernelBase - - -class XTensaReplay(ReplayKernelBase): - - ASSET_DAY02 = Asset( - 'https://qemu-advcal.gitlab.io/qac-best-of-multiarch/download/day02.tar.xz', - '68ff07f9b3fd3df36d015eb46299ba44748e94bfbb2d5295fddc1a8d4a9fd324') - - def test_replay(self): - self.set_machine('lx60') - self.cpu = 'dc233c' - kernel_path = self.archive_extract(self.ASSET_DAY02, - member='day02/santas-sleigh-ride.elf') - self.run_rr(kernel_path, self.REPLAY_KERNEL_COMMAND_LINE, - 'QEMU advent calendar') - - -if __name__ == '__main__': - ReplayKernelBase.main() diff --git a/tests/functional/xtensa/meson.build b/tests/functional/xtensa/meson.build new file mode 100644 index 0000000..d61d82a --- /dev/null +++ b/tests/functional/xtensa/meson.build @@ -0,0 +1,6 @@ +# SPDX-License-Identifier: GPL-2.0-or-later + +tests_xtensa_system_thorough = [ + 'lx60', + 'replay', +] diff --git a/tests/functional/xtensa/test_lx60.py b/tests/functional/xtensa/test_lx60.py new file mode 100755 index 0000000..147c920 --- /dev/null +++ b/tests/functional/xtensa/test_lx60.py @@ -0,0 +1,26 @@ +#!/usr/bin/env python3 +# +# Functional test that boots a Linux kernel on an xtensa lx650 machine +# and checks the console +# +# SPDX-License-Identifier: GPL-2.0-or-later + +from qemu_test import LinuxKernelTest, Asset + + +class XTensaLX60Test(LinuxKernelTest): + + ASSET_DAY02 = Asset( + 'https://qemu-advcal.gitlab.io/qac-best-of-multiarch/download/day02.tar.xz', + '68ff07f9b3fd3df36d015eb46299ba44748e94bfbb2d5295fddc1a8d4a9fd324') + + def test_xtensa_lx60(self): + self.set_machine('lx60') + self.cpu = 'dc233c' + self.archive_extract(self.ASSET_DAY02) + self.launch_kernel(self.scratch_file('day02', + 'santas-sleigh-ride.elf'), + wait_for='QEMU advent calendar') + +if __name__ == '__main__': + LinuxKernelTest.main() diff --git a/tests/functional/xtensa/test_replay.py b/tests/functional/xtensa/test_replay.py new file mode 100755 index 0000000..eb00a3b --- /dev/null +++ b/tests/functional/xtensa/test_replay.py @@ -0,0 +1,28 @@ +#!/usr/bin/env python3 +# +# Replay test that boots a Linux kernel on an xtensa lx650 machine +# and checks the console +# +# SPDX-License-Identifier: GPL-2.0-or-later + +from qemu_test import Asset +from replay_kernel import ReplayKernelBase + + +class XTensaReplay(ReplayKernelBase): + + ASSET_DAY02 = Asset( + 'https://qemu-advcal.gitlab.io/qac-best-of-multiarch/download/day02.tar.xz', + '68ff07f9b3fd3df36d015eb46299ba44748e94bfbb2d5295fddc1a8d4a9fd324') + + def test_replay(self): + self.set_machine('lx60') + self.cpu = 'dc233c' + kernel_path = self.archive_extract(self.ASSET_DAY02, + member='day02/santas-sleigh-ride.elf') + self.run_rr(kernel_path, self.REPLAY_KERNEL_COMMAND_LINE, + 'QEMU advent calendar') + + +if __name__ == '__main__': + ReplayKernelBase.main() -- cgit v1.1 From 0137f60b37c5678e9fa4971fd7e4f07afed33294 Mon Sep 17 00:00:00 2001 From: Thomas Huth Date: Tue, 19 Aug 2025 13:24:01 +0200 Subject: tests/functional: Move the generic tests to a subfolder This also removes the line for using tests from the main folder since we do not have any tests left here. And while we're at it, also mark the vnc test as generic now since it is not specific to x86. Reviewed-by: Pierrick Bouvier Signed-off-by: Thomas Huth Message-ID: <20250819112403.432587-25-thuth@redhat.com> --- tests/functional/generic/meson.build | 14 +++ tests/functional/generic/test_empty_cpu_model.py | 24 +++++ tests/functional/generic/test_info_usernet.py | 34 +++++++ tests/functional/generic/test_version.py | 28 ++++++ tests/functional/generic/test_vnc.py | 116 +++++++++++++++++++++++ tests/functional/meson.build | 17 +--- tests/functional/test_empty_cpu_model.py | 24 ----- tests/functional/test_info_usernet.py | 34 ------- tests/functional/test_version.py | 28 ------ tests/functional/test_vnc.py | 116 ----------------------- tests/functional/x86_64/meson.build | 1 - 11 files changed, 218 insertions(+), 218 deletions(-) create mode 100644 tests/functional/generic/meson.build create mode 100755 tests/functional/generic/test_empty_cpu_model.py create mode 100755 tests/functional/generic/test_info_usernet.py create mode 100755 tests/functional/generic/test_version.py create mode 100755 tests/functional/generic/test_vnc.py delete mode 100755 tests/functional/test_empty_cpu_model.py delete mode 100755 tests/functional/test_info_usernet.py delete mode 100755 tests/functional/test_version.py delete mode 100755 tests/functional/test_vnc.py (limited to 'tests') diff --git a/tests/functional/generic/meson.build b/tests/functional/generic/meson.build new file mode 100644 index 0000000..013cc96 --- /dev/null +++ b/tests/functional/generic/meson.build @@ -0,0 +1,14 @@ +# SPDX-License-Identifier: GPL-2.0-or-later + +tests_generic_system = [ + 'empty_cpu_model', + 'info_usernet', + 'version', + 'vnc', +] + +tests_generic_linuxuser = [ +] + +tests_generic_bsduser = [ +] diff --git a/tests/functional/generic/test_empty_cpu_model.py b/tests/functional/generic/test_empty_cpu_model.py new file mode 100755 index 0000000..0081b06 --- /dev/null +++ b/tests/functional/generic/test_empty_cpu_model.py @@ -0,0 +1,24 @@ +#!/usr/bin/env python3 +# +# Check for crash when using empty -cpu option +# +# Copyright (c) 2019 Red Hat, Inc. +# +# Author: +# Eduardo Habkost +# +# This work is licensed under the terms of the GNU GPL, version 2 or +# later. See the COPYING file in the top-level directory. +from qemu_test import QemuSystemTest + +class EmptyCPUModel(QemuSystemTest): + def test(self): + self.vm.add_args('-S', '-display', 'none', '-machine', 'none', '-cpu', '') + self.vm.set_qmp_monitor(enabled=False) + self.vm.launch() + self.vm.wait() + self.assertEqual(self.vm.exitcode(), 1, "QEMU exit code should be 1") + self.assertRegex(self.vm.get_log(), r'-cpu option cannot be empty') + +if __name__ == '__main__': + QemuSystemTest.main() diff --git a/tests/functional/generic/test_info_usernet.py b/tests/functional/generic/test_info_usernet.py new file mode 100755 index 0000000..e8cbc37 --- /dev/null +++ b/tests/functional/generic/test_info_usernet.py @@ -0,0 +1,34 @@ +#!/usr/bin/env python3 +# +# Test for the hmp command "info usernet" +# +# Copyright (c) 2021 Red Hat, Inc. +# +# Author: +# Cleber Rosa +# +# This work is licensed under the terms of the GNU GPL, version 2 or +# later. See the COPYING file in the top-level directory. + +from qemu_test import QemuSystemTest +from qemu_test.utils import get_usernet_hostfwd_port + + +class InfoUsernet(QemuSystemTest): + + def test_hostfwd(self): + self.require_netdev('user') + self.set_machine('none') + self.vm.add_args('-netdev', 'user,id=vnet,hostfwd=:127.0.0.1:0-:22') + self.vm.launch() + + port = get_usernet_hostfwd_port(self.vm) + self.assertIsNotNone(port, + ('"info usernet" output content does not seem to ' + 'contain the redirected port')) + self.assertGreater(port, 0, + ('Found a redirected port that is not greater than' + ' zero')) + +if __name__ == '__main__': + QemuSystemTest.main() diff --git a/tests/functional/generic/test_version.py b/tests/functional/generic/test_version.py new file mode 100755 index 0000000..3ab3b67 --- /dev/null +++ b/tests/functional/generic/test_version.py @@ -0,0 +1,28 @@ +#!/usr/bin/env python3 +# +# Version check example test +# +# Copyright (c) 2018 Red Hat, Inc. +# +# Author: +# Cleber Rosa +# +# This work is licensed under the terms of the GNU GPL, version 2 or +# later. See the COPYING file in the top-level directory. + + +from qemu_test import QemuSystemTest + + +class Version(QemuSystemTest): + + def test_qmp_human_info_version(self): + self.set_machine('none') + self.vm.add_args('-nodefaults') + self.vm.launch() + res = self.vm.cmd('human-monitor-command', + command_line='info version') + self.assertRegex(res, r'^(\d+\.\d+\.\d)') + +if __name__ == '__main__': + QemuSystemTest.main() diff --git a/tests/functional/generic/test_vnc.py b/tests/functional/generic/test_vnc.py new file mode 100755 index 0000000..f1dd159 --- /dev/null +++ b/tests/functional/generic/test_vnc.py @@ -0,0 +1,116 @@ +#!/usr/bin/env python3 +# +# Simple functional tests for VNC functionality +# +# Copyright (c) 2018 Red Hat, Inc. +# +# Author: +# Cleber Rosa +# +# This work is licensed under the terms of the GNU GPL, version 2 or +# later. See the COPYING file in the top-level directory. + +import socket + +from qemu.machine.machine import VMLaunchFailure +from qemu_test import QemuSystemTest +from qemu_test.ports import Ports + + +VNC_ADDR = '127.0.0.1' + +def check_connect(port: int) -> bool: + with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock: + try: + sock.connect((VNC_ADDR, port)) + except ConnectionRefusedError: + return False + + return True + +class Vnc(QemuSystemTest): + + def test_no_vnc_change_password(self): + self.set_machine('none') + self.vm.add_args('-nodefaults', '-S') + self.vm.launch() + + query_vnc_response = self.vm.qmp('query-vnc') + if 'error' in query_vnc_response: + self.assertEqual(query_vnc_response['error']['class'], + 'CommandNotFound') + self.skipTest('VNC support not available') + self.assertFalse(query_vnc_response['return']['enabled']) + + set_password_response = self.vm.qmp('change-vnc-password', + password='new_password') + self.assertIn('error', set_password_response) + self.assertEqual(set_password_response['error']['class'], + 'GenericError') + self.assertEqual(set_password_response['error']['desc'], + 'Could not set password') + + def launch_guarded(self): + try: + self.vm.launch() + except VMLaunchFailure as excp: + if "-vnc: invalid option" in excp.output: + self.skipTest("VNC support not available") + elif "Cipher backend does not support DES algorithm" in excp.output: + self.skipTest("No cryptographic backend available") + else: + self.log.info("unhandled launch failure: %s", excp.output) + raise excp + + def test_change_password_requires_a_password(self): + self.set_machine('none') + self.vm.add_args('-nodefaults', '-S', '-vnc', ':1,to=999') + self.launch_guarded() + self.assertTrue(self.vm.qmp('query-vnc')['return']['enabled']) + set_password_response = self.vm.qmp('change-vnc-password', + password='new_password') + self.assertIn('error', set_password_response) + self.assertEqual(set_password_response['error']['class'], + 'GenericError') + self.assertEqual(set_password_response['error']['desc'], + 'Could not set password') + + def test_change_password(self): + self.set_machine('none') + self.vm.add_args('-nodefaults', '-S', '-vnc', ':1,to=999,password=on') + self.launch_guarded() + self.assertTrue(self.vm.qmp('query-vnc')['return']['enabled']) + self.vm.cmd('change-vnc-password', + password='new_password') + + def do_test_change_listen(self, a, b, c): + self.assertFalse(check_connect(a)) + self.assertFalse(check_connect(b)) + self.assertFalse(check_connect(c)) + + self.vm.add_args('-nodefaults', '-S', '-vnc', f'{VNC_ADDR}:{a - 5900}') + self.launch_guarded() + self.assertEqual(self.vm.qmp('query-vnc')['return']['service'], str(a)) + self.assertTrue(check_connect(a)) + self.assertFalse(check_connect(b)) + self.assertFalse(check_connect(c)) + + self.vm.cmd('display-update', type='vnc', + addresses=[{'type': 'inet', 'host': VNC_ADDR, + 'port': str(b)}, + {'type': 'inet', 'host': VNC_ADDR, + 'port': str(c)}]) + self.assertEqual(self.vm.qmp('query-vnc')['return']['service'], str(b)) + self.assertFalse(check_connect(a)) + self.assertTrue(check_connect(b)) + self.assertTrue(check_connect(c)) + + def test_change_listen(self): + self.set_machine('none') + with Ports() as ports: + a, b, c = ports.find_free_ports(3) + self.do_test_change_listen(a, b, c) + + +if __name__ == '__main__': + QemuSystemTest.main() diff --git a/tests/functional/meson.build b/tests/functional/meson.build index b1eec16..2a0c5aa 100644 --- a/tests/functional/meson.build +++ b/tests/functional/meson.build @@ -36,18 +36,7 @@ subdir('sparc') subdir('sparc64') subdir('x86_64') subdir('xtensa') - -tests_generic_system = [ - 'empty_cpu_model', - 'info_usernet', - 'version', -] - -tests_generic_linuxuser = [ -] - -tests_generic_bsduser = [ -] +subdir('generic') precache_all = [] foreach speed : ['quick', 'thorough'] @@ -90,9 +79,7 @@ foreach speed : ['quick', 'thorough'] foreach test : target_tests testname = '@0@-@1@'.format(target_base, test) - if fs.exists('test_' + test + '.py') - testfile = 'test_' + test + '.py' - elif fs.exists('generic' / 'test_' + test + '.py') + if fs.exists('generic' / 'test_' + test + '.py') testfile = 'generic' / 'test_' + test + '.py' else testfile = target_base / 'test_' + test + '.py' diff --git a/tests/functional/test_empty_cpu_model.py b/tests/functional/test_empty_cpu_model.py deleted file mode 100755 index 0081b06..0000000 --- a/tests/functional/test_empty_cpu_model.py +++ /dev/null @@ -1,24 +0,0 @@ -#!/usr/bin/env python3 -# -# Check for crash when using empty -cpu option -# -# Copyright (c) 2019 Red Hat, Inc. -# -# Author: -# Eduardo Habkost -# -# This work is licensed under the terms of the GNU GPL, version 2 or -# later. See the COPYING file in the top-level directory. -from qemu_test import QemuSystemTest - -class EmptyCPUModel(QemuSystemTest): - def test(self): - self.vm.add_args('-S', '-display', 'none', '-machine', 'none', '-cpu', '') - self.vm.set_qmp_monitor(enabled=False) - self.vm.launch() - self.vm.wait() - self.assertEqual(self.vm.exitcode(), 1, "QEMU exit code should be 1") - self.assertRegex(self.vm.get_log(), r'-cpu option cannot be empty') - -if __name__ == '__main__': - QemuSystemTest.main() diff --git a/tests/functional/test_info_usernet.py b/tests/functional/test_info_usernet.py deleted file mode 100755 index e8cbc37..0000000 --- a/tests/functional/test_info_usernet.py +++ /dev/null @@ -1,34 +0,0 @@ -#!/usr/bin/env python3 -# -# Test for the hmp command "info usernet" -# -# Copyright (c) 2021 Red Hat, Inc. -# -# Author: -# Cleber Rosa -# -# This work is licensed under the terms of the GNU GPL, version 2 or -# later. See the COPYING file in the top-level directory. - -from qemu_test import QemuSystemTest -from qemu_test.utils import get_usernet_hostfwd_port - - -class InfoUsernet(QemuSystemTest): - - def test_hostfwd(self): - self.require_netdev('user') - self.set_machine('none') - self.vm.add_args('-netdev', 'user,id=vnet,hostfwd=:127.0.0.1:0-:22') - self.vm.launch() - - port = get_usernet_hostfwd_port(self.vm) - self.assertIsNotNone(port, - ('"info usernet" output content does not seem to ' - 'contain the redirected port')) - self.assertGreater(port, 0, - ('Found a redirected port that is not greater than' - ' zero')) - -if __name__ == '__main__': - QemuSystemTest.main() diff --git a/tests/functional/test_version.py b/tests/functional/test_version.py deleted file mode 100755 index 3ab3b67..0000000 --- a/tests/functional/test_version.py +++ /dev/null @@ -1,28 +0,0 @@ -#!/usr/bin/env python3 -# -# Version check example test -# -# Copyright (c) 2018 Red Hat, Inc. -# -# Author: -# Cleber Rosa -# -# This work is licensed under the terms of the GNU GPL, version 2 or -# later. See the COPYING file in the top-level directory. - - -from qemu_test import QemuSystemTest - - -class Version(QemuSystemTest): - - def test_qmp_human_info_version(self): - self.set_machine('none') - self.vm.add_args('-nodefaults') - self.vm.launch() - res = self.vm.cmd('human-monitor-command', - command_line='info version') - self.assertRegex(res, r'^(\d+\.\d+\.\d)') - -if __name__ == '__main__': - QemuSystemTest.main() diff --git a/tests/functional/test_vnc.py b/tests/functional/test_vnc.py deleted file mode 100755 index f1dd159..0000000 --- a/tests/functional/test_vnc.py +++ /dev/null @@ -1,116 +0,0 @@ -#!/usr/bin/env python3 -# -# Simple functional tests for VNC functionality -# -# Copyright (c) 2018 Red Hat, Inc. -# -# Author: -# Cleber Rosa -# -# This work is licensed under the terms of the GNU GPL, version 2 or -# later. See the COPYING file in the top-level directory. - -import socket - -from qemu.machine.machine import VMLaunchFailure -from qemu_test import QemuSystemTest -from qemu_test.ports import Ports - - -VNC_ADDR = '127.0.0.1' - -def check_connect(port: int) -> bool: - with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock: - try: - sock.connect((VNC_ADDR, port)) - except ConnectionRefusedError: - return False - - return True - -class Vnc(QemuSystemTest): - - def test_no_vnc_change_password(self): - self.set_machine('none') - self.vm.add_args('-nodefaults', '-S') - self.vm.launch() - - query_vnc_response = self.vm.qmp('query-vnc') - if 'error' in query_vnc_response: - self.assertEqual(query_vnc_response['error']['class'], - 'CommandNotFound') - self.skipTest('VNC support not available') - self.assertFalse(query_vnc_response['return']['enabled']) - - set_password_response = self.vm.qmp('change-vnc-password', - password='new_password') - self.assertIn('error', set_password_response) - self.assertEqual(set_password_response['error']['class'], - 'GenericError') - self.assertEqual(set_password_response['error']['desc'], - 'Could not set password') - - def launch_guarded(self): - try: - self.vm.launch() - except VMLaunchFailure as excp: - if "-vnc: invalid option" in excp.output: - self.skipTest("VNC support not available") - elif "Cipher backend does not support DES algorithm" in excp.output: - self.skipTest("No cryptographic backend available") - else: - self.log.info("unhandled launch failure: %s", excp.output) - raise excp - - def test_change_password_requires_a_password(self): - self.set_machine('none') - self.vm.add_args('-nodefaults', '-S', '-vnc', ':1,to=999') - self.launch_guarded() - self.assertTrue(self.vm.qmp('query-vnc')['return']['enabled']) - set_password_response = self.vm.qmp('change-vnc-password', - password='new_password') - self.assertIn('error', set_password_response) - self.assertEqual(set_password_response['error']['class'], - 'GenericError') - self.assertEqual(set_password_response['error']['desc'], - 'Could not set password') - - def test_change_password(self): - self.set_machine('none') - self.vm.add_args('-nodefaults', '-S', '-vnc', ':1,to=999,password=on') - self.launch_guarded() - self.assertTrue(self.vm.qmp('query-vnc')['return']['enabled']) - self.vm.cmd('change-vnc-password', - password='new_password') - - def do_test_change_listen(self, a, b, c): - self.assertFalse(check_connect(a)) - self.assertFalse(check_connect(b)) - self.assertFalse(check_connect(c)) - - self.vm.add_args('-nodefaults', '-S', '-vnc', f'{VNC_ADDR}:{a - 5900}') - self.launch_guarded() - self.assertEqual(self.vm.qmp('query-vnc')['return']['service'], str(a)) - self.assertTrue(check_connect(a)) - self.assertFalse(check_connect(b)) - self.assertFalse(check_connect(c)) - - self.vm.cmd('display-update', type='vnc', - addresses=[{'type': 'inet', 'host': VNC_ADDR, - 'port': str(b)}, - {'type': 'inet', 'host': VNC_ADDR, - 'port': str(c)}]) - self.assertEqual(self.vm.qmp('query-vnc')['return']['service'], str(b)) - self.assertFalse(check_connect(a)) - self.assertTrue(check_connect(b)) - self.assertTrue(check_connect(c)) - - def test_change_listen(self): - self.set_machine('none') - with Ports() as ports: - a, b, c = ports.find_free_ports(3) - self.do_test_change_listen(a, b, c) - - -if __name__ == '__main__': - QemuSystemTest.main() diff --git a/tests/functional/x86_64/meson.build b/tests/functional/x86_64/meson.build index 696a9ec..d0b4667 100644 --- a/tests/functional/x86_64/meson.build +++ b/tests/functional/x86_64/meson.build @@ -16,7 +16,6 @@ tests_x86_64_system_quick = [ 'migration', 'pc_cpu_hotplug_props', 'virtio_version', - 'vnc', 'memlock', ] -- cgit v1.1 From 0ac3c314130eff8e3ea9860fe3202908a7746225 Mon Sep 17 00:00:00 2001 From: Gustavo Romero Date: Tue, 19 Aug 2025 14:39:15 +0000 Subject: tests/functional: Mark main in QemuBaseTest class as a static method MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The main() method in the QemuBaseTest class has no parameters but is defined as a regular method. Currently, this does not cause any issues because in the functional tests main() is always called directly from QemuBaseTest (never from instances), but the way this method is defined makes its signature wrong, implying a 'self'. Hence, it's best practice to define such a method as a static method, so decorate it with @staticmethod. Signed-off-by: Gustavo Romero Message-ID: <20250819143916.4138035-4-gustavo.romero@linaro.org> Reviewed-by: Daniel P. Berrangé Signed-off-by: Thomas Huth --- tests/functional/qemu_test/testcase.py | 1 + 1 file changed, 1 insertion(+) (limited to 'tests') diff --git a/tests/functional/qemu_test/testcase.py b/tests/functional/qemu_test/testcase.py index 5caf7b1..fbeb171 100644 --- a/tests/functional/qemu_test/testcase.py +++ b/tests/functional/qemu_test/testcase.py @@ -235,6 +235,7 @@ class QemuBaseTest(unittest.TestCase): self.log.removeHandler(self._log_fh) self._log_fh.close() + @staticmethod def main(): warnings.simplefilter("default") os.environ["PYTHONWARNINGS"] = "default" -- cgit v1.1