diff options
author | Stefan Hajnoczi <stefanha@redhat.com> | 2025-03-08 11:31:26 +0800 |
---|---|---|
committer | Stefan Hajnoczi <stefanha@redhat.com> | 2025-03-08 11:31:26 +0800 |
commit | e88a579392f74aa7658299f29dc43aca199e4533 (patch) | |
tree | 91b52d7cd5a8007869381e03927bddea3db5034f | |
parent | cfadd798dec85f1dc2f3db0debf139e2b92f9c4f (diff) | |
parent | d9b5dfc7122559e5b5959ecf534788b90c3dd102 (diff) | |
download | qemu-e88a579392f74aa7658299f29dc43aca199e4533.zip qemu-e88a579392f74aa7658299f29dc43aca199e4533.tar.gz qemu-e88a579392f74aa7658299f29dc43aca199e4533.tar.bz2 |
Merge tag 'pull-request-2025-03-07' of https://gitlab.com/thuth/qemu into staging
* Bug fixes and some small improvements for functional tests
* Improve performance of s390x PCI passthrough devices with relaxed translation
# -----BEGIN PGP SIGNATURE-----
#
# iQJFBAABCAAvFiEEJ7iIR+7gJQEY8+q5LtnXdP5wLbUFAmfK3dsRHHRodXRoQHJl
# ZGhhdC5jb20ACgkQLtnXdP5wLbUfDQ/8CopnzCKGKFhyM5skrHbhDbUVbul6yV4L
# kIOo7N8OlrNcQB90bj+Udy+mUANHjkmSiBa5lJ/78ej4DFS6CxeVgrl1fSEl36xn
# GjWDwSUiN8pG1O4YtnDqWVTBieGSzbkQr1jHgpeAnvv08s+TtmudP1T8IznWU2v9
# FqD78SdebZ0Kua+ksBgMxwkHd6VMw13vsu6KuT9VBhie40LcDrFOuG8RDz/qo4IO
# Yg9s1Bqcy7Wa4+0ldMXS1plSdIqJBtVc/HDTg1QwH994b4Lvr7ffrFZmuVcd2dbE
# XKQ5jAMOYZqWdlXszkyd8moYGhmevCkQlALhpnbHixnfakfFYX0wTiJB6oCthFQ0
# It0J/ntNsCmJiIHNbPLzsJ1pE5+ureRnGbxVe05n+zfm8MaXL6s4nSdZzHyp8n43
# UZQqVzK55Q34K9O0qoUdCdBCjMKS9v5u95jjJo8+nc8sJoeQTssOoiixwB/E4y21
# 9qSh7CbDjQK4zwuzQ7jKD603zAJH6ivvsHXlMBMXJFBiSMCAoQQ1vyou6yRHswRr
# gLHDwiWUx8SX8ckbbJ/+Zo9+T8JBMvC5hNYG8VoAtlTQusG4bHSbKdPNNH0eHsEp
# f7RlZPRizkcK3w0Nj+u4kXdnnex3QLLSgnyAYq7zEl6V+mho8KqaBezkO7wQDHZy
# +GW5ignQ1Gs=
# =CyiZ
# -----END PGP SIGNATURE-----
# gpg: Signature made Fri 07 Mar 2025 19:51:55 HKT
# gpg: using RSA key 27B88847EEE0250118F3EAB92ED9D774FE702DB5
# gpg: issuer "thuth@redhat.com"
# gpg: Good signature from "Thomas Huth <th.huth@gmx.de>" [full]
# gpg: aka "Thomas Huth <thuth@redhat.com>" [full]
# gpg: aka "Thomas Huth <huth@tuxfamily.org>" [full]
# gpg: aka "Thomas Huth <th.huth@posteo.de>" [unknown]
# Primary key fingerprint: 27B8 8847 EEE0 2501 18F3 EAB9 2ED9 D774 FE70 2DB5
* tag 'pull-request-2025-03-07' of https://gitlab.com/thuth/qemu:
s390x/pci: indicate QEMU supports relaxed translation for passthrough
s390x/pci: add support for guests that request direct mapping
MAINTAINERS: Add docs/devel/testing/functional.rst to the functional section
doc: add missing 'Asset' type in function test doc
tests/functional/test_virtio_balloon: Only use KVM for running this test
tests/functional: fix race in virtio balloon test
tests/functional: Increase the timeout of the mips64el_replay test
tests/functional/test_mips_malta: Add a network test via the pcnet NIC
tests/functional: Move the code for testing HTTP downloads to a common function
tests/functional: stop output from zstd command when uncompressing
tests/functional: drop unused 'get_tag' method
tests/functional: skip memaddr tests on 32-bit builds
tests/functional: reduce tuxrun maxmem to work on 32-bit hosts
tests/functional: set 'qemu_bin' as an object level field
tests/functional: remove unused 'bin_prefix' variable
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
-rw-r--r-- | MAINTAINERS | 1 | ||||
-rw-r--r-- | docs/devel/testing/functional.rst | 8 | ||||
-rw-r--r-- | hw/s390x/s390-pci-bus.c | 39 | ||||
-rw-r--r-- | hw/s390x/s390-pci-inst.c | 13 | ||||
-rw-r--r-- | hw/s390x/s390-pci-vfio.c | 28 | ||||
-rw-r--r-- | hw/s390x/s390-virtio-ccw.c | 5 | ||||
-rw-r--r-- | include/hw/s390x/s390-pci-bus.h | 3 | ||||
-rw-r--r-- | include/hw/s390x/s390-pci-clp.h | 1 | ||||
-rw-r--r-- | tests/functional/meson.build | 1 | ||||
-rw-r--r-- | tests/functional/qemu_test/linuxkernel.py | 26 | ||||
-rw-r--r-- | tests/functional/qemu_test/testcase.py | 8 | ||||
-rw-r--r-- | tests/functional/qemu_test/tuxruntest.py | 11 | ||||
-rw-r--r-- | tests/functional/qemu_test/uncompress.py | 6 | ||||
-rwxr-xr-x | tests/functional/test_intel_iommu.py | 22 | ||||
-rwxr-xr-x | tests/functional/test_mem_addr_space.py | 34 | ||||
-rwxr-xr-x | tests/functional/test_mips_malta.py | 20 | ||||
-rwxr-xr-x | tests/functional/test_ppc64_tuxrun.py | 2 | ||||
-rwxr-xr-x | tests/functional/test_virtio_balloon.py | 29 |
18 files changed, 197 insertions, 60 deletions
diff --git a/MAINTAINERS b/MAINTAINERS index 5df6020..77fab92 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -4236,6 +4236,7 @@ Functional testing framework M: Thomas Huth <thuth@redhat.com> R: Philippe Mathieu-Daudé <philmd@linaro.org> R: Daniel P. Berrange <berrange@redhat.com> +F: docs/devel/testing/functional.rst F: tests/functional/qemu_test/ Windows Hosted Continuous Integration diff --git a/docs/devel/testing/functional.rst b/docs/devel/testing/functional.rst index ecc7389..a9fa45e 100644 --- a/docs/devel/testing/functional.rst +++ b/docs/devel/testing/functional.rst @@ -173,7 +173,7 @@ QEMU binary selection ^^^^^^^^^^^^^^^^^^^^^ The QEMU binary used for the ``self.vm`` QEMUMachine instance will -primarily depend on the value of the ``qemu_bin`` class attribute. +primarily depend on the value of the ``qemu_bin`` instance attribute. If it is not explicitly set by the test code, its default value will be the result the QEMU_TEST_QEMU_BINARY environment variable. @@ -251,7 +251,7 @@ Many functional tests download assets (e.g. Linux kernels, initrds, firmware images, etc.) from the internet to be able to run tests with them. This imposes additional challenges to the test framework. -First there is the the problem that some people might not have an +First there is the problem that some people might not have an unconstrained internet connection, so such tests should not be run by default when running ``make check``. To accomplish this situation, the tests that download files should only be added to the "thorough" @@ -274,7 +274,9 @@ the tests are run. This pre-caching is done with the qemu_test.Asset class. To use it in your test, declare an asset in your test class with its URL and SHA256 checksum like this:: - ASSET_somename = ( + from qemu_test import Asset + + ASSET_somename = Asset( ('https://www.qemu.org/assets/images/qemu_head_200.png'), '34b74cad46ea28a2966c1d04e102510daf1fd73e6582b6b74523940d5da029dd') diff --git a/hw/s390x/s390-pci-bus.c b/hw/s390x/s390-pci-bus.c index 04cdd4a..2591ee4 100644 --- a/hw/s390x/s390-pci-bus.c +++ b/hw/s390x/s390-pci-bus.c @@ -18,6 +18,8 @@ #include "hw/s390x/s390-pci-inst.h" #include "hw/s390x/s390-pci-kvm.h" #include "hw/s390x/s390-pci-vfio.h" +#include "hw/s390x/s390-virtio-ccw.h" +#include "hw/boards.h" #include "hw/pci/pci_bus.h" #include "hw/qdev-properties.h" #include "hw/pci/pci_bridge.h" @@ -724,12 +726,42 @@ void s390_pci_iommu_enable(S390PCIIOMMU *iommu) g_free(name); } +void s390_pci_iommu_direct_map_enable(S390PCIIOMMU *iommu) +{ + MachineState *ms = MACHINE(qdev_get_machine()); + S390CcwMachineState *s390ms = S390_CCW_MACHINE(ms); + + /* + * For direct-mapping we must map the entire guest address space. Rather + * than using an iommu, create a memory region alias that maps GPA X to + * IOVA X + SDMA. VFIO will handle pinning via its memory listener. + */ + g_autofree char *name = g_strdup_printf("iommu-dm-s390-%04x", + iommu->pbdev->uid); + + iommu->dm_mr = g_malloc0(sizeof(*iommu->dm_mr)); + memory_region_init_alias(iommu->dm_mr, OBJECT(&iommu->mr), name, + get_system_memory(), 0, + s390_get_memory_limit(s390ms)); + iommu->enabled = true; + memory_region_add_subregion(&iommu->mr, iommu->pbdev->zpci_fn.sdma, + iommu->dm_mr); +} + void s390_pci_iommu_disable(S390PCIIOMMU *iommu) { iommu->enabled = false; g_hash_table_remove_all(iommu->iotlb); - memory_region_del_subregion(&iommu->mr, MEMORY_REGION(&iommu->iommu_mr)); - object_unparent(OBJECT(&iommu->iommu_mr)); + if (iommu->dm_mr) { + memory_region_del_subregion(&iommu->mr, iommu->dm_mr); + object_unparent(OBJECT(iommu->dm_mr)); + g_free(iommu->dm_mr); + iommu->dm_mr = NULL; + } else { + memory_region_del_subregion(&iommu->mr, + MEMORY_REGION(&iommu->iommu_mr)); + object_unparent(OBJECT(&iommu->iommu_mr)); + } } static void s390_pci_iommu_free(S390pciState *s, PCIBus *bus, int32_t devfn) @@ -1145,6 +1177,7 @@ static void s390_pcihost_plug(HotplugHandler *hotplug_dev, DeviceState *dev, /* Always intercept emulated devices */ pbdev->interp = false; pbdev->forwarding_assist = false; + pbdev->rtr_avail = false; } if (s390_pci_msix_init(pbdev) && !pbdev->interp) { @@ -1511,6 +1544,8 @@ static const Property s390_pci_device_properties[] = { DEFINE_PROP_BOOL("interpret", S390PCIBusDevice, interp, true), DEFINE_PROP_BOOL("forwarding-assist", S390PCIBusDevice, forwarding_assist, true), + DEFINE_PROP_BOOL("relaxed-translation", S390PCIBusDevice, rtr_avail, + true), }; static const VMStateDescription s390_pci_device_vmstate = { diff --git a/hw/s390x/s390-pci-inst.c b/hw/s390x/s390-pci-inst.c index e386d75..8cdeb6c 100644 --- a/hw/s390x/s390-pci-inst.c +++ b/hw/s390x/s390-pci-inst.c @@ -16,6 +16,7 @@ #include "exec/memory.h" #include "qemu/error-report.h" #include "system/hw_accel.h" +#include "hw/boards.h" #include "hw/pci/pci_device.h" #include "hw/s390x/s390-pci-inst.h" #include "hw/s390x/s390-pci-bus.h" @@ -1008,17 +1009,25 @@ static int reg_ioat(CPUS390XState *env, S390PCIBusDevice *pbdev, ZpciFib fib, } /* currently we only support designation type 1 with translation */ - if (!(dt == ZPCI_IOTA_RTTO && t)) { + if (t && dt != ZPCI_IOTA_RTTO) { error_report("unsupported ioat dt %d t %d", dt, t); s390_program_interrupt(env, PGM_OPERAND, ra); return -EINVAL; + } else if (!t && !pbdev->rtr_avail) { + error_report("relaxed translation not allowed"); + s390_program_interrupt(env, PGM_OPERAND, ra); + return -EINVAL; } iommu->pba = pba; iommu->pal = pal; iommu->g_iota = g_iota; - s390_pci_iommu_enable(iommu); + if (t) { + s390_pci_iommu_enable(iommu); + } else { + s390_pci_iommu_direct_map_enable(iommu); + } return 0; } diff --git a/hw/s390x/s390-pci-vfio.c b/hw/s390x/s390-pci-vfio.c index 7dbbc76..6236ac7 100644 --- a/hw/s390x/s390-pci-vfio.c +++ b/hw/s390x/s390-pci-vfio.c @@ -132,12 +132,27 @@ static void s390_pci_read_base(S390PCIBusDevice *pbdev, pbdev->pft = cap->pft; /* + * If the device is a passthrough ISM device, disallow relaxed + * translation. + */ + if (pbdev->pft == ZPCI_PFT_ISM) { + pbdev->rtr_avail = false; + } + + /* * If appropriate, reduce the size of the supported DMA aperture reported - * to the guest based upon the vfio DMA limit. + * to the guest based upon the vfio DMA limit. This is applicable for + * devices that are guaranteed to not use relaxed translation. If the + * device is capable of relaxed translation then we must advertise the + * full aperture. In this case, if translation is used then we will + * rely on the vfio DMA limit counting and use RPCIT CC1 / status 16 + * to request that the guest free DMA mappings as necessary. */ - vfio_size = pbdev->iommu->max_dma_limit << TARGET_PAGE_BITS; - if (vfio_size > 0 && vfio_size < cap->end_dma - cap->start_dma + 1) { - pbdev->zpci_fn.edma = cap->start_dma + vfio_size - 1; + if (!pbdev->rtr_avail) { + vfio_size = pbdev->iommu->max_dma_limit << TARGET_PAGE_BITS; + if (vfio_size > 0 && vfio_size < cap->end_dma - cap->start_dma + 1) { + pbdev->zpci_fn.edma = cap->start_dma + vfio_size - 1; + } } } @@ -223,8 +238,11 @@ static void s390_pci_read_group(S390PCIBusDevice *pbdev, pbdev->pci_group = s390_group_create(pbdev->zpci_fn.pfgid, start_gid); resgrp = &pbdev->pci_group->zpci_group; + if (pbdev->rtr_avail) { + resgrp->fr |= CLP_RSP_QPCIG_MASK_RTR; + } if (cap->flags & VFIO_DEVICE_INFO_ZPCI_FLAG_REFRESH) { - resgrp->fr = 1; + resgrp->fr |= CLP_RSP_QPCIG_MASK_REFRESH; } resgrp->dasm = cap->dasm; resgrp->msia = cap->msi_addr; diff --git a/hw/s390x/s390-virtio-ccw.c b/hw/s390x/s390-virtio-ccw.c index 51ae0c1..a9b3db1 100644 --- a/hw/s390x/s390-virtio-ccw.c +++ b/hw/s390x/s390-virtio-ccw.c @@ -936,8 +936,13 @@ static void ccw_machine_9_2_instance_options(MachineState *machine) static void ccw_machine_9_2_class_options(MachineClass *mc) { + static GlobalProperty compat[] = { + { TYPE_S390_PCI_DEVICE, "relaxed-translation", "off", }, + }; + ccw_machine_10_0_class_options(mc); compat_props_add(mc->compat_props, hw_compat_9_2, hw_compat_9_2_len); + compat_props_add(mc->compat_props, compat, G_N_ELEMENTS(compat)); } DEFINE_CCW_MACHINE(9, 2); diff --git a/include/hw/s390x/s390-pci-bus.h b/include/hw/s390x/s390-pci-bus.h index 2c43ea1..04944d4 100644 --- a/include/hw/s390x/s390-pci-bus.h +++ b/include/hw/s390x/s390-pci-bus.h @@ -277,6 +277,7 @@ struct S390PCIIOMMU { AddressSpace as; MemoryRegion mr; IOMMUMemoryRegion iommu_mr; + MemoryRegion *dm_mr; bool enabled; uint64_t g_iota; uint64_t pba; @@ -362,6 +363,7 @@ struct S390PCIBusDevice { bool interp; bool forwarding_assist; bool aif; + bool rtr_avail; QTAILQ_ENTRY(S390PCIBusDevice) link; }; @@ -389,6 +391,7 @@ int pci_chsc_sei_nt2_have_event(void); void s390_pci_sclp_configure(SCCB *sccb); void s390_pci_sclp_deconfigure(SCCB *sccb); void s390_pci_iommu_enable(S390PCIIOMMU *iommu); +void s390_pci_iommu_direct_map_enable(S390PCIIOMMU *iommu); void s390_pci_iommu_disable(S390PCIIOMMU *iommu); void s390_pci_generate_error_event(uint16_t pec, uint32_t fh, uint32_t fid, uint64_t faddr, uint32_t e); diff --git a/include/hw/s390x/s390-pci-clp.h b/include/hw/s390x/s390-pci-clp.h index 03b7f9b..6a635d6 100644 --- a/include/hw/s390x/s390-pci-clp.h +++ b/include/hw/s390x/s390-pci-clp.h @@ -158,6 +158,7 @@ typedef struct ClpRspQueryPciGrp { #define CLP_RSP_QPCIG_MASK_NOI 0xfff uint16_t i; uint8_t version; +#define CLP_RSP_QPCIG_MASK_RTR 0x20 #define CLP_RSP_QPCIG_MASK_FRAME 0x2 #define CLP_RSP_QPCIG_MASK_REFRESH 0x1 uint8_t fr; diff --git a/tests/functional/meson.build b/tests/functional/meson.build index 3fd2652..97c3f4a 100644 --- a/tests/functional/meson.build +++ b/tests/functional/meson.build @@ -36,6 +36,7 @@ test_timeouts = { 'intel_iommu': 300, 'mips_malta' : 120, 'mipsel_replay' : 480, + 'mips64el_replay' : 180, 'netdev_ethtool' : 180, 'ppc_40p' : 240, 'ppc64_hv' : 1000, diff --git a/tests/functional/qemu_test/linuxkernel.py b/tests/functional/qemu_test/linuxkernel.py index 2c95981..2aca0ee 100644 --- a/tests/functional/qemu_test/linuxkernel.py +++ b/tests/functional/qemu_test/linuxkernel.py @@ -3,8 +3,12 @@ # 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 hashlib +import urllib.request + +from .cmd import wait_for_console_pattern, exec_command_and_wait_for_pattern from .testcase import QemuSystemTest -from .cmd import wait_for_console_pattern +from .utils import get_usernet_hostfwd_port class LinuxKernelTest(QemuSystemTest): @@ -26,3 +30,23 @@ class LinuxKernelTest(QemuSystemTest): self.vm.launch() if wait_for: self.wait_for_console_pattern(wait_for) + + def check_http_download(self, filename, hashsum, guestport=8080, + pythoncmd='python3 -m http.server'): + exec_command_and_wait_for_pattern(self, + f'{pythoncmd} {guestport} & sleep 1', + f'Serving HTTP on 0.0.0.0 port {guestport}') + hl = hashlib.sha256() + hostport = get_usernet_hostfwd_port(self.vm) + url = f'http://localhost:{hostport}{filename}' + self.log.info(f'Downloading {url} ...') + with urllib.request.urlopen(url) as response: + while True: + chunk = response.read(1 << 20) + if not chunk: + break + hl.update(chunk) + + digest = hl.hexdigest() + self.log.info(f'sha256sum of download is {digest}.') + self.assertEqual(digest, hashsum) diff --git a/tests/functional/qemu_test/testcase.py b/tests/functional/qemu_test/testcase.py index 869f394..058bf27 100644 --- a/tests/functional/qemu_test/testcase.py +++ b/tests/functional/qemu_test/testcase.py @@ -33,7 +33,6 @@ from .uncompress import uncompress class QemuBaseTest(unittest.TestCase): - qemu_bin = os.getenv('QEMU_TEST_QEMU_BINARY') arch = None workdir = None @@ -192,7 +191,8 @@ class QemuBaseTest(unittest.TestCase): return False return True - def setUp(self, bin_prefix): + def setUp(self): + self.qemu_bin = os.getenv('QEMU_TEST_QEMU_BINARY') self.assertIsNotNone(self.qemu_bin, 'QEMU_TEST_QEMU_BINARY must be set') self.arch = self.qemu_bin.split('-')[-1] self.socketdir = None @@ -254,7 +254,7 @@ class QemuBaseTest(unittest.TestCase): class QemuUserTest(QemuBaseTest): def setUp(self): - super().setUp('qemu-') + super().setUp() self._ldpath = [] def add_ldpath(self, ldpath): @@ -277,7 +277,7 @@ class QemuSystemTest(QemuBaseTest): def setUp(self): self._vms = {} - super().setUp('qemu-system-') + super().setUp() console_log = logging.getLogger('console') console_log.setLevel(logging.DEBUG) diff --git a/tests/functional/qemu_test/tuxruntest.py b/tests/functional/qemu_test/tuxruntest.py index 41a4945..ad74156 100644 --- a/tests/functional/qemu_test/tuxruntest.py +++ b/tests/functional/qemu_test/tuxruntest.py @@ -24,17 +24,6 @@ class TuxRunBaselineTest(QemuSystemTest): # Tests are ~10-40s, allow for --debug/--enable-gcov overhead timeout = 100 - def get_tag(self, tagname, default=None): - """ - Get the metadata tag or return the default. - """ - utag = self._get_unique_tag_val(tagname) - print(f"{tagname}/{default} -> {utag}") - if utag: - return utag - - return default - def setUp(self): super().setUp() diff --git a/tests/functional/qemu_test/uncompress.py b/tests/functional/qemu_test/uncompress.py index 76dcf22..ce79da1 100644 --- a/tests/functional/qemu_test/uncompress.py +++ b/tests/functional/qemu_test/uncompress.py @@ -13,7 +13,7 @@ import os import stat import shutil from urllib.parse import urlparse -from subprocess import check_call, CalledProcessError +from subprocess import run, CalledProcessError, DEVNULL from .asset import Asset @@ -46,8 +46,8 @@ def zstd_uncompress(zstd_path, output_path): return try: - check_call(['zstd', "-f", "-d", zstd_path, - "-o", output_path]) + run(['zstd', "-f", "-d", zstd_path, + "-o", output_path], capture_output=True, check=True) except CalledProcessError as e: os.remove(output_path) raise Exception( diff --git a/tests/functional/test_intel_iommu.py b/tests/functional/test_intel_iommu.py index a9e8f82..62268d6 100755 --- a/tests/functional/test_intel_iommu.py +++ b/tests/functional/test_intel_iommu.py @@ -10,11 +10,7 @@ # 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 hashlib -import urllib.request - from qemu_test import LinuxKernelTest, Asset, exec_command_and_wait_for_pattern -from qemu_test.utils import get_usernet_hostfwd_port class IntelIOMMU(LinuxKernelTest): @@ -125,23 +121,7 @@ class IntelIOMMU(LinuxKernelTest): # Check virtio-net via HTTP: exec_command_and_wait_for_pattern(self, 'dhclient eth0', prompt) - exec_command_and_wait_for_pattern(self, - f'python3 -m http.server {self.GUEST_PORT} & sleep 1', - f'Serving HTTP on 0.0.0.0 port {self.GUEST_PORT}') - hl = hashlib.sha256() - hostport = get_usernet_hostfwd_port(self.vm) - url = f'http://localhost:{hostport}{filename}' - self.log.info(f'Downloading {url} ...') - with urllib.request.urlopen(url) as response: - while True: - chunk = response.read(1 << 20) - if not chunk: - break - hl.update(chunk) - - digest = hl.hexdigest() - self.log.info(f'sha256sum of download is {digest}.') - self.assertEqual(digest, hashsum) + self.check_http_download(filename, hashsum, self.GUEST_PORT) def test_intel_iommu(self): self.common_vm_setup() diff --git a/tests/functional/test_mem_addr_space.py b/tests/functional/test_mem_addr_space.py index bb0cf06..2d9d31e 100755 --- a/tests/functional/test_mem_addr_space.py +++ b/tests/functional/test_mem_addr_space.py @@ -20,6 +20,25 @@ class MemAddrCheck(QemuSystemTest): # this reason. DELAY_Q35_BOOT_SEQUENCE = 1 + # This helper can go away when the 32-bit host deprecation + # turns into full & final removal of support. + def ensure_64bit_binary(self): + with open(self.qemu_bin, "rb") as fh: + ident = fh.read(4) + + # "\x7fELF" + if ident != bytes([0x7f, 0x45, 0x4C, 0x46]): + # Non-ELF file implies macOS or Windows which + # we already assume to be 64-bit only + return + + # bits == 1 -> 32-bit; bits == 2 -> 64-bit + bits = int.from_bytes(fh.read(1), byteorder='little') + if bits != 2: + # 32-bit ELF builds won't be able to address sufficient + # RAM to run the tests + self.skipTest("64-bit build host is required") + # first, lets test some 32-bit processors. # for all 32-bit cases, pci64_hole_size is 0. def test_phybits_low_pse36(self): @@ -38,6 +57,7 @@ class MemAddrCheck(QemuSystemTest): If maxmem is set to 59.5G with all other QEMU parameters identical, QEMU should start fine. """ + self.ensure_64bit_binary() self.vm.add_args('-S', '-machine', 'q35', '-m', '512,slots=1,maxmem=59.6G', '-cpu', 'pentium,pse36=on', '-display', 'none', @@ -55,6 +75,7 @@ class MemAddrCheck(QemuSystemTest): access up to a maximum of 64GiB of memory. Rest is the same as the case with pse36 above. """ + self.ensure_64bit_binary() self.vm.add_args('-S', '-machine', 'q35', '-m', '512,slots=1,maxmem=59.6G', '-cpu', 'pentium,pae=on', '-display', 'none', @@ -71,6 +92,7 @@ class MemAddrCheck(QemuSystemTest): Setting maxmem to 59.5G and making sure that QEMU can start with the same options as the failing case above with pse36 cpu feature. """ + self.ensure_64bit_binary() self.vm.add_args('-machine', 'q35', '-m', '512,slots=1,maxmem=59.5G', '-cpu', 'pentium,pse36=on', '-display', 'none', @@ -88,6 +110,7 @@ class MemAddrCheck(QemuSystemTest): Setting maxmem to 59.5G and making sure that QEMU can start fine with the same options as the case above. """ + self.ensure_64bit_binary() self.vm.add_args('-machine', 'q35', '-m', '512,slots=1,maxmem=59.5G', '-cpu', 'pentium,pae=on', '-display', 'none', @@ -104,6 +127,7 @@ class MemAddrCheck(QemuSystemTest): Pentium2 has 36 bits of addressing, so its same as pentium with pse36 ON. """ + self.ensure_64bit_binary() self.vm.add_args('-machine', 'q35', '-m', '512,slots=1,maxmem=59.5G', '-cpu', 'pentium2', '-display', 'none', @@ -123,6 +147,7 @@ class MemAddrCheck(QemuSystemTest): message because the region for memory hotplug is always placed above 4 GiB due to the PCI hole and simplicity. """ + self.ensure_64bit_binary() self.vm.add_args('-S', '-machine', 'q35', '-m', '512,slots=1,maxmem=4G', '-cpu', 'pentium', '-display', 'none', @@ -150,6 +175,7 @@ class MemAddrCheck(QemuSystemTest): which is equal to 987.5 GiB. Setting the value to 988 GiB should make QEMU fail with the error message. """ + self.ensure_64bit_binary() self.vm.add_args('-S', '-machine', 'pc-q35-7.0', '-m', '512,slots=1,maxmem=988G', '-display', 'none', @@ -170,6 +196,7 @@ class MemAddrCheck(QemuSystemTest): Make sure QEMU fails when maxmem size is 976 GiB (12 GiB less than 988 GiB). """ + self.ensure_64bit_binary() self.vm.add_args('-S', '-machine', 'pc-q35-7.1', '-m', '512,slots=1,maxmem=976G', '-display', 'none', @@ -186,6 +213,7 @@ class MemAddrCheck(QemuSystemTest): Same as q35-7.0 AMD case except that here we check that QEMU can successfully start when maxmem is < 988G. """ + self.ensure_64bit_binary() self.vm.add_args('-S', '-machine', 'pc-q35-7.0', '-m', '512,slots=1,maxmem=987.5G', '-display', 'none', @@ -202,6 +230,7 @@ class MemAddrCheck(QemuSystemTest): Same as q35-7.1 AMD case except that here we check that QEMU can successfully start when maxmem is < 976G. """ + self.ensure_64bit_binary() self.vm.add_args('-S', '-machine', 'pc-q35-7.1', '-m', '512,slots=1,maxmem=975.5G', '-display', 'none', @@ -219,6 +248,7 @@ class MemAddrCheck(QemuSystemTest): Intel cpu instead. QEMU should start fine in this case as "above_4G" memory starts at 4G. """ + self.ensure_64bit_binary() self.vm.add_args('-S', '-cpu', 'Skylake-Server', '-machine', 'pc-q35-7.1', '-m', '512,slots=1,maxmem=976G', @@ -243,6 +273,7 @@ class MemAddrCheck(QemuSystemTest): memory for the VM (1024 - 32 - 1 + 0.5). With 992 GiB, QEMU should fail to start. """ + self.ensure_64bit_binary() self.vm.add_args('-S', '-cpu', 'EPYC-v4,phys-bits=41', '-machine', 'pc-q35-7.1', '-m', '512,slots=1,maxmem=992G', @@ -261,6 +292,7 @@ class MemAddrCheck(QemuSystemTest): Same as above but by setting maxram between 976 GiB and 992 Gib, QEMU should start fine. """ + self.ensure_64bit_binary() self.vm.add_args('-S', '-cpu', 'EPYC-v4,phys-bits=41', '-machine', 'pc-q35-7.1', '-m', '512,slots=1,maxmem=990G', @@ -281,6 +313,7 @@ class MemAddrCheck(QemuSystemTest): So maxmem here should be at most 986 GiB considering all memory boundary alignment constraints with 40 bits (1 TiB) of processor physical bits. """ + self.ensure_64bit_binary() self.vm.add_args('-S', '-cpu', 'Skylake-Server,phys-bits=40', '-machine', 'q35,cxl=on', '-m', '512,slots=1,maxmem=987G', @@ -299,6 +332,7 @@ class MemAddrCheck(QemuSystemTest): with the exact same parameters as above, QEMU should start fine even with cxl enabled. """ + self.ensure_64bit_binary() self.vm.add_args('-S', '-cpu', 'Skylake-Server,phys-bits=40', '-machine', 'q35,cxl=on', '-m', '512,slots=1,maxmem=987G', diff --git a/tests/functional/test_mips_malta.py b/tests/functional/test_mips_malta.py index eaf3722..9697c7d 100755 --- a/tests/functional/test_mips_malta.py +++ b/tests/functional/test_mips_malta.py @@ -45,12 +45,15 @@ class MaltaMachineConsole(LinuxKernelTest): 'dcfe3a7fe3200da3a00d176b95caaa086495eb158f2bff64afc67d7e1eb2cddc') def test_mips_malta_cpio(self): + self.require_netdev('user') + self.set_machine('malta') + self.require_device('pcnet') + kernel_path = self.archive_extract( self.ASSET_KERNEL_4_5_0, member='boot/vmlinux-4.5.0-2-4kc-malta') initrd_path = self.uncompress(self.ASSET_INITRD) - self.set_machine('malta') self.vm.set_console() kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE + 'console=ttyS0 console=tty ' @@ -58,6 +61,8 @@ class MaltaMachineConsole(LinuxKernelTest): self.vm.add_args('-kernel', kernel_path, '-initrd', initrd_path, '-append', kernel_command_line, + '-netdev', 'user,id=n1,tftp=' + self.scratch_file('boot'), + '-device', 'pcnet,netdev=n1', '-no-reboot') self.vm.launch() self.wait_for_console_pattern('Boot successful.') @@ -66,6 +71,19 @@ class MaltaMachineConsole(LinuxKernelTest): 'BogoMIPS') exec_command_and_wait_for_pattern(self, 'uname -a', 'Debian') + + exec_command_and_wait_for_pattern(self, 'ip link set eth0 up', + 'eth0: link up') + exec_command_and_wait_for_pattern(self, + 'ip addr add 10.0.2.15 dev eth0', + '#') + exec_command_and_wait_for_pattern(self, 'route add default eth0', '#') + exec_command_and_wait_for_pattern(self, + 'tftp -g -r vmlinux-4.5.0-2-4kc-malta 10.0.2.2', '#') + exec_command_and_wait_for_pattern(self, + 'md5sum vmlinux-4.5.0-2-4kc-malta', + 'a98218a7efbdefb2dfdf9ecd08c98318') + exec_command_and_wait_for_pattern(self, 'reboot', 'reboot: Restarting system') # Wait for VM to shut down gracefully diff --git a/tests/functional/test_ppc64_tuxrun.py b/tests/functional/test_ppc64_tuxrun.py index 05c6162..e8f79c6 100755 --- a/tests/functional/test_ppc64_tuxrun.py +++ b/tests/functional/test_ppc64_tuxrun.py @@ -64,7 +64,7 @@ class TuxRunPPC64Test(TuxRunBaselineTest): ',"index":1,"id":"pci.1"}') self.vm.add_args('-device', '{"driver":"spapr-vscsi","id":"scsi1"' ',"reg":12288}') - self.vm.add_args('-m', '2G,slots=32,maxmem=4G', + self.vm.add_args('-m', '1G,slots=32,maxmem=2G', '-object', 'memory-backend-ram,id=ram1,size=1G', '-device', 'pc-dimm,id=dimm1,memdev=ram1') diff --git a/tests/functional/test_virtio_balloon.py b/tests/functional/test_virtio_balloon.py index 67b48e1..5877b6c 100755 --- a/tests/functional/test_virtio_balloon.py +++ b/tests/functional/test_virtio_balloon.py @@ -32,7 +32,7 @@ class VirtioBalloonx86(QemuSystemTest): 'e3c1b309d9203604922d6e255c2c5d098a309c2d46215d8fc026954f3c5c27a0') DEFAULT_KERNEL_PARAMS = ('root=/dev/vda1 console=ttyS0 net.ifnames=0 ' - 'rd.rescue') + 'rd.rescue quiet') def wait_for_console_pattern(self, success_message, vm=None): wait_for_console_pattern( @@ -47,6 +47,11 @@ class VirtioBalloonx86(QemuSystemTest): prompt = '# ' self.wait_for_console_pattern(prompt) + # Synchronize on virtio-block driver creating the root device + exec_command_and_wait_for_pattern(self, + "while ! (dmesg -c | grep vda:) ; do sleep 1 ; done", + "vda1") + exec_command_and_wait_for_pattern(self, 'mount /dev/vda1 /sysroot', prompt) exec_command_and_wait_for_pattern(self, 'chroot /sysroot', @@ -65,10 +70,21 @@ class VirtioBalloonx86(QemuSystemTest): assert val == UNSET_STATS_VALUE def assert_running_stats(self, then): - ret = self.vm.qmp('qom-get', - {'path': '/machine/peripheral/balloon', - 'property': 'guest-stats'})['return'] - when = ret.get('last-update') + # We told the QEMU to refresh stats every 100ms, but + # there can be a delay between virtio-ballon driver + # being modprobed and seeing the first stats refresh + # Retry a few times for robustness under heavy load + retries = 10 + when = 0 + while when == 0 and retries: + ret = self.vm.qmp('qom-get', + {'path': '/machine/peripheral/balloon', + 'property': 'guest-stats'})['return'] + when = ret.get('last-update') + if when == 0: + retries = retries - 1 + time.sleep(0.5) + now = time.time() assert when > then and when < now @@ -94,6 +110,7 @@ class VirtioBalloonx86(QemuSystemTest): def test_virtio_balloon_stats(self): self.set_machine('q35') + self.require_accelerator("kvm") kernel_path = self.ASSET_KERNEL.fetch() initrd_path = self.ASSET_INITRD.fetch() diskimage_path = self.ASSET_DISKIMAGE.fetch() @@ -106,7 +123,7 @@ class VirtioBalloonx86(QemuSystemTest): # reset, we can reliably catch the clean stats again in BIOS # phase before the guest OS launches self.vm.add_args("-boot", "menu=on") - self.vm.add_args("-machine", "q35,accel=kvm:tcg") + self.vm.add_args("-accel", "kvm") self.vm.add_args("-device", "virtio-balloon,id=balloon") self.vm.add_args('-drive', f'file={diskimage_path},if=none,id=drv0,snapshot=on') |