aboutsummaryrefslogtreecommitdiff
path: root/tests/functional
diff options
context:
space:
mode:
Diffstat (limited to 'tests/functional')
-rw-r--r--tests/functional/aarch64/meson.build49
-rwxr-xr-xtests/functional/aarch64/test_aspeed_ast2700.py (renamed from tests/functional/test_aarch64_aspeed_ast2700.py)56
-rwxr-xr-xtests/functional/aarch64/test_aspeed_ast2700fc.py (renamed from tests/functional/test_aarch64_aspeed_ast2700fc.py)64
-rwxr-xr-xtests/functional/aarch64/test_device_passthrough.py149
-rwxr-xr-xtests/functional/aarch64/test_hotplug_pci.py72
-rwxr-xr-xtests/functional/aarch64/test_imx8mp_evk.py (renamed from tests/functional/test_aarch64_imx8mp_evk.py)1
-rwxr-xr-xtests/functional/aarch64/test_kvm.py69
-rwxr-xr-xtests/functional/aarch64/test_migration.py26
-rwxr-xr-xtests/functional/aarch64/test_multiprocess.py31
-rwxr-xr-xtests/functional/aarch64/test_raspi3.py (renamed from tests/functional/test_aarch64_raspi3.py)0
-rwxr-xr-xtests/functional/aarch64/test_raspi4.py (renamed from tests/functional/test_aarch64_raspi4.py)0
-rwxr-xr-xtests/functional/aarch64/test_replay.py (renamed from tests/functional/test_aarch64_replay.py)0
-rwxr-xr-xtests/functional/aarch64/test_reverse_debug.py (renamed from tests/functional/test_aarch64_reverse_debug.py)18
-rwxr-xr-xtests/functional/aarch64/test_rme_sbsaref.py76
-rwxr-xr-xtests/functional/aarch64/test_rme_virt.py76
-rwxr-xr-xtests/functional/aarch64/test_sbsaref.py (renamed from tests/functional/test_aarch64_sbsaref.py)5
-rwxr-xr-xtests/functional/aarch64/test_sbsaref_alpine.py (renamed from tests/functional/test_aarch64_sbsaref_alpine.py)11
-rwxr-xr-xtests/functional/aarch64/test_sbsaref_freebsd.py (renamed from tests/functional/test_aarch64_sbsaref_freebsd.py)13
-rwxr-xr-xtests/functional/aarch64/test_smmu.py (renamed from tests/functional/test_aarch64_smmu.py)12
-rwxr-xr-xtests/functional/aarch64/test_tcg_plugins.py (renamed from tests/functional/test_aarch64_tcg_plugins.py)0
-rwxr-xr-xtests/functional/aarch64/test_tuxrun.py (renamed from tests/functional/test_aarch64_tuxrun.py)0
-rwxr-xr-xtests/functional/aarch64/test_virt.py (renamed from tests/functional/test_aarch64_virt.py)9
-rwxr-xr-xtests/functional/aarch64/test_virt_gpu.py (renamed from tests/functional/test_aarch64_virt_gpu.py)10
-rwxr-xr-xtests/functional/aarch64/test_xen.py (renamed from tests/functional/test_aarch64_xen.py)13
-rwxr-xr-xtests/functional/aarch64/test_xlnx_versal.py (renamed from tests/functional/test_aarch64_xlnx_versal.py)12
-rw-r--r--tests/functional/alpha/meson.build10
-rwxr-xr-xtests/functional/alpha/test_clipper.py (renamed from tests/functional/test_alpha_clipper.py)1
-rwxr-xr-xtests/functional/alpha/test_migration.py26
-rwxr-xr-xtests/functional/alpha/test_replay.py (renamed from tests/functional/test_alpha_replay.py)0
-rw-r--r--tests/functional/arm/meson.build64
-rwxr-xr-xtests/functional/arm/test_aspeed_ast1030.py (renamed from tests/functional/test_arm_aspeed_ast1030.py)36
-rwxr-xr-xtests/functional/arm/test_aspeed_ast2500.py (renamed from tests/functional/test_arm_aspeed_ast2500.py)8
-rwxr-xr-xtests/functional/arm/test_aspeed_ast2600_buildroot.py (renamed from tests/functional/test_arm_aspeed_ast2600.py)55
-rwxr-xr-xtests/functional/arm/test_aspeed_ast2600_sdk.py94
-rwxr-xr-x[-rw-r--r--]tests/functional/arm/test_aspeed_bletchley.py (renamed from tests/functional/test_arm_aspeed_bletchley.py)0
-rwxr-xr-xtests/functional/arm/test_aspeed_catalina.py25
-rwxr-xr-xtests/functional/arm/test_aspeed_gb200nvl_bmc.py26
-rwxr-xr-xtests/functional/arm/test_aspeed_palmetto.py (renamed from tests/functional/test_arm_aspeed_palmetto.py)0
-rwxr-xr-xtests/functional/arm/test_aspeed_rainier.py (renamed from tests/functional/test_arm_aspeed_rainier.py)0
-rwxr-xr-xtests/functional/arm/test_aspeed_romulus.py (renamed from tests/functional/test_arm_aspeed_romulus.py)0
-rwxr-xr-x[-rw-r--r--]tests/functional/arm/test_aspeed_witherspoon.py (renamed from tests/functional/test_arm_aspeed_witherspoon.py)0
-rwxr-xr-xtests/functional/arm/test_bflt.py (renamed from tests/functional/test_arm_bflt.py)0
-rwxr-xr-xtests/functional/arm/test_bpim2u.py (renamed from tests/functional/test_arm_bpim2u.py)0
-rwxr-xr-xtests/functional/arm/test_canona1100.py (renamed from tests/functional/test_arm_canona1100.py)0
-rwxr-xr-xtests/functional/arm/test_collie.py (renamed from tests/functional/test_arm_collie.py)0
-rwxr-xr-xtests/functional/arm/test_cubieboard.py (renamed from tests/functional/test_arm_cubieboard.py)0
-rwxr-xr-xtests/functional/arm/test_emcraft_sf2.py (renamed from tests/functional/test_arm_emcraft_sf2.py)0
-rwxr-xr-xtests/functional/arm/test_integratorcp.py (renamed from tests/functional/test_arm_integratorcp.py)9
-rwxr-xr-xtests/functional/arm/test_max78000fthr.py48
-rwxr-xr-xtests/functional/arm/test_microbit.py (renamed from tests/functional/test_arm_microbit.py)0
-rwxr-xr-xtests/functional/arm/test_migration.py26
-rwxr-xr-xtests/functional/arm/test_orangepi.py (renamed from tests/functional/test_arm_orangepi.py)0
-rwxr-xr-xtests/functional/arm/test_quanta_gsj.py (renamed from tests/functional/test_arm_quanta_gsj.py)0
-rwxr-xr-xtests/functional/arm/test_raspi2.py (renamed from tests/functional/test_arm_raspi2.py)0
-rwxr-xr-xtests/functional/arm/test_realview.py47
-rwxr-xr-xtests/functional/arm/test_replay.py (renamed from tests/functional/test_arm_replay.py)0
-rwxr-xr-xtests/functional/arm/test_smdkc210.py (renamed from tests/functional/test_arm_smdkc210.py)0
-rwxr-xr-xtests/functional/arm/test_stellaris.py48
-rwxr-xr-xtests/functional/arm/test_sx1.py (renamed from tests/functional/test_arm_sx1.py)0
-rwxr-xr-xtests/functional/arm/test_tuxrun.py (renamed from tests/functional/test_arm_tuxrun.py)0
-rwxr-xr-xtests/functional/arm/test_vexpress.py (renamed from tests/functional/test_arm_vexpress.py)0
-rwxr-xr-xtests/functional/arm/test_virt.py (renamed from tests/functional/test_arm_virt.py)0
-rw-r--r--tests/functional/aspeed.py17
-rw-r--r--tests/functional/avr/meson.build6
-rwxr-xr-xtests/functional/avr/test_mega2560.py (renamed from tests/functional/test_avr_mega2560.py)11
-rwxr-xr-xtests/functional/avr/test_uno.py32
-rw-r--r--tests/functional/generic/meson.build14
-rwxr-xr-xtests/functional/generic/test_empty_cpu_model.py (renamed from tests/functional/test_empty_cpu_model.py)0
-rwxr-xr-xtests/functional/generic/test_info_usernet.py (renamed from tests/functional/test_info_usernet.py)0
-rwxr-xr-xtests/functional/generic/test_version.py (renamed from tests/functional/test_version.py)0
-rwxr-xr-xtests/functional/generic/test_vmstate.py67
-rwxr-xr-xtests/functional/generic/test_vnc.py (renamed from tests/functional/test_vnc.py)4
-rw-r--r--tests/functional/hppa/meson.build9
-rwxr-xr-xtests/functional/hppa/test_cdboot.py38
-rwxr-xr-xtests/functional/hppa/test_seabios.py (renamed from tests/functional/test_hppa_seabios.py)0
-rw-r--r--tests/functional/i386/meson.build10
-rwxr-xr-xtests/functional/i386/test_migration.py26
-rwxr-xr-xtests/functional/i386/test_replay.py (renamed from tests/functional/test_i386_replay.py)1
-rwxr-xr-xtests/functional/i386/test_tuxrun.py (renamed from tests/functional/test_i386_tuxrun.py)0
-rw-r--r--tests/functional/loongarch64/meson.build5
-rwxr-xr-xtests/functional/loongarch64/test_virt.py (renamed from tests/functional/test_loongarch64_virt.py)0
-rw-r--r--tests/functional/m68k/meson.build13
-rwxr-xr-xtests/functional/m68k/test_mcf5208evb.py (renamed from tests/functional/test_m68k_mcf5208evb.py)0
-rwxr-xr-xtests/functional/m68k/test_nextcube.py (renamed from tests/functional/test_m68k_nextcube.py)26
-rwxr-xr-xtests/functional/m68k/test_q800.py (renamed from tests/functional/test_m68k_q800.py)3
-rwxr-xr-xtests/functional/m68k/test_replay.py (renamed from tests/functional/test_m68k_replay.py)3
-rwxr-xr-xtests/functional/m68k/test_tuxrun.py (renamed from tests/functional/test_m68k_tuxrun.py)0
-rw-r--r--tests/functional/meson.build377
-rw-r--r--tests/functional/microblaze/meson.build6
-rwxr-xr-xtests/functional/microblaze/test_replay.py (renamed from tests/functional/test_microblaze_replay.py)0
-rwxr-xr-xtests/functional/microblaze/test_s3adsp1800.py (renamed from tests/functional/test_microblaze_s3adsp1800.py)18
-rw-r--r--tests/functional/microblazeel/meson.build5
-rwxr-xr-xtests/functional/microblazeel/test_s3adsp1800.py (renamed from tests/functional/test_microblazeel_s3adsp1800.py)8
-rw-r--r--[-rwxr-xr-x]tests/functional/migration.py (renamed from tests/functional/test_migration.py)39
-rw-r--r--tests/functional/mips/meson.build11
-rwxr-xr-xtests/functional/mips/test_malta.py (renamed from tests/functional/test_mips_malta.py)8
-rwxr-xr-xtests/functional/mips/test_replay.py (renamed from tests/functional/test_mips_replay.py)2
-rwxr-xr-xtests/functional/mips/test_tuxrun.py (renamed from tests/functional/test_mips_tuxrun.py)0
-rw-r--r--tests/functional/mips64/meson.build10
-rwxr-xr-xtests/functional/mips64/test_malta.py (renamed from tests/functional/test_mips64_malta.py)4
-rwxr-xr-xtests/functional/mips64/test_tuxrun.py (renamed from tests/functional/test_mips64_tuxrun.py)0
-rw-r--r--tests/functional/mips64el/meson.build14
-rwxr-xr-xtests/functional/mips64el/test_fuloong2e.py (renamed from tests/functional/test_mips64el_fuloong2e.py)0
-rwxr-xr-xtests/functional/mips64el/test_loongson3v.py (renamed from tests/functional/test_mips64el_loongson3v.py)0
-rwxr-xr-xtests/functional/mips64el/test_malta.py (renamed from tests/functional/test_mips64el_malta.py)27
-rwxr-xr-xtests/functional/mips64el/test_replay.py (renamed from tests/functional/test_mips64el_replay.py)7
-rwxr-xr-xtests/functional/mips64el/test_tuxrun.py (renamed from tests/functional/test_mips64el_tuxrun.py)0
-rw-r--r--tests/functional/mipsel/meson.build12
-rwxr-xr-xtests/functional/mipsel/test_malta.py (renamed from tests/functional/test_mipsel_malta.py)4
-rwxr-xr-x[-rw-r--r--]tests/functional/mipsel/test_replay.py (renamed from tests/functional/test_mipsel_replay.py)0
-rwxr-xr-xtests/functional/mipsel/test_tuxrun.py (renamed from tests/functional/test_mipsel_tuxrun.py)0
-rw-r--r--[-rwxr-xr-x]tests/functional/multiprocess.py (renamed from tests/functional/test_multiprocess.py)41
-rw-r--r--tests/functional/or1k/meson.build6
-rwxr-xr-xtests/functional/or1k/test_replay.py (renamed from tests/functional/test_or1k_replay.py)0
-rwxr-xr-xtests/functional/or1k/test_sim.py (renamed from tests/functional/test_or1k_sim.py)0
-rw-r--r--tests/functional/ppc/meson.build23
-rwxr-xr-xtests/functional/ppc/test_40p.py (renamed from tests/functional/test_ppc_40p.py)0
-rwxr-xr-xtests/functional/ppc/test_74xx.py (renamed from tests/functional/test_ppc_74xx.py)2
-rwxr-xr-xtests/functional/ppc/test_amiga.py (renamed from tests/functional/test_ppc_amiga.py)6
-rwxr-xr-xtests/functional/ppc/test_bamboo.py48
-rwxr-xr-xtests/functional/ppc/test_mac.py (renamed from tests/functional/test_ppc_mac.py)0
-rwxr-xr-xtests/functional/ppc/test_migration.py26
-rwxr-xr-xtests/functional/ppc/test_mpc8544ds.py (renamed from tests/functional/test_ppc_mpc8544ds.py)0
-rw-r--r--tests/functional/ppc/test_ppe42.py79
-rwxr-xr-xtests/functional/ppc/test_replay.py (renamed from tests/functional/test_ppc_replay.py)0
-rwxr-xr-x[-rw-r--r--]tests/functional/ppc/test_sam460ex.py (renamed from tests/functional/test_ppc_sam460ex.py)5
-rwxr-xr-xtests/functional/ppc/test_tuxrun.py (renamed from tests/functional/test_ppc_tuxrun.py)0
-rwxr-xr-xtests/functional/ppc/test_virtex_ml507.py (renamed from tests/functional/test_ppc_virtex_ml507.py)0
-rw-r--r--tests/functional/ppc64/meson.build28
-rwxr-xr-xtests/functional/ppc64/test_e500.py (renamed from tests/functional/test_ppc64_e500.py)0
-rwxr-xr-xtests/functional/ppc64/test_fadump.py182
-rwxr-xr-xtests/functional/ppc64/test_hv.py (renamed from tests/functional/test_ppc64_hv.py)0
-rwxr-xr-xtests/functional/ppc64/test_mac99.py (renamed from tests/functional/test_ppc64_mac99.py)8
-rwxr-xr-xtests/functional/ppc64/test_migration.py26
-rwxr-xr-xtests/functional/ppc64/test_powernv.py (renamed from tests/functional/test_ppc64_powernv.py)36
-rwxr-xr-xtests/functional/ppc64/test_pseries.py (renamed from tests/functional/test_ppc64_pseries.py)2
-rwxr-xr-xtests/functional/ppc64/test_replay.py (renamed from tests/functional/test_ppc64_replay.py)0
-rwxr-xr-xtests/functional/ppc64/test_reverse_debug.py (renamed from tests/functional/test_ppc64_reverse_debug.py)17
-rwxr-xr-xtests/functional/ppc64/test_tuxrun.py (renamed from tests/functional/test_ppc64_tuxrun.py)0
-rw-r--r--tests/functional/qemu_test/__init__.py4
-rw-r--r--tests/functional/qemu_test/asset.py58
-rw-r--r--tests/functional/qemu_test/cmd.py67
-rw-r--r--tests/functional/qemu_test/decorators.py176
-rw-r--r--tests/functional/qemu_test/gdb.py86
-rw-r--r--tests/functional/qemu_test/linuxkernel.py65
-rw-r--r--tests/functional/qemu_test/ports.py5
-rw-r--r--tests/functional/qemu_test/testcase.py278
-rw-r--r--tests/functional/qemu_test/uncompress.py40
-rw-r--r--tests/functional/qemu_test/utils.py22
-rw-r--r--tests/functional/replay_kernel.py16
-rw-r--r--tests/functional/reverse_debugging.py189
-rw-r--r--tests/functional/riscv32/meson.build10
-rwxr-xr-xtests/functional/riscv32/test_migration.py26
-rwxr-xr-xtests/functional/riscv32/test_opensbi.py10
-rwxr-xr-xtests/functional/riscv32/test_tuxrun.py (renamed from tests/functional/test_riscv32_tuxrun.py)0
-rw-r--r--tests/functional/riscv64/meson.build15
-rwxr-xr-xtests/functional/riscv64/test_migration.py26
-rwxr-xr-xtests/functional/riscv64/test_opensbi.py (renamed from tests/functional/test_riscv_opensbi.py)0
-rwxr-xr-xtests/functional/riscv64/test_sifive_u.py63
-rwxr-xr-xtests/functional/riscv64/test_tuxrun.py (renamed from tests/functional/test_riscv64_tuxrun.py)0
-rw-r--r--tests/functional/rx/meson.build5
-rwxr-xr-xtests/functional/rx/test_gdbsim.py (renamed from tests/functional/test_rx_gdbsim.py)6
-rw-r--r--tests/functional/s390x/meson.build17
-rwxr-xr-xtests/functional/s390x/test_ccw_virtio.py (renamed from tests/functional/test_s390x_ccw_virtio.py)26
-rwxr-xr-xtests/functional/s390x/test_pxelinux.py130
-rwxr-xr-xtests/functional/s390x/test_replay.py (renamed from tests/functional/test_s390x_replay.py)0
-rwxr-xr-xtests/functional/s390x/test_topology.py (renamed from tests/functional/test_s390x_topology.py)0
-rwxr-xr-xtests/functional/s390x/test_tuxrun.py (renamed from tests/functional/test_s390x_tuxrun.py)1
-rw-r--r--tests/functional/sh4/meson.build10
-rwxr-xr-xtests/functional/sh4/test_r2d.py (renamed from tests/functional/test_sh4_r2d.py)0
-rwxr-xr-xtests/functional/sh4/test_tuxrun.py (renamed from tests/functional/test_sh4_tuxrun.py)0
-rw-r--r--tests/functional/sh4eb/meson.build5
-rwxr-xr-xtests/functional/sh4eb/test_r2d.py (renamed from tests/functional/test_sh4eb_r2d.py)0
-rw-r--r--tests/functional/sparc/meson.build10
-rwxr-xr-xtests/functional/sparc/test_migration.py26
-rwxr-xr-xtests/functional/sparc/test_replay.py (renamed from tests/functional/test_sparc_replay.py)0
-rwxr-xr-xtests/functional/sparc/test_sun4m.py (renamed from tests/functional/test_sparc_sun4m.py)0
-rw-r--r--tests/functional/sparc64/meson.build10
-rwxr-xr-xtests/functional/sparc64/test_migration.py26
-rwxr-xr-xtests/functional/sparc64/test_sun4u.py (renamed from tests/functional/test_sparc64_sun4u.py)0
-rwxr-xr-xtests/functional/sparc64/test_tuxrun.py (renamed from tests/functional/test_sparc64_tuxrun.py)1
-rwxr-xr-xtests/functional/test_aarch64_rme_sbsaref.py69
-rwxr-xr-xtests/functional/test_aarch64_rme_virt.py101
-rwxr-xr-xtests/functional/test_ppc_bamboo.py44
-rw-r--r--tests/functional/x86_64/meson.build39
-rwxr-xr-xtests/functional/x86_64/test_acpi_bits.py (renamed from tests/functional/test_acpi_bits.py)37
-rwxr-xr-xtests/functional/x86_64/test_bad_vmstate.py58
-rwxr-xr-xtests/functional/x86_64/test_cpu_model_versions.py (renamed from tests/functional/test_x86_cpu_model_versions.py)110
-rwxr-xr-xtests/functional/x86_64/test_cpu_queries.py (renamed from tests/functional/test_cpu_queries.py)0
-rwxr-xr-xtests/functional/x86_64/test_hotplug_blk.py (renamed from tests/functional/test_x86_64_hotplug_blk.py)0
-rwxr-xr-xtests/functional/x86_64/test_hotplug_cpu.py (renamed from tests/functional/test_x86_64_hotplug_cpu.py)0
-rwxr-xr-xtests/functional/x86_64/test_intel_iommu.py (renamed from tests/functional/test_intel_iommu.py)0
-rwxr-xr-xtests/functional/x86_64/test_kvm_xen.py (renamed from tests/functional/test_x86_64_kvm_xen.py)17
-rwxr-xr-xtests/functional/x86_64/test_linux_initrd.py (renamed from tests/functional/test_linux_initrd.py)0
-rwxr-xr-xtests/functional/x86_64/test_mem_addr_space.py (renamed from tests/functional/test_mem_addr_space.py)63
-rwxr-xr-xtests/functional/x86_64/test_memlock.py82
-rwxr-xr-xtests/functional/x86_64/test_migration.py26
-rwxr-xr-xtests/functional/x86_64/test_multiprocess.py31
-rwxr-xr-xtests/functional/x86_64/test_netdev_ethtool.py (renamed from tests/functional/test_netdev_ethtool.py)14
-rwxr-xr-xtests/functional/x86_64/test_pc_cpu_hotplug_props.py (renamed from tests/functional/test_pc_cpu_hotplug_props.py)1
-rwxr-xr-xtests/functional/x86_64/test_replay.py (renamed from tests/functional/test_x86_64_replay.py)0
-rwxr-xr-xtests/functional/x86_64/test_reverse_debug.py (renamed from tests/functional/test_x86_64_reverse_debug.py)17
-rwxr-xr-xtests/functional/x86_64/test_tuxrun.py (renamed from tests/functional/test_x86_64_tuxrun.py)0
-rwxr-xr-xtests/functional/x86_64/test_vfio_user_client.py201
-rwxr-xr-xtests/functional/x86_64/test_virtio_balloon.py (renamed from tests/functional/test_virtio_balloon.py)8
-rwxr-xr-xtests/functional/x86_64/test_virtio_gpu.py (renamed from tests/functional/test_virtio_gpu.py)54
-rwxr-xr-xtests/functional/x86_64/test_virtio_version.py (renamed from tests/functional/test_virtio_version.py)0
-rw-r--r--tests/functional/xtensa/meson.build6
-rwxr-xr-xtests/functional/xtensa/test_lx60.py (renamed from tests/functional/test_xtensa_lx60.py)0
-rwxr-xr-xtests/functional/xtensa/test_replay.py (renamed from tests/functional/test_xtensa_replay.py)0
210 files changed, 3648 insertions, 1426 deletions
diff --git a/tests/functional/aarch64/meson.build b/tests/functional/aarch64/meson.build
new file mode 100644
index 0000000..5ad52f9
--- /dev/null
+++ b/tests/functional/aarch64/meson.build
@@ -0,0 +1,49 @@
+# 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',
+ 'vmstate',
+]
+
+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/test_aarch64_aspeed_ast2700.py b/tests/functional/aarch64/test_aspeed_ast2700.py
index d02dc79..0ced1a2 100755
--- a/tests/functional/test_aarch64_aspeed_ast2700.py
+++ b/tests/functional/aarch64/test_aspeed_ast2700.py
@@ -37,22 +37,21 @@ class AST2x00MachineSDK(QemuSystemTest):
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):
+ def verify_openbmc_boot_start(self):
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, 'Linux version ')
+
+ def verify_openbmc_boot_and_login(self, name):
+ self.verify_openbmc_boot_start()
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')
+ ASSET_SDK_V908_AST2700A1 = Asset(
+ 'https://github.com/AspeedTech-BMC/openbmc/releases/download/v09.08/ast2700-default-obmc.tar.gz',
+ 'eac3dc409b7ea3cd4b03d4792d3cebd469792ad893cb51e1d15f0fc20bd1e2cd')
def do_ast2700_i2c_test(self):
exec_command_and_wait_for_pattern(self,
@@ -65,6 +64,19 @@ class AST2x00MachineSDK(QemuSystemTest):
exec_command_and_wait_for_pattern(self,
'cat /sys/bus/i2c/devices/1-004d/hwmon/hwmon*/temp1_input', '18000')
+ def do_ast2700_pcie_test(self):
+ exec_command_and_wait_for_pattern(self,
+ 'lspci -s 0002:00:00.0',
+ '0002:00:00.0 PCI bridge: '
+ 'ASPEED Technology, Inc. AST1150 PCI-to-PCI Bridge')
+ exec_command_and_wait_for_pattern(self,
+ 'lspci -s 0002:01:00.0',
+ '0002:01:00.0 Ethernet controller: '
+ 'Intel Corporation 82574L Gigabit Network Connection')
+ exec_command_and_wait_for_pattern(self,
+ 'ip addr show dev eth2',
+ 'inet 10.0.2.15/24')
+
def start_ast2700_test(self, name):
num_cpu = 4
uboot_size = os.path.getsize(self.scratch_file(name,
@@ -111,30 +123,28 @@ class AST2x00MachineSDK(QemuSystemTest):
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):
+ def test_aarch64_ast2700a1_evb_sdk_v09_08(self):
self.set_machine('ast2700a1-evb')
+ self.require_netdev('user')
- self.archive_extract(self.ASSET_SDK_V906_AST2700A1)
+ self.archive_extract(self.ASSET_SDK_V908_AST2700A1)
+ self.vm.add_args('-device', 'e1000e,netdev=net1,bus=pcie.2')
+ self.vm.add_args('-netdev', 'user,id=net1')
self.start_ast2700_test('ast2700-default')
self.verify_openbmc_boot_and_login('ast2700-default')
self.do_ast2700_i2c_test()
+ self.do_ast2700_pcie_test()
- def test_aarch64_ast2700a1_evb_sdk_vbootrom_v09_06(self):
+ def test_aarch64_ast2700a1_evb_sdk_vbootrom_v09_08(self):
self.set_machine('ast2700a1-evb')
+ self.require_netdev('user')
- self.archive_extract(self.ASSET_SDK_V906_AST2700A1)
+ self.archive_extract(self.ASSET_SDK_V908_AST2700A1)
+ self.vm.add_args('-device', 'e1000e,netdev=net1,bus=pcie.2')
+ self.vm.add_args('-netdev', 'user,id=net1')
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()
+ self.verify_openbmc_boot_start()
if __name__ == '__main__':
QemuSystemTest.main()
diff --git a/tests/functional/test_aarch64_aspeed_ast2700fc.py b/tests/functional/aarch64/test_aspeed_ast2700fc.py
index b85370e..8dbc8f2 100755
--- a/tests/functional/test_aarch64_aspeed_ast2700fc.py
+++ b/tests/functional/aarch64/test_aspeed_ast2700fc.py
@@ -20,6 +20,8 @@ class AST2x00MachineSDK(QemuSystemTest):
self.vm.set_console()
self.vm.add_args('-device',
'tmp105,bus=aspeed.i2c.bus.1,address=0x4d,id=tmp-test')
+ self.vm.add_args('-device', 'e1000e,netdev=net1,bus=pcie.2')
+ self.vm.add_args('-netdev', 'user,id=net1')
self.vm.add_args('-drive', 'file=' + image + ',if=mtd,format=raw',
'-net', 'nic', '-net', 'user', '-snapshot')
@@ -34,9 +36,20 @@ class AST2x00MachineSDK(QemuSystemTest):
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 load_ast2700fc_coprocessor(self, name):
+ 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}')
+
+ ASSET_SDK_V908_AST2700 = Asset(
+ 'https://github.com/AspeedTech-BMC/openbmc/releases/download/v09.08/ast2700-default-obmc.tar.gz',
+ 'eac3dc409b7ea3cd4b03d4792d3cebd469792ad893cb51e1d15f0fc20bd1e2cd')
def do_ast2700_i2c_test(self):
exec_command_and_wait_for_pattern(self,
@@ -49,12 +62,25 @@ class AST2x00MachineSDK(QemuSystemTest):
exec_command_and_wait_for_pattern(self,
'cat /sys/bus/i2c/devices/1-004d/hwmon/hwmon*/temp1_input', '18000')
+ def do_ast2700_pcie_test(self):
+ exec_command_and_wait_for_pattern(self,
+ 'lspci -s 0002:00:00.0',
+ '0002:00:00.0 PCI bridge: '
+ 'ASPEED Technology, Inc. AST1150 PCI-to-PCI Bridge')
+ exec_command_and_wait_for_pattern(self,
+ 'lspci -s 0002:01:00.0',
+ '0002:01:00.0 Ethernet controller: '
+ 'Intel Corporation 82574L Gigabit Network Connection')
+ exec_command_and_wait_for_pattern(self,
+ 'ip addr show dev eth2',
+ 'inet 10.0.2.15/24')
+
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, '\012', 'ssp_tsp:~$')
exec_command_and_wait_for_pattern(self, 'version',
'Zephyr version 3.7.1')
exec_command_and_wait_for_pattern(self, 'md 72c02000 1',
@@ -108,26 +134,34 @@ class AST2x00MachineSDK(QemuSystemTest):
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.load_ast2700fc_coprocessor(name)
+ self.do_test_aarch64_aspeed_sdk_start(
+ self.scratch_file(name, 'image-bmc'))
+ def start_ast2700fc_test_vbootrom(self, name):
+ self.vm.add_args('-bios', 'ast27x0_bootrom.bin')
+ self.load_ast2700fc_coprocessor(name)
self.do_test_aarch64_aspeed_sdk_start(
self.scratch_file(name, 'image-bmc'))
- def test_aarch64_ast2700fc_sdk_v09_06(self):
+ def test_aarch64_ast2700fc_sdk_v09_08(self):
self.set_machine('ast2700fc')
+ self.require_netdev('user')
- self.archive_extract(self.ASSET_SDK_V906_AST2700)
+ self.archive_extract(self.ASSET_SDK_V908_AST2700)
self.start_ast2700fc_test('ast2700-default')
self.verify_openbmc_boot_and_login('ast2700-default')
self.do_ast2700_i2c_test()
+ self.do_ast2700_pcie_test()
+ self.do_ast2700fc_ssp_test()
+ self.do_ast2700fc_tsp_test()
+
+ def test_aarch64_ast2700fc_sdk_vbootrom_v09_08(self):
+ self.set_machine('ast2700fc')
+
+ self.archive_extract(self.ASSET_SDK_V908_AST2700)
+ self.start_ast2700fc_test_vbootrom('ast2700-default')
+ self.verify_openbmc_boot_and_login('ast2700-default')
self.do_ast2700fc_ssp_test()
self.do_ast2700fc_tsp_test()
diff --git a/tests/functional/aarch64/test_device_passthrough.py b/tests/functional/aarch64/test_device_passthrough.py
new file mode 100755
index 0000000..10c7372
--- /dev/null
+++ b/tests/functional/aarch64/test_device_passthrough.py
@@ -0,0 +1,149 @@
+#!/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 <pierrick.bouvier@linaro.org>
+#
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+from os.path import join
+from random import randbytes
+
+from qemu_test import QemuSystemTest, Asset
+from qemu_test import wait_for_console_pattern
+
+
+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/tree/device_passthrough
+ # $ ./build.sh && ./archive_artifacts.sh out.tar.xz
+ #
+ # 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://github.com/pbo-linaro/qemu-linux-stack/'
+ 'releases/download/build/device_passthrough-a9612a2.tar.xz'),
+ 'f7d2f70912e7231986e6e293e1a2c4786dd02bec113a7acb6bfc619e96155455')
+
+ # 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 = self.ASSET_DEVICE_PASSTHROUGH_STACK.fetch()
+ self.archive_extract(stack_path_tar, format="tar")
+
+ stack = self.scratch_file('out')
+ kernel = join(stack, 'Image.gz')
+ rootfs_host = join(stack, 'host.ext4')
+ disk_vfio = join(stack, 'disk_vfio')
+ disk_iommufd = join(stack, 'disk_iommufd')
+ guest_cmd = join(stack, 'guest.sh')
+ nested_guest_cmd = 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', encoding='utf-8') as s:
+ s.write(GUEST_SCRIPT)
+ with open(nested_guest_cmd, 'w', encoding='utf-8') 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..bf67720
--- /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 <gustavo.romero@linaro.org>
+#
+# 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/trixie/main/installer-arm64/'
+ '20250803/images/netboot/debian-installer/arm64/linux'),
+ '93a6e4f9627d759375d28f863437a86a0659e125792a435f8e526dda006b7d5e')
+
+ ASSET_INITRD = Asset(
+ ('https://ftp.debian.org/debian/dists/trixie/main/installer-arm64/'
+ '20250803/images/netboot/debian-installer/arm64/initrd.gz'),
+ 'f6c78af7078ca67638ef3a50c926cd3c1485673243f8b37952e6bd854d6ba007')
+
+ 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/aarch64/test_imx8mp_evk.py
index 638bf9e..99ddcde 100755
--- a/tests/functional/test_aarch64_imx8mp_evk.py
+++ b/tests/functional/aarch64/test_imx8mp_evk.py
@@ -49,6 +49,7 @@ class Imx8mpEvkMachine(LinuxKernelTest):
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',
diff --git a/tests/functional/aarch64/test_kvm.py b/tests/functional/aarch64/test_kvm.py
new file mode 100755
index 0000000..7545f5e
--- /dev/null
+++ b/tests/functional/aarch64/test_kvm.py
@@ -0,0 +1,69 @@
+#!/usr/bin/env python3
+#
+# Functional test that runs subsets of kvm-unit-tests on Aarch64.
+# These can run on TCG and any accelerator supporting nested
+# virtualisation.
+#
+# Copyright (c) 2025 Linaro
+#
+# Author:
+# Alex Bennée <alex.bennee@linaro.org>
+#
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+from qemu_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://share.linaro.org/downloadFile?id=Bs8Eb2Wb7yWtkTA',
+ '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/test_aarch64_raspi3.py b/tests/functional/aarch64/test_raspi3.py
index 74f6630..74f6630 100755
--- a/tests/functional/test_aarch64_raspi3.py
+++ b/tests/functional/aarch64/test_raspi3.py
diff --git a/tests/functional/test_aarch64_raspi4.py b/tests/functional/aarch64/test_raspi4.py
index 7a4302b..7a4302b 100755
--- a/tests/functional/test_aarch64_raspi4.py
+++ b/tests/functional/aarch64/test_raspi4.py
diff --git a/tests/functional/test_aarch64_replay.py b/tests/functional/aarch64/test_replay.py
index db12e76..db12e76 100755
--- a/tests/functional/test_aarch64_replay.py
+++ b/tests/functional/aarch64/test_replay.py
diff --git a/tests/functional/test_aarch64_reverse_debug.py b/tests/functional/aarch64/test_reverse_debug.py
index 58d4532..e9fa447 100755
--- a/tests/functional/test_aarch64_reverse_debug.py
+++ b/tests/functional/aarch64/test_reverse_debug.py
@@ -2,36 +2,34 @@
#
# SPDX-License-Identifier: GPL-2.0-or-later
#
-# Reverse debugging test
+# Reverse debugging test for aarch64
#
# Copyright (c) 2020 ISP RAS
+# Copyright (c) 2025 Linaro Limited
#
# Author:
# Pavel Dovgalyuk <Pavel.Dovgalyuk@ispras.ru>
+# Gustavo Romero <gustavo.romero@linaro.org> (Run without Avocado)
#
# 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 qemu_test import Asset
from reverse_debugging import ReverseDebugging
-@skipIfMissingImports('avocado.utils')
-class ReverseDebugging_AArch64(ReverseDebugging):
+class ReverseDebuggingAArch64(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')
- @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.KERNEL_ASSET.fetch()
- self.reverse_debugging(args=('-kernel', kernel_path))
+ kernel_path = self.ASSET_KERNEL.fetch()
+ self.reverse_debugging(gdb_arch='aarch64', args=('-kernel', kernel_path))
if __name__ == '__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..4845c82
--- /dev/null
+++ b/tests/functional/aarch64/test_rme_sbsaref.py
@@ -0,0 +1,76 @@
+#!/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 <pierrick.bouvier@linaro.org>
+#
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+import os
+from os.path import join
+import shutil
+
+from qemu_test import QemuSystemTest, Asset, wait_for_console_pattern
+
+
+class Aarch64RMESbsaRefMachine(QemuSystemTest):
+
+ # Stack is inspired from:
+ # https://linaro.atlassian.net/wiki/spaces/QEMU/pages/29051027459/
+ # https://github.com/pbo-linaro/qemu-linux-stack/tree/rme_sbsa_release
+ # ./build.sh && ./archive_artifacts.sh out.tar.xz
+ ASSET_RME_STACK_SBSA = Asset(
+ ('https://github.com/pbo-linaro/qemu-linux-stack/'
+ 'releases/download/build/rme_sbsa_release-6a2dfc5.tar.xz'),
+ '5adba482aa069912292a8da746c6b21268224d9d81c97fe7c0bed690579ebdcb')
+
+ # 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 = self.ASSET_RME_STACK_SBSA.fetch()
+ self.archive_extract(stack_path_tar, format="tar")
+
+ rme_stack = self.scratch_file('.')
+ pflash0 = join(rme_stack, 'out', 'SBSA_FLASH0.fd')
+ pflash1 = join(rme_stack, 'out', 'SBSA_FLASH1.fd')
+ rootfs = join(rme_stack, 'out', 'host.ext4')
+
+ efi = join(rme_stack, 'out', 'EFI')
+ os.makedirs(efi, exist_ok=True)
+ shutil.copyfile(join(rme_stack, 'out', 'Image'), join(efi, 'Image'))
+ with open(join(efi, 'startup.nsh'), 'w', encoding='ascii') as startup:
+ startup.write('fs0:Image nokaslr root=/dev/vda rw init=/init --'
+ ' /host/out/lkvm run --realm'
+ ' -m 256m'
+ ' --restricted_mem'
+ ' --kernel /host/out/Image'
+ ' --disk /host/out/guest.ext4'
+ ' --params "root=/dev/vda rw init=/init"')
+
+ self.vm.add_args('-cpu', 'max,x-rme=on')
+ self.vm.add_args('-smp', '2')
+ 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:{efi},format=raw')
+ self.vm.add_args('-drive', f'format=raw,file={rootfs},if=virtio')
+ self.vm.add_args('-virtfs',
+ f'local,path={rme_stack}/,mount_tag=host,'
+ 'security_model=mapped,readonly=off')
+ self.vm.launch()
+ # Wait for host and guest VM boot to complete.
+ wait_for_console_pattern(self, 'root@guest',
+ failure_message='Kernel panic')
+
+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..5e23773
--- /dev/null
+++ b/tests/functional/aarch64/test_rme_virt.py
@@ -0,0 +1,76 @@
+#!/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 <pierrick.bouvier@linaro.org>
+#
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+from os.path import join
+
+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
+
+class Aarch64RMEVirtMachine(QemuSystemTest):
+
+ # Stack is inspired from:
+ # https://linaro.atlassian.net/wiki/spaces/QEMU/pages/29051027459/
+ # https://github.com/pbo-linaro/qemu-linux-stack/tree/rme_release
+ # ./build.sh && ./archive_artifacts.sh out.tar.xz
+ ASSET_RME_STACK_VIRT = Asset(
+ ('https://github.com/pbo-linaro/qemu-linux-stack/'
+ 'releases/download/build/rme_release-56bc99e.tar.xz'),
+ '0e3dc6b8a4b828dbae09c951a40dcb710eded084b32432b50c69cf4173ffa4be')
+
+ # 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 = self.ASSET_RME_STACK_VIRT.fetch()
+ self.archive_extract(stack_path_tar, format="tar")
+
+ rme_stack = self.scratch_file('.')
+ kernel = join(rme_stack, 'out', 'Image')
+ bios = join(rme_stack, 'out', 'flash.bin')
+ rootfs = join(rme_stack, 'out', 'host.ext4')
+
+ self.vm.add_args('-cpu', 'max,x-rme=on')
+ self.vm.add_args('-smp', '2')
+ 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,file={rootfs},if=virtio')
+ self.vm.add_args('-virtfs',
+ f'local,path={rme_stack}/,mount_tag=host,'
+ 'security_model=mapped,readonly=off')
+ # We need to add nokaslr to avoid triggering this sporadic bug:
+ # https://gitlab.com/qemu-project/qemu/-/issues/2823
+ self.vm.add_args('-append',
+ 'nokaslr root=/dev/vda rw init=/init --'
+ ' /host/out/lkvm run --realm'
+ ' -m 256m'
+ ' --restricted_mem'
+ ' --kernel /host/out/Image'
+ ' --disk /host/out/guest.ext4'
+ ' --params "root=/dev/vda rw init=/init"')
+
+ self.vm.launch()
+ # Wait for host and guest VM boot to complete.
+ wait_for_console_pattern(self, 'root@guest',
+ failure_message='Kernel panic')
+
+if __name__ == '__main__':
+ QemuSystemTest.main()
diff --git a/tests/functional/test_aarch64_sbsaref.py b/tests/functional/aarch64/test_sbsaref.py
index e6a55ae..d3402f5 100755
--- a/tests/functional/test_aarch64_sbsaref.py
+++ b/tests/functional/aarch64/test_sbsaref.py
@@ -40,8 +40,6 @@ def fetch_firmware(test):
with open(path, "ab+") as fd:
fd.truncate(256 << 20) # Expand volumes to 256MiB
- test.set_machine('sbsa-ref')
- test.vm.set_console()
test.vm.add_args(
"-drive", f"if=pflash,file={fs0_path},format=raw",
"-drive", f"if=pflash,file={fs1_path},format=raw",
@@ -68,8 +66,11 @@ class Aarch64SbsarefMachine(QemuSystemTest):
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()
diff --git a/tests/functional/test_aarch64_sbsaref_alpine.py b/tests/functional/aarch64/test_sbsaref_alpine.py
index 6108ec6..be84b7a 100755
--- a/tests/functional/test_aarch64_sbsaref_alpine.py
+++ b/tests/functional/aarch64/test_sbsaref_alpine.py
@@ -12,7 +12,7 @@
from qemu_test import QemuSystemTest, Asset, skipSlowTest
from qemu_test import wait_for_console_pattern
-from test_aarch64_sbsaref import fetch_firmware
+from test_sbsaref import fetch_firmware
class Aarch64SbsarefAlpine(QemuSystemTest):
@@ -26,8 +26,9 @@ class Aarch64SbsarefAlpine(QemuSystemTest):
# 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):
- fetch_firmware(self)
+ self.set_machine('sbsa-ref')
+ fetch_firmware(self)
iso_path = self.ASSET_ALPINE_ISO.fetch()
self.vm.set_console()
@@ -40,15 +41,9 @@ class Aarch64SbsarefAlpine(QemuSystemTest):
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")
diff --git a/tests/functional/test_aarch64_sbsaref_freebsd.py b/tests/functional/aarch64/test_sbsaref_freebsd.py
index 26dfc58..3b942f7 100755
--- a/tests/functional/test_aarch64_sbsaref_freebsd.py
+++ b/tests/functional/aarch64/test_sbsaref_freebsd.py
@@ -12,23 +12,24 @@
from qemu_test import QemuSystemTest, Asset, skipSlowTest
from qemu_test import wait_for_console_pattern
-from test_aarch64_sbsaref import fetch_firmware
+from test_sbsaref import fetch_firmware
class Aarch64SbsarefFreeBSD(QemuSystemTest):
ASSET_FREEBSD_ISO = Asset(
- ('https://download.freebsd.org/releases/arm64/aarch64/ISO-IMAGES/'
- '14.1/FreeBSD-14.1-RELEASE-arm64-aarch64-bootonly.iso'),
- '44cdbae275ef1bb6dab1d5fbb59473d4f741e1c8ea8a80fd9e906b531d6ad461')
+ ('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):
- fetch_firmware(self)
+ self.set_machine('sbsa-ref')
- img_path = self.ASSET_FREEBSD_ISO.fetch()
+ fetch_firmware(self)
+ img_path = self.uncompress(self.ASSET_FREEBSD_ISO)
self.vm.set_console()
self.vm.add_args(
diff --git a/tests/functional/test_aarch64_smmu.py b/tests/functional/aarch64/test_smmu.py
index c65d0f2..e0f4a92 100755
--- a/tests/functional/test_aarch64_smmu.py
+++ b/tests/functional/aarch64/test_smmu.py
@@ -17,7 +17,7 @@ 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
+from qemu.utils import kvm_available, hvf_available
class SMMU(LinuxKernelTest):
@@ -45,11 +45,17 @@ class SMMU(LinuxKernelTest):
self.vm.add_args('-device', 'virtio-net,netdev=n1' + self.IOMMU_ADDON)
def common_vm_setup(self, kernel, initrd, disk):
- self.require_accelerator("kvm")
+ 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", "kvm")
+ 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")
diff --git a/tests/functional/test_aarch64_tcg_plugins.py b/tests/functional/aarch64/test_tcg_plugins.py
index cb7e929..cb7e929 100755
--- a/tests/functional/test_aarch64_tcg_plugins.py
+++ b/tests/functional/aarch64/test_tcg_plugins.py
diff --git a/tests/functional/test_aarch64_tuxrun.py b/tests/functional/aarch64/test_tuxrun.py
index 75adc8a..75adc8a 100755
--- a/tests/functional/test_aarch64_tuxrun.py
+++ b/tests/functional/aarch64/test_tuxrun.py
diff --git a/tests/functional/test_aarch64_virt.py b/tests/functional/aarch64/test_virt.py
index 4d0ad90..f9e3ec0 100755
--- a/tests/functional/test_aarch64_virt.py
+++ b/tests/functional/aarch64/test_virt.py
@@ -60,8 +60,7 @@ class Aarch64VirtMachine(QemuSystemTest):
ASSET_KERNEL = Asset(
- ('https://fileserver.linaro.org/s/'
- 'z6B2ARM7DQT3HWN/download'),
+ 'https://share.linaro.org/downloadFile?id=3zGlbmXh8pXFewt',
'12a54d4805cda6ab647cb7c7bbdb16fafb3df400e0d6f16445c1a0436100ef8d')
def common_aarch64_virt(self, machine):
@@ -72,14 +71,12 @@ class Aarch64VirtMachine(QemuSystemTest):
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',
+ self.vm.add_args('-cpu', 'max',
'-machine', machine,
'-accel', 'tcg',
'-kernel', kernel_path,
@@ -91,7 +88,7 @@ class Aarch64VirtMachine(QemuSystemTest):
'rng-random,id=rng0,filename=/dev/urandom')
# Also add a scratch block device
- logger.info('creating scratch qcow2 image')
+ self.log.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'],
diff --git a/tests/functional/test_aarch64_virt_gpu.py b/tests/functional/aarch64/test_virt_gpu.py
index 3844727..c26a1f2 100755
--- a/tests/functional/test_aarch64_virt_gpu.py
+++ b/tests/functional/aarch64/test_virt_gpu.py
@@ -23,15 +23,11 @@ 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',
+ 'https://share.linaro.org/downloadFile?id=lL8wgnMmSXZo7Co',
'7888c51c55d37e86bbbdeb5acea9f08c34e6b0f03c1f5b2463285f6a6f6eec8b')
ASSET_VIRT_GPU_ROOTFS = Asset(
- 'https://fileserver.linaro.org/s/ce5jXBFinPxtEdx/'
- 'download?path=%2F&files='
- 'rootfs.aarch64.ext2.zstd',
+ 'https://share.linaro.org/downloadFile?id=qOn1wbfKmS6KVHZ',
'd45118c899420b7e673f1539a37a35480134b3e36e3a59e2cb69b1781cbb14ef')
def _launch_virt_gpu(self, gpu_device):
@@ -76,6 +72,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
diff --git a/tests/functional/test_aarch64_xen.py b/tests/functional/aarch64/test_xen.py
index 3399042..d90595c 100755
--- a/tests/functional/test_aarch64_xen.py
+++ b/tests/functional/aarch64/test_xen.py
@@ -25,14 +25,14 @@ class BootXen(LinuxKernelTest):
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'),
+ 'https://share.linaro.org/downloadFile?id=RRahAWwAwYKTZQd',
'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()
@@ -54,8 +54,7 @@ class BootXen(LinuxKernelTest):
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'),
+ 'https://share.linaro.org/downloadFile?id=ALU4n2NGGYbE4fO',
'b745c2631342f9fcc0147ddc364edb62c20ecfebd430e5a3546e7d7c6891c0bc')
def test_arm64_xen_411_and_dom0(self):
@@ -65,8 +64,7 @@ class BootXen(LinuxKernelTest):
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'),
+ 'https://share.linaro.org/downloadFile?id=os4zSXPl7WW4lqX',
'e930a3293248edabd367d5b4b3b6448b9c99c057096ea8b47228a7870661d5cb')
def test_arm64_xen_414_and_dom0(self):
@@ -76,8 +74,7 @@ class BootXen(LinuxKernelTest):
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'),
+ 'https://share.linaro.org/downloadFile?id=jjjG4uTp2wuO4Ks',
'2a9a8af8acf0231844657cc28baab95bd918b0ee2d493ee4ee6f8846e1358bc9')
def test_arm64_xen_415_and_dom0(self):
diff --git a/tests/functional/test_aarch64_xlnx_versal.py b/tests/functional/aarch64/test_xlnx_versal.py
index 4b9c49e..45aa6e1 100755
--- a/tests/functional/test_aarch64_xlnx_versal.py
+++ b/tests/functional/aarch64/test_xlnx_versal.py
@@ -6,7 +6,7 @@
from qemu_test import LinuxKernelTest, Asset
-class XlnxVersalVirtMachine(LinuxKernelTest):
+class AmdVersalVirtMachine(LinuxKernelTest):
ASSET_KERNEL = Asset(
('http://ports.ubuntu.com/ubuntu-ports/dists/bionic-updates/main/'
@@ -20,8 +20,8 @@ class XlnxVersalVirtMachine(LinuxKernelTest):
'/ubuntu-installer/arm64/initrd.gz'),
'e7a5e716b6f516d8be315c06e7331aaf16994fe4222e0e7cfb34bc015698929e')
- def test_aarch64_xlnx_versal_virt(self):
- self.set_machine('xlnx-versal-virt')
+ def common_aarch64_amd_versal_virt(self, machine):
+ self.set_machine(machine)
kernel_path = self.ASSET_KERNEL.fetch()
initrd_path = self.ASSET_INITRD.fetch()
@@ -33,5 +33,11 @@ class XlnxVersalVirtMachine(LinuxKernelTest):
self.vm.launch()
self.wait_for_console_pattern('Checked W+X mappings: passed')
+ def test_aarch64_amd_versal_virt(self):
+ self.common_aarch64_amd_versal_virt('amd-versal-virt')
+
+ def test_aarch64_amd_versal2_virt(self):
+ self.common_aarch64_amd_versal_virt('amd-versal2-virt')
+
if __name__ == '__main__':
LinuxKernelTest.main()
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/test_alpha_clipper.py b/tests/functional/alpha/test_clipper.py
index c5d7181..d2a4c2a 100755
--- a/tests/functional/test_alpha_clipper.py
+++ b/tests/functional/alpha/test_clipper.py
@@ -17,7 +17,6 @@ class AlphaClipperTest(LinuxKernelTest):
def test_alpha_clipper(self):
self.set_machine('clipper')
- kernel_path = self.ASSET_KERNEL.fetch()
uncompressed_kernel = self.uncompress(self.ASSET_KERNEL, format="gz")
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/test_alpha_replay.py b/tests/functional/alpha/test_replay.py
index 24a17ef..24a17ef 100755
--- a/tests/functional/test_alpha_replay.py
+++ b/tests/functional/alpha/test_replay.py
diff --git a/tests/functional/arm/meson.build b/tests/functional/arm/meson.build
new file mode 100644
index 0000000..d1ed076
--- /dev/null
+++ b/tests/functional/arm/meson.build
@@ -0,0 +1,64 @@
+# 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_buildroot' : 720,
+ 'aspeed_ast2600_sdk' : 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_buildroot',
+ 'aspeed_ast2600_sdk',
+ '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/test_arm_aspeed_ast1030.py b/tests/functional/arm/test_aspeed_ast1030.py
index 77037f0..d1822ed 100755
--- a/tests/functional/test_arm_aspeed_ast1030.py
+++ b/tests/functional/arm/test_aspeed_ast1030.py
@@ -6,23 +6,23 @@
#
# SPDX-License-Identifier: GPL-2.0-or-later
-from qemu_test import LinuxKernelTest, Asset
-from qemu_test import exec_command_and_wait_for_pattern
+from aspeed import AspeedTest
+from qemu_test import Asset, exec_command_and_wait_for_pattern
-class AST1030Machine(LinuxKernelTest):
+class AST1030Machine(AspeedTest):
- ASSET_ZEPHYR_3_00 = Asset(
+ ASSET_ZEPHYR_3_03 = Asset(
('https://github.com/AspeedTech-BMC'
- '/zephyr/releases/download/v00.03.00/ast1030-evb-demo.zip'),
- '37fe3ecd4a1b9d620971a15b96492a81093435396eeac69b6f3e384262ff555f')
+ '/zephyr/releases/download/v00.03.03/ast1030-evb-demo.zip'),
+ '27cd73cdee6374bceb4ee58b3ace87989fa3f0684f4e612510804b588b24d4e0')
- def test_ast1030_zephyros_3_00(self):
+ def test_arm_ast1030_zephyros_3_03(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.ASSET_ZEPHYR_3_03, member=kernel_name)
self.vm.set_console()
self.vm.add_args('-kernel', kernel_file, '-nographic')
@@ -36,7 +36,7 @@ class AST1030Machine(LinuxKernelTest):
'/zephyr/releases/download/v00.01.07/ast1030-evb-demo.zip'),
'ad52e27959746988afaed8429bf4e12ab988c05c4d07c9d90e13ec6f7be4574c')
- def test_ast1030_zephyros_1_07(self):
+ def test_arm_ast1030_zephyros_1_07(self):
self.set_machine('ast1030-evb')
kernel_name = "ast1030-evb-demo/zephyr.bin"
@@ -68,6 +68,22 @@ class AST1030Machine(LinuxKernelTest):
'kernel uptime',
]: exec_command_and_wait_for_pattern(self, shell_cmd, "uart:~$")
+ def test_arm_ast1030_otp_blockdev_device(self):
+ self.vm.set_machine("ast1030-evb")
+
+ kernel_name = "ast1030-evb-demo/zephyr.elf"
+ kernel_file = self.archive_extract(self.ASSET_ZEPHYR_3_03,
+ member=kernel_name)
+ otp_img = self.generate_otpmem_image()
+
+ self.vm.set_console()
+ self.vm.add_args(
+ "-kernel", kernel_file,
+ "-blockdev", f"driver=file,filename={otp_img},node-name=otp",
+ "-global", "aspeed-otp.drive=otp",
+ )
+ self.vm.launch()
+ self.wait_for_console_pattern("Booting Zephyr OS")
if __name__ == '__main__':
- LinuxKernelTest.main()
+ AspeedTest.main()
diff --git a/tests/functional/test_arm_aspeed_ast2500.py b/tests/functional/arm/test_aspeed_ast2500.py
index 6923fe8..5efd104 100755
--- a/tests/functional/test_arm_aspeed_ast2500.py
+++ b/tests/functional/arm/test_aspeed_ast2500.py
@@ -37,14 +37,14 @@ class AST2500Machine(AspeedTest):
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')
+ ASSET_SDK_V908_AST2500 = Asset(
+ 'https://github.com/AspeedTech-BMC/openbmc/releases/download/v09.08/ast2500-default-obmc.tar.gz',
+ 'c0a2ba169efd19be5eb77c50ec2a6afd9d826e196a0be3432f969fc72d4b7c0e')
def test_arm_ast2500_evb_sdk(self):
self.set_machine('ast2500-evb')
- self.archive_extract(self.ASSET_SDK_V906_AST2500)
+ self.archive_extract(self.ASSET_SDK_V908_AST2500)
self.do_test_arm_aspeed_sdk_start(
self.scratch_file("ast2500-default", "image-bmc"))
diff --git a/tests/functional/test_arm_aspeed_ast2600.py b/tests/functional/arm/test_aspeed_ast2600_buildroot.py
index fdae4c9..575a5f6 100755
--- a/tests/functional/test_arm_aspeed_ast2600.py
+++ b/tests/functional/arm/test_aspeed_ast2600_buildroot.py
@@ -9,8 +9,8 @@ import time
import tempfile
import subprocess
-from qemu_test import Asset
from aspeed import AspeedTest
+from qemu_test import Asset
from qemu_test import exec_command_and_wait_for_pattern, skipIfMissingCommands
@@ -66,21 +66,18 @@ class AST2600Machine(AspeedTest):
'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')
-
+ def _test_arm_ast2600_evb_buildroot_tpm(self, tpmstate_dir):
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')
+ socket = os.path.join(tpmstate_dir, '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}'])
+ '--tpmstate', f'dir={tpmstate_dir}',
+ '--ctrl', f'type=unixio,path={socket}'],
+ check=True)
self.vm.add_args('-chardev', f'socket,id=chrtpm,path={socket}')
self.vm.add_args('-tpmdev', 'emulator,id=tpm0,chardev=chrtpm')
@@ -97,44 +94,12 @@ class AST2600Machine(AspeedTest):
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):
+ @skipIfMissingCommands('swtpm')
+ def test_arm_ast2600_evb_buildroot_tpm(self):
self.set_machine('ast2600-evb')
+ with tempfile.TemporaryDirectory(prefix="qemu_") as tpmstate_dir:
+ self._test_arm_ast2600_evb_buildroot_tpm(tpmstate_dir)
- 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_ast2600_sdk.py b/tests/functional/arm/test_aspeed_ast2600_sdk.py
new file mode 100755
index 0000000..e3d4ed0
--- /dev/null
+++ b/tests/functional/arm/test_aspeed_ast2600_sdk.py
@@ -0,0 +1,94 @@
+#!/usr/bin/env python3
+#
+# Functional test that boots the ASPEED machines
+#
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+import os
+import time
+
+from qemu_test import Asset
+from aspeed import AspeedTest
+from qemu_test import exec_command_and_wait_for_pattern
+
+
+class AST2600Machine(AspeedTest):
+
+ ASSET_SDK_V908_AST2600 = Asset(
+ 'https://github.com/AspeedTech-BMC/openbmc/releases/download/v09.08/ast2600-default-obmc.tar.gz',
+ 'a0414f14ad696550efe083c2156dbeda855c08cc9ae7f40fe1b41bf292295f82')
+
+ def do_ast2600_pcie_test(self):
+ exec_command_and_wait_for_pattern(self,
+ 'lspci -s 80:00.0',
+ '80:00.0 Host bridge: '
+ 'ASPEED Technology, Inc. Device 2600')
+ exec_command_and_wait_for_pattern(self,
+ 'lspci -s 80:08.0',
+ '80:08.0 PCI bridge: '
+ 'ASPEED Technology, Inc. AST1150 PCI-to-PCI Bridge')
+ exec_command_and_wait_for_pattern(self,
+ 'lspci -s 81:00.0',
+ '81:00.0 Ethernet controller: '
+ 'Intel Corporation 82574L Gigabit Network Connection')
+ exec_command_and_wait_for_pattern(self,
+ 'ip addr show dev eth4',
+ 'inet 10.0.2.15/24')
+
+ def test_arm_ast2600_evb_sdk(self):
+ self.set_machine('ast2600-evb')
+ self.require_netdev('user')
+
+ self.archive_extract(self.ASSET_SDK_V908_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.vm.add_args('-device', 'e1000e,netdev=net1,bus=pcie.0')
+ self.vm.add_args('-netdev', 'user,id=net1')
+ 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)
+ self.do_ast2600_pcie_test()
+
+ def test_arm_ast2600_otp_blockdev_device(self):
+ self.vm.set_machine("ast2600-evb")
+
+ image_path = self.archive_extract(self.ASSET_SDK_V908_AST2600)
+ otp_img = self.generate_otpmem_image()
+
+ self.vm.set_console()
+ self.vm.add_args(
+ "-blockdev", f"driver=file,filename={otp_img},node-name=otp",
+ "-global", "aspeed-otp.drive=otp",
+ )
+ self.do_test_arm_aspeed_sdk_start(
+ self.scratch_file("ast2600-default", "image-bmc"))
+ self.wait_for_console_pattern("ast2600-default login:")
+
+
+if __name__ == '__main__':
+ AspeedTest.main()
diff --git a/tests/functional/test_arm_aspeed_bletchley.py b/tests/functional/arm/test_aspeed_bletchley.py
index 5a60b24..5a60b24 100644..100755
--- a/tests/functional/test_arm_aspeed_bletchley.py
+++ b/tests/functional/arm/test_aspeed_bletchley.py
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/test_arm_aspeed_palmetto.py b/tests/functional/arm/test_aspeed_palmetto.py
index ff0b821..ff0b821 100755
--- a/tests/functional/test_arm_aspeed_palmetto.py
+++ b/tests/functional/arm/test_aspeed_palmetto.py
diff --git a/tests/functional/test_arm_aspeed_rainier.py b/tests/functional/arm/test_aspeed_rainier.py
index 602d619..602d619 100755
--- a/tests/functional/test_arm_aspeed_rainier.py
+++ b/tests/functional/arm/test_aspeed_rainier.py
diff --git a/tests/functional/test_arm_aspeed_romulus.py b/tests/functional/arm/test_aspeed_romulus.py
index 0447212..0447212 100755
--- a/tests/functional/test_arm_aspeed_romulus.py
+++ b/tests/functional/arm/test_aspeed_romulus.py
diff --git a/tests/functional/test_arm_aspeed_witherspoon.py b/tests/functional/arm/test_aspeed_witherspoon.py
index 51a2d47..51a2d47 100644..100755
--- a/tests/functional/test_arm_aspeed_witherspoon.py
+++ b/tests/functional/arm/test_aspeed_witherspoon.py
diff --git a/tests/functional/test_arm_bflt.py b/tests/functional/arm/test_bflt.py
index f273fc8..f273fc8 100755
--- a/tests/functional/test_arm_bflt.py
+++ b/tests/functional/arm/test_bflt.py
diff --git a/tests/functional/test_arm_bpim2u.py b/tests/functional/arm/test_bpim2u.py
index 8bed64b..8bed64b 100755
--- a/tests/functional/test_arm_bpim2u.py
+++ b/tests/functional/arm/test_bpim2u.py
diff --git a/tests/functional/test_arm_canona1100.py b/tests/functional/arm/test_canona1100.py
index 21a1a59..21a1a59 100755
--- a/tests/functional/test_arm_canona1100.py
+++ b/tests/functional/arm/test_canona1100.py
diff --git a/tests/functional/test_arm_collie.py b/tests/functional/arm/test_collie.py
index fe1be3d..fe1be3d 100755
--- a/tests/functional/test_arm_collie.py
+++ b/tests/functional/arm/test_collie.py
diff --git a/tests/functional/test_arm_cubieboard.py b/tests/functional/arm/test_cubieboard.py
index b536c2f..b536c2f 100755
--- a/tests/functional/test_arm_cubieboard.py
+++ b/tests/functional/arm/test_cubieboard.py
diff --git a/tests/functional/test_arm_emcraft_sf2.py b/tests/functional/arm/test_emcraft_sf2.py
index f9f3f06..f9f3f06 100755
--- a/tests/functional/test_arm_emcraft_sf2.py
+++ b/tests/functional/arm/test_emcraft_sf2.py
diff --git a/tests/functional/test_arm_integratorcp.py b/tests/functional/arm/test_integratorcp.py
index a85b339..23ae919 100755
--- a/tests/functional/test_arm_integratorcp.py
+++ b/tests/functional/arm/test_integratorcp.py
@@ -73,9 +73,10 @@ class IntegratorMachine(QemuSystemTest):
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')
- self.vm.cmd('human-monitor-command',
- command_line='screendump %s' % screendump_path)
- logger = logging.getLogger('framebuffer')
+ res = self.vm.cmd('human-monitor-command',
+ command_line='screendump %s' % screendump_path)
+ if 'unknown command' in res:
+ self.skipTest('screendump not available')
cpu_count = 1
match_threshold = 0.92
@@ -86,7 +87,7 @@ class IntegratorMachine(QemuSystemTest):
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.log.debug('found Tux at position [x, y] = %s', pt)
self.assertGreaterEqual(tux_count, cpu_count)
if __name__ == '__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/test_arm_microbit.py b/tests/functional/arm/test_microbit.py
index 68ea4e7..68ea4e7 100755
--- a/tests/functional/test_arm_microbit.py
+++ b/tests/functional/arm/test_microbit.py
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/test_arm_orangepi.py b/tests/functional/arm/test_orangepi.py
index f9bfa8c..f9bfa8c 100755
--- a/tests/functional/test_arm_orangepi.py
+++ b/tests/functional/arm/test_orangepi.py
diff --git a/tests/functional/test_arm_quanta_gsj.py b/tests/functional/arm/test_quanta_gsj.py
index cb0545f..cb0545f 100755
--- a/tests/functional/test_arm_quanta_gsj.py
+++ b/tests/functional/arm/test_quanta_gsj.py
diff --git a/tests/functional/test_arm_raspi2.py b/tests/functional/arm/test_raspi2.py
index d3c7aaa..d3c7aaa 100755
--- a/tests/functional/test_arm_raspi2.py
+++ b/tests/functional/arm/test_raspi2.py
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/test_arm_replay.py b/tests/functional/arm/test_replay.py
index e002e6a..e002e6a 100755
--- a/tests/functional/test_arm_replay.py
+++ b/tests/functional/arm/test_replay.py
diff --git a/tests/functional/test_arm_smdkc210.py b/tests/functional/arm/test_smdkc210.py
index 3154e7f..3154e7f 100755
--- a/tests/functional/test_arm_smdkc210.py
+++ b/tests/functional/arm/test_smdkc210.py
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/test_arm_sx1.py b/tests/functional/arm/test_sx1.py
index 25800b3..25800b3 100755
--- a/tests/functional/test_arm_sx1.py
+++ b/tests/functional/arm/test_sx1.py
diff --git a/tests/functional/test_arm_tuxrun.py b/tests/functional/arm/test_tuxrun.py
index 4ac85f4..4ac85f4 100755
--- a/tests/functional/test_arm_tuxrun.py
+++ b/tests/functional/arm/test_tuxrun.py
diff --git a/tests/functional/test_arm_vexpress.py b/tests/functional/arm/test_vexpress.py
index 6b11552..6b11552 100755
--- a/tests/functional/test_arm_vexpress.py
+++ b/tests/functional/arm/test_vexpress.py
diff --git a/tests/functional/test_arm_virt.py b/tests/functional/arm/test_virt.py
index 7b65491..7b65491 100755
--- a/tests/functional/test_arm_virt.py
+++ b/tests/functional/arm/test_virt.py
diff --git a/tests/functional/aspeed.py b/tests/functional/aspeed.py
index 7a40d5d..47e84e0 100644
--- a/tests/functional/aspeed.py
+++ b/tests/functional/aspeed.py
@@ -8,8 +8,13 @@ from qemu_test import LinuxKernelTest
class AspeedTest(LinuxKernelTest):
def do_test_arm_aspeed_openbmc(self, machine, image, uboot='2019.04',
- cpu_id='0x0', soc='AST2500 rev A1'):
- hostname = machine.removesuffix('-bmc')
+ cpu_id='0x0', soc='AST2500 rev A1',
+ image_hostname=None):
+ # Allow for the image hostname to not end in "-bmc"
+ if image_hostname is not None:
+ hostname = image_hostname
+ else:
+ hostname = machine.removesuffix('-bmc')
self.set_machine(machine)
self.vm.set_console()
@@ -56,3 +61,11 @@ class AspeedTest(LinuxKernelTest):
self.wait_for_console_pattern('U-Boot 2019.04')
self.wait_for_console_pattern('## Loading kernel from FIT Image')
self.wait_for_console_pattern('Starting kernel ...')
+
+ def generate_otpmem_image(self):
+ path = self.scratch_file("otpmem.img")
+ pattern = b'\x00\x00\x00\x00\xff\xff\xff\xff' * (16 * 1024 // 8)
+ with open(path, "wb") as f:
+ f.write(pattern)
+ return path
+
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/test_avr_mega2560.py b/tests/functional/avr/test_mega2560.py
index 8e47b42..6359b72 100755
--- a/tests/functional/test_avr_mega2560.py
+++ b/tests/functional/avr/test_mega2560.py
@@ -18,12 +18,10 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
-import time
+from qemu_test import QemuSystemTest, Asset, wait_for_console_pattern
-from qemu_test import QemuSystemTest, Asset
class AVR6Machine(QemuSystemTest):
- timeout = 5
ASSET_ROM = Asset(('https://github.com/seharris/qemu-avr-tests'
'/raw/36c3e67b8755dcf/free-rtos/Demo'
@@ -40,13 +38,12 @@ class AVR6Machine(QemuSystemTest):
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()
- time.sleep(2)
- self.vm.shutdown()
+ wait_for_console_pattern(self,
+ 'XABCDEFGHIJKLMNOPQRSTUVWXABCDEFGHIJKLMNOPQRSTUVWXA')
- self.assertIn('ABCDEFGHIJKLMNOPQRSTUVWXABCDEFGHIJKLMNOPQRSTUVWX',
- self.vm.get_log())
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/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/test_empty_cpu_model.py b/tests/functional/generic/test_empty_cpu_model.py
index 0081b06..0081b06 100755
--- a/tests/functional/test_empty_cpu_model.py
+++ b/tests/functional/generic/test_empty_cpu_model.py
diff --git a/tests/functional/test_info_usernet.py b/tests/functional/generic/test_info_usernet.py
index e8cbc37..e8cbc37 100755
--- a/tests/functional/test_info_usernet.py
+++ b/tests/functional/generic/test_info_usernet.py
diff --git a/tests/functional/test_version.py b/tests/functional/generic/test_version.py
index 3ab3b67..3ab3b67 100755
--- a/tests/functional/test_version.py
+++ b/tests/functional/generic/test_version.py
diff --git a/tests/functional/generic/test_vmstate.py b/tests/functional/generic/test_vmstate.py
new file mode 100755
index 0000000..387ff54
--- /dev/null
+++ b/tests/functional/generic/test_vmstate.py
@@ -0,0 +1,67 @@
+#!/usr/bin/env python3
+#
+# SPDX-License-Identifier: GPL-2.0-or-later
+#
+'''This test runs the vmstate-static-checker script with the current QEMU'''
+
+import subprocess
+
+from qemu_test import QemuSystemTest, skipFlakyTest
+
+
+@skipFlakyTest("vmstate-static-checker can produce false positives")
+class VmStateTest(QemuSystemTest):
+ '''
+ This test helps to check whether there are problems between old
+ reference data and the current QEMU
+ '''
+
+ def test_vmstate_7_2(self):
+ '''Check reference data from QEMU v7.2'''
+
+ target_machine = {
+ 'aarch64': 'virt-7.2',
+ 'm68k': 'virt-7.2',
+ 'ppc64': 'pseries-7.2',
+ 's390x': 's390-ccw-virtio-7.2',
+ 'x86_64': 'pc-q35-7.2',
+ }
+ self.set_machine(target_machine[self.arch])
+
+ # Run QEMU to get the current vmstate json file:
+ dst_json = self.scratch_file('dest.json')
+ self.log.info('Dumping vmstate from %s', self.qemu_bin)
+ cp = subprocess.run([self.qemu_bin, '-nodefaults',
+ '-M', target_machine[self.arch],
+ '-dump-vmstate', dst_json],
+ stdout=subprocess.PIPE,
+ stderr=subprocess.STDOUT,
+ text=True, check=True)
+ if cp.stdout:
+ self.log.info('QEMU output: %s', cp.stdout)
+
+ # Check whether the old vmstate json file is still compatible:
+ src_json = self.data_file('..', 'data', 'vmstate-static-checker',
+ self.arch,
+ target_machine[self.arch] + '.json')
+ self.log.info('Comparing vmstate with %s', src_json)
+ checkerscript = self.data_file('..', '..', 'scripts',
+ 'vmstate-static-checker.py')
+ cp = subprocess.run([checkerscript, '-s', src_json, '-d', dst_json],
+ stdout=subprocess.PIPE,
+ stderr=subprocess.STDOUT,
+ text=True, check=False)
+ if cp.returncode != 0:
+ self.fail('Running vmstate-static-checker failed:\n' + cp.stdout +
+ '\nThis either means that there is a migration bug '
+ 'that needs to be fixed, or\nvmstate-static-checker.py '
+ 'needs to be improved (e.g. extend the changed_names\n'
+ 'in case a field has been renamed), or drop the '
+ 'problematic field from\n' + src_json +
+ '\nin case the script cannot be fixed easily.')
+ if cp.stdout:
+ self.log.warning('vmstate-static-checker output: %s', cp.stdout)
+
+
+if __name__ == '__main__':
+ QemuSystemTest.main()
diff --git a/tests/functional/test_vnc.py b/tests/functional/generic/test_vnc.py
index 5c0ee5f..f1dd159 100755
--- a/tests/functional/test_vnc.py
+++ b/tests/functional/generic/test_vnc.py
@@ -31,6 +31,7 @@ def check_connect(port: int) -> bool:
class Vnc(QemuSystemTest):
def test_no_vnc_change_password(self):
+ self.set_machine('none')
self.vm.add_args('-nodefaults', '-S')
self.vm.launch()
@@ -62,6 +63,7 @@ class Vnc(QemuSystemTest):
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'])
@@ -74,6 +76,7 @@ class Vnc(QemuSystemTest):
'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'])
@@ -103,6 +106,7 @@ class Vnc(QemuSystemTest):
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)
diff --git a/tests/functional/hppa/meson.build b/tests/functional/hppa/meson.build
new file mode 100644
index 0000000..df2f7cc
--- /dev/null
+++ b/tests/functional/hppa/meson.build
@@ -0,0 +1,9 @@
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+tests_hppa_system_quick = [
+ 'seabios',
+]
+
+tests_hppa_system_thorough = [
+ 'cdboot',
+]
diff --git a/tests/functional/hppa/test_cdboot.py b/tests/functional/hppa/test_cdboot.py
new file mode 100755
index 0000000..84421e8
--- /dev/null
+++ b/tests/functional/hppa/test_cdboot.py
@@ -0,0 +1,38 @@
+#!/usr/bin/env python3
+#
+# CD boot test for HPPA 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 HppaCdBoot(QemuSystemTest):
+
+ ASSET_CD = Asset(
+ ('https://github.com/philmd/qemu-testing-blob/raw/ec1b741/'
+ 'hppa/hp9000/712/C7120023.frm'),
+ '32c612ad2074516986bdc27768903c561fa92af2ca48e5ac3f3359ade1c42f70')
+
+ def test_cdboot(self):
+ self.set_machine('B160L')
+ cdrom_path = self.ASSET_CD.fetch()
+
+ self.vm.set_console()
+ self.vm.add_args('-cdrom', cdrom_path,
+ '-boot', 'd',
+ '-no-reboot')
+ self.vm.launch()
+ wait_for_console_pattern(self, 'Unrecognized MODEL TYPE = 502')
+ wait_for_console_pattern(self, 'UPDATE PAUSED>')
+
+ exec_command_and_wait_for_pattern(self, 'exit\r', 'UPDATE>')
+ exec_command_and_wait_for_pattern(self, 'ls\r', 'IMAGE1B')
+ wait_for_console_pattern(self, 'UPDATE>')
+ exec_command_and_wait_for_pattern(self, 'exit\r',
+ 'THIS UTILITY WILL NOW RESET THE SYSTEM.....')
+
+
+if __name__ == '__main__':
+ QemuSystemTest.main()
diff --git a/tests/functional/test_hppa_seabios.py b/tests/functional/hppa/test_seabios.py
index 661b246..661b246 100755
--- a/tests/functional/test_hppa_seabios.py
+++ b/tests/functional/hppa/test_seabios.py
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/test_i386_replay.py b/tests/functional/i386/test_replay.py
index 7c4c260..3a92ecd 100755
--- a/tests/functional/test_i386_replay.py
+++ b/tests/functional/i386/test_replay.py
@@ -17,7 +17,6 @@ class I386Replay(ReplayKernelBase):
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'
diff --git a/tests/functional/test_i386_tuxrun.py b/tests/functional/i386/test_tuxrun.py
index f3ccf11..f3ccf11 100755
--- a/tests/functional/test_i386_tuxrun.py
+++ b/tests/functional/i386/test_tuxrun.py
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/test_loongarch64_virt.py b/tests/functional/loongarch64/test_virt.py
index b7d9abf..b7d9abf 100755
--- a/tests/functional/test_loongarch64_virt.py
+++ b/tests/functional/loongarch64/test_virt.py
diff --git a/tests/functional/m68k/meson.build b/tests/functional/m68k/meson.build
new file mode 100644
index 0000000..679faaf
--- /dev/null
+++ b/tests/functional/m68k/meson.build
@@ -0,0 +1,13 @@
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+tests_m68k_system_quick = [
+ 'vmstate',
+]
+
+tests_m68k_system_thorough = [
+ 'mcf5208evb',
+ 'nextcube',
+ 'replay',
+ 'q800',
+ 'tuxrun',
+]
diff --git a/tests/functional/test_m68k_mcf5208evb.py b/tests/functional/m68k/test_mcf5208evb.py
index c7d1998..c7d1998 100755
--- a/tests/functional/test_m68k_mcf5208evb.py
+++ b/tests/functional/m68k/test_mcf5208evb.py
diff --git a/tests/functional/test_m68k_nextcube.py b/tests/functional/m68k/test_nextcube.py
index ff773a7..71c160d 100755
--- a/tests/functional/test_m68k_nextcube.py
+++ b/tests/functional/m68k/test_nextcube.py
@@ -29,11 +29,20 @@ class NextCubeMachine(QemuSystemTest):
self.vm.launch()
self.log.info('VM launched, waiting for display')
- # TODO: wait for the 'displaysurface_create 1120x832' trace-event.
- time.sleep(2)
+ # Wait for the FPU test to finish, then the display is available, too:
+ while True:
+ res = self.vm.cmd('human-monitor-command',
+ command_line='info registers')
+ if ("F0 = 400e 8400000000000000" in res and
+ "F1 = 400e 83ff000000000000" in res and
+ "F2 = 400e 83ff000000000000" in res):
+ break
+ time.sleep(0.1)
- self.vm.cmd('human-monitor-command',
- command_line='screendump %s' % screenshot_path)
+ res = self.vm.cmd('human-monitor-command',
+ command_line=f"screendump {screenshot_path}")
+ if 'unknown command' in res:
+ self.skipTest('screendump not available')
@skipIfMissingImports("PIL")
def test_bootrom_framebuffer_size(self):
@@ -42,7 +51,8 @@ class NextCubeMachine(QemuSystemTest):
self.check_bootrom_framebuffer(screenshot_path)
from PIL import Image
- width, height = Image.open(screenshot_path).size
+ with Image.open(screenshot_path) as image:
+ width, height = image.size
self.assertEqual(width, 1120)
self.assertEqual(height, 832)
@@ -53,10 +63,10 @@ class NextCubeMachine(QemuSystemTest):
self.check_bootrom_framebuffer(screenshot_path)
lines = tesseract_ocr(screenshot_path)
text = '\n'.join(lines)
+ self.assertIn('Backplane slot', text)
+ self.assertIn('Ethernet address', text)
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/m68k/test_q800.py
index 400b7ae..b3e6553 100755
--- a/tests/functional/test_m68k_q800.py
+++ b/tests/functional/m68k/test_q800.py
@@ -25,7 +25,8 @@ class Q800MachineTest(LinuxKernelTest):
kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE +
'console=ttyS0 vga=off')
self.vm.add_args('-kernel', kernel_path,
- '-append', kernel_command_line)
+ '-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)
diff --git a/tests/functional/test_m68k_replay.py b/tests/functional/m68k/test_replay.py
index 18c1db5..213d6ae 100755
--- a/tests/functional/test_m68k_replay.py
+++ b/tests/functional/m68k/test_replay.py
@@ -24,7 +24,8 @@ class M68kReplay(ReplayKernelBase):
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)
+ 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',
diff --git a/tests/functional/test_m68k_tuxrun.py b/tests/functional/m68k/test_tuxrun.py
index 7eacba1..7eacba1 100755
--- a/tests/functional/test_m68k_tuxrun.py
+++ b/tests/functional/m68k/test_tuxrun.py
diff --git a/tests/functional/meson.build b/tests/functional/meson.build
index 52b4706..725630d 100644
--- a/tests/functional/meson.build
+++ b/tests/functional/meson.build
@@ -9,330 +9,34 @@ if get_option('tcg_interpreter')
subdir_done()
endif
-# Timeouts for individual tests that can be slow e.g. with debugging enabled
-test_timeouts = {
- 'aarch64_aspeed_ast2700' : 600,
- 'aarch64_aspeed_ast2700fc' : 600,
- '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,
- 'acpi_bits' : 420,
- '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_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,
- 'intel_iommu': 300,
- 'mips_malta' : 480,
- 'mipsel_malta' : 420,
- 'mipsel_replay' : 480,
- 'mips64_malta' : 240,
- 'mips64el_malta' : 420,
- 'mips64el_replay' : 180,
- 'netdev_ethtool' : 180,
- 'ppc_40p' : 240,
- 'ppc64_hv' : 1000,
- 'ppc64_powernv' : 480,
- 'ppc64_pseries' : 480,
- 'ppc64_replay' : 210,
- 'ppc64_tuxrun' : 420,
- 'ppc64_mac99' : 120,
- 'riscv64_tuxrun' : 120,
- 's390x_ccw_virtio' : 420,
- 'sh4_tuxrun' : 240,
- 'virtio_balloon': 120,
- 'x86_64_kvm_xen' : 180,
- 'x86_64_replay' : 480,
-}
-
-tests_generic_system = [
- 'empty_cpu_model',
- 'info_usernet',
- 'version',
-]
-
-tests_generic_linuxuser = [
-]
-
-tests_generic_bsduser = [
-]
-
-tests_aarch64_system_quick = [
- 'migration',
-]
-
-tests_aarch64_system_thorough = [
- 'aarch64_aspeed_ast2700',
- 'aarch64_aspeed_ast2700fc',
- 'aarch64_imx8mp_evk',
- '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',
- 'multiprocess',
-]
-
-tests_alpha_system_quick = [
- 'migration',
-]
-
-tests_alpha_system_thorough = [
- 'alpha_clipper',
- 'alpha_replay',
-]
-
-tests_arm_system_quick = [
- '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_rainier',
- 'arm_bpim2u',
- 'arm_canona1100',
- 'arm_collie',
- 'arm_cubieboard',
- 'arm_emcraft_sf2',
- 'arm_integratorcp',
- 'arm_microbit',
- 'arm_orangepi',
- 'arm_quanta_gsj',
- 'arm_raspi2',
- 'arm_replay',
- 'arm_smdkc210',
- 'arm_sx1',
- 'arm_vexpress',
- 'arm_virt',
- 'arm_tuxrun',
-]
-
-tests_arm_linuxuser_thorough = [
- 'arm_bflt',
-]
-
-tests_avr_system_thorough = [
- 'avr_mega2560',
-]
-
-tests_hppa_system_quick = [
- 'hppa_seabios',
-]
-
-tests_i386_system_quick = [
- 'migration',
-]
-
-tests_i386_system_thorough = [
- 'i386_replay',
- 'i386_tuxrun',
-]
-
-tests_loongarch64_system_thorough = [
- 'loongarch64_virt',
-]
-
-tests_m68k_system_thorough = [
- 'm68k_mcf5208evb',
- 'm68k_nextcube',
- 'm68k_replay',
- 'm68k_q800',
- 'm68k_tuxrun',
-]
-
-tests_microblaze_system_thorough = [
- 'microblaze_replay',
- 'microblaze_s3adsp1800'
-]
-
-tests_microblazeel_system_thorough = [
- 'microblazeel_s3adsp1800'
-]
-
-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',
-]
-
-tests_ppc_system_quick = [
- '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 = [
- '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 = [
- 'migration',
- 'riscv_opensbi',
-]
-
-tests_riscv32_system_thorough = [
- 'riscv32_tuxrun',
-]
-
-tests_riscv64_system_quick = [
- 'migration',
- 'riscv_opensbi',
-]
-
-tests_riscv64_system_thorough = [
- 'riscv64_tuxrun',
-]
-
-tests_rx_system_thorough = [
- 'rx_gdbsim',
-]
-
-tests_s390x_system_thorough = [
- 's390x_ccw_virtio',
- 's390x_replay',
- 's390x_topology',
- 's390x_tuxrun',
-]
-
-tests_sh4_system_thorough = [
- 'sh4_r2d',
- 'sh4_tuxrun',
-]
-
-tests_sh4eb_system_thorough = [
- 'sh4eb_r2d',
-]
-
-tests_sparc_system_quick = [
- 'migration',
-]
-
-tests_sparc_system_thorough = [
- 'sparc_replay',
- 'sparc_sun4m',
-]
-
-tests_sparc64_system_quick = [
- 'migration',
-]
-
-tests_sparc64_system_thorough = [
- 'sparc64_sun4u',
- 'sparc64_tuxrun',
-]
-
-tests_x86_64_system_quick = [
- 'cpu_queries',
- 'mem_addr_space',
- 'migration',
- 'pc_cpu_hotplug_props',
- 'virtio_version',
- 'x86_cpu_model_versions',
- 'vnc',
-]
-
-tests_x86_64_system_thorough = [
- 'acpi_bits',
- 'intel_iommu',
- 'linux_initrd',
- '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',
-]
+subdir('aarch64')
+subdir('alpha')
+subdir('arm')
+subdir('avr')
+subdir('hppa')
+subdir('i386')
+subdir('loongarch64')
+subdir('m68k')
+subdir('microblaze')
+subdir('microblazeel')
+subdir('mips')
+subdir('mipsel')
+subdir('mips64')
+subdir('mips64el')
+subdir('or1k')
+subdir('ppc')
+subdir('ppc64')
+subdir('riscv32')
+subdir('riscv64')
+subdir('rx')
+subdir('s390x')
+subdir('sh4')
+subdir('sh4eb')
+subdir('sparc')
+subdir('sparc64')
+subdir('x86_64')
+subdir('xtensa')
+subdir('generic')
precache_all = []
foreach speed : ['quick', 'thorough']
@@ -362,7 +66,7 @@ foreach speed : ['quick', 'thorough']
target_tests = get_variable('tests_' + target_base + '_' + sysmode + '_' + speed, [])
endif
- test_deps = roms
+ test_deps = [roms, keymap_targets]
test_env = environment()
if have_tools
test_env.set('QEMU_TEST_QEMU_IMG', meson.global_build_root() / 'qemu-img')
@@ -373,9 +77,19 @@ foreach speed : ['quick', 'thorough']
test_env.set('PYTHONPATH', meson.project_source_root() / 'python:' +
meson.current_source_dir())
+ # Define the GDB environment variable if gdb is available.
+ gdb = get_option('gdb')
+ if gdb != ''
+ test_env.set('QEMU_TEST_GDB', gdb)
+ endif
+
foreach test : target_tests
testname = '@0@-@1@'.format(target_base, test)
- testfile = 'test_' + test + '.py'
+ if 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()
@@ -389,6 +103,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
@@ -404,8 +123,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
@@ -413,4 +132,4 @@ endforeach
run_target('precache-functional',
depends: precache_all,
- command: ['true'])
+ command: [python, '-c', ''])
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/test_microblaze_replay.py b/tests/functional/microblaze/test_replay.py
index 7484c41..7484c41 100755
--- a/tests/functional/test_microblaze_replay.py
+++ b/tests/functional/microblaze/test_replay.py
diff --git a/tests/functional/test_microblaze_s3adsp1800.py b/tests/functional/microblaze/test_s3adsp1800.py
index c93fa14..f093b16 100755
--- a/tests/functional/test_microblaze_s3adsp1800.py
+++ b/tests/functional/microblaze/test_s3adsp1800.py
@@ -25,12 +25,14 @@ class MicroblazeMachine(QemuSystemTest):
('http://www.qemu-advent-calendar.org/2023/download/day13.tar.gz'),
'b9b3d43c5dd79db88ada495cc6e0d1f591153fe41355e925d791fbf44de50c22')
- def do_ballerina_be_test(self, machine):
- self.set_machine(machine)
+ 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')
@@ -39,12 +41,14 @@ class MicroblazeMachine(QemuSystemTest):
# 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, machine):
+ def do_xmaton_le_test(self, force_endianness=False):
self.require_netdev('user')
- self.set_machine(machine)
+ 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()
@@ -59,9 +63,13 @@ class MicroblazeMachine(QemuSystemTest):
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('petalogix-s3adsp1800')
+ self.do_ballerina_be_test()
+
+ def test_microblaze_s3adsp1800_legacy_le(self):
+ self.do_xmaton_le_test(force_endianness=True)
if __name__ == '__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/test_microblazeel_s3adsp1800.py b/tests/functional/microblazeel/test_s3adsp1800.py
index ab59941..75ce885 100755
--- a/tests/functional/test_microblazeel_s3adsp1800.py
+++ b/tests/functional/microblazeel/test_s3adsp1800.py
@@ -7,15 +7,19 @@
# 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
+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('petalogix-s3adsp1800')
+ self.do_xmaton_le_test()
+
+ def test_microblaze_s3adsp1800_legacy_be(self):
+ self.do_ballerina_be_test(force_endianness=True)
if __name__ == '__main__':
diff --git a/tests/functional/test_migration.py b/tests/functional/migration.py
index c4393c3..2bfb1f7 100755..100644
--- a/tests/functional/test_migration.py
+++ b/tests/functional/migration.py
@@ -1,6 +1,6 @@
-#!/usr/bin/env python3
+# SPDX-License-Identifier: GPL-2.0-or-later
#
-# Migration test
+# Migration test base class
#
# Copyright (c) 2019 Red Hat, Inc.
#
@@ -14,7 +14,7 @@
import tempfile
import time
-from qemu_test import QemuSystemTest, skipIfMissingCommands
+from qemu_test import QemuSystemTest, which
from qemu_test.ports import Ports
@@ -30,35 +30,18 @@ class MigrationTest(QemuSystemTest):
end = time.monotonic() + self.timeout
while time.monotonic() < end and not self.migration_finished(src_vm):
- time.sleep(0.1)
+ time.sleep(0.1)
end = time.monotonic() + self.timeout
while time.monotonic() < end and not self.migration_finished(dst_vm):
- time.sleep(0.1)
+ 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()
@@ -76,23 +59,21 @@ class MigrationTest(QemuSystemTest):
self.skipTest('Failed to find a free port')
return port
- def test_migration_with_tcp_localhost(self):
+ 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 test_migration_with_unix(self):
+ 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)
- @skipIfMissingCommands('ncat')
- def test_migration_with_exec(self):
+ 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)
-
-if __name__ == '__main__':
- QemuSystemTest.main()
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/test_mips_malta.py b/tests/functional/mips/test_malta.py
index 89b9556..7a734bc 100755
--- a/tests/functional/test_mips_malta.py
+++ b/tests/functional/mips/test_malta.py
@@ -9,6 +9,7 @@
import os
from qemu_test import LinuxKernelTest, Asset, wait_for_console_pattern
+from qemu_test import skipFlakyTest
from qemu_test import exec_command_and_wait_for_pattern
@@ -80,10 +81,8 @@ def mips_check_wheezy(test, kernel_path, image_path, kernel_command_line,
exec_command_and_wait_for_pattern(test, 'cat /proc/devices', 'usb')
exec_command_and_wait_for_pattern(test, 'cat /proc/ioports',
' : piix4_smbus')
- # lspci for the host bridge does not work on big endian targets:
- # https://gitlab.com/qemu-project/qemu/-/issues/2826
- # exec_command_and_wait_for_pattern(test, 'lspci -d 11ab:4620',
- # 'GT-64120')
+ 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')
@@ -183,6 +182,7 @@ class MaltaMachineConsole(LinuxKernelTest):
'debian_wheezy_mips_standard.qcow2'),
'de03599285b8382ad309309a6c4869f6c6c42a5cfc983342bab9ec0dfa7849a2')
+ @skipFlakyTest("https://gitlab.com/qemu-project/qemu/-/issues/3109")
def test_wheezy(self):
kernel_path = self.ASSET_WHEEZY_KERNEL.fetch()
image_path = self.ASSET_WHEEZY_DISK.fetch()
diff --git a/tests/functional/test_mips_replay.py b/tests/functional/mips/test_replay.py
index 4327481..747835b 100755
--- a/tests/functional/test_mips_replay.py
+++ b/tests/functional/mips/test_replay.py
@@ -5,6 +5,7 @@
# SPDX-License-Identifier: GPL-2.0-or-later
from qemu_test import Asset, skipSlowTest
+from qemu_test import skipFlakyTest
from replay_kernel import ReplayKernelBase
@@ -16,6 +17,7 @@ class MipsReplay(ReplayKernelBase):
'linux-image-2.6.32-5-4kc-malta_2.6.32-48_mips.deb'),
'16ca524148afb0626f483163e5edf352bc1ab0e4fc7b9f9d473252762f2c7a43')
+ @skipFlakyTest("https://gitlab.com/qemu-project/qemu/-/issues/2013")
def test_replay_mips_malta(self):
self.set_machine('malta')
kernel_path = self.archive_extract(self.ASSET_KERNEL_2_63_2,
diff --git a/tests/functional/test_mips_tuxrun.py b/tests/functional/mips/test_tuxrun.py
index 6771dbd..6771dbd 100755
--- a/tests/functional/test_mips_tuxrun.py
+++ b/tests/functional/mips/test_tuxrun.py
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/test_mips64_malta.py b/tests/functional/mips64/test_malta.py
index 53c3e0c..91c57c5 100755
--- a/tests/functional/test_mips64_malta.py
+++ b/tests/functional/mips64/test_malta.py
@@ -5,7 +5,8 @@
# SPDX-License-Identifier: GPL-2.0-or-later
from qemu_test import LinuxKernelTest, Asset
-from test_mips_malta import mips_check_wheezy
+from qemu_test import skipFlakyTest
+from mips.test_malta import mips_check_wheezy
class MaltaMachineConsole(LinuxKernelTest):
@@ -20,6 +21,7 @@ class MaltaMachineConsole(LinuxKernelTest):
'debian_wheezy_mips_standard.qcow2'),
'de03599285b8382ad309309a6c4869f6c6c42a5cfc983342bab9ec0dfa7849a2')
+ @skipFlakyTest("https://gitlab.com/qemu-project/qemu/-/issues/3109")
def test_wheezy(self):
kernel_path = self.ASSET_WHEEZY_KERNEL.fetch()
image_path = self.ASSET_WHEEZY_DISK.fetch()
diff --git a/tests/functional/test_mips64_tuxrun.py b/tests/functional/mips64/test_tuxrun.py
index 0e4c659..0e4c659 100755
--- a/tests/functional/test_mips64_tuxrun.py
+++ b/tests/functional/mips64/test_tuxrun.py
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/test_mips64el_fuloong2e.py b/tests/functional/mips64el/test_fuloong2e.py
index 35e500b..35e500b 100755
--- a/tests/functional/test_mips64el_fuloong2e.py
+++ b/tests/functional/mips64el/test_fuloong2e.py
diff --git a/tests/functional/test_mips64el_loongson3v.py b/tests/functional/mips64el/test_loongson3v.py
index f85371e..f85371e 100755
--- a/tests/functional/test_mips64el_loongson3v.py
+++ b/tests/functional/mips64el/test_loongson3v.py
diff --git a/tests/functional/test_mips64el_malta.py b/tests/functional/mips64el/test_malta.py
index dd37212..bc750cb 100755
--- a/tests/functional/test_mips64el_malta.py
+++ b/tests/functional/mips64el/test_malta.py
@@ -10,13 +10,12 @@
# 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
+from mips.test_malta import mips_check_wheezy
class MaltaMachineConsole(LinuxKernelTest):
@@ -50,7 +49,7 @@ class MaltaMachineConsole(LinuxKernelTest):
self.vm.add_args('-kernel', kernel_path,
'-append', kernel_command_line)
self.vm.launch()
- console_pattern = 'Kernel command line: %s' % kernel_command_line
+ console_pattern = f'Kernel command line: {kernel_command_line}'
self.wait_for_console_pattern(console_pattern)
ASSET_KERNEL_3_19_3 = Asset(
@@ -66,7 +65,7 @@ class MaltaMachineConsole(LinuxKernelTest):
'75ba10cd35fb44e32948eeb26974f061b703c81c4ba2fab1ebcacf1d1bec3b61')
@skipUntrustedTest()
- def test_mips64el_malta_5KEc_cpio(self):
+ def test_mips64el_malta_5kec_cpio(self):
kernel_path = self.ASSET_KERNEL_3_19_3.fetch()
initrd_path = self.uncompress(self.ASSET_CPIO_R1)
@@ -102,6 +101,7 @@ class MaltaMachineConsole(LinuxKernelTest):
'debian_wheezy_mipsel_standard.qcow2'),
'454f09ae39f7e6461c84727b927100d2c7813841f2a0a5dce328114887ecf914')
+ @skipFlakyTest("https://gitlab.com/qemu-project/qemu/-/issues/3109")
def test_wheezy(self):
kernel_path = self.ASSET_WHEEZY_KERNEL.fetch()
image_path = self.ASSET_WHEEZY_DISK.fetch()
@@ -133,8 +133,8 @@ class MaltaMachineFramebuffer(LinuxKernelTest):
Boot Linux kernel and check Tux logo is displayed on the framebuffer.
"""
- import numpy as np
- import cv2
+ import numpy as np # pylint: disable=import-outside-toplevel
+ import cv2 # pylint: disable=import-outside-toplevel
screendump_path = self.scratch_file('screendump.pbm')
@@ -148,16 +148,17 @@ class MaltaMachineFramebuffer(LinuxKernelTest):
'clocksource=GIC console=tty0 console=ttyS0')
self.vm.add_args('-kernel', kernel_path,
'-cpu', 'I6400',
- '-smp', '%u' % cpu_cores_count,
+ '-smp', str(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')
- self.vm.cmd('human-monitor-command',
- command_line='screendump %s' % screendump_path)
- logger = logging.getLogger('framebuffer')
+ res = self.vm.cmd('human-monitor-command',
+ command_line=f'screendump {screendump_path}')
+ if 'unknown command' in res:
+ self.skipTest('screendump not available')
match_threshold = 0.95
screendump_bgr = cv2.imread(screendump_path, cv2.IMREAD_COLOR)
@@ -169,7 +170,7 @@ class MaltaMachineFramebuffer(LinuxKernelTest):
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)
+ self.log.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:
@@ -189,7 +190,9 @@ class MaltaMachineFramebuffer(LinuxKernelTest):
self.do_test_i6400_framebuffer_logo(8)
-from test_mipsel_malta import MaltaMachineYAMON
+# Add the tests from the 32-bit mipsel file here, too.
+# pylint: disable=unused-import,wrong-import-position
+from mipsel.test_malta import MaltaMachineYAMON
if __name__ == '__main__':
LinuxKernelTest.main()
diff --git a/tests/functional/test_mips64el_replay.py b/tests/functional/mips64el/test_replay.py
index 26a6ccf..9a432be 100755
--- a/tests/functional/test_mips64el_replay.py
+++ b/tests/functional/mips64el/test_replay.py
@@ -5,6 +5,7 @@
# SPDX-License-Identifier: GPL-2.0-or-later
from qemu_test import Asset, skipUntrustedTest
+from qemu_test import skipFlakyTest
from replay_kernel import ReplayKernelBase
@@ -16,12 +17,13 @@ class Mips64elReplay(ReplayKernelBase):
'linux-image-2.6.32-5-5kc-malta_2.6.32-48_mipsel.deb'),
'35eb476f03be589824b0310358f1c447d85e645b88cbcd2ac02b97ef560f9f8d')
+ @skipFlakyTest("https://gitlab.com/qemu-project/qemu/-/issues/2013")
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
+ console_pattern = f'Kernel command line: {kernel_command_line}'
self.run_rr(kernel_path, kernel_command_line, console_pattern, shift=5)
@@ -38,7 +40,8 @@ class Mips64elReplay(ReplayKernelBase):
'75ba10cd35fb44e32948eeb26974f061b703c81c4ba2fab1ebcacf1d1bec3b61')
@skipUntrustedTest()
- def test_replay_mips64el_malta_5KEc_cpio(self):
+ @skipFlakyTest("https://gitlab.com/qemu-project/qemu/-/issues/2013")
+ def test_replay_mips64el_malta_5kec_cpio(self):
self.set_machine('malta')
self.cpu = '5KEc'
kernel_path = self.ASSET_KERNEL_3_19_3.fetch()
diff --git a/tests/functional/test_mips64el_tuxrun.py b/tests/functional/mips64el/test_tuxrun.py
index 0a24757..0a24757 100755
--- a/tests/functional/test_mips64el_tuxrun.py
+++ b/tests/functional/mips64el/test_tuxrun.py
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/test_mipsel_malta.py b/tests/functional/mipsel/test_malta.py
index 9ee2884..59ab4a6 100755
--- a/tests/functional/test_mipsel_malta.py
+++ b/tests/functional/mipsel/test_malta.py
@@ -10,10 +10,11 @@
# SPDX-License-Identifier: GPL-2.0-or-later
from qemu_test import QemuSystemTest, LinuxKernelTest, Asset
+from qemu_test import skipFlakyTest
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
+from mips.test_malta import mips_check_wheezy
class MaltaMachineConsole(LinuxKernelTest):
@@ -69,6 +70,7 @@ class MaltaMachineConsole(LinuxKernelTest):
'debian_wheezy_mipsel_standard.qcow2'),
'454f09ae39f7e6461c84727b927100d2c7813841f2a0a5dce328114887ecf914')
+ @skipFlakyTest("https://gitlab.com/qemu-project/qemu/-/issues/3109")
def test_wheezy(self):
kernel_path = self.ASSET_WHEEZY_KERNEL.fetch()
image_path = self.ASSET_WHEEZY_DISK.fetch()
diff --git a/tests/functional/test_mipsel_replay.py b/tests/functional/mipsel/test_replay.py
index 5f4796c..5f4796c 100644..100755
--- a/tests/functional/test_mipsel_replay.py
+++ b/tests/functional/mipsel/test_replay.py
diff --git a/tests/functional/test_mipsel_tuxrun.py b/tests/functional/mipsel/test_tuxrun.py
index d4b39ba..d4b39ba 100755
--- a/tests/functional/test_mipsel_tuxrun.py
+++ b/tests/functional/mipsel/test_tuxrun.py
diff --git a/tests/functional/test_multiprocess.py b/tests/functional/multiprocess.py
index 751cf10..6a06c1e 100755..100644
--- a/tests/functional/test_multiprocess.py
+++ b/tests/functional/multiprocess.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python3
+# SPDX-License-Identifier: GPL-2.0-or-later
#
# Test for multiprocess qemu
#
@@ -9,33 +9,13 @@
import os
import socket
-from qemu_test import QemuSystemTest, Asset, wait_for_console_pattern
+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 '
- 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"""
@@ -83,18 +63,5 @@ class Multiprocess(QemuSystemTest):
'cat /sys/bus/pci/devices/*/uevent',
'PCI_ID=1000:0012')
- 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()
+ proxy_sock.close()
+ remote_sock.close()
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/test_or1k_replay.py b/tests/functional/or1k/test_replay.py
index 2b60a93..2b60a93 100755
--- a/tests/functional/test_or1k_replay.py
+++ b/tests/functional/or1k/test_replay.py
diff --git a/tests/functional/test_or1k_sim.py b/tests/functional/or1k/test_sim.py
index f9f0b69..f9f0b69 100755
--- a/tests/functional/test_or1k_sim.py
+++ b/tests/functional/or1k/test_sim.py
diff --git a/tests/functional/ppc/meson.build b/tests/functional/ppc/meson.build
new file mode 100644
index 0000000..ae061fe
--- /dev/null
+++ b/tests/functional/ppc/meson.build
@@ -0,0 +1,23 @@
+# 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',
+ 'ppe42',
+ 'replay',
+ 'sam460ex',
+ 'tuxrun',
+ 'virtex_ml507',
+]
diff --git a/tests/functional/test_ppc_40p.py b/tests/functional/ppc/test_40p.py
index 614972a..614972a 100755
--- a/tests/functional/test_ppc_40p.py
+++ b/tests/functional/ppc/test_40p.py
diff --git a/tests/functional/test_ppc_74xx.py b/tests/functional/ppc/test_74xx.py
index 5386016..219c799 100755
--- a/tests/functional/test_ppc_74xx.py
+++ b/tests/functional/ppc/test_74xx.py
@@ -10,7 +10,7 @@
from qemu_test import QemuSystemTest
from qemu_test import wait_for_console_pattern
-class ppc74xxCpu(QemuSystemTest):
+class Ppc74xxCpu(QemuSystemTest):
timeout = 5
diff --git a/tests/functional/test_ppc_amiga.py b/tests/functional/ppc/test_amiga.py
index 8600e2e..36378fb 100755
--- a/tests/functional/test_ppc_amiga.py
+++ b/tests/functional/ppc/test_amiga.py
@@ -15,8 +15,6 @@ 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'),
@@ -25,19 +23,19 @@ class AmigaOneMachine(QemuSystemTest):
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)
+ stdout=bios_fh, check=True)
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/test_ppc_mac.py b/tests/functional/ppc/test_mac.py
index 9e4bc1a..9e4bc1a 100755
--- a/tests/functional/test_ppc_mac.py
+++ b/tests/functional/ppc/test_mac.py
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/test_ppc_mpc8544ds.py b/tests/functional/ppc/test_mpc8544ds.py
index 0715410..0715410 100755
--- a/tests/functional/test_ppc_mpc8544ds.py
+++ b/tests/functional/ppc/test_mpc8544ds.py
diff --git a/tests/functional/ppc/test_ppe42.py b/tests/functional/ppc/test_ppe42.py
new file mode 100644
index 0000000..7b360a4
--- /dev/null
+++ b/tests/functional/ppc/test_ppe42.py
@@ -0,0 +1,79 @@
+#!/usr/bin/env python3
+#
+# Functional tests for the IBM PPE42 processor
+#
+# Copyright (c) 2025, IBM Corporation
+#
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+import asyncio
+from qemu_test import QemuSystemTest, Asset
+
+
+class Ppe42Machine(QemuSystemTest):
+
+ timeout = 90
+ poll_period = 1.0
+
+ ASSET_PPE42_TEST_IMAGE = Asset(
+ ('https://github.com/milesg-github/ppe42-tests/raw/refs/heads/main/'
+ 'images/ppe42-test.out'),
+ '03c1ac0fb7f6c025102a02776a93b35101dae7c14b75e4eab36a337e39042ea8')
+
+ def _test_completed(self):
+ self.log.info("Checking for test completion...")
+ try:
+ output = self.vm.cmd('human-monitor-command',
+ command_line='info registers')
+ except Exception as err:
+ self.log.debug(f"'info registers' cmd failed due to {err=},"
+ " {type(err)=}")
+ raise
+
+ self.log.info(output)
+ if "NIP fff80200" not in output:
+ self.log.info("<test not completed>")
+ return False
+
+ self.log.info("<test completed>")
+ return True
+
+ def _wait_pass_fail(self, timeout):
+ while not self._test_completed():
+ if timeout >= self.poll_period:
+ timeout = timeout - self.poll_period
+ self.log.info(f"Waiting {self.poll_period} seconds for test"
+ " to complete...")
+ e = None
+ try:
+ e = self.vm.event_wait('STOP', self.poll_period)
+
+ except asyncio.TimeoutError:
+ self.log.info("Poll period ended.")
+
+ except Exception as err:
+ self.log.debug(f"event_wait() failed due to {err=},"
+ " {type(err)=}")
+ raise
+
+ if e is not None:
+ self.log.debug(f"Execution stopped: {e}")
+ self.log.debug("Exiting due to test failure")
+ self.fail("Failure detected!")
+ break
+ else:
+ self.fail("Timed out waiting for test completion.")
+
+ def test_ppe42_instructions(self):
+ self.set_machine('ppe42_machine')
+ self.require_accelerator("tcg")
+ image_path = self.ASSET_PPE42_TEST_IMAGE.fetch()
+ self.vm.add_args('-nographic')
+ self.vm.add_args('-device', f'loader,file={image_path}')
+ self.vm.add_args('-device', 'loader,addr=0xfff80040,cpu-num=0')
+ self.vm.add_args('-action', 'panic=pause')
+ self.vm.launch()
+ self._wait_pass_fail(self.timeout)
+
+if __name__ == '__main__':
+ QemuSystemTest.main()
diff --git a/tests/functional/test_ppc_replay.py b/tests/functional/ppc/test_replay.py
index 8382070..8382070 100755
--- a/tests/functional/test_ppc_replay.py
+++ b/tests/functional/ppc/test_replay.py
diff --git a/tests/functional/test_ppc_sam460ex.py b/tests/functional/ppc/test_sam460ex.py
index 31cf9dd..024406d 100644..100755
--- a/tests/functional/test_ppc_sam460ex.py
+++ b/tests/functional/ppc/test_sam460ex.py
@@ -8,10 +8,11 @@ from qemu_test import LinuxKernelTest, Asset
from qemu_test import exec_command_and_wait_for_pattern
-class sam460exTest(LinuxKernelTest):
+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',
+ ('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):
diff --git a/tests/functional/test_ppc_tuxrun.py b/tests/functional/ppc/test_tuxrun.py
index 5458a7f..5458a7f 100755
--- a/tests/functional/test_ppc_tuxrun.py
+++ b/tests/functional/ppc/test_tuxrun.py
diff --git a/tests/functional/test_ppc_virtex_ml507.py b/tests/functional/ppc/test_virtex_ml507.py
index 8fe4354..8fe4354 100755
--- a/tests/functional/test_ppc_virtex_ml507.py
+++ b/tests/functional/ppc/test_virtex_ml507.py
diff --git a/tests/functional/ppc64/meson.build b/tests/functional/ppc64/meson.build
new file mode 100644
index 0000000..f0f8ab8
--- /dev/null
+++ b/tests/functional/ppc64/meson.build
@@ -0,0 +1,28 @@
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+test_ppc64_timeouts = {
+ 'fadump' : 480,
+ 'hv' : 1000,
+ 'mac99' : 120,
+ 'powernv' : 480,
+ 'pseries' : 480,
+ 'replay' : 210,
+ 'tuxrun' : 420,
+}
+
+tests_ppc64_system_quick = [
+ 'migration',
+ 'vmstate',
+]
+
+tests_ppc64_system_thorough = [
+ 'e500',
+ 'fadump',
+ 'hv',
+ 'mac99',
+ 'powernv',
+ 'pseries',
+ 'replay',
+ 'reverse_debug',
+ 'tuxrun',
+]
diff --git a/tests/functional/test_ppc64_e500.py b/tests/functional/ppc64/test_e500.py
index f5fcad9..f5fcad9 100755
--- a/tests/functional/test_ppc64_e500.py
+++ b/tests/functional/ppc64/test_e500.py
diff --git a/tests/functional/ppc64/test_fadump.py b/tests/functional/ppc64/test_fadump.py
new file mode 100755
index 0000000..2d6b801
--- /dev/null
+++ b/tests/functional/ppc64/test_fadump.py
@@ -0,0 +1,182 @@
+#!/usr/bin/env python3
+#
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+from unittest import skip
+from qemu_test import Asset
+from qemu_test import wait_for_console_pattern
+from qemu_test import LinuxKernelTest
+from qemu_test import exec_command, exec_command_and_wait_for_pattern
+
+class QEMUFadump(LinuxKernelTest):
+ """
+ Functional test to verify Fadump is working in following scenarios:
+
+ 1. test_fadump_pseries: PSeries
+ 2. test_fadump_pseries_kvm: PSeries + KVM
+ """
+
+ timeout = 90
+ KERNEL_COMMON_COMMAND_LINE = 'console=hvc0 fadump=on '
+ msg_panic = 'Kernel panic - not syncing'
+ msg_not_supported = 'Firmware-Assisted Dump is not supported on this hardware'
+ msg_registered_success = ''
+ msg_registered_failed = ''
+ msg_dump_active = ''
+
+ ASSET_EPAPR_KERNEL = Asset(
+ ('https://github.com/open-power/op-build/releases/download/v2.7/'
+ 'zImage.epapr'),
+ '0ab237df661727e5392cee97460e8674057a883c5f74381a128fa772588d45cd')
+
+ ASSET_VMLINUZ_KERNEL = Asset(
+ ('https://archives.fedoraproject.org/pub/archive/fedora-secondary/'
+ 'releases/39/Everything/ppc64le/os/ppc/ppc64/vmlinuz'),
+ ('81e5541d243b50c8f9568906c6918dda22239744d637bb9a7b22d23c3d661226'
+ '8d5302beb2ca5c06f93bdbc9736c414ef5120756c8bf496ff488ad07d116d67f')
+ )
+
+ ASSET_FEDORA_INITRD = Asset(
+ ('https://archives.fedoraproject.org/pub/archive/fedora-secondary/'
+ 'releases/39/Everything/ppc64le/os/ppc/ppc64/initrd.img'),
+ 'e7f24b44cb2aaa67d30e551db6ac8d29cc57c934b158dabca6b7f885f2cfdd9b')
+
+ def do_test_fadump(self, is_kvm=False, is_powernv=False):
+ """
+ Helper Function for Fadump tests below
+
+ It boots the VM with fadump enabled, checks if fadump is correctly
+ registered.
+ Then crashes the system causing a QEMU_SYSTEM_RESET, after which
+ dump should be available in the kernel.
+ Finally it checks the filesize of the exported /proc/vmcore in 2nd
+ kernel to verify it's same as the VM's memory size
+ """
+ if is_kvm:
+ self.require_accelerator("kvm")
+ self.vm.add_args("-accel", "kvm")
+ else:
+ self.require_accelerator("tcg")
+
+ if is_powernv:
+ self.set_machine("powernv10")
+ else:
+ # SLOF takes upto >20s in startup time, use VOF
+ self.set_machine("pseries")
+ self.vm.add_args("-machine", "x-vof=on")
+ self.vm.add_args("-m", "6G")
+
+ self.vm.set_console()
+
+ kernel_path = None
+
+ if is_powernv:
+ kernel_path = self.ASSET_EPAPR_KERNEL.fetch()
+ else:
+ kernel_path = self.ASSET_VMLINUZ_KERNEL.fetch()
+
+ initrd_path = self.ASSET_FEDORA_INITRD.fetch()
+
+ self.vm.add_args('-kernel', kernel_path)
+ self.vm.add_args('-initrd', initrd_path)
+ self.vm.add_args('-append', "fadump=on"\
+ " -nodefaults -serial mon:stdio crashkernel=2G"\
+ " rdinit=/bin/sh ")
+
+ self.vm.launch()
+
+ # If kernel detects fadump support, and "fadump=on" is in command
+ # line which we add above, it will print something like:
+ #
+ # fadump: Reserved 1024MB of memory at 0x00000040000000 ...
+ #
+ # Else, if the kernel doesn't detect fadump support, it prints:
+ #
+ # fadump: Firmware-Assisted Dump is not supported on this hardware
+ #
+ # Timeout after 20s if kernel doesn't print any fadump logs, this
+ # can happen due to fadump being disabled in the kernel
+ self.wait_for_regex_console_pattern(
+ success_pattern="fadump: Reserved ",
+ failure_pattern=r"fadump: (Firmware-Assisted Dump is not"\
+ " supported on this hardware|Failed to find memory chunk for"\
+ " reservation!)",
+ timeout=20
+ )
+
+ # Ensure fadump is registered successfully, if registration
+ # succeeds, we get a log from rtas fadump:
+ #
+ # rtas fadump: Registration is successful!
+ self.wait_for_console_pattern(
+ "rtas fadump: Registration is successful!"
+ )
+
+ # Wait for the shell
+ self.wait_for_console_pattern("#")
+
+ # Mount /proc since not available in the initrd used
+ exec_command(self, command="mount -t proc proc /proc")
+
+ # Crash the kernel
+ exec_command(self, command="echo c > /proc/sysrq-trigger")
+
+ # Check for the kernel panic message, setting timeout to 20s as it
+ # should occur almost immediately after previous echo c
+ self.wait_for_regex_console_pattern(
+ success_pattern="Kernel panic - not syncing: sysrq" \
+ " triggered crash",
+ timeout=20
+ )
+
+ # Check if fadump is active
+ # If the kernel shows that fadump is active, that implies it's a
+ # crashkernel boot
+ # Else if the kernel shows "fadump: Reserved ..." then it's
+ # treating this as the first kernel boot, this is likely the case
+ # that qemu didn't pass the 'ibm,kernel-dump' device tree node
+ wait_for_console_pattern(
+ test=self,
+ success_message="rtas fadump: Firmware-assisted dump is active",
+ failure_message="fadump: Reserved "
+ )
+
+ # In a successful fadump boot, we get these logs:
+ #
+ # [ 0.000000] fadump: Firmware-assisted dump is active.
+ # [ 0.000000] fadump: Reserving <>MB of memory at <> for preserving crash data
+ #
+ # Check if these logs are present in the fadump boot
+ self.wait_for_console_pattern("preserving crash data")
+
+ # Wait for prompt
+ self.wait_for_console_pattern("sh-5.2#")
+
+ # Mount /proc since not available in the initrd used
+ exec_command_and_wait_for_pattern(self,
+ command="mount -t proc proc /proc",
+ success_message="#"
+ )
+
+ # Check if vmcore exists
+ exec_command_and_wait_for_pattern(self,
+ command="stat /proc/vmcore",
+ success_message="File: /proc/vmcore",
+ failure_message="No such file or directory"
+ )
+
+ def test_fadump_pseries(self):
+ return self.do_test_fadump(is_kvm=False, is_powernv=False)
+
+ @skip("PowerNV Fadump not supported yet")
+ def test_fadump_powernv(self):
+ return
+
+ def test_fadump_pseries_kvm(self):
+ """
+ Test Fadump in PSeries with KVM accel
+ """
+ self.do_test_fadump(is_kvm=True, is_powernv=False)
+
+if __name__ == '__main__':
+ QEMUFadump.main()
diff --git a/tests/functional/test_ppc64_hv.py b/tests/functional/ppc64/test_hv.py
index d87f440..d87f440 100755
--- a/tests/functional/test_ppc64_hv.py
+++ b/tests/functional/ppc64/test_hv.py
diff --git a/tests/functional/test_ppc64_mac99.py b/tests/functional/ppc64/test_mac99.py
index dfd9c01..a3261a8 100755
--- a/tests/functional/test_ppc64_mac99.py
+++ b/tests/functional/ppc64/test_mac99.py
@@ -7,14 +7,16 @@
from qemu_test import LinuxKernelTest, Asset
from qemu_test import exec_command_and_wait_for_pattern
-class mac99Test(LinuxKernelTest):
+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',
+ ('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',
+ ('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):
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/test_ppc64_powernv.py b/tests/functional/ppc64/test_powernv.py
index 685e217..0ea6c93 100755
--- a/tests/functional/test_ppc64_powernv.py
+++ b/tests/functional/ppc64/test_powernv.py
@@ -10,7 +10,7 @@
from qemu_test import LinuxKernelTest, Asset
from qemu_test import wait_for_console_pattern
-class powernvMachine(LinuxKernelTest):
+class PowernvMachine(LinuxKernelTest):
timeout = 90
KERNEL_COMMON_COMMAND_LINE = 'printk.time=0 console=hvc0 '
@@ -18,9 +18,14 @@ class powernvMachine(LinuxKernelTest):
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')
+ ('https://github.com/legoater/qemu-ppc-boot/raw/refs/heads/main/'
+ 'buildroot/qemu_ppc64le_powernv8-2025.02/vmlinux'),
+ '6fd29aff9ad4362511ea5d0acbb510667c7031928e97d64ec15bbc5daf4b8151')
+
+ ASSET_INITRD = Asset(
+ ('https://github.com/legoater/qemu-ppc-boot/raw/refs/heads/main/'
+ 'buildroot/qemu_ppc64le_powernv8-2025.02/rootfs.ext2'),
+ 'aee2192b692077c4bde31cb56ce474424b358f17cec323d5c94af3970c9aada2')
def do_test_linux_boot(self, command_line = KERNEL_COMMON_COMMAND_LINE):
self.require_accelerator("tcg")
@@ -78,27 +83,24 @@ class powernvMachine(LinuxKernelTest):
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()
+ kernel_path = self.ASSET_KERNEL.fetch()
+ initrd_path = self.ASSET_INITRD.fetch()
self.vm.set_console()
self.vm.add_args('-kernel', kernel_path,
- '-append', 'console=tty0 console=hvc0',
+ '-drive',
+ f'file={initrd_path},format=raw,if=none,id=drive0,readonly=on',
+ '-append', 'root=/dev/nvme0n1 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', 'nvme,drive=drive0,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")
+ self.wait_for_console_pattern("INIT: Starting kernel at ")
+ self.wait_for_console_pattern("Run /sbin/init as init process")
# Device detection output driven by udev probing is sometimes cut off
# from console output, suspect S14silence-console init script.
@@ -114,5 +116,9 @@ class powernvMachine(LinuxKernelTest):
self.set_machine('powernv10')
self.do_test_ppc64_powernv('P10')
+ def test_powernv11(self):
+ self.set_machine('powernv11')
+ self.do_test_ppc64_powernv('Power11')
+
if __name__ == '__main__':
LinuxKernelTest.main()
diff --git a/tests/functional/test_ppc64_pseries.py b/tests/functional/ppc64/test_pseries.py
index 6705793..7840c4e 100755
--- a/tests/functional/test_ppc64_pseries.py
+++ b/tests/functional/ppc64/test_pseries.py
@@ -10,7 +10,7 @@
from qemu_test import QemuSystemTest, Asset
from qemu_test import wait_for_console_pattern
-class pseriesMachine(QemuSystemTest):
+class PseriesMachine(QemuSystemTest):
timeout = 90
KERNEL_COMMON_COMMAND_LINE = 'printk.time=0 console=hvc0 '
diff --git a/tests/functional/test_ppc64_replay.py b/tests/functional/ppc64/test_replay.py
index e8c9c4b..e8c9c4b 100755
--- a/tests/functional/test_ppc64_replay.py
+++ b/tests/functional/ppc64/test_replay.py
diff --git a/tests/functional/test_ppc64_reverse_debug.py b/tests/functional/ppc64/test_reverse_debug.py
index 5931ade..4eef779 100755
--- a/tests/functional/test_ppc64_reverse_debug.py
+++ b/tests/functional/ppc64/test_reverse_debug.py
@@ -2,24 +2,23 @@
#
# SPDX-License-Identifier: GPL-2.0-or-later
#
-# Reverse debugging test
+# Reverse debugging test for ppc64
#
# Copyright (c) 2020 ISP RAS
+# Copyright (c) 2025 Linaro Limited
#
# Author:
# Pavel Dovgalyuk <Pavel.Dovgalyuk@ispras.ru>
+# Gustavo Romero <gustavo.romero@linaro.org> (Run without Avocado)
#
# 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 qemu_test import skipFlakyTest
from reverse_debugging import ReverseDebugging
-@skipIfMissingImports('avocado.utils')
-class ReverseDebugging_ppc64(ReverseDebugging):
-
- REG_PC = 0x40
+class ReverseDebuggingPpc64(ReverseDebugging):
@skipFlakyTest("https://gitlab.com/qemu-project/qemu/-/issues/1992")
def test_ppc64_pseries(self):
@@ -27,14 +26,12 @@ class ReverseDebugging_ppc64(ReverseDebugging):
# 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()
+ self.reverse_debugging(gdb_arch='powerpc:common64')
@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()
+ self.reverse_debugging(gdb_arch='powerpc:common64')
if __name__ == '__main__':
diff --git a/tests/functional/test_ppc64_tuxrun.py b/tests/functional/ppc64/test_tuxrun.py
index e8f79c6..e8f79c6 100755
--- a/tests/functional/test_ppc64_tuxrun.py
+++ b/tests/functional/ppc64/test_tuxrun.py
diff --git a/tests/functional/qemu_test/__init__.py b/tests/functional/qemu_test/__init__.py
index af41c2c..3201935 100644
--- a/tests/functional/qemu_test/__init__.py
+++ b/tests/functional/qemu_test/__init__.py
@@ -15,6 +15,8 @@ from .testcase import QemuBaseTest, QemuUserTest, QemuSystemTest
from .linuxkernel import LinuxKernelTest
from .decorators import skipIfMissingCommands, skipIfNotMachine, \
skipFlakyTest, skipUntrustedTest, skipBigDataTest, skipSlowTest, \
- skipIfMissingImports, skipIfOperatingSystem
+ skipIfMissingImports, skipIfOperatingSystem, skipLockedMemoryTest, \
+ skipIfMissingEnv
from .archive import archive_extract
from .uncompress import uncompress
+from .gdb import GDB
diff --git a/tests/functional/qemu_test/asset.py b/tests/functional/qemu_test/asset.py
index 704b84d..bae4076 100644
--- a/tests/functional/qemu_test/asset.py
+++ b/tests/functional/qemu_test/asset.py
@@ -10,12 +10,13 @@ import logging
import os
import stat
import sys
+import time
import unittest
import urllib.request
from time import sleep
from pathlib import Path
from shutil import copyfileobj
-from urllib.error import HTTPError
+from urllib.error import HTTPError, URLError
class AssetError(Exception):
def __init__(self, asset, msg, transient=False):
@@ -72,6 +73,10 @@ class Asset:
return self.hash == hl.hexdigest()
def valid(self):
+ if os.getenv("QEMU_TEST_REFRESH_CACHE", None) is not None:
+ self.log.info("Force refresh of asset %s", self.url)
+ return False
+
return self.cache_file.exists() and self._check(self.cache_file)
def fetchable(self):
@@ -107,7 +112,17 @@ class Asset:
return False
self.log.debug("Time out while waiting for %s!", tmp_cache_file)
- raise
+ raise TimeoutError(f"Time out while waiting for {tmp_cache_file}")
+
+ def _save_time_stamp(self):
+ '''
+ Update the time stamp of the asset in the cache. Unfortunately, we
+ cannot use the modification or access time of the asset file itself,
+ since e.g. the functional jobs in the gitlab CI reload the files
+ from the gitlab cache and thus always have recent file time stamps,
+ so we have to save our asset time stamp to a separate file instead.
+ '''
+ self.cache_file.with_suffix(".stamp").write_text(f"{int(time.time())}")
def fetch(self):
if not self.cache_dir.exists():
@@ -116,6 +131,7 @@ class Asset:
if self.valid():
self.log.debug("Using cached asset %s for %s",
self.cache_file, self.url)
+ self._save_time_stamp()
return str(self.cache_file)
if not self.fetchable():
@@ -125,7 +141,7 @@ class Asset:
self.log.info("Downloading %s to %s...", self.url, self.cache_file)
tmp_cache_file = self.cache_file.with_suffix(".download")
- for retries in range(3):
+ for _retries in range(3):
try:
with tmp_cache_file.open("xb") as dst:
with urllib.request.urlopen(self.url) as resp:
@@ -165,11 +181,27 @@ class Asset:
# server or networking problem
if e.code == 404:
raise AssetError(self, "Unable to download: "
- "HTTP error %d" % e.code)
+ "HTTP error %d" % e.code) from e
+ continue
+ except URLError as e:
+ # This is typically a network/service level error
+ # eg urlopen error [Errno 110] Connection timed out>
+ tmp_cache_file.unlink()
+ self.log.error("Unable to download %s: URL error %s",
+ self.url, e.reason)
+ raise AssetError(self, "Unable to download: URL error %s" %
+ e.reason, transient=True) from e
+ except ConnectionError as e:
+ # A socket connection failure, such as dropped conn
+ # or refused conn
+ tmp_cache_file.unlink()
+ self.log.error("Unable to download %s: Connection error %s",
+ self.url, e)
continue
except Exception as e:
tmp_cache_file.unlink()
- raise AssetError(self, "Unable to download: " % e)
+ raise AssetError(self, "Unable to download: %s" % e,
+ transient=True) from e
if not os.path.exists(tmp_cache_file):
raise AssetError(self, "Download retries exceeded", transient=True)
@@ -182,18 +214,19 @@ class Asset:
self.hash.encode('utf8'))
except Exception as e:
self.log.debug("Unable to set xattr on %s: %s", tmp_cache_file, e)
- pass
if not self._check(tmp_cache_file):
tmp_cache_file.unlink()
raise AssetError(self, "Hash does not match %s" % self.hash)
tmp_cache_file.replace(self.cache_file)
+ self._save_time_stamp()
# Remove write perms to stop tests accidentally modifying them
os.chmod(self.cache_file, stat.S_IRUSR | stat.S_IRGRP)
- self.log.info("Cached %s at %s" % (self.url, self.cache_file))
+ self.log.info("Cached %s at %s", self.url, self.cache_file)
return str(self.cache_file)
+ @staticmethod
def precache_test(test):
log = logging.getLogger('qemu-test')
log.setLevel(logging.DEBUG)
@@ -204,17 +237,17 @@ class Asset:
handler.setFormatter(formatter)
log.addHandler(handler)
for name, asset in vars(test.__class__).items():
- if name.startswith("ASSET_") and type(asset) == Asset:
- log.info("Attempting to cache '%s'" % asset)
+ if name.startswith("ASSET_") and isinstance(asset, Asset):
try:
asset.fetch()
except AssetError as e:
if not e.transient:
raise
- log.error("%s: skipping asset precache" % e)
+ log.error("%s: skipping asset precache", e)
log.removeHandler(handler)
+ @staticmethod
def precache_suite(suite):
for test in suite:
if isinstance(test, unittest.TestSuite):
@@ -222,9 +255,10 @@ class Asset:
elif isinstance(test, unittest.TestCase):
Asset.precache_test(test)
- def precache_suites(path, cacheTstamp):
+ @staticmethod
+ def precache_suites(path, cache_tstamp):
loader = unittest.loader.defaultTestLoader
tests = loader.loadTestsFromNames([path], None)
- with open(cacheTstamp, "w") as fh:
+ with open(cache_tstamp, "w", encoding='utf-8'):
Asset.precache_suite(tests)
diff --git a/tests/functional/qemu_test/cmd.py b/tests/functional/qemu_test/cmd.py
index dc5f422..f544566 100644
--- a/tests/functional/qemu_test/cmd.py
+++ b/tests/functional/qemu_test/cmd.py
@@ -45,13 +45,16 @@ def is_readable_executable_file(path):
# If end of line is seen, with neither @success or @failure
# return False
#
+# In both cases, also return the contents of the line (in bytes)
+# up to that point.
+#
# If @failure is seen, then mark @test as failed
def _console_read_line_until_match(test, vm, success, failure):
msg = bytes([])
done = False
while True:
c = vm.console_socket.recv(1)
- if c is None:
+ if not c:
done = True
test.fail(
f"EOF in console, expected '{success}'")
@@ -76,10 +79,23 @@ def _console_read_line_until_match(test, vm, success, failure):
except:
console_logger.debug(msg)
- return done
+ return done, msg
def _console_interaction(test, success_message, failure_message,
send_string, keep_sending=False, vm=None):
+ """
+ Interact with the console until either message is seen.
+
+ :param success_message: if this message appears, finish interaction
+ :param failure_message: if this message appears, test fails
+ :param send_string: a string to send to the console before trying
+ to read a new line
+ :param keep_sending: keep sending the send string each time
+ :param vm: the VM to interact with
+
+ :return: The collected output (in bytes form).
+ """
+
assert not keep_sending or send_string
assert success_message or send_string
@@ -101,6 +117,8 @@ def _console_interaction(test, success_message, failure_message,
if failure_message is not None:
failure_message_b = failure_message.encode()
+ out = bytes([])
+
while True:
if send_string:
vm.console_socket.sendall(send_string.encode())
@@ -113,14 +131,21 @@ def _console_interaction(test, success_message, failure_message,
break
continue
- if _console_read_line_until_match(test, vm,
- success_message_b,
- failure_message_b):
+ done, line = _console_read_line_until_match(test, vm,
+ success_message_b,
+ failure_message_b)
+
+ out += line
+
+ if done:
break
+ return out
+
def interrupt_interactive_console_until_pattern(test, success_message,
failure_message=None,
- interrupt_string='\r'):
+ interrupt_string='\r',
+ vm=None):
"""
Keep sending a string to interrupt a console prompt, while logging the
console output. Typical use case is to break a boot loader prompt, such:
@@ -140,10 +165,13 @@ def interrupt_interactive_console_until_pattern(test, success_message,
:param failure_message: if this message appears, test fails
:param interrupt_string: a string to send to the console before trying
to read a new line
+ :param vm: VM to use
+
+ :return: The collected output (in bytes form).
"""
assert success_message
- _console_interaction(test, success_message, failure_message,
- interrupt_string, True)
+ return _console_interaction(test, success_message, failure_message,
+ interrupt_string, True, vm=vm)
def wait_for_console_pattern(test, success_message, failure_message=None,
vm=None):
@@ -155,11 +183,15 @@ def wait_for_console_pattern(test, success_message, failure_message=None,
:type test: :class:`qemu_test.QemuSystemTest`
:param success_message: if this message appears, test succeeds
:param failure_message: if this message appears, test fails
+ :param vm: VM to use
+
+ :return: The collected output (in bytes form).
"""
assert success_message
- _console_interaction(test, success_message, failure_message, None, vm=vm)
+ return _console_interaction(test, success_message, failure_message,
+ None, vm=vm)
-def exec_command(test, command):
+def exec_command(test, command, vm=None):
"""
Send a command to a console (appending CRLF characters), while logging
the content.
@@ -167,12 +199,16 @@ def exec_command(test, command):
:param test: a test containing a VM.
:type test: :class:`qemu_test.QemuSystemTest`
:param command: the command to send
+ :param vm: VM to use
:type command: str
+
+ :return: The collected output (in bytes form).
"""
- _console_interaction(test, None, None, command + '\r')
+ return _console_interaction(test, None, None, command + '\r', vm=vm)
def exec_command_and_wait_for_pattern(test, command,
- success_message, failure_message=None):
+ success_message, failure_message=None,
+ vm=None):
"""
Send a command to a console (appending CRLF characters), then wait
for success_message to appear on the console, while logging the.
@@ -184,9 +220,14 @@ def exec_command_and_wait_for_pattern(test, command,
:param command: the command to send
:param success_message: if this message appears, test succeeds
:param failure_message: if this message appears, test fails
+ :param vm: VM to use
+
+ :return: The collected output (in bytes form).
"""
assert success_message
- _console_interaction(test, success_message, failure_message, command + '\r')
+
+ return _console_interaction(test, success_message, failure_message,
+ command + '\r', vm=vm)
def get_qemu_img(test):
test.log.debug('Looking for and selecting a qemu-img binary')
diff --git a/tests/functional/qemu_test/decorators.py b/tests/functional/qemu_test/decorators.py
index 50d29de..8074183 100644
--- a/tests/functional/qemu_test/decorators.py
+++ b/tests/functional/qemu_test/decorators.py
@@ -5,122 +5,139 @@
import importlib
import os
import platform
+import resource
from unittest import skipIf, skipUnless
from .cmd import which
-'''
-Decorator to skip execution of a test if the list
-of command binaries is not available in $PATH.
-Example:
- @skipIfMissingCommands("mkisofs", "losetup")
-'''
+def skipIfMissingEnv(*vars_):
+ '''
+ Decorator to skip execution of a test if the provided
+ environment variables are not set.
+ Example:
+
+ @skipIfMissingEnv("QEMU_ENV_VAR0", "QEMU_ENV_VAR1")
+ '''
+ missing_vars = []
+ for var in vars_:
+ if os.getenv(var) is None:
+ missing_vars.append(var)
+
+ has_vars = len(missing_vars) == 0
+
+ return skipUnless(has_vars, f"Missing env var(s): {', '.join(missing_vars)}")
+
def skipIfMissingCommands(*args):
+ '''
+ Decorator to skip execution of a test if the list
+ of command binaries is not available in $PATH.
+ Example:
+
+ @skipIfMissingCommands("mkisofs", "losetup")
+ '''
has_cmds = True
for cmd in args:
- if not which(cmd):
- has_cmds = False
- break
+ if not which(cmd):
+ has_cmds = False
+ break
return skipUnless(has_cmds, 'required command(s) "%s" not installed' %
", ".join(args))
-'''
-Decorator to skip execution of a test if the current
-host operating system does match one of the prohibited
-ones.
-Example
-
- @skipIfOperatingSystem("Linux", "Darwin")
-'''
def skipIfOperatingSystem(*args):
+ '''
+ Decorator to skip execution of a test if the current host
+ operating system does match one of the prohibited ones.
+ Example:
+
+ @skipIfOperatingSystem("Linux", "Darwin")
+ '''
return skipIf(platform.system() in args,
'running on an OS (%s) that is not able to run this test' %
", ".join(args))
-'''
-Decorator to skip execution of a test if the current
-host machine does not match one of the permitted
-machines.
-Example
-
- @skipIfNotMachine("x86_64", "aarch64")
-'''
def skipIfNotMachine(*args):
+ '''
+ Decorator to skip execution of a test if the current
+ host machine does not match one of the permitted machines.
+ Example:
+
+ @skipIfNotMachine("x86_64", "aarch64")
+ '''
return skipUnless(platform.machine() in args,
'not running on one of the required machine(s) "%s"' %
", ".join(args))
-'''
-Decorator to skip execution of flaky tests, unless
-the $QEMU_TEST_FLAKY_TESTS environment variable is set.
-A bug URL must be provided that documents the observed
-failure behaviour, so it can be tracked & re-evaluated
-in future.
+def skipFlakyTest(bug_url):
+ '''
+ Decorator to skip execution of flaky tests, unless
+ the $QEMU_TEST_FLAKY_TESTS environment variable is set.
+ A bug URL must be provided that documents the observed
+ failure behaviour, so it can be tracked & re-evaluated
+ in future.
-Historical tests may be providing "None" as the bug_url
-but this should not be done for new test.
+ Historical tests may be providing "None" as the bug_url
+ but this should not be done for new test.
-Example:
+ Example:
- @skipFlakyTest("https://gitlab.com/qemu-project/qemu/-/issues/NNN")
-'''
-def skipFlakyTest(bug_url):
+ @skipFlakyTest("https://gitlab.com/qemu-project/qemu/-/issues/NNN")
+ '''
if bug_url is None:
bug_url = "FIXME: reproduce flaky test and file bug report or remove"
return skipUnless(os.getenv('QEMU_TEST_FLAKY_TESTS'),
f'Test is unstable: {bug_url}')
-'''
-Decorator to skip execution of tests which are likely
-to execute untrusted commands on the host, or commands
-which process untrusted code, unless the
-$QEMU_TEST_ALLOW_UNTRUSTED_CODE env var is set.
-Example:
-
- @skipUntrustedTest()
-'''
def skipUntrustedTest():
+ '''
+ Decorator to skip execution of tests which are likely
+ to execute untrusted commands on the host, or commands
+ which process untrusted code, unless the
+ $QEMU_TEST_ALLOW_UNTRUSTED_CODE env var is set.
+ Example:
+
+ @skipUntrustedTest()
+ '''
return skipUnless(os.getenv('QEMU_TEST_ALLOW_UNTRUSTED_CODE'),
'Test runs untrusted code / processes untrusted data')
-'''
-Decorator to skip execution of tests which need large
-data storage (over around 500MB-1GB mark) on the host,
-unless the $QEMU_TEST_ALLOW_LARGE_STORAGE environment
-variable is set
+def skipBigDataTest():
+ '''
+ Decorator to skip execution of tests which need large
+ data storage (over around 500MB-1GB mark) on the host,
+ unless the $QEMU_TEST_ALLOW_LARGE_STORAGE environment
+ variable is set
-Example:
+ Example:
- @skipBigDataTest()
-'''
-def skipBigDataTest():
+ @skipBigDataTest()
+ '''
return skipUnless(os.getenv('QEMU_TEST_ALLOW_LARGE_STORAGE'),
'Test requires large host storage space')
-'''
-Decorator to skip execution of tests which have a really long
-runtime (and might e.g. time out if QEMU has been compiled with
-debugging enabled) unless the $QEMU_TEST_ALLOW_SLOW
-environment variable is set
+def skipSlowTest():
+ '''
+ Decorator to skip execution of tests which have a really long
+ runtime (and might e.g. time out if QEMU has been compiled with
+ debugging enabled) unless the $QEMU_TEST_ALLOW_SLOW
+ environment variable is set
-Example:
+ Example:
- @skipSlowTest()
-'''
-def skipSlowTest():
+ @skipSlowTest()
+ '''
return skipUnless(os.getenv('QEMU_TEST_ALLOW_SLOW'),
'Test has a very long runtime and might time out')
-'''
-Decorator to skip execution of a test if the list
-of python imports is not available.
-Example:
-
- @skipIfMissingImports("numpy", "cv2")
-'''
def skipIfMissingImports(*args):
+ '''
+ Decorator to skip execution of a test if the list
+ of python imports is not available.
+ Example:
+
+ @skipIfMissingImports("numpy", "cv2")
+ '''
has_imports = True
for impname in args:
try:
@@ -131,3 +148,20 @@ def skipIfMissingImports(*args):
return skipUnless(has_imports, 'required import(s) "%s" not installed' %
", ".join(args))
+
+def skipLockedMemoryTest(locked_memory):
+ '''
+ Decorator to skip execution of a test if the system's
+ locked memory limit is below the required threshold.
+ Takes required locked memory threshold in kB.
+ Example:
+
+ @skipLockedMemoryTest(2_097_152)
+ '''
+ # get memlock hard limit in bytes
+ _, ulimit_memory = resource.getrlimit(resource.RLIMIT_MEMLOCK)
+
+ return skipUnless(
+ ulimit_memory == resource.RLIM_INFINITY or ulimit_memory >= locked_memory * 1024,
+ f'Test required {locked_memory} kB of available locked memory',
+ )
diff --git a/tests/functional/qemu_test/gdb.py b/tests/functional/qemu_test/gdb.py
new file mode 100644
index 0000000..558d476
--- /dev/null
+++ b/tests/functional/qemu_test/gdb.py
@@ -0,0 +1,86 @@
+# SPDX-License-Identifier: GPL-2.0-or-later
+#
+# A simple interface module built around pygdbmi for handling GDB commands.
+#
+# Copyright (c) 2025 Linaro Limited
+#
+# Author:
+# Gustavo Romero <gustavo.romero@linaro.org>
+#
+
+import re
+
+
+class GDB:
+ """Provides methods to run and capture GDB command output."""
+
+
+ def __init__(self, gdb_path, echo=True, suffix='# ', prompt="$ "):
+ from pygdbmi.gdbcontroller import GdbController
+ from pygdbmi.constants import GdbTimeoutError
+ type(self).TimeoutError = GdbTimeoutError
+
+ gdb_cmd = [gdb_path, "-q", "--interpreter=mi2"]
+ self.gdbmi = GdbController(gdb_cmd)
+ self.echo = echo
+ self.suffix = suffix
+ self.prompt = prompt
+ self.response = None
+ self.cmd_output = None
+
+
+ def get_payload(self, response, kind):
+ output = []
+ for o in response:
+ # Unpack payloads of the same type.
+ _type, _, payload, *_ = o.values()
+ if _type == kind:
+ output += [payload]
+
+ # Some output lines do not end with \n but begin with it,
+ # so remove the leading \n and merge them with the next line
+ # that ends with \n.
+ lines = [line.lstrip('\n') for line in output]
+ lines = "".join(lines)
+ lines = lines.splitlines(keepends=True)
+
+ return lines
+
+
+ def cli(self, cmd, timeout=32.0):
+ self.response = self.gdbmi.write(cmd, timeout_sec=timeout)
+ self.cmd_output = self.get_payload(self.response, kind="console")
+ if self.echo:
+ print(self.suffix + self.prompt + cmd)
+
+ if len(self.cmd_output) > 0:
+ cmd_output = self.suffix.join(self.cmd_output)
+ print(self.suffix + cmd_output, end="")
+
+ return self
+
+
+ def get_addr(self):
+ address_pattern = r"0x[0-9A-Fa-f]+"
+ cmd_output = "".join(self.cmd_output) # Concat output lines.
+
+ match = re.search(address_pattern, cmd_output)
+
+ return int(match[0], 16) if match else None
+
+
+ def get_log(self):
+ r = self.get_payload(self.response, kind="log")
+ r = "".join(r)
+
+ return r
+
+
+ def get_console(self):
+ r = "".join(self.cmd_output)
+
+ return r
+
+
+ def exit(self):
+ self.gdbmi.exit()
diff --git a/tests/functional/qemu_test/linuxkernel.py b/tests/functional/qemu_test/linuxkernel.py
index 2aca0ee..eb10a81 100644
--- a/tests/functional/qemu_test/linuxkernel.py
+++ b/tests/functional/qemu_test/linuxkernel.py
@@ -5,6 +5,9 @@
import hashlib
import urllib.request
+import logging
+import re
+import time
from .cmd import wait_for_console_pattern, exec_command_and_wait_for_pattern
from .testcase import QemuSystemTest
@@ -19,17 +22,73 @@ class LinuxKernelTest(QemuSystemTest):
failure_message='Kernel panic - not syncing',
vm=vm)
+ def wait_for_regex_console_pattern(self, success_pattern,
+ failure_pattern=None,
+ timeout=None):
+ """
+ Similar to 'wait_for_console_pattern', but supports regex patterns,
+ hence multiple failure/success patterns can be detected at a time.
+
+ Args:
+ success_pattern (str | re.Pattern): A regex pattern that indicates
+ a successful event. If found, the method exits normally.
+ failure_pattern (str | re.Pattern, optional): A regex pattern that
+ indicates a failure event. If found, the test fails
+ timeout (int, optional): The maximum time (in seconds) to wait for
+ a match.
+ If exceeded, the test fails.
+ """
+
+ console = self.vm.console_file
+ console_logger = logging.getLogger('console')
+
+ self.log.debug(
+ f"Console interaction: success_msg='{success_pattern}' " +
+ f"failure_msg='{failure_pattern}' timeout='{timeout}s'")
+
+ # Only consume console output if waiting for something
+ if success_pattern is None and failure_pattern is None:
+ return
+
+ start_time = time.time()
+
+ while time.time() - start_time < timeout:
+ try:
+ msg = console.readline().decode().strip()
+ except UnicodeDecodeError:
+ msg = None
+ if not msg:
+ continue
+ console_logger.debug(msg)
+ if success_pattern is None or re.search(success_pattern, msg):
+ break
+ if failure_pattern:
+ # Find the matching error to print in log
+ match = re.search(failure_pattern, msg)
+ if not match:
+ continue
+
+ console.close()
+ fail = 'Failure message found in console: "%s".' \
+ ' Expected: "%s"' % \
+ (match.group(), success_pattern)
+ self.fail(fail)
+
+ if time.time() - start_time >= timeout:
+ fail = f"Timeout ({timeout}s) while trying to search pattern"
+ self.fail(fail)
+
def launch_kernel(self, kernel, initrd=None, dtb=None, console_index=0,
wait_for=None):
self.vm.set_console(console_index=console_index)
self.vm.add_args('-kernel', kernel)
if initrd:
- self.vm.add_args('-initrd', initrd)
+ self.vm.add_args('-initrd', initrd)
if dtb:
- self.vm.add_args('-dtb', dtb)
+ self.vm.add_args('-dtb', dtb)
self.vm.launch()
if wait_for:
- self.wait_for_console_pattern(wait_for)
+ self.wait_for_console_pattern(wait_for)
def check_http_download(self, filename, hashsum, guestport=8080,
pythoncmd='python3 -m http.server'):
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
diff --git a/tests/functional/qemu_test/testcase.py b/tests/functional/qemu_test/testcase.py
index 50c401b..58f2740 100644
--- a/tests/functional/qemu_test/testcase.py
+++ b/tests/functional/qemu_test/testcase.py
@@ -14,16 +14,18 @@
import logging
import os
from pathlib import Path
-import pycotap
import shutil
from subprocess import run
import sys
import tempfile
+import warnings
import unittest
import uuid
+import pycotap
+
from qemu.machine import QEMUMachine
-from qemu.utils import kvm_available, tcg_available
+from qemu.utils import hvf_available, kvm_available, tcg_available
from .archive import archive_extract
from .asset import Asset
@@ -33,50 +35,50 @@ from .uncompress import uncompress
class QemuBaseTest(unittest.TestCase):
- '''
- @params compressed: filename, Asset, or file-like object to uncompress
- @params format: optional compression format (gzip, lzma)
+ def uncompress(self, compressed, format=None):
+ '''
+ @params compressed: filename, Asset, or file-like object to uncompress
+ @params format: optional compression format (gzip, lzma)
- Uncompresses @compressed into the scratch directory.
+ Uncompresses @compressed into the scratch directory.
- If @format is None, heuristics will be applied to guess the format
- from the filename or Asset URL. @format must be non-None if @uncompressed
- is a file-like object.
+ If @format is None, heuristics will be applied to guess the
+ format from the filename or Asset URL. @format must be non-None
+ if @uncompressed is a file-like object.
- Returns the fully qualified path to the uncompressed file
- '''
- def uncompress(self, compressed, format=None):
+ Returns the fully qualified path to the uncompressed file
+ '''
self.log.debug(f"Uncompress {compressed} format={format}")
- if type(compressed) == Asset:
+ if isinstance(compressed, Asset):
compressed.fetch()
- (name, ext) = os.path.splitext(str(compressed))
+ (name, _ext) = os.path.splitext(str(compressed))
uncompressed = self.scratch_file(os.path.basename(name))
uncompress(compressed, uncompressed, format)
return uncompressed
- '''
- @params archive: filename, Asset, or file-like object to extract
- @params format: optional archive format (tar, zip, deb, cpio)
- @params sub_dir: optional sub-directory to extract into
- @params member: optional member file to limit extraction to
-
- Extracts @archive into the scratch directory, or a directory beneath
- named by @sub_dir. All files are extracted unless @member specifies
- a limit.
-
- If @format is None, heuristics will be applied to guess the format
- from the filename or Asset URL. @format must be non-None if @archive
- is a file-like object.
-
- If @member is non-None, returns the fully qualified path to @member
- '''
def archive_extract(self, archive, format=None, sub_dir=None, member=None):
+ '''
+ @params archive: filename, Asset, or file-like object to extract
+ @params format: optional archive format (tar, zip, deb, cpio)
+ @params sub_dir: optional sub-directory to extract into
+ @params member: optional member file to limit extraction to
+
+ Extracts @archive into the scratch directory, or a directory beneath
+ named by @sub_dir. All files are extracted unless @member specifies
+ a limit.
+
+ If @format is None, heuristics will be applied to guess the
+ format from the filename or Asset URL. @format must be non-None
+ if @archive is a file-like object.
+
+ If @member is non-None, returns the fully qualified path to @member
+ '''
self.log.debug(f"Extract {archive} format={format}" +
f"sub_dir={sub_dir} member={member}")
- if type(archive) == Asset:
+ if isinstance(archive, Asset):
archive.fetch()
if sub_dir is None:
archive_extract(archive, self.scratch_file(), format, member)
@@ -88,108 +90,108 @@ class QemuBaseTest(unittest.TestCase):
return self.scratch_file(member)
return None
- '''
- Create a temporary directory suitable for storing UNIX
- socket paths.
-
- Returns: a tempfile.TemporaryDirectory instance
- '''
def socket_dir(self):
+ '''
+ Create a temporary directory suitable for storing UNIX
+ socket paths.
+
+ Returns: a tempfile.TemporaryDirectory instance
+ '''
if self.socketdir is None:
self.socketdir = tempfile.TemporaryDirectory(
prefix="qemu_func_test_sock_")
return self.socketdir
- '''
- @params args list of zero or more subdirectories or file
-
- Construct a path for accessing a data file located
- relative to the source directory that is the root for
- functional tests.
-
- @args may be an empty list to reference the root dir
- itself, may be a single element to reference a file in
- the root directory, or may be multiple elements to
- reference a file nested below. The path components
- will be joined using the platform appropriate path
- separator.
-
- Returns: string representing a file path
- '''
def data_file(self, *args):
+ '''
+ @params args list of zero or more subdirectories or file
+
+ Construct a path for accessing a data file located
+ relative to the source directory that is the root for
+ functional tests.
+
+ @args may be an empty list to reference the root dir
+ itself, may be a single element to reference a file in
+ the root directory, or may be multiple elements to
+ reference a file nested below. The path components
+ will be joined using the platform appropriate path
+ separator.
+
+ Returns: string representing a file path
+ '''
return str(Path(Path(__file__).parent.parent, *args))
- '''
- @params args list of zero or more subdirectories or file
-
- Construct a path for accessing a data file located
- relative to the build directory root.
-
- @args may be an empty list to reference the build dir
- itself, may be a single element to reference a file in
- the build directory, or may be multiple elements to
- reference a file nested below. The path components
- will be joined using the platform appropriate path
- separator.
-
- Returns: string representing a file path
- '''
def build_file(self, *args):
- return str(Path(BUILD_DIR, *args))
+ '''
+ @params args list of zero or more subdirectories or file
- '''
- @params args list of zero or more subdirectories or file
+ Construct a path for accessing a data file located
+ relative to the build directory root.
- Construct a path for accessing/creating a scratch file
- located relative to a temporary directory dedicated to
- this test case. The directory and its contents will be
- purged upon completion of the test.
+ @args may be an empty list to reference the build dir
+ itself, may be a single element to reference a file in
+ the build directory, or may be multiple elements to
+ reference a file nested below. The path components
+ will be joined using the platform appropriate path
+ separator.
- @args may be an empty list to reference the scratch dir
- itself, may be a single element to reference a file in
- the scratch directory, or may be multiple elements to
- reference a file nested below. The path components
- will be joined using the platform appropriate path
- separator.
+ Returns: string representing a file path
+ '''
+ return str(Path(BUILD_DIR, *args))
- Returns: string representing a file path
- '''
def scratch_file(self, *args):
+ '''
+ @params args list of zero or more subdirectories or file
+
+ Construct a path for accessing/creating a scratch file
+ located relative to a temporary directory dedicated to
+ this test case. The directory and its contents will be
+ purged upon completion of the test.
+
+ @args may be an empty list to reference the scratch dir
+ itself, may be a single element to reference a file in
+ the scratch directory, or may be multiple elements to
+ reference a file nested below. The path components
+ will be joined using the platform appropriate path
+ separator.
+
+ Returns: string representing a file path
+ '''
return str(Path(self.workdir, *args))
- '''
- @params args list of zero or more subdirectories or file
-
- Construct a path for accessing/creating a log file
- located relative to a temporary directory dedicated to
- this test case. The directory and its log files will be
- preserved upon completion of the test.
-
- @args may be an empty list to reference the log dir
- itself, may be a single element to reference a file in
- the log directory, or may be multiple elements to
- reference a file nested below. The path components
- will be joined using the platform appropriate path
- separator.
-
- Returns: string representing a file path
- '''
def log_file(self, *args):
+ '''
+ @params args list of zero or more subdirectories or file
+
+ Construct a path for accessing/creating a log file
+ located relative to a temporary directory dedicated to
+ this test case. The directory and its log files will be
+ preserved upon completion of the test.
+
+ @args may be an empty list to reference the log dir
+ itself, may be a single element to reference a file in
+ the log directory, or may be multiple elements to
+ reference a file nested below. The path components
+ will be joined using the platform appropriate path
+ separator.
+
+ Returns: string representing a file path
+ '''
return str(Path(self.outputdir, *args))
- '''
- @params plugin name
-
- Return the full path to the plugin taking into account any host OS
- specific suffixes.
- '''
def plugin_file(self, plugin_name):
+ '''
+ @params plugin name
+
+ Return the full path to the plugin taking into account any host OS
+ specific suffixes.
+ '''
sfx = dso_suffix()
return os.path.join('tests', 'tcg', 'plugins', f'{plugin_name}.{sfx}')
def assets_available(self):
for name, asset in vars(self.__class__).items():
- if name.startswith("ASSET_") and type(asset) == Asset:
+ if name.startswith("ASSET_") and isinstance(asset, Asset):
if not asset.available():
self.log.debug(f"Asset {asset.url} not available")
return False
@@ -204,6 +206,10 @@ class QemuBaseTest(unittest.TestCase):
self.outputdir = self.build_file('tests', 'functional',
self.arch, self.id())
self.workdir = os.path.join(self.outputdir, 'scratch')
+ if os.path.exists(self.workdir):
+ # Purge as safety net in case of unclean termination of
+ # previous test, or use of QEMU_TEST_KEEP_SCRATCH
+ shutil.rmtree(self.workdir)
os.makedirs(self.workdir, exist_ok=True)
self.log_filename = self.log_file('base.log')
@@ -211,15 +217,18 @@ class QemuBaseTest(unittest.TestCase):
self.log.setLevel(logging.DEBUG)
self._log_fh = logging.FileHandler(self.log_filename, mode='w')
self._log_fh.setLevel(logging.DEBUG)
- fileFormatter = logging.Formatter(
- '%(asctime)s - %(levelname)s: %(message)s')
- self._log_fh.setFormatter(fileFormatter)
+ file_formatter = logging.Formatter(
+ '%(asctime)s - %(levelname)s: %(name)s.%(funcName)s %(message)s')
+ self._log_fh.setFormatter(file_formatter)
self.log.addHandler(self._log_fh)
# Capture QEMUMachine logging
self.machinelog = logging.getLogger('qemu.machine')
self.machinelog.setLevel(logging.DEBUG)
self.machinelog.addHandler(self._log_fh)
+ self.qmplog = logging.getLogger('qemu.qmp')
+ self.qmplog.setLevel(logging.DEBUG)
+ self.qmplog.addHandler(self._log_fh)
if not self.assets_available():
self.skipTest('One or more assets is not available')
@@ -228,12 +237,18 @@ class QemuBaseTest(unittest.TestCase):
if "QEMU_TEST_KEEP_SCRATCH" not in os.environ:
shutil.rmtree(self.workdir)
if self.socketdir is not None:
- shutil.rmtree(self.socketdir.name)
+ self.socketdir.cleanup()
self.socketdir = None
+ self.qmplog.removeHandler(self._log_fh)
self.machinelog.removeHandler(self._log_fh)
self.log.removeHandler(self._log_fh)
+ self._log_fh.close()
+ @staticmethod
def main():
+ warnings.simplefilter("default")
+ os.environ["PYTHONWARNINGS"] = "default"
+
path = os.path.basename(sys.argv[0])[:-3]
cache = os.environ.get("QEMU_TEST_PRECACHE", None)
@@ -244,14 +259,15 @@ class QemuBaseTest(unittest.TestCase):
tr = pycotap.TAPTestRunner(message_log = pycotap.LogMode.LogToError,
test_output_log = pycotap.LogMode.LogToError)
res = unittest.main(module = None, testRunner = tr, exit = False,
- argv=["__dummy__", path])
- for (test, message) in res.result.errors + res.result.failures:
-
- if hasattr(test, "log_filename"):
+ argv=[sys.argv[0], path] + sys.argv[1:])
+ failed = {}
+ for (test, _message) in res.result.errors + res.result.failures:
+ if hasattr(test, "log_filename") and not test.id() in failed:
print('More information on ' + test.id() + ' could be found here:'
'\n %s' % test.log_filename, file=sys.stderr)
if hasattr(test, 'console_log_name'):
print(' %s' % test.console_log_name, file=sys.stderr)
+ failed[test.id()] = True
sys.exit(not res.result.wasSuccessful())
@@ -264,7 +280,9 @@ class QemuUserTest(QemuBaseTest):
def add_ldpath(self, ldpath):
self._ldpath.append(os.path.abspath(ldpath))
- def run_cmd(self, bin_path, args=[]):
+ def run_cmd(self, bin_path, args=None):
+ if args is None:
+ args = []
return run([self.qemu_bin]
+ ["-L %s" % ldpath for ldpath in self._ldpath]
+ [bin_path]
@@ -289,8 +307,8 @@ class QemuSystemTest(QemuBaseTest):
self._console_log_fh = logging.FileHandler(self.console_log_name,
mode='w')
self._console_log_fh.setLevel(logging.DEBUG)
- fileFormatter = logging.Formatter('%(asctime)s: %(message)s')
- self._console_log_fh.setFormatter(fileFormatter)
+ file_formatter = logging.Formatter('%(asctime)s: %(message)s')
+ self._console_log_fh.setFormatter(file_formatter)
console_log.addHandler(self._console_log_fh)
def set_machine(self, machinename):
@@ -317,7 +335,9 @@ class QemuSystemTest(QemuBaseTest):
:type accelerator: str
"""
checker = {'tcg': tcg_available,
- 'kvm': kvm_available}.get(accelerator)
+ 'kvm': kvm_available,
+ 'hvf': hvf_available,
+ }.get(accelerator)
if checker is None:
self.skipTest("Don't know how to check for the presence "
"of accelerator %s" % accelerator)
@@ -326,17 +346,15 @@ class QemuSystemTest(QemuBaseTest):
"available" % accelerator)
def require_netdev(self, netdevname):
- help = run([self.qemu_bin,
- '-M', 'none', '-netdev', 'help'],
- capture_output=True, check=True, encoding='utf8').stdout;
- if help.find('\n' + netdevname + '\n') < 0:
+ helptxt = run([self.qemu_bin, '-M', 'none', '-netdev', 'help'],
+ capture_output=True, check=True, encoding='utf8').stdout
+ if helptxt.find('\n' + netdevname + '\n') < 0:
self.skipTest('no support for " + netdevname + " networking')
def require_device(self, devicename):
- help = run([self.qemu_bin,
- '-M', 'none', '-device', 'help'],
- capture_output=True, check=True, encoding='utf8').stdout;
- if help.find(devicename) < 0:
+ helptxt = run([self.qemu_bin, '-M', 'none', '-device', 'help'],
+ capture_output=True, check=True, encoding='utf8').stdout
+ if helptxt.find(devicename) < 0:
self.skipTest('no support for device ' + devicename)
def _new_vm(self, name, *args):
@@ -395,6 +413,10 @@ class QemuSystemTest(QemuBaseTest):
def tearDown(self):
for vm in self._vms.values():
- vm.shutdown()
+ try:
+ vm.shutdown()
+ except Exception as ex:
+ self.log.error("Failed to teardown VM: %s", ex)
logging.getLogger('console').removeHandler(self._console_log_fh)
+ self._console_log_fh.close()
super().tearDown()
diff --git a/tests/functional/qemu_test/uncompress.py b/tests/functional/qemu_test/uncompress.py
index b7ef8f7..5bbdf8f 100644
--- a/tests/functional/qemu_test/uncompress.py
+++ b/tests/functional/qemu_test/uncompress.py
@@ -58,20 +58,20 @@ def zstd_uncompress(zstd_path, output_path):
os.chmod(output_path, stat.S_IRUSR | stat.S_IWUSR)
-'''
-@params compressed: filename, Asset, or file-like object to uncompress
-@params uncompressed: filename to uncompress into
-@params format: optional compression format (gzip, lzma)
+def uncompress(compressed, uncompressed, format=None):
+ '''
+ @params compressed: filename, Asset, or file-like object to uncompress
+ @params uncompressed: filename to uncompress into
+ @params format: optional compression format (gzip, lzma)
-Uncompresses @compressed into @uncompressed
+ Uncompresses @compressed into @uncompressed
-If @format is None, heuristics will be applied to guess the format
-from the filename or Asset URL. @format must be non-None if @uncompressed
-is a file-like object.
+ If @format is None, heuristics will be applied to guess the
+ format from the filename or Asset URL. @format must be non-None
+ if @uncompressed is a file-like object.
-Returns the fully qualified path to the uncompessed file
-'''
-def uncompress(compressed, uncompressed, format=None):
+ Returns the fully qualified path to the uncompessed file
+ '''
if format is None:
format = guess_uncompress_format(compressed)
@@ -84,19 +84,19 @@ def uncompress(compressed, uncompressed, format=None):
else:
raise Exception(f"Unknown compression format {format}")
-'''
-@params compressed: filename, Asset, or file-like object to guess
-
-Guess the format of @compressed, raising an exception if
-no format can be determined
-'''
def guess_uncompress_format(compressed):
- if type(compressed) == Asset:
+ '''
+ @params compressed: filename, Asset, or file-like object to guess
+
+ Guess the format of @compressed, raising an exception if
+ no format can be determined
+ '''
+ if isinstance(compressed, Asset):
compressed = urlparse(compressed.url).path
- elif type(compressed) != str:
+ elif not isinstance(compressed, str):
raise Exception(f"Unable to guess compression cformat for {compressed}")
- (name, ext) = os.path.splitext(compressed)
+ (_name, ext) = os.path.splitext(compressed)
if ext == ".xz":
return "xz"
elif ext == ".gz":
diff --git a/tests/functional/qemu_test/utils.py b/tests/functional/qemu_test/utils.py
index e7c8de8..826c267 100644
--- a/tests/functional/qemu_test/utils.py
+++ b/tests/functional/qemu_test/utils.py
@@ -17,10 +17,10 @@ def get_usernet_hostfwd_port(vm):
res = vm.cmd('human-monitor-command', command_line='info usernet')
return get_info_usernet_hostfwd_port(res)
-"""
-Round up to next power of 2
-"""
def pow2ceil(x):
+ """
+ Round up to next power of 2
+ """
return 1 if x == 0 else 2**(x - 1).bit_length()
def file_truncate(path, size):
@@ -28,12 +28,12 @@ def file_truncate(path, size):
with open(path, 'ab+') as fd:
fd.truncate(size)
-"""
-Expand file size to next power of 2
-"""
def image_pow2ceil_expand(path):
- size = os.path.getsize(path)
- size_aligned = pow2ceil(size)
- if size != size_aligned:
- with open(path, 'ab+') as fd:
- fd.truncate(size_aligned)
+ """
+ Expand file size to next power of 2
+ """
+ size = os.path.getsize(path)
+ size_aligned = pow2ceil(size)
+ if size != size_aligned:
+ with open(path, 'ab+') as fd:
+ fd.truncate(size_aligned)
diff --git a/tests/functional/replay_kernel.py b/tests/functional/replay_kernel.py
index 80795eb..acb1d29 100644
--- a/tests/functional/replay_kernel.py
+++ b/tests/functional/replay_kernel.py
@@ -32,15 +32,14 @@ class ReplayKernelBase(LinuxKernelTest):
# icount requires TCG to be available
self.require_accelerator('tcg')
- logger = logging.getLogger('replay')
start_time = time.time()
vm = self.get_vm(name='recording' if record else 'replay')
vm.set_console()
if record:
- logger.info('recording the execution...')
+ self.log.info('recording the execution...')
mode = 'record'
else:
- logger.info('replaying the execution...')
+ self.log.info('replaying the execution...')
mode = 'replay'
vm.add_args('-icount', 'shift=%s,rr=%s,rrfile=%s' %
(shift, mode, replay_path),
@@ -54,15 +53,15 @@ class ReplayKernelBase(LinuxKernelTest):
self.wait_for_console_pattern(console_pattern, vm)
if record:
vm.shutdown()
- logger.info('finished the recording with log size %s bytes'
+ self.log.info('finished the recording with log size %s bytes'
% os.path.getsize(replay_path))
self.run_replay_dump(replay_path)
- logger.info('successfully tested replay-dump.py')
+ self.log.info('successfully tested replay-dump.py')
else:
vm.wait()
- logger.info('successfully finished the replay')
+ self.log.info('successfully finished the replay')
elapsed = time.time() - start_time
- logger.info('elapsed time %.2f sec' % elapsed)
+ self.log.info('elapsed time %.2f sec' % elapsed)
return elapsed
def run_replay_dump(self, replay_path):
@@ -80,5 +79,4 @@ class ReplayKernelBase(LinuxKernelTest):
True, shift, args, replay_path)
t2 = self.run_vm(kernel_path, kernel_command_line, console_pattern,
False, shift, args, replay_path)
- logger = logging.getLogger('replay')
- logger.info('replay overhead {:.2%}'.format(t2 / t1 - 1))
+ self.log.info('replay overhead {:.2%}'.format(t2 / t1 - 1))
diff --git a/tests/functional/reverse_debugging.py b/tests/functional/reverse_debugging.py
index f9a1d39..86fca8d 100644
--- a/tests/functional/reverse_debugging.py
+++ b/tests/functional/reverse_debugging.py
@@ -1,18 +1,23 @@
-# Reverse debugging test
-#
# SPDX-License-Identifier: GPL-2.0-or-later
#
+# Reverse debugging test
+#
# Copyright (c) 2020 ISP RAS
+# Copyright (c) 2025 Linaro Limited
#
# Author:
# Pavel Dovgalyuk <Pavel.Dovgalyuk@ispras.ru>
+# Gustavo Romero <gustavo.romero@linaro.org> (Run without Avocado)
#
# 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 logging
+import os
+from subprocess import check_output
-from qemu_test import LinuxKernelTest, get_qemu_img
+from qemu_test import LinuxKernelTest, get_qemu_img, GDB, \
+ skipIfMissingEnv, skipIfMissingImports
from qemu_test.ports import Ports
@@ -28,21 +33,16 @@ class ReverseDebugging(LinuxKernelTest):
that the execution is stopped at the last of them.
"""
- timeout = 10
STEPS = 10
- endian_is_le = True
def run_vm(self, record, shift, args, replay_path, image_path, port):
- from avocado.utils import datadrainer
-
- logger = logging.getLogger('replay')
vm = self.get_vm(name='record' if record else 'replay')
vm.set_console()
if record:
- logger.info('recording the execution...')
+ self.log.info('recording the execution...')
mode = 'record'
else:
- logger.info('replaying the execution...')
+ self.log.info('replaying the execution...')
mode = 'replay'
vm.add_args('-gdb', 'tcp::%d' % port, '-S')
vm.add_args('-icount', 'shift=%s,rr=%s,rrfile=%s,rrsnapshot=init' %
@@ -52,67 +52,31 @@ class ReverseDebugging(LinuxKernelTest):
if args:
vm.add_args(*args)
vm.launch()
- console_drainer = datadrainer.LineLogger(vm.console_socket.fileno(),
- logger=self.log.getChild('console'),
- stop_check=(lambda : not vm.is_running()))
- console_drainer.start()
return vm
@staticmethod
- def get_reg_le(g, reg):
- res = g.cmd(b'p%x' % reg)
- num = 0
- for i in range(len(res))[-2::-2]:
- num = 0x100 * num + int(res[i:i + 2], 16)
- return num
-
- @staticmethod
- def get_reg_be(g, reg):
- res = g.cmd(b'p%x' % reg)
- return int(res, 16)
-
- def get_reg(self, g, reg):
- # value may be encoded in BE or LE order
- if self.endian_is_le:
- return self.get_reg_le(g, reg)
- else:
- return self.get_reg_be(g, reg)
-
- def get_pc(self, g):
- return self.get_reg(g, self.REG_PC)
-
- def check_pc(self, g, addr):
- pc = self.get_pc(g)
- if pc != addr:
- self.fail('Invalid PC (read %x instead of %x)' % (pc, addr))
-
- @staticmethod
- def gdb_step(g):
- g.cmd(b's', b'T05thread:01;')
-
- @staticmethod
- def gdb_bstep(g):
- g.cmd(b'bs', b'T05thread:01;')
+ def get_pc(gdb: GDB):
+ return gdb.cli("print $pc").get_addr()
@staticmethod
def vm_get_icount(vm):
return vm.qmp('query-replay')['return']['icount']
- def reverse_debugging(self, shift=7, args=None):
- from avocado.utils import gdb
- from avocado.utils import process
-
- logger = logging.getLogger('replay')
+ @skipIfMissingImports("pygdbmi") # Required by GDB class
+ @skipIfMissingEnv("QEMU_TEST_GDB")
+ def reverse_debugging(self, gdb_arch, shift=7, args=None):
+ from qemu_test import GDB
# create qcow2 for snapshots
- logger.info('creating qcow2 image for VM snapshots')
+ self.log.info('creating qcow2 image for VM snapshots')
image_path = os.path.join(self.workdir, 'disk.qcow2')
qemu_img = get_qemu_img(self)
if qemu_img is None:
self.skipTest('Could not find "qemu-img", which is required to '
'create the temporary qcow2 image')
- cmd = '%s create -f qcow2 %s 128M' % (qemu_img, image_path)
- process.run(cmd)
+ out = check_output([qemu_img, 'create', '-f', 'qcow2', image_path, '128M'],
+ encoding='utf8')
+ self.log.info("qemu-img: %s" % out)
replay_path = os.path.join(self.workdir, 'replay.bin')
@@ -123,74 +87,111 @@ class ReverseDebugging(LinuxKernelTest):
last_icount = self.vm_get_icount(vm)
vm.shutdown()
- logger.info("recorded log with %s+ steps" % last_icount)
+ self.log.info("recorded log with %s+ steps" % last_icount)
# replay and run debug commands
with Ports() as ports:
port = ports.find_free_port()
vm = self.run_vm(False, shift, args, replay_path, image_path, port)
- logger.info('connecting to gdbstub')
- g = gdb.GDBRemote('127.0.0.1', port, False, False)
- g.connect()
- r = g.cmd(b'qSupported')
- if b'qXfer:features:read+' in r:
- g.cmd(b'qXfer:features:read:target.xml:0,ffb')
- if b'ReverseStep+' not in r:
+
+ try:
+ self.log.info('Connecting to gdbstub...')
+ gdb_cmd = os.getenv('QEMU_TEST_GDB')
+ gdb = GDB(gdb_cmd)
+ try:
+ self.reverse_debugging_run(gdb, vm, port, gdb_arch, last_icount)
+ finally:
+ self.log.info('exiting gdb and qemu')
+ gdb.exit()
+ vm.shutdown()
+ self.log.info('Test passed.')
+ except GDB.TimeoutError:
+ # Convert a GDB timeout exception into a unittest failure exception.
+ raise self.failureException("Timeout while connecting to or "
+ "communicating with gdbstub...") from None
+ except Exception:
+ # Re-throw exceptions from unittest, like the ones caused by fail(),
+ # skipTest(), etc.
+ raise
+
+ def reverse_debugging_run(self, gdb, vm, port, gdb_arch, last_icount):
+ r = gdb.cli("set architecture").get_log()
+ if gdb_arch not in r:
+ self.skipTest(f"GDB does not support arch '{gdb_arch}'")
+
+ gdb.cli("set debug remote 1")
+
+ c = gdb.cli(f"target remote localhost:{port}").get_console()
+ if not f"Remote debugging using localhost:{port}" in c:
+ self.fail("Could not connect to gdbstub!")
+
+ # Remote debug messages are in 'log' payloads.
+ r = gdb.get_log()
+ if 'ReverseStep+' not in r:
self.fail('Reverse step is not supported by QEMU')
- if b'ReverseContinue+' not in r:
+ if 'ReverseContinue+' not in r:
self.fail('Reverse continue is not supported by QEMU')
- logger.info('stepping forward')
+ gdb.cli("set debug remote 0")
+
+ self.log.info('stepping forward')
steps = []
# record first instruction addresses
for _ in range(self.STEPS):
- pc = self.get_pc(g)
- logger.info('saving position %x' % pc)
+ pc = self.get_pc(gdb)
+ self.log.info('saving position %x' % pc)
steps.append(pc)
- self.gdb_step(g)
+ gdb.cli("stepi")
# visit the recorded instruction in reverse order
- logger.info('stepping backward')
+ self.log.info('stepping backward')
for addr in steps[::-1]:
- self.gdb_bstep(g)
- self.check_pc(g, addr)
- logger.info('found position %x' % addr)
+ self.log.info('found position %x' % addr)
+ gdb.cli("reverse-stepi")
+ pc = self.get_pc(gdb)
+ if pc != addr:
+ self.log.info('Invalid PC (read %x instead of %x)' % (pc, addr))
+ self.fail('Reverse stepping failed!')
# visit the recorded instruction in forward order
- logger.info('stepping forward')
+ self.log.info('stepping forward')
for addr in steps:
- self.check_pc(g, addr)
- self.gdb_step(g)
- logger.info('found position %x' % addr)
+ self.log.info('found position %x' % addr)
+ pc = self.get_pc(gdb)
+ if pc != addr:
+ self.log.info('Invalid PC (read %x instead of %x)' % (pc, addr))
+ self.fail('Forward stepping failed!')
+ gdb.cli("stepi")
# set breakpoints for the instructions just stepped over
- logger.info('setting breakpoints')
+ self.log.info('setting breakpoints')
for addr in steps:
- # hardware breakpoint at addr with len=1
- g.cmd(b'Z1,%x,1' % addr, b'OK')
+ gdb.cli(f"break *{hex(addr)}")
# this may hit a breakpoint if first instructions are executed
# again
- logger.info('continuing execution')
+ self.log.info('continuing execution')
vm.qmp('replay-break', icount=last_icount - 1)
# continue - will return after pausing
- # This could stop at the end and get a T02 return, or by
- # re-executing one of the breakpoints and get a T05 return.
- g.cmd(b'c')
+ # This can stop at the end of the replay-break and gdb gets a SIGINT,
+ # or by re-executing one of the breakpoints and gdb stops at a
+ # breakpoint.
+ gdb.cli("continue")
+
if self.vm_get_icount(vm) == last_icount - 1:
- logger.info('reached the end (icount %s)' % (last_icount - 1))
+ self.log.info('reached the end (icount %s)' % (last_icount - 1))
else:
- logger.info('hit a breakpoint again at %x (icount %s)' %
- (self.get_pc(g), self.vm_get_icount(vm)))
+ self.log.info('hit a breakpoint again at %x (icount %s)' %
+ (self.get_pc(gdb), self.vm_get_icount(vm)))
- logger.info('running reverse continue to reach %x' % steps[-1])
+ self.log.info('running reverse continue to reach %x' % steps[-1])
# reverse continue - will return after stopping at the breakpoint
- g.cmd(b'bc', b'T05thread:01;')
+ gdb.cli("reverse-continue")
# assume that none of the first instructions is executed again
# breaking the order of the breakpoints
- self.check_pc(g, steps[-1])
- logger.info('successfully reached %x' % steps[-1])
+ pc = self.get_pc(gdb)
+ if pc != steps[-1]:
+ self.fail("'reverse-continue' did not hit the first PC in reverse order!")
- logger.info('exiting gdb and qemu')
- vm.shutdown()
+ self.log.info('successfully reached %x' % steps[-1])
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/test_riscv32_tuxrun.py b/tests/functional/riscv32/test_tuxrun.py
index 3c57020..3c57020 100755
--- a/tests/functional/test_riscv32_tuxrun.py
+++ b/tests/functional/riscv32/test_tuxrun.py
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/test_riscv_opensbi.py b/tests/functional/riscv64/test_opensbi.py
index d077e40..d077e40 100755
--- a/tests/functional/test_riscv_opensbi.py
+++ b/tests/functional/riscv64/test_opensbi.py
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/test_riscv64_tuxrun.py b/tests/functional/riscv64/test_tuxrun.py
index 0d8de36..0d8de36 100755
--- a/tests/functional/test_riscv64_tuxrun.py
+++ b/tests/functional/riscv64/test_tuxrun.py
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/test_rx_gdbsim.py b/tests/functional/rx/test_gdbsim.py
index 4924579..d31f9a4 100755
--- a/tests/functional/test_rx_gdbsim.py
+++ b/tests/functional/rx/test_gdbsim.py
@@ -17,9 +17,6 @@ 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'),
@@ -47,7 +44,7 @@ class RxGdbSimMachine(QemuSystemTest):
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)'
+ #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)
@@ -63,7 +60,6 @@ class RxGdbSimMachine(QemuSystemTest):
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')
diff --git a/tests/functional/s390x/meson.build b/tests/functional/s390x/meson.build
new file mode 100644
index 0000000..70cd36e
--- /dev/null
+++ b/tests/functional/s390x/meson.build
@@ -0,0 +1,17 @@
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+test_s390x_timeouts = {
+ 'ccw_virtio' : 420,
+}
+
+tests_s390x_system_quick = [
+ 'vmstate',
+]
+
+tests_s390x_system_thorough = [
+ 'ccw_virtio',
+ 'pxelinux',
+ 'replay',
+ 'topology',
+ 'tuxrun',
+]
diff --git a/tests/functional/test_s390x_ccw_virtio.py b/tests/functional/s390x/test_ccw_virtio.py
index 453711a..0455337 100755
--- a/tests/functional/test_s390x_ccw_virtio.py
+++ b/tests/functional/s390x/test_ccw_virtio.py
@@ -15,6 +15,7 @@ import os
import tempfile
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
@@ -270,5 +271,30 @@ class S390CCWVirtioMachine(QemuSystemTest):
'while ! (dmesg -c | grep Start.virtcrypto_remove) ; do'
' sleep 1 ; done', 'Start virtcrypto_remove.')
+ # Test SCLP event Control-Program Identification (CPI)
+ cpi = '/sys/firmware/cpi/'
+ sclpcpi = '/machine/sclp/s390-sclp-event-facility/sclpcpi'
+ self.log.info("Test SCLP event CPI")
+ exec_command(self, 'echo TESTVM > ' + cpi + 'system_name')
+ exec_command(self, 'echo LINUX > ' + cpi + 'system_type')
+ exec_command(self, 'echo TESTPLEX > ' + cpi + 'sysplex_name')
+ exec_command(self, 'echo 0x001a000000060b00 > ' + cpi + 'system_level')
+ exec_command_and_wait_for_pattern(self,
+ 'echo 1 > ' + cpi + 'set', ':/#')
+ try:
+ event = self.vm.event_wait('SCLP_CPI_INFO_AVAILABLE')
+ except TimeoutError:
+ self.fail('Timed out waiting for the SCLP_CPI_INFO_AVAILABLE event')
+ ts = self.vm.cmd('qom-get', path=sclpcpi, property='timestamp')
+ self.assertNotEqual(ts, 0)
+ name = self.vm.cmd('qom-get', path=sclpcpi, property='system_name')
+ self.assertEqual(name.strip(), 'TESTVM')
+ typ = self.vm.cmd('qom-get', path=sclpcpi, property='system_type')
+ self.assertEqual(typ.strip(), 'LINUX')
+ sysplex = self.vm.cmd('qom-get', path=sclpcpi, property='sysplex_name')
+ self.assertEqual(sysplex.strip(), 'TESTPLEX')
+ level = self.vm.cmd('qom-get', path=sclpcpi, property='system_level')
+ self.assertEqual(level, 0x001a000000060b00)
+
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..c00cce6
--- /dev/null
+++ b/tests/functional/s390x/test_pxelinux.py
@@ -0,0 +1,130 @@
+#!/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):
+ '''
+ Test various ways of booting via a pxelinux.cfg file, for details see:
+ https://wiki.syslinux.org/wiki/index.php?title=PXELINUX#Configuration
+ '''
+
+ 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):
+ '''Create a pxelinux.cfg file in the right location and launch QEMU'''
+ 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):
+ '''Check whether the guest uses the "default" file name'''
+ 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):
+ '''Check whether the guest uses file name based on its MAC address'''
+ 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):
+ '''Check whether the guest uses file name based on its UUID'''
+ # 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):
+ '''Check whether the guest uses file name based on its IP address'''
+ 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):
+ '''Check whether the boot menu works for pxelinux.cfg booting'''
+ 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/s390x/test_replay.py
index 33b5843..33b5843 100755
--- a/tests/functional/test_s390x_replay.py
+++ b/tests/functional/s390x/test_replay.py
diff --git a/tests/functional/test_s390x_topology.py b/tests/functional/s390x/test_topology.py
index 1b5dc65..1b5dc65 100755
--- a/tests/functional/test_s390x_topology.py
+++ b/tests/functional/s390x/test_topology.py
diff --git a/tests/functional/test_s390x_tuxrun.py b/tests/functional/s390x/test_tuxrun.py
index a7db4bf..8df3c68 100755
--- a/tests/functional/test_s390x_tuxrun.py
+++ b/tests/functional/s390x/test_tuxrun.py
@@ -24,6 +24,7 @@ class TuxRunS390xTest(TuxRunBaselineTest):
'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,
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/test_sh4_r2d.py b/tests/functional/sh4/test_r2d.py
index 03a64837..03a64837 100755
--- a/tests/functional/test_sh4_r2d.py
+++ b/tests/functional/sh4/test_r2d.py
diff --git a/tests/functional/test_sh4_tuxrun.py b/tests/functional/sh4/test_tuxrun.py
index 1748f8c..1748f8c 100755
--- a/tests/functional/test_sh4_tuxrun.py
+++ b/tests/functional/sh4/test_tuxrun.py
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/test_sh4eb_r2d.py b/tests/functional/sh4eb/test_r2d.py
index 473093b..473093b 100755
--- a/tests/functional/test_sh4eb_r2d.py
+++ b/tests/functional/sh4eb/test_r2d.py
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/test_sparc_replay.py b/tests/functional/sparc/test_replay.py
index 865d648..865d648 100755
--- a/tests/functional/test_sparc_replay.py
+++ b/tests/functional/sparc/test_replay.py
diff --git a/tests/functional/test_sparc_sun4m.py b/tests/functional/sparc/test_sun4m.py
index 7cd28eb..7cd28eb 100755
--- a/tests/functional/test_sparc_sun4m.py
+++ b/tests/functional/sparc/test_sun4m.py
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/test_sparc64_sun4u.py b/tests/functional/sparc64/test_sun4u.py
index 27ac289..27ac289 100755
--- a/tests/functional/test_sparc64_sun4u.py
+++ b/tests/functional/sparc64/test_sun4u.py
diff --git a/tests/functional/test_sparc64_tuxrun.py b/tests/functional/sparc64/test_tuxrun.py
index 3be08d6..0d7b43d 100755
--- a/tests/functional/test_sparc64_tuxrun.py
+++ b/tests/functional/sparc64/test_tuxrun.py
@@ -24,6 +24,7 @@ class TuxRunSparc64Test(TuxRunBaselineTest):
'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,
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 <pierrick.bouvier@linaro.org>
-#
-# 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 <pierrick.bouvier@linaro.org>
-#
-# 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_ppc_bamboo.py b/tests/functional/test_ppc_bamboo.py
deleted file mode 100755
index fddcc24..0000000
--- a/tests/functional/test_ppc_bamboo.py
+++ /dev/null
@@ -1,44 +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_IMAGE = Asset(
- ('http://landley.net/aboriginal/downloads/binaries/'
- 'system-image-powerpc-440fp.tar.gz'),
- 'c12b58f841c775a0e6df4832a55afe6b74814d1565d08ddeafc1fb949a075c5e')
-
- def test_ppc_bamboo(self):
- self.set_machine('bamboo')
- self.require_accelerator("tcg")
- self.require_netdev('user')
- self.archive_extract(self.ASSET_IMAGE)
- self.vm.set_console()
- self.vm.add_args('-kernel',
- self.scratch_file('system-image-powerpc-440fp',
- 'linux'),
- '-initrd',
- self.scratch_file('system-image-powerpc-440fp',
- 'rootfs.cpio.gz'),
- '-nic', 'user,model=rtl8139,restrict=on')
- self.vm.launch()
- wait_for_console_pattern(self, 'Type exit when done')
- exec_command_and_wait_for_pattern(self, 'ping 10.0.2.2',
- '10.0.2.2 is alive!')
- exec_command_and_wait_for_pattern(self, 'halt', 'System Halted')
-
-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..f78eec5
--- /dev/null
+++ b/tests/functional/x86_64/meson.build
@@ -0,0 +1,39 @@
+# 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 = [
+ 'bad_vmstate',
+ 'cpu_model_versions',
+ 'cpu_queries',
+ 'mem_addr_space',
+ 'memlock',
+ 'migration',
+ 'pc_cpu_hotplug_props',
+ 'virtio_version',
+ 'vmstate',
+]
+
+tests_x86_64_system_thorough = [
+ 'acpi_bits',
+ 'hotplug_blk',
+ 'hotplug_cpu',
+ 'intel_iommu',
+ 'kvm_xen',
+ 'linux_initrd',
+ 'multiprocess',
+ 'netdev_ethtool',
+ 'replay',
+ 'reverse_debug',
+ 'tuxrun',
+ 'vfio_user_client',
+ 'virtio_balloon',
+ 'virtio_gpu',
+]
diff --git a/tests/functional/test_acpi_bits.py b/tests/functional/x86_64/test_acpi_bits.py
index 8e0563a..ec716d6 100755
--- a/tests/functional/test_acpi_bits.py
+++ b/tests/functional/x86_64/test_acpi_bits.py
@@ -57,6 +57,7 @@ class QEMUBitsMachine(QEMUMachine): # pylint: disable=too-few-public-methods
"""
def __init__(self,
binary: str,
+ *,
args: Sequence[str] = (),
wrapper: Sequence[str] = (),
name: Optional[str] = None,
@@ -121,10 +122,10 @@ class AcpiBitsTest(QemuSystemTest): #pylint: disable=too-many-instance-attribute
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')
+ self.log.info('\nlogs from biosbits follows:')
+ self.log.info('==========================================\n')
+ self.log.info(log)
+ self.log.info('==========================================\n')
def copy_bits_config(self):
""" copies the bios bits config file into bits.
@@ -138,8 +139,8 @@ class AcpiBitsTest(QemuSystemTest): #pylint: disable=too-many-instance-attribute
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)
+ self.log.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. """
@@ -163,8 +164,8 @@ class AcpiBitsTest(QemuSystemTest): #pylint: disable=too-many-instance-attribute
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)
+ self.log.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.
@@ -172,9 +173,9 @@ class AcpiBitsTest(QemuSystemTest): #pylint: disable=too-many-instance-attribute
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))
+ self.log.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
@@ -216,7 +217,7 @@ class AcpiBitsTest(QemuSystemTest): #pylint: disable=too-many-instance-attribute
self.fix_mkrescue(mkrescue_script)
- self.logger.info('using grub-mkrescue for generating biosbits iso ...')
+ self.log.info('using grub-mkrescue for generating biosbits iso ...')
try:
if os.getenv('V') or os.getenv('BITS_DEBUG'):
@@ -225,7 +226,7 @@ class AcpiBitsTest(QemuSystemTest): #pylint: disable=too-many-instance-attribute
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT,
check=True)
- self.logger.info("grub-mkrescue output %s" % proc.stdout)
+ self.log.info("grub-mkrescue output %s", proc.stdout)
else:
subprocess.check_call([mkrescue_script, '-o',
iso_file, bits_dir],
@@ -238,11 +239,10 @@ class AcpiBitsTest(QemuSystemTest): #pylint: disable=too-many-instance-attribute
self.assertTrue(os.access(iso_file, os.R_OK))
- self.logger.info('iso file %s successfully generated.', iso_file)
+ self.log.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):
@@ -288,9 +288,8 @@ class AcpiBitsTest(QemuSystemTest): #pylint: disable=too-many-instance-attribute
except AssertionError as e:
self._print_log(log)
raise e
- else:
- if os.getenv('V') or os.getenv('BITS_DEBUG'):
- self._print_log(log)
+ if os.getenv('V') or os.getenv('BITS_DEBUG'):
+ self._print_log(log)
def tearDown(self):
"""
@@ -333,7 +332,7 @@ class AcpiBitsTest(QemuSystemTest): #pylint: disable=too-many-instance-attribute
# 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.log.debug("Checking console output ...")
self.parse_log()
if __name__ == '__main__':
diff --git a/tests/functional/x86_64/test_bad_vmstate.py b/tests/functional/x86_64/test_bad_vmstate.py
new file mode 100755
index 0000000..40098a8
--- /dev/null
+++ b/tests/functional/x86_64/test_bad_vmstate.py
@@ -0,0 +1,58 @@
+#!/usr/bin/env python3
+#
+# SPDX-License-Identifier: GPL-2.0-or-later
+#
+'''Test whether the vmstate-static-checker script detects problems correctly'''
+
+import subprocess
+
+from qemu_test import QemuBaseTest
+
+
+EXPECTED_OUTPUT='''Warning: checking incompatible machine types: "pc-i440fx-2.1", "pc-i440fx-2.2"
+Section "fw_cfg" does not exist in dest
+Section "fusbh200-ehci-usb" version error: 2 > 1
+Section "fusbh200-ehci-usb", Description "ehci-core": expected field "usbsts", got "usbsts_pending"; skipping rest
+Section "pci-serial-4x" Description "pci-serial-multi": Entry "Fields" missing
+Section "intel-hda-generic", Description "intel-hda", Field "pci": missing description
+Section "cfi.pflash01": Entry "Description" missing
+Section "megasas", Description "PCIDevice": expected field "irq_state", while dest has no further fields
+Section "PIIX3-xen" Description "PIIX3": minimum version error: 1 < 2
+Section "PIIX3-xen" Description "PIIX3": Entry "Subsections" missing
+Section "tpci200": Description "tpci200" missing, got "tpci2002" instead; skipping
+Section "sun-fdtwo" Description "fdc": version error: 2 > 1
+Section "sun-fdtwo", Description "fdrive": Subsection "fdrive/media_rate" not found
+Section "usb-kbd" Description "usb-kbd" Field "kbd.keycodes" size mismatch: 4 , 2
+'''
+
+class BadVmStateTest(QemuBaseTest):
+ '''Test class for testing vmstat-static-checker script with bad input'''
+
+ def test_checker(self):
+ """
+ Test whether the checker script correctly detects the changes
+ between dump1.json and dump2.json.
+ """
+ src_json = self.data_file('..', 'data', 'vmstate-static-checker',
+ 'dump1.json')
+ dst_json = self.data_file('..', 'data', 'vmstate-static-checker',
+ 'dump2.json')
+ checkerscript = self.data_file('..', '..', 'scripts',
+ 'vmstate-static-checker.py')
+
+ self.log.info('Comparing %s with %s', src_json, dst_json)
+ cp = subprocess.run([checkerscript, '-s', src_json, '-d', dst_json],
+ stdout=subprocess.PIPE,
+ stderr=subprocess.STDOUT,
+ text=True, check=False)
+ if cp.returncode != 13:
+ self.fail('Unexpected return code of vmstate-static-checker: ' +
+ cp.returncode)
+ if cp.stdout != EXPECTED_OUTPUT:
+ self.log.info('vmstate-static-checker output:\n%s', cp.stdout)
+ self.log.info('expected output:\n%s', EXPECTED_OUTPUT)
+ self.fail('Unexpected vmstate-static-checker output!')
+
+
+if __name__ == '__main__':
+ QemuBaseTest.main()
diff --git a/tests/functional/test_x86_cpu_model_versions.py b/tests/functional/x86_64/test_cpu_model_versions.py
index bd18acd..36c968f 100755
--- a/tests/functional/test_x86_cpu_model_versions.py
+++ b/tests/functional/x86_64/test_cpu_model_versions.py
@@ -72,44 +72,11 @@ class X86CPUModelAliases(QemuSystemTest):
self.assertNotIn("EPYC-IBPB-v1", cpus,
"EPYC-IBPB shouldn't be versioned")
- def test_4_0_alias_compatibility(self):
- """
- Check if pc-*-4.0 unversioned CPU model won't be reported as aliases
- """
- self.set_machine('pc-i440fx-4.0')
- # pc-*-4.0 won't expose non-versioned CPU models as aliases
- # We do this to help management software to keep compatibility
- # with older QEMU versions that didn't have the versioned CPU model
- 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.assertNotIn('alias-of', cpus['Cascadelake-Server'],
- 'Cascadelake-Server must not be an alias')
- 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.assertNotIn('alias-of', cpus['qemu64'],
- 'qemu64 must not be an alias')
- self.assertNotIn('alias-of', cpus['qemu64-v1'],
- 'qemu64-v1 must not be an alias')
-
- self.validate_variant_aliases(cpus)
-
- # On pc-*-4.0, no CPU model should be reported as an alias:
- for name,c in cpus.items():
- self.assertNotIn('alias-of', c, "%s shouldn't be an alias" % (name))
-
- def test_4_1_alias(self):
+ def test_unversioned_alias(self):
"""
Check if unversioned CPU model is an alias pointing to right version
"""
- self.set_machine('pc-i440fx-4.1')
+ self.set_machine('pc')
self.vm.add_args('-S')
self.vm.launch()
@@ -133,7 +100,7 @@ class X86CPUModelAliases(QemuSystemTest):
self.validate_variant_aliases(cpus)
- # On pc-*-4.1, -noTSX and -IBRS models should be aliases:
+ # 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")
@@ -247,8 +214,8 @@ class CascadelakeArchCapabilities(QemuSystemTest):
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_4_1(self):
- self.set_machine('pc-i440fx-4.1')
+ def test(self):
+ self.set_machine('pc')
# machine-type only:
self.vm.add_args('-S')
self.set_vm_arg('-cpu',
@@ -256,80 +223,27 @@ class CascadelakeArchCapabilities(QemuSystemTest):
'enforce=off')
self.vm.launch()
self.assertFalse(self.get_cpu_prop('arch-capabilities'),
- 'pc-i440fx-4.1 + Cascadelake-Server should not have arch-capabilities')
-
- def test_4_0(self):
- self.set_machine('pc-i440fx-4.0')
- 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-i440fx-4.0 + Cascadelake-Server should not have arch-capabilities')
-
- def test_set_4_0(self):
- self.set_machine('pc-i440fx-4.0')
- # command line must override machine-type if CPU model is not versioned:
- 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.assertTrue(self.get_cpu_prop('arch-capabilities'),
- 'pc-i440fx-4.0 + Cascadelake-Server,+arch-capabilities should have arch-capabilities')
+ 'pc + Cascadelake-Server should not have arch-capabilities')
- def test_unset_4_1(self):
- self.set_machine('pc-i440fx-4.1')
+ 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-i440fx-4.1 + Cascadelake-Server,-arch-capabilities should not have arch-capabilities')
-
- def test_v1_4_0(self):
- self.set_machine('pc-i440fx-4.0')
- # versioned CPU model overrides machine-type:
- self.vm.add_args('-S')
- self.set_vm_arg('-cpu',
- 'Cascadelake-Server-v1,x-force-features=on,check=off,'
- 'enforce=off')
- self.vm.launch()
- self.assertFalse(self.get_cpu_prop('arch-capabilities'),
- 'pc-i440fx-4.0 + Cascadelake-Server-v1 should not have arch-capabilities')
-
- def test_v2_4_0(self):
- self.set_machine('pc-i440fx-4.0')
- self.vm.add_args('-S')
- self.set_vm_arg('-cpu',
- 'Cascadelake-Server-v2,x-force-features=on,check=off,'
- 'enforce=off')
- self.vm.launch()
- self.assertTrue(self.get_cpu_prop('arch-capabilities'),
- 'pc-i440fx-4.0 + Cascadelake-Server-v2 should have arch-capabilities')
-
- def test_v1_set_4_0(self):
- self.set_machine('pc-i440fx-4.0')
- # command line must override machine-type and versioned CPU model:
- self.vm.add_args('-S')
- self.set_vm_arg('-cpu',
- 'Cascadelake-Server-v1,x-force-features=on,check=off,'
- 'enforce=off,+arch-capabilities')
- self.vm.launch()
- self.assertTrue(self.get_cpu_prop('arch-capabilities'),
- 'pc-i440fx-4.0 + Cascadelake-Server-v1,+arch-capabilities should have arch-capabilities')
+ 'pc + Cascadelake-Server,-arch-capabilities should not have arch-capabilities')
- def test_v2_unset_4_1(self):
- self.set_machine('pc-i440fx-4.1')
+ 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-i440fx-4.1 + Cascadelake-Server-v2,-arch-capabilities should not have arch-capabilities')
+ 'pc + Cascadelake-Server-v2,-arch-capabilities should not have arch-capabilities')
if __name__ == '__main__':
QemuSystemTest.main()
diff --git a/tests/functional/test_cpu_queries.py b/tests/functional/x86_64/test_cpu_queries.py
index b1122a0..b1122a0 100755
--- a/tests/functional/test_cpu_queries.py
+++ b/tests/functional/x86_64/test_cpu_queries.py
diff --git a/tests/functional/test_x86_64_hotplug_blk.py b/tests/functional/x86_64/test_hotplug_blk.py
index 7ddbfef..7ddbfef 100755
--- a/tests/functional/test_x86_64_hotplug_blk.py
+++ b/tests/functional/x86_64/test_hotplug_blk.py
diff --git a/tests/functional/test_x86_64_hotplug_cpu.py b/tests/functional/x86_64/test_hotplug_cpu.py
index 7b9200a..7b9200a 100755
--- a/tests/functional/test_x86_64_hotplug_cpu.py
+++ b/tests/functional/x86_64/test_hotplug_cpu.py
diff --git a/tests/functional/test_intel_iommu.py b/tests/functional/x86_64/test_intel_iommu.py
index 62268d6..62268d6 100755
--- a/tests/functional/test_intel_iommu.py
+++ b/tests/functional/x86_64/test_intel_iommu.py
diff --git a/tests/functional/test_x86_64_kvm_xen.py b/tests/functional/x86_64/test_kvm_xen.py
index a5d4450..424d4b2 100755
--- a/tests/functional/test_x86_64_kvm_xen.py
+++ b/tests/functional/x86_64/test_kvm_xen.py
@@ -23,18 +23,11 @@ class KVMXenGuest(QemuSystemTest):
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')
+ ASSET_KERNEL = Asset('https://share.linaro.org/downloadFile?id=UG0V8dzzHrrHb9X',
+ 'ec0ad7bb8c33c5982baee0a75505fe7dbf29d3ff5d44258204d6307c6fe0132a')
+
+ ASSET_ROOTFS = Asset('https://share.linaro.org/downloadFile?id=VwLRKDXKFl6oKti',
+ 'b11045d649006c649c184e93339aaa41a8fe20a1a86620af70323252eb29e40b')
def common_vm_setup(self):
# We also catch lack of KVM_XEN support if we fail to launch
diff --git a/tests/functional/test_linux_initrd.py b/tests/functional/x86_64/test_linux_initrd.py
index 2207f83..2207f83 100755
--- a/tests/functional/test_linux_initrd.py
+++ b/tests/functional/x86_64/test_linux_initrd.py
diff --git a/tests/functional/test_mem_addr_space.py b/tests/functional/x86_64/test_mem_addr_space.py
index 2d9d31e..61b4a19 100755
--- a/tests/functional/test_mem_addr_space.py
+++ b/tests/functional/x86_64/test_mem_addr_space.py
@@ -58,8 +58,8 @@ class MemAddrCheck(QemuSystemTest):
should start fine.
"""
self.ensure_64bit_binary()
- self.vm.add_args('-S', '-machine', 'q35', '-m',
- '512,slots=1,maxmem=59.6G',
+ 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')
@@ -76,8 +76,8 @@ class MemAddrCheck(QemuSystemTest):
with pse36 above.
"""
self.ensure_64bit_binary()
- self.vm.add_args('-S', '-machine', 'q35', '-m',
- '512,slots=1,maxmem=59.6G',
+ 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')
@@ -93,8 +93,8 @@ class MemAddrCheck(QemuSystemTest):
same options as the failing case above with pse36 cpu feature.
"""
self.ensure_64bit_binary()
- self.vm.add_args('-machine', 'q35', '-m',
- '512,slots=1,maxmem=59.5G',
+ 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')
@@ -111,8 +111,8 @@ class MemAddrCheck(QemuSystemTest):
with the same options as the case above.
"""
self.ensure_64bit_binary()
- self.vm.add_args('-machine', 'q35', '-m',
- '512,slots=1,maxmem=59.5G',
+ 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')
@@ -128,8 +128,8 @@ class MemAddrCheck(QemuSystemTest):
with pse36 ON.
"""
self.ensure_64bit_binary()
- self.vm.add_args('-machine', 'q35', '-m',
- '512,slots=1,maxmem=59.5G',
+ 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')
@@ -148,8 +148,8 @@ class MemAddrCheck(QemuSystemTest):
above 4 GiB due to the PCI hole and simplicity.
"""
self.ensure_64bit_binary()
- self.vm.add_args('-S', '-machine', 'q35', '-m',
- '512,slots=1,maxmem=4G',
+ 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')
@@ -176,8 +176,8 @@ class MemAddrCheck(QemuSystemTest):
make QEMU fail with the error message.
"""
self.ensure_64bit_binary()
- self.vm.add_args('-S', '-machine', 'pc-q35-7.0', '-m',
- '512,slots=1,maxmem=988G',
+ 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')
@@ -197,8 +197,8 @@ class MemAddrCheck(QemuSystemTest):
than 988 GiB).
"""
self.ensure_64bit_binary()
- self.vm.add_args('-S', '-machine', 'pc-q35-7.1', '-m',
- '512,slots=1,maxmem=976G',
+ 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')
@@ -214,8 +214,8 @@ class MemAddrCheck(QemuSystemTest):
successfully start when maxmem is < 988G.
"""
self.ensure_64bit_binary()
- self.vm.add_args('-S', '-machine', 'pc-q35-7.0', '-m',
- '512,slots=1,maxmem=987.5G',
+ 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')
@@ -231,8 +231,8 @@ class MemAddrCheck(QemuSystemTest):
successfully start when maxmem is < 976G.
"""
self.ensure_64bit_binary()
- self.vm.add_args('-S', '-machine', 'pc-q35-7.1', '-m',
- '512,slots=1,maxmem=975.5G',
+ 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')
@@ -249,9 +249,9 @@ class MemAddrCheck(QemuSystemTest):
"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',
- '-machine', 'pc-q35-7.1', '-m',
- '512,slots=1,maxmem=976G',
+ '-m', '512,slots=1,maxmem=976G',
'-display', 'none',
'-object', 'memory-backend-ram,id=mem1,size=1G',
'-device', 'pc-dimm,id=vm0,memdev=mem1')
@@ -274,9 +274,9 @@ class MemAddrCheck(QemuSystemTest):
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',
- '-machine', 'pc-q35-7.1', '-m',
- '512,slots=1,maxmem=992G',
+ '-m', '512,slots=1,maxmem=992G',
'-display', 'none',
'-object', 'memory-backend-ram,id=mem1,size=1G',
'-device', 'pc-dimm,id=vm0,memdev=mem1')
@@ -293,9 +293,9 @@ class MemAddrCheck(QemuSystemTest):
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',
- '-machine', 'pc-q35-7.1', '-m',
- '512,slots=1,maxmem=990G',
+ '-m', '512,slots=1,maxmem=990G',
'-display', 'none',
'-object', 'memory-backend-ram,id=mem1,size=1G',
'-device', 'pc-dimm,id=vm0,memdev=mem1')
@@ -314,12 +314,12 @@ class MemAddrCheck(QemuSystemTest):
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',
- '-machine', 'q35,cxl=on', '-m',
- '512,slots=1,maxmem=987G',
+ '-m', '512,slots=1,maxmem=987G',
'-display', 'none',
'-device', 'pxb-cxl,bus_nr=12,bus=pcie.0,id=cxl.1',
- '-M', 'cxl-fmw.0.targets.0=cxl.1,cxl-fmw.0.size=1G')
+ '-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()
@@ -333,9 +333,10 @@ class MemAddrCheck(QemuSystemTest):
with cxl enabled.
"""
self.ensure_64bit_binary()
+ self.set_machine('q35')
self.vm.add_args('-S', '-cpu', 'Skylake-Server,phys-bits=40',
- '-machine', 'q35,cxl=on', '-m',
- '512,slots=1,maxmem=987G',
+ '-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)
diff --git a/tests/functional/x86_64/test_memlock.py b/tests/functional/x86_64/test_memlock.py
new file mode 100755
index 0000000..f970a2c
--- /dev/null
+++ b/tests/functional/x86_64/test_memlock.py
@@ -0,0 +1,82 @@
+#!/usr/bin/env python3
+#
+# Functional test that check overcommit memlock options
+#
+# Copyright (c) Yandex Technologies LLC, 2025
+#
+# Author:
+# Alexandr Moshkov <dtalexundeer@yandex-team.ru>
+#
+# 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())
+
+ # libgcrypt may mlock a few pages
+ self.assertTrue(status['VmLck'] < 32)
+
+ 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:
+ status = None
+ try:
+ with open(f'/proc/{pid}/status', 'r', encoding="ascii") as f:
+ status = f.read()
+ except FileNotFoundError:
+ self.skipTest("Can't open status file of the process")
+ return status
+
+
+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/test_netdev_ethtool.py b/tests/functional/x86_64/test_netdev_ethtool.py
index ee1a397..ac8a925 100755
--- a/tests/functional/test_netdev_ethtool.py
+++ b/tests/functional/x86_64/test_netdev_ethtool.py
@@ -16,16 +16,10 @@ 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")
+ ASSET_BZIMAGE = Asset("https://share.linaro.org/downloadFile?id=QD37GYYAJhGOgVe",
+ "ed62ee06ea620b1035747f3f66a5e9fc5d3096b29f75562ada888b04cd1c4baf")
+ ASSET_ROOTFS = Asset("https://share.linaro.org/downloadFile?id=YAqnr0W8fruDh3f",
+ "8f0207e3c4d40832ae73c1a927e42ca30ccb1e71f047acb6ddb161ba422934e6")
def common_test_code(self, netdev, extra_args=None):
self.set_machine('q35')
diff --git a/tests/functional/test_pc_cpu_hotplug_props.py b/tests/functional/x86_64/test_pc_cpu_hotplug_props.py
index 9d5a37c..2bed8ad 100755
--- a/tests/functional/test_pc_cpu_hotplug_props.py
+++ b/tests/functional/x86_64/test_pc_cpu_hotplug_props.py
@@ -26,6 +26,7 @@ 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')
diff --git a/tests/functional/test_x86_64_replay.py b/tests/functional/x86_64/test_replay.py
index 27287d4..27287d4 100755
--- a/tests/functional/test_x86_64_replay.py
+++ b/tests/functional/x86_64/test_replay.py
diff --git a/tests/functional/test_x86_64_reverse_debug.py b/tests/functional/x86_64/test_reverse_debug.py
index d713e91..ab5dac9 100755
--- a/tests/functional/test_x86_64_reverse_debug.py
+++ b/tests/functional/x86_64/test_reverse_debug.py
@@ -2,34 +2,29 @@
#
# SPDX-License-Identifier: GPL-2.0-or-later
#
-# Reverse debugging test
+# Reverse debugging test for x86_64
#
# Copyright (c) 2020 ISP RAS
+# Copyright (c) 2025 Linaro Limited
#
# Author:
# Pavel Dovgalyuk <Pavel.Dovgalyuk@ispras.ru>
+# Gustavo Romero <gustavo.romero@linaro.org> (Run without Avocado)
#
# 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 qemu_test import 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
+class ReverseDebuggingX86(ReverseDebugging):
@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()
+ self.reverse_debugging(gdb_arch='x86-64')
if __name__ == '__main__':
diff --git a/tests/functional/test_x86_64_tuxrun.py b/tests/functional/x86_64/test_tuxrun.py
index fcbc62b..fcbc62b 100755
--- a/tests/functional/test_x86_64_tuxrun.py
+++ b/tests/functional/x86_64/test_tuxrun.py
diff --git a/tests/functional/x86_64/test_vfio_user_client.py b/tests/functional/x86_64/test_vfio_user_client.py
new file mode 100755
index 0000000..8bc16e5
--- /dev/null
+++ b/tests/functional/x86_64/test_vfio_user_client.py
@@ -0,0 +1,201 @@
+#!/usr/bin/env python3
+#
+# Copyright (c) 2025 Nutanix, Inc.
+#
+# Author:
+# Mark Cave-Ayland <mark.caveayland@nutanix.com>
+# John Levon <john.levon@nutanix.com>
+#
+# SPDX-License-Identifier: GPL-2.0-or-later
+"""
+Check basic vfio-user-pci client functionality. The test starts two VMs:
+
+ - the server VM runs the libvfio-user "gpio" example server inside it,
+ piping vfio-user traffic between a local UNIX socket and a virtio-serial
+ port. On the host, the virtio-serial port is backed by a local socket.
+
+ - the client VM loads the gpio-pci-idio-16 kernel module, with the
+ vfio-user client connecting to the above local UNIX socket.
+
+This way, we don't depend on trying to run a vfio-user server on the host
+itself.
+
+Once both VMs are running, we run some basic configuration on the gpio device
+and verify that the server is logging the expected out. As this is consistent
+given the same VM images, we just do a simple direct comparison.
+"""
+
+import os
+
+from qemu_test import Asset
+from qemu_test import QemuSystemTest
+from qemu_test import exec_command_and_wait_for_pattern
+from qemu_test import wait_for_console_pattern
+
+# Exact output can vary, so we just sample for some expected lines.
+EXPECTED_SERVER_LINES = [
+ "gpio: adding DMA region [0, 0xc0000) offset=0 flags=0x3",
+ "gpio: devinfo flags 0x3, num_regions 9, num_irqs 5",
+ "gpio: region_info[0] offset 0 flags 0 size 0 argsz 32",
+ "gpio: region_info[1] offset 0 flags 0 size 0 argsz 32",
+ "gpio: region_info[2] offset 0 flags 0x3 size 256 argsz 32",
+ "gpio: region_info[3] offset 0 flags 0 size 0 argsz 32",
+ "gpio: region_info[4] offset 0 flags 0 size 0 argsz 32",
+ "gpio: region_info[5] offset 0 flags 0 size 0 argsz 32",
+ "gpio: region_info[7] offset 0 flags 0x3 size 256 argsz 32",
+ "gpio: region7: read 256 bytes at 0",
+ "gpio: region7: read 0 from (0x30:4)",
+ "gpio: cleared EROM",
+ "gpio: I/O space enabled",
+ "gpio: memory space enabled",
+ "gpio: SERR# enabled",
+ "gpio: region7: wrote 0x103 to (0x4:2)",
+ "gpio: I/O space enabled",
+ "gpio: memory space enabled",
+]
+
+class VfioUserClient(QemuSystemTest):
+ """vfio-user testing class."""
+
+ ASSET_REPO = 'https://github.com/mcayland-ntx/libvfio-user-test'
+
+ ASSET_KERNEL = Asset(
+ f'{ASSET_REPO}/raw/refs/heads/main/images/bzImage',
+ '40292fa6ce95d516e26bccf5974e138d0db65a6de0bc540cabae060fe9dea605'
+ )
+
+ ASSET_ROOTFS = Asset(
+ f'{ASSET_REPO}/raw/refs/heads/main/images/rootfs.ext2',
+ 'e1e3abae8aebb8e6e77f08b1c531caeacf46250c94c815655c6bbea59fc3d1c1'
+ )
+
+ def __init__(self, *args, **kwargs):
+ super().__init__(*args, **kwargs)
+
+ self.kernel_path = None
+ self.rootfs_path = None
+
+ def configure_server_vm_args(self, server_vm, sock_path):
+ """
+ Configuration for the server VM. Set up virtio-serial device backed by
+ the given socket path.
+ """
+ server_vm.add_args('-kernel', self.kernel_path)
+ server_vm.add_args('-append', 'console=ttyS0 root=/dev/sda')
+ server_vm.add_args('-drive',
+ f"file={self.rootfs_path},if=ide,format=raw,id=drv0")
+ server_vm.add_args('-snapshot')
+ server_vm.add_args('-chardev',
+ f"socket,id=sock0,path={sock_path},telnet=off,server=on,wait=off")
+ server_vm.add_args('-device', 'virtio-serial')
+ server_vm.add_args('-device',
+ 'virtserialport,chardev=sock0,name=org.fedoraproject.port.0')
+
+ def configure_client_vm_args(self, client_vm, sock_path):
+ """
+ Configuration for the client VM. Point the vfio-user-pci device to the
+ socket path configured above.
+ """
+
+ client_vm.add_args('-kernel', self.kernel_path)
+ client_vm.add_args('-append', 'console=ttyS0 root=/dev/sda')
+ client_vm.add_args('-drive',
+ f'file={self.rootfs_path},if=ide,format=raw,id=drv0')
+ client_vm.add_args('-snapshot')
+ client_vm.add_args('-device',
+ '{"driver":"vfio-user-pci",' +
+ '"socket":{"path": "%s", "type": "unix"}}' % sock_path)
+
+ def setup_vfio_user_pci_server(self, server_vm):
+ """
+ Start the libvfio-user server within the server VM, and arrange
+ for data to shuttle between its socket and the virtio serial port.
+ """
+ wait_for_console_pattern(self, 'login:', None, server_vm)
+ exec_command_and_wait_for_pattern(self, 'root', '#', None, server_vm)
+
+ exec_command_and_wait_for_pattern(self,
+ 'gpio-pci-idio-16 -v /tmp/vfio-user.sock >/var/tmp/gpio.out 2>&1 &',
+ '#', None, server_vm)
+
+ # wait for libvfio-user socket to appear
+ while True:
+ out = exec_command_and_wait_for_pattern(self,
+ 'ls --color=no /tmp/vfio-user.sock', '#', None, server_vm)
+ ls_out = out.decode().splitlines()[1].strip()
+ if ls_out == "/tmp/vfio-user.sock":
+ break
+
+ exec_command_and_wait_for_pattern(self,
+ 'socat UNIX-CONNECT:/tmp/vfio-user.sock /dev/vport0p1,ignoreeof ' +
+ ' &', '#', None, server_vm)
+
+ def test_vfio_user_pci(self):
+ """Run basic sanity test."""
+
+ self.set_machine('pc')
+ self.require_device('virtio-serial')
+ self.require_device('vfio-user-pci')
+
+ self.kernel_path = self.ASSET_KERNEL.fetch()
+ self.rootfs_path = self.ASSET_ROOTFS.fetch()
+
+ sock_dir = self.socket_dir()
+ socket_path = os.path.join(sock_dir.name, 'vfio-user.sock')
+
+ server_vm = self.get_vm(name='server')
+ server_vm.set_console()
+ self.configure_server_vm_args(server_vm, socket_path)
+
+ server_vm.launch()
+
+ self.log.debug('starting libvfio-user server')
+
+ self.setup_vfio_user_pci_server(server_vm)
+
+ client_vm = self.get_vm(name="client")
+ client_vm.set_console()
+ self.configure_client_vm_args(client_vm, socket_path)
+
+ try:
+ client_vm.launch()
+ except:
+ self.log.error('client VM failed to start, dumping server logs')
+ exec_command_and_wait_for_pattern(self, 'cat /var/tmp/gpio.out',
+ '#', None, server_vm)
+ raise
+
+ self.log.debug('waiting for client VM boot')
+
+ wait_for_console_pattern(self, 'login:', None, client_vm)
+ exec_command_and_wait_for_pattern(self, 'root', '#', None, client_vm)
+
+ #
+ # Here, we'd like to actually interact with the gpio device a little
+ # more as described at:
+ #
+ # https://github.com/nutanix/libvfio-user/blob/master/docs/qemu.md
+ #
+ # Unfortunately, the buildroot Linux kernel has some undiagnosed issue
+ # so we don't get /sys/class/gpio. Nonetheless just the basic
+ # initialization and setup is enough for basic testing of vfio-user.
+ #
+
+ self.log.debug('collecting libvfio-user server output')
+
+ out = exec_command_and_wait_for_pattern(self,
+ 'cat /var/tmp/gpio.out',
+ 'gpio: region2: wrote 0 to (0x1:1)',
+ None, server_vm)
+
+ gpio_server_out = [s for s in out.decode().splitlines()
+ if s.startswith("gpio:")]
+
+ for line in EXPECTED_SERVER_LINES:
+ if line not in gpio_server_out:
+ self.log.error(f'Missing server debug line: {line}')
+ self.fail(False)
+
+
+if __name__ == '__main__':
+ QemuSystemTest.main()
diff --git a/tests/functional/test_virtio_balloon.py b/tests/functional/x86_64/test_virtio_balloon.py
index 5877b6c..7a579e0 100755
--- a/tests/functional/test_virtio_balloon.py
+++ b/tests/functional/x86_64/test_virtio_balloon.py
@@ -66,7 +66,7 @@ class VirtioBalloonx86(QemuSystemTest):
when = ret.get('last-update')
assert when == 0
stats = ret.get('stats')
- for name, val in stats.items():
+ for _name, val in stats.items():
assert val == UNSET_STATS_VALUE
def assert_running_stats(self, then):
@@ -87,10 +87,10 @@ class VirtioBalloonx86(QemuSystemTest):
now = time.time()
- assert when > then and when < now
+ assert now > when > then
stats = ret.get('stats')
# Stat we expect this particular Kernel to have set
- expectData = [
+ expect_data = [
"stat-available-memory",
"stat-disk-caches",
"stat-free-memory",
@@ -103,7 +103,7 @@ class VirtioBalloonx86(QemuSystemTest):
"stat-total-memory",
]
for name, val in stats.items():
- if name in expectData:
+ if name in expect_data:
assert val != UNSET_STATS_VALUE
else:
assert val == UNSET_STATS_VALUE
diff --git a/tests/functional/test_virtio_gpu.py b/tests/functional/x86_64/test_virtio_gpu.py
index 81c9156..58b0f72 100755
--- a/tests/functional/test_virtio_gpu.py
+++ b/tests/functional/x86_64/test_virtio_gpu.py
@@ -5,22 +5,23 @@
# 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
+import subprocess
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
+from qemu.machine.machine import VMLaunchFailure
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
+ return None
class VirtioGPUx86(QemuSystemTest):
@@ -46,8 +47,8 @@ class VirtioGPUx86(QemuSystemTest):
)
def test_virtio_vga_virgl(self):
- # FIXME: should check presence of virtio, virgl etc
self.require_accelerator('kvm')
+ self.require_device('virtio-vga-gl')
kernel_path = self.ASSET_KERNEL.fetch()
initrd_path = self.ASSET_INITRD.fetch()
@@ -68,7 +69,7 @@ class VirtioGPUx86(QemuSystemTest):
)
try:
self.vm.launch()
- except:
+ except VMLaunchFailure:
# TODO: probably fails because we are missing the VirGL features
self.skipTest("VirGL not enabled?")
@@ -78,8 +79,8 @@ class VirtioGPUx86(QemuSystemTest):
)
def test_vhost_user_vga_virgl(self):
- # FIXME: should check presence of vhost-user-gpu, virgl, memfd etc
self.require_accelerator('kvm')
+ self.require_device('vhost-user-vga')
vug = pick_default_vug_bin(self)
if not vug:
@@ -95,26 +96,29 @@ class VirtioGPUx86(QemuSystemTest):
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,
- )
-
+ vug_log_path = self.log_file("vhost-user-gpu.log")
+ self.log.info('Complete vhost-user-gpu.log file can be found at %s',
+ vug_log_path)
+ with open(vug_log_path, "wb") as vug_log_file:
+ with subprocess.Popen([vug, "--virgl", f"--fd={vug_sock.fileno()}"],
+ stdin=subprocess.DEVNULL,
+ stdout=vug_log_file,
+ stderr=subprocess.STDOUT,
+ shell=False,
+ close_fds=False) as vugp:
+ self._test_vhost_user_vga_virgl(qemu_sock,
+ kernel_path, initrd_path)
+ qemu_sock.close()
+ vug_sock.close()
+ vugp.terminate()
+
+ def _test_vhost_user_vga_virgl(self, qemu_sock, kernel_path, initrd_path):
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("-chardev", f"socket,id=vug,fd={qemu_sock.fileno()}")
self.vm.add_args("-device", "vhost-user-vga,chardev=vug")
self.vm.add_args("-display", "egl-headless")
self.vm.add_args(
@@ -127,16 +131,14 @@ class VirtioGPUx86(QemuSystemTest):
)
try:
self.vm.launch()
- except:
+ except VMLaunchFailure:
# 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()
- vugp.terminate()
- vugp.wait()
+
if __name__ == '__main__':
QemuSystemTest.main()
diff --git a/tests/functional/test_virtio_version.py b/tests/functional/x86_64/test_virtio_version.py
index a5ea732..a5ea732 100755
--- a/tests/functional/test_virtio_version.py
+++ b/tests/functional/x86_64/test_virtio_version.py
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/test_xtensa_lx60.py b/tests/functional/xtensa/test_lx60.py
index 147c920..147c920 100755
--- a/tests/functional/test_xtensa_lx60.py
+++ b/tests/functional/xtensa/test_lx60.py
diff --git a/tests/functional/test_xtensa_replay.py b/tests/functional/xtensa/test_replay.py
index eb00a3b..eb00a3b 100755
--- a/tests/functional/test_xtensa_replay.py
+++ b/tests/functional/xtensa/test_replay.py