]> xenbits.xensource.com Git - qemu-xen.git/commitdiff
tests/functional: Convert simple avocado tests into standalone python tests
authorThomas Huth <thuth@redhat.com>
Fri, 30 Aug 2024 13:38:06 +0000 (15:38 +0200)
committerThomas Huth <thuth@redhat.com>
Wed, 4 Sep 2024 08:52:29 +0000 (10:52 +0200)
These test are rather simple and don't need any modifications apart
from adjusting the "from avocado_qemu" line. To ease debugging, make
the files executable and add a shebang line and Python '__main__'
handling, too, so that these tests can now be run by executing them
directly.

Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Tested-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Message-ID: <20240830133841.142644-13-thuth@redhat.com>
Signed-off-by: Thomas Huth <thuth@redhat.com>
12 files changed:
MAINTAINERS
tests/avocado/cpu_queries.py [deleted file]
tests/avocado/empty_cpu_model.py [deleted file]
tests/avocado/mem-addr-space-check.py [deleted file]
tests/avocado/pc_cpu_hotplug_props.py [deleted file]
tests/avocado/virtio_version.py [deleted file]
tests/functional/meson.build
tests/functional/test_cpu_queries.py [new file with mode: 0755]
tests/functional/test_empty_cpu_model.py [new file with mode: 0755]
tests/functional/test_mem_addr_space.py [new file with mode: 0755]
tests/functional/test_pc_cpu_hotplug_props.py [new file with mode: 0755]
tests/functional/test_virtio_version.py [new file with mode: 0755]

index 80cc84dd996eb1f43d3c6f31eca7e27cd50a2429..b3a0ac0e8b7482b08b133322c38a1176226ef051 100644 (file)
@@ -1833,6 +1833,8 @@ F: hw/isa/apm.c
 F: include/hw/isa/apm.h
 F: tests/unit/test-x86-topo.c
 F: tests/qtest/test-x86-cpuid-compat.c
+F: tests/functional/test_mem_addr_space.py
+F: tests/functional/test_pc_cpu_hotplug_props.py
 
 PC Chipset
 M: Michael S. Tsirkin <mst@redhat.com>
@@ -1899,6 +1901,8 @@ F: include/hw/boards.h
 F: include/hw/core/cpu.h
 F: include/hw/cpu/cluster.h
 F: include/sysemu/numa.h
+F: tests/functional/test_cpu_queries.py
+F: tests/functional/test_empty_cpu_model.py
 F: tests/unit/test-smp-parse.c
 T: git https://gitlab.com/ehabkost/qemu.git machine-next
 
@@ -2238,6 +2242,7 @@ F: net/vhost-user.c
 F: include/hw/virtio/
 F: docs/devel/virtio*
 F: docs/devel/migration/virtio.rst
+F: tests/functional/test_virtio_version.py
 
 virtio-balloon
 M: Michael S. Tsirkin <mst@redhat.com>
diff --git a/tests/avocado/cpu_queries.py b/tests/avocado/cpu_queries.py
deleted file mode 100644 (file)
index d3faa14..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-# Sanity check of query-cpu-* results
-#
-# Copyright (c) 2019 Red Hat, Inc.
-#
-# Author:
-#  Eduardo Habkost <ehabkost@redhat.com>
-#
-# 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 avocado_qemu import QemuSystemTest
-
-class QueryCPUModelExpansion(QemuSystemTest):
-    """
-    Run query-cpu-model-expansion for each CPU model, and validate results
-    """
-
-    def test(self):
-        """
-        :avocado: tags=arch:x86_64
-        :avocado: tags=machine:none
-        """
-        self.vm.add_args('-S')
-        self.vm.launch()
-
-        cpus = self.vm.cmd('query-cpu-definitions')
-        for c in cpus:
-            self.log.info("Checking CPU: %s", c)
-            self.assertNotIn('', c['unavailable-features'], c['name'])
-
-        for c in cpus:
-            model = {'name': c['name']}
-            e = self.vm.cmd('query-cpu-model-expansion', model=model,
-                            type='full')
-            self.assertEqual(e['model']['name'], c['name'])
diff --git a/tests/avocado/empty_cpu_model.py b/tests/avocado/empty_cpu_model.py
deleted file mode 100644 (file)
index d906ef3..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-# Check for crash when using empty -cpu option
-#
-# Copyright (c) 2019 Red Hat, Inc.
-#
-# Author:
-#  Eduardo Habkost <ehabkost@redhat.com>
-#
-# 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 avocado_qemu import QemuSystemTest
-
-class EmptyCPUModel(QemuSystemTest):
-    def test(self):
-        self.vm.add_args('-S', '-display', 'none', '-machine', 'none', '-cpu', '')
-        self.vm.set_qmp_monitor(enabled=False)
-        self.vm.launch()
-        self.vm.wait()
-        self.assertEqual(self.vm.exitcode(), 1, "QEMU exit code should be 1")
-        self.assertRegex(self.vm.get_log(), r'-cpu option cannot be empty')
diff --git a/tests/avocado/mem-addr-space-check.py b/tests/avocado/mem-addr-space-check.py
deleted file mode 100644 (file)
index d397459..0000000
+++ /dev/null
@@ -1,354 +0,0 @@
-# Check for crash when using memory beyond the available guest processor
-# address space.
-#
-# Copyright (c) 2023 Red Hat, Inc.
-#
-# Author:
-#  Ani Sinha <anisinha@redhat.com>
-#
-# SPDX-License-Identifier: GPL-2.0-or-later
-
-from avocado_qemu import QemuSystemTest
-import time
-
-class MemAddrCheck(QemuSystemTest):
-    # after launch, in order to generate the logs from QEMU we need to
-    # wait for some time. Launching and then immediately shutting down
-    # the VM generates empty logs. A delay of 1 second is added for
-    # this reason.
-    DELAY_Q35_BOOT_SEQUENCE = 1
-
-    # first, lets test some 32-bit processors.
-    # for all 32-bit cases, pci64_hole_size is 0.
-    def test_phybits_low_pse36(self):
-        """
-        :avocado: tags=machine:q35
-        :avocado: tags=arch:x86_64
-
-        With pse36 feature ON, a processor has 36 bits of addressing. So it can
-        access up to a maximum of 64GiB of memory. Memory hotplug region begins
-        at 4 GiB boundary when "above_4g_mem_size" is 0 (this would be true when
-        we have 0.5 GiB of VM memory, see pc_q35_init()). This means total
-        hotpluggable memory size is 60 GiB. Per slot, we reserve 1 GiB of memory
-        for dimm alignment for all machines. That leaves total hotpluggable
-        actual memory size of 59 GiB. If the VM is started with 0.5 GiB of
-        memory, maxmem should be set to a maximum value of 59.5 GiB to ensure
-        that the processor can address all memory directly.
-        Note that 64-bit pci hole size is 0 in this case. If maxmem is set to
-        59.6G, QEMU should fail to start with a message "phy-bits are too low".
-        If maxmem is set to 59.5G with all other QEMU parameters identical, QEMU
-        should start fine.
-        """
-        self.vm.add_args('-S', '-machine', 'q35', '-m',
-                         '512,slots=1,maxmem=59.6G',
-                         '-cpu', 'pentium,pse36=on', '-display', 'none',
-                         '-object', 'memory-backend-ram,id=mem1,size=1G',
-                         '-device', 'pc-dimm,id=vm0,memdev=mem1')
-        self.vm.set_qmp_monitor(enabled=False)
-        self.vm.launch()
-        self.vm.wait()
-        self.assertEqual(self.vm.exitcode(), 1, "QEMU exit code should be 1")
-        self.assertRegex(self.vm.get_log(), r'phys-bits too low')
-
-    def test_phybits_low_pae(self):
-        """
-        :avocado: tags=machine:q35
-        :avocado: tags=arch:x86_64
-
-        With pae feature ON, a processor has 36 bits of addressing. So it can
-        access up to a maximum of 64GiB of memory. Rest is the same as the case
-        with pse36 above.
-        """
-        self.vm.add_args('-S', '-machine', 'q35', '-m',
-                         '512,slots=1,maxmem=59.6G',
-                         '-cpu', 'pentium,pae=on', '-display', 'none',
-                         '-object', 'memory-backend-ram,id=mem1,size=1G',
-                         '-device', 'pc-dimm,id=vm0,memdev=mem1')
-        self.vm.set_qmp_monitor(enabled=False)
-        self.vm.launch()
-        self.vm.wait()
-        self.assertEqual(self.vm.exitcode(), 1, "QEMU exit code should be 1")
-        self.assertRegex(self.vm.get_log(), r'phys-bits too low')
-
-    def test_phybits_ok_pentium_pse36(self):
-        """
-        :avocado: tags=machine:q35
-        :avocado: tags=arch:x86_64
-
-        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.vm.add_args('-machine', 'q35', '-m',
-                         '512,slots=1,maxmem=59.5G',
-                         '-cpu', 'pentium,pse36=on', '-display', 'none',
-                         '-object', 'memory-backend-ram,id=mem1,size=1G',
-                         '-device', 'pc-dimm,id=vm0,memdev=mem1')
-        self.vm.set_qmp_monitor(enabled=False)
-        self.vm.launch()
-        time.sleep(self.DELAY_Q35_BOOT_SEQUENCE)
-        self.vm.shutdown()
-        self.assertNotRegex(self.vm.get_log(), r'phys-bits too low')
-
-    def test_phybits_ok_pentium_pae(self):
-        """
-        :avocado: tags=machine:q35
-        :avocado: tags=arch:x86_64
-
-        Test is same as above but now with pae cpu feature turned on.
-        Setting maxmem to 59.5G and making sure that QEMU can start fine
-        with the same options as the case above.
-        """
-        self.vm.add_args('-machine', 'q35', '-m',
-                         '512,slots=1,maxmem=59.5G',
-                         '-cpu', 'pentium,pae=on', '-display', 'none',
-                         '-object', 'memory-backend-ram,id=mem1,size=1G',
-                         '-device', 'pc-dimm,id=vm0,memdev=mem1')
-        self.vm.set_qmp_monitor(enabled=False)
-        self.vm.launch()
-        time.sleep(self.DELAY_Q35_BOOT_SEQUENCE)
-        self.vm.shutdown()
-        self.assertNotRegex(self.vm.get_log(), r'phys-bits too low')
-
-    def test_phybits_ok_pentium2(self):
-        """
-        :avocado: tags=machine:q35
-        :avocado: tags=arch:x86_64
-
-        Pentium2 has 36 bits of addressing, so its same as pentium
-        with pse36 ON.
-        """
-        self.vm.add_args('-machine', 'q35', '-m',
-                         '512,slots=1,maxmem=59.5G',
-                         '-cpu', 'pentium2', '-display', 'none',
-                         '-object', 'memory-backend-ram,id=mem1,size=1G',
-                         '-device', 'pc-dimm,id=vm0,memdev=mem1')
-        self.vm.set_qmp_monitor(enabled=False)
-        self.vm.launch()
-        time.sleep(self.DELAY_Q35_BOOT_SEQUENCE)
-        self.vm.shutdown()
-        self.assertNotRegex(self.vm.get_log(), r'phys-bits too low')
-
-    def test_phybits_low_nonpse36(self):
-        """
-        :avocado: tags=machine:q35
-        :avocado: tags=arch:x86_64
-
-        Pentium processor has 32 bits of addressing without pse36 or pae
-        so it can access physical address up to 4 GiB. Setting maxmem to
-        4 GiB should make QEMU fail to start with "phys-bits too low"
-        message because the region for memory hotplug is always placed
-        above 4 GiB due to the PCI hole and simplicity.
-        """
-        self.vm.add_args('-S', '-machine', 'q35', '-m',
-                         '512,slots=1,maxmem=4G',
-                         '-cpu', 'pentium', '-display', 'none',
-                         '-object', 'memory-backend-ram,id=mem1,size=1G',
-                         '-device', 'pc-dimm,id=vm0,memdev=mem1')
-        self.vm.set_qmp_monitor(enabled=False)
-        self.vm.launch()
-        self.vm.wait()
-        self.assertEqual(self.vm.exitcode(), 1, "QEMU exit code should be 1")
-        self.assertRegex(self.vm.get_log(), r'phys-bits too low')
-
-    # now lets test some 64-bit CPU cases.
-    def test_phybits_low_tcg_q35_70_amd(self):
-        """
-        :avocado: tags=machine:q35
-        :avocado: tags=arch:x86_64
-
-        For q35 7.1 machines and above, there is a HT window that starts at
-        1024 GiB and ends at 1 TiB - 1. If the max GPA falls in this range,
-        "above_4G" memory is adjusted to start at 1 TiB boundary for AMD cpus
-        in the default case. Lets test without that case for machines 7.0.
-        For q35-7.0 machines, "above 4G" memory starts are 4G.
-        pci64_hole size is 32 GiB. Since TCG_PHYS_ADDR_BITS is defined to
-        be 40, TCG emulated CPUs have maximum of 1 TiB (1024 GiB) of
-        directly addressable memory.
-        Hence, maxmem value at most can be
-        1024 GiB - 4 GiB - 1 GiB per slot for alignment - 32 GiB + 0.5 GiB
-        which is equal to 987.5 GiB. Setting the value to 988 GiB should
-        make QEMU fail with the error message.
-        """
-        self.vm.add_args('-S', '-machine', 'pc-q35-7.0', '-m',
-                         '512,slots=1,maxmem=988G',
-                         '-display', 'none',
-                         '-object', 'memory-backend-ram,id=mem1,size=1G',
-                         '-device', 'pc-dimm,id=vm0,memdev=mem1')
-        self.vm.set_qmp_monitor(enabled=False)
-        self.vm.launch()
-        self.vm.wait()
-        self.assertEqual(self.vm.exitcode(), 1, "QEMU exit code should be 1")
-        self.assertRegex(self.vm.get_log(), r'phys-bits too low')
-
-    def test_phybits_low_tcg_q35_71_amd(self):
-        """
-        :avocado: tags=machine:q35
-        :avocado: tags=arch:x86_64
-
-        AMD_HT_START is defined to be at 1012 GiB. So for q35 machines
-        version > 7.0 and AMD cpus, instead of 1024 GiB limit for 40 bit
-        processor address space, it has to be 1012 GiB , that is 12 GiB
-        less than the case above in order to accommodate HT hole.
-        Make sure QEMU fails when maxmem size is 976 GiB (12 GiB less
-        than 988 GiB).
-        """
-        self.vm.add_args('-S', '-machine', 'pc-q35-7.1', '-m',
-                         '512,slots=1,maxmem=976G',
-                         '-display', 'none',
-                         '-object', 'memory-backend-ram,id=mem1,size=1G',
-                         '-device', 'pc-dimm,id=vm0,memdev=mem1')
-        self.vm.set_qmp_monitor(enabled=False)
-        self.vm.launch()
-        self.vm.wait()
-        self.assertEqual(self.vm.exitcode(), 1, "QEMU exit code should be 1")
-        self.assertRegex(self.vm.get_log(), r'phys-bits too low')
-
-    def test_phybits_ok_tcg_q35_70_amd(self):
-        """
-        :avocado: tags=machine:q35
-        :avocado: tags=arch:x86_64
-
-        Same as q35-7.0 AMD case except that here we check that QEMU can
-        successfully start when maxmem is < 988G.
-        """
-        self.vm.add_args('-S', '-machine', 'pc-q35-7.0', '-m',
-                         '512,slots=1,maxmem=987.5G',
-                         '-display', 'none',
-                         '-object', 'memory-backend-ram,id=mem1,size=1G',
-                         '-device', 'pc-dimm,id=vm0,memdev=mem1')
-        self.vm.set_qmp_monitor(enabled=False)
-        self.vm.launch()
-        time.sleep(self.DELAY_Q35_BOOT_SEQUENCE)
-        self.vm.shutdown()
-        self.assertNotRegex(self.vm.get_log(), r'phys-bits too low')
-
-    def test_phybits_ok_tcg_q35_71_amd(self):
-        """
-        :avocado: tags=machine:q35
-        :avocado: tags=arch:x86_64
-
-        Same as q35-7.1 AMD case except that here we check that QEMU can
-        successfully start when maxmem is < 976G.
-        """
-        self.vm.add_args('-S', '-machine', 'pc-q35-7.1', '-m',
-                         '512,slots=1,maxmem=975.5G',
-                         '-display', 'none',
-                         '-object', 'memory-backend-ram,id=mem1,size=1G',
-                         '-device', 'pc-dimm,id=vm0,memdev=mem1')
-        self.vm.set_qmp_monitor(enabled=False)
-        self.vm.launch()
-        time.sleep(self.DELAY_Q35_BOOT_SEQUENCE)
-        self.vm.shutdown()
-        self.assertNotRegex(self.vm.get_log(), r'phys-bits too low')
-
-    def test_phybits_ok_tcg_q35_71_intel(self):
-        """
-        :avocado: tags=machine:q35
-        :avocado: tags=arch:x86_64
-
-        Same parameters as test_phybits_low_tcg_q35_71_amd() but use
-        Intel cpu instead. QEMU should start fine in this case as
-        "above_4G" memory starts at 4G.
-        """
-        self.vm.add_args('-S', '-cpu', 'Skylake-Server',
-                         '-machine', 'pc-q35-7.1', '-m',
-                         '512,slots=1,maxmem=976G',
-                         '-display', 'none',
-                         '-object', 'memory-backend-ram,id=mem1,size=1G',
-                         '-device', 'pc-dimm,id=vm0,memdev=mem1')
-        self.vm.set_qmp_monitor(enabled=False)
-        self.vm.launch()
-        time.sleep(self.DELAY_Q35_BOOT_SEQUENCE)
-        self.vm.shutdown()
-        self.assertNotRegex(self.vm.get_log(), r'phys-bits too low')
-
-    def test_phybits_low_tcg_q35_71_amd_41bits(self):
-        """
-        :avocado: tags=machine:q35
-        :avocado: tags=arch:x86_64
-
-        AMD processor with 41 bits. Max cpu hw address = 2 TiB.
-        By setting maxram above 1012 GiB  - 32 GiB - 4 GiB = 976 GiB, we can
-        force "above_4G" memory to start at 1 TiB for q35-7.1 machines
-        (max GPA will be above AMD_HT_START which is defined as 1012 GiB).
-
-        With pci_64_hole size at 32 GiB, in this case, maxmem should be 991.5
-        GiB with 1 GiB per slot for alignment and 0.5 GiB as non-hotplug
-        memory for the VM (1024 - 32 - 1 + 0.5). With 992 GiB, QEMU should
-        fail to start.
-        """
-        self.vm.add_args('-S', '-cpu', 'EPYC-v4,phys-bits=41',
-                         '-machine', 'pc-q35-7.1', '-m',
-                         '512,slots=1,maxmem=992G',
-                         '-display', 'none',
-                         '-object', 'memory-backend-ram,id=mem1,size=1G',
-                         '-device', 'pc-dimm,id=vm0,memdev=mem1')
-        self.vm.set_qmp_monitor(enabled=False)
-        self.vm.launch()
-        self.vm.wait()
-        self.assertEqual(self.vm.exitcode(), 1, "QEMU exit code should be 1")
-        self.assertRegex(self.vm.get_log(), r'phys-bits too low')
-
-    def test_phybits_ok_tcg_q35_71_amd_41bits(self):
-        """
-        :avocado: tags=machine:q35
-        :avocado: tags=arch:x86_64
-
-        AMD processor with 41 bits. Max cpu hw address = 2 TiB.
-        Same as above but by setting maxram between 976 GiB and 992 Gib,
-        QEMU should start fine.
-        """
-        self.vm.add_args('-S', '-cpu', 'EPYC-v4,phys-bits=41',
-                         '-machine', 'pc-q35-7.1', '-m',
-                         '512,slots=1,maxmem=990G',
-                         '-display', 'none',
-                         '-object', 'memory-backend-ram,id=mem1,size=1G',
-                         '-device', 'pc-dimm,id=vm0,memdev=mem1')
-        self.vm.set_qmp_monitor(enabled=False)
-        self.vm.launch()
-        time.sleep(self.DELAY_Q35_BOOT_SEQUENCE)
-        self.vm.shutdown()
-        self.assertNotRegex(self.vm.get_log(), r'phys-bits too low')
-
-    def test_phybits_low_tcg_q35_intel_cxl(self):
-        """
-        :avocado: tags=machine:q35
-        :avocado: tags=arch:x86_64
-
-        cxl memory window starts after memory device range. Here, we use 1 GiB
-        of cxl window memory. 4G_mem end aligns at 4G. pci64_hole is 32 GiB and
-        starts after the cxl memory window.
-        So maxmem here should be at most 986 GiB considering all memory boundary
-        alignment constraints with 40 bits (1 TiB) of processor physical bits.
-        """
-        self.vm.add_args('-S', '-cpu', 'Skylake-Server,phys-bits=40',
-                         '-machine', 'q35,cxl=on', '-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')
-        self.vm.set_qmp_monitor(enabled=False)
-        self.vm.launch()
-        self.vm.wait()
-        self.assertEqual(self.vm.exitcode(), 1, "QEMU exit code should be 1")
-        self.assertRegex(self.vm.get_log(), r'phys-bits too low')
-
-    def test_phybits_ok_tcg_q35_intel_cxl(self):
-        """
-        :avocado: tags=machine:q35
-        :avocado: tags=arch:x86_64
-
-        Same as above but here we do not reserve any cxl memory window. Hence,
-        with the exact same parameters as above, QEMU should start fine even
-        with cxl enabled.
-        """
-        self.vm.add_args('-S', '-cpu', 'Skylake-Server,phys-bits=40',
-                         '-machine', 'q35,cxl=on', '-m',
-                         '512,slots=1,maxmem=987G',
-                         '-display', 'none',
-                         '-device', 'pxb-cxl,bus_nr=12,bus=pcie.0,id=cxl.1')
-        self.vm.set_qmp_monitor(enabled=False)
-        self.vm.launch()
-        time.sleep(self.DELAY_Q35_BOOT_SEQUENCE)
-        self.vm.shutdown()
-        self.assertNotRegex(self.vm.get_log(), r'phys-bits too low')
diff --git a/tests/avocado/pc_cpu_hotplug_props.py b/tests/avocado/pc_cpu_hotplug_props.py
deleted file mode 100644 (file)
index 4bd3e02..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-#
-# Ensure CPU die-id can be omitted on -device
-#
-#  Copyright (c) 2019 Red Hat Inc
-#
-# Author:
-#  Eduardo Habkost <ehabkost@redhat.com>
-#
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of the GNU Lesser General Public
-# License as published by the Free Software Foundation; either
-# version 2.1 of the License, or (at your option) any later version.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library; if not, see <http://www.gnu.org/licenses/>.
-#
-
-from avocado_qemu import QemuSystemTest
-
-class OmittedCPUProps(QemuSystemTest):
-    """
-    :avocado: tags=arch:x86_64
-    :avocado: tags=cpu:qemu64
-    """
-    def test_no_die_id(self):
-        self.vm.add_args('-nodefaults', '-S')
-        self.vm.add_args('-smp', '1,sockets=2,cores=2,threads=2,maxcpus=8')
-        self.vm.add_args('-device', 'qemu64-x86_64-cpu,socket-id=1,core-id=0,thread-id=0')
-        self.vm.launch()
-        self.assertEqual(len(self.vm.cmd('query-cpus-fast')), 2)
diff --git a/tests/avocado/virtio_version.py b/tests/avocado/virtio_version.py
deleted file mode 100644 (file)
index afe5e82..0000000
+++ /dev/null
@@ -1,175 +0,0 @@
-"""
-Check compatibility of virtio device types
-"""
-# Copyright (c) 2018 Red Hat, Inc.
-#
-# Author:
-#  Eduardo Habkost <ehabkost@redhat.com>
-#
-# 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 sys
-import os
-
-from qemu.machine import QEMUMachine
-from avocado_qemu import QemuSystemTest
-
-# Virtio Device IDs:
-VIRTIO_NET = 1
-VIRTIO_BLOCK = 2
-VIRTIO_CONSOLE = 3
-VIRTIO_RNG = 4
-VIRTIO_BALLOON = 5
-VIRTIO_RPMSG = 7
-VIRTIO_SCSI = 8
-VIRTIO_9P = 9
-VIRTIO_RPROC_SERIAL = 11
-VIRTIO_CAIF = 12
-VIRTIO_GPU = 16
-VIRTIO_INPUT = 18
-VIRTIO_VSOCK = 19
-VIRTIO_CRYPTO = 20
-
-PCI_VENDOR_ID_REDHAT_QUMRANET = 0x1af4
-
-# Device IDs for legacy/transitional devices:
-PCI_LEGACY_DEVICE_IDS = {
-    VIRTIO_NET:     0x1000,
-    VIRTIO_BLOCK:   0x1001,
-    VIRTIO_BALLOON: 0x1002,
-    VIRTIO_CONSOLE: 0x1003,
-    VIRTIO_SCSI:    0x1004,
-    VIRTIO_RNG:     0x1005,
-    VIRTIO_9P:      0x1009,
-    VIRTIO_VSOCK:   0x1012,
-}
-
-def pci_modern_device_id(virtio_devid):
-    return virtio_devid + 0x1040
-
-def devtype_implements(vm, devtype, implements):
-    return devtype in [d['name'] for d in
-                       vm.cmd('qom-list-types', implements=implements)]
-
-def get_pci_interfaces(vm, devtype):
-    interfaces = ('pci-express-device', 'conventional-pci-device')
-    return [i for i in interfaces if devtype_implements(vm, devtype, i)]
-
-class VirtioVersionCheck(QemuSystemTest):
-    """
-    Check if virtio-version-specific device types result in the
-    same device tree created by `disable-modern` and
-    `disable-legacy`.
-
-    :avocado: tags=arch:x86_64
-    """
-
-    # just in case there are failures, show larger diff:
-    maxDiff = 4096
-
-    def run_device(self, devtype, opts=None, machine='pc'):
-        """
-        Run QEMU with `-device DEVTYPE`, return device info from `query-pci`
-        """
-        with QEMUMachine(self.qemu_bin) as vm:
-            vm.set_machine(machine)
-            if opts:
-                devtype += ',' + opts
-            vm.add_args('-device', '%s,id=devfortest' % (devtype))
-            vm.add_args('-S')
-            vm.launch()
-
-            pcibuses = vm.cmd('query-pci')
-            alldevs = [dev for bus in pcibuses for dev in bus['devices']]
-            devfortest = [dev for dev in alldevs
-                          if dev['qdev_id'] == 'devfortest']
-            return devfortest[0], get_pci_interfaces(vm, devtype)
-
-
-    def assert_devids(self, dev, devid, non_transitional=False):
-        self.assertEqual(dev['id']['vendor'], PCI_VENDOR_ID_REDHAT_QUMRANET)
-        self.assertEqual(dev['id']['device'], devid)
-        if non_transitional:
-            self.assertTrue(0x1040 <= dev['id']['device'] <= 0x107f)
-            self.assertGreaterEqual(dev['id']['subsystem'], 0x40)
-
-    def check_all_variants(self, qemu_devtype, virtio_devid):
-        """Check if a virtio device type and its variants behave as expected"""
-        # Force modern mode:
-        dev_modern, _ = self.run_device(qemu_devtype,
-                                       'disable-modern=off,disable-legacy=on')
-        self.assert_devids(dev_modern, pci_modern_device_id(virtio_devid),
-                           non_transitional=True)
-
-        # <prefix>-non-transitional device types should be 100% equivalent to
-        # <prefix>,disable-modern=off,disable-legacy=on
-        dev_1_0, nt_ifaces = self.run_device('%s-non-transitional' % (qemu_devtype))
-        self.assertEqual(dev_modern, dev_1_0)
-
-        # Force transitional mode:
-        dev_trans, _ = self.run_device(qemu_devtype,
-                                      'disable-modern=off,disable-legacy=off')
-        self.assert_devids(dev_trans, PCI_LEGACY_DEVICE_IDS[virtio_devid])
-
-        # Force legacy mode:
-        dev_legacy, _ = self.run_device(qemu_devtype,
-                                       'disable-modern=on,disable-legacy=off')
-        self.assert_devids(dev_legacy, PCI_LEGACY_DEVICE_IDS[virtio_devid])
-
-        # No options: default to transitional on PC machine-type:
-        no_opts_pc, generic_ifaces = self.run_device(qemu_devtype)
-        self.assertEqual(dev_trans, no_opts_pc)
-
-        #TODO: check if plugging on a PCI Express bus will make the
-        #      device non-transitional
-        #no_opts_q35 = self.run_device(qemu_devtype, machine='q35')
-        #self.assertEqual(dev_modern, no_opts_q35)
-
-        # <prefix>-transitional device types should be 100% equivalent to
-        # <prefix>,disable-modern=off,disable-legacy=off
-        dev_trans, trans_ifaces = self.run_device('%s-transitional' % (qemu_devtype))
-        self.assertEqual(dev_trans, dev_trans)
-
-        # ensure the interface information is correct:
-        self.assertIn('conventional-pci-device', generic_ifaces)
-        self.assertIn('pci-express-device', generic_ifaces)
-
-        self.assertIn('conventional-pci-device', nt_ifaces)
-        self.assertIn('pci-express-device', nt_ifaces)
-
-        self.assertIn('conventional-pci-device', trans_ifaces)
-        self.assertNotIn('pci-express-device', trans_ifaces)
-
-
-    def test_conventional_devs(self):
-        self.check_all_variants('virtio-net-pci', VIRTIO_NET)
-        # virtio-blk requires 'driver' parameter
-        #self.check_all_variants('virtio-blk-pci', VIRTIO_BLOCK)
-        self.check_all_variants('virtio-serial-pci', VIRTIO_CONSOLE)
-        self.check_all_variants('virtio-rng-pci', VIRTIO_RNG)
-        self.check_all_variants('virtio-balloon-pci', VIRTIO_BALLOON)
-        self.check_all_variants('virtio-scsi-pci', VIRTIO_SCSI)
-        # virtio-9p requires 'fsdev' parameter
-        #self.check_all_variants('virtio-9p-pci', VIRTIO_9P)
-
-    def check_modern_only(self, qemu_devtype, virtio_devid):
-        """Check if a modern-only virtio device type behaves as expected"""
-        # Force modern mode:
-        dev_modern, _ = self.run_device(qemu_devtype,
-                                       'disable-modern=off,disable-legacy=on')
-        self.assert_devids(dev_modern, pci_modern_device_id(virtio_devid),
-                           non_transitional=True)
-
-        # No options: should be modern anyway
-        dev_no_opts, ifaces = self.run_device(qemu_devtype)
-        self.assertEqual(dev_modern, dev_no_opts)
-
-        self.assertIn('conventional-pci-device', ifaces)
-        self.assertIn('pci-express-device', ifaces)
-
-    def test_modern_only_devs(self):
-        self.check_modern_only('virtio-vga', VIRTIO_GPU)
-        self.check_modern_only('virtio-gpu-pci', VIRTIO_GPU)
-        self.check_modern_only('virtio-mouse-pci', VIRTIO_INPUT)
-        self.check_modern_only('virtio-tablet-pci', VIRTIO_INPUT)
-        self.check_modern_only('virtio-keyboard-pci', VIRTIO_INPUT)
index 052d2e87817ebf7455d68b2236a8d847dada8405..91201a2e26da15ac5b8c28bf05a543cc8e231f6f 100644 (file)
@@ -14,6 +14,7 @@ test_timeouts = {
 }
 
 tests_generic_system = [
+  'empty_cpu_model',
 ]
 
 tests_generic_linuxuser = [
@@ -23,6 +24,10 @@ tests_generic_bsduser = [
 ]
 
 tests_x86_64_system_quick = [
+  'cpu_queries',
+  'mem_addr_space',
+  'pc_cpu_hotplug_props',
+  'virtio_version',
 ]
 
 tests_x86_64_system_thorough = [
diff --git a/tests/functional/test_cpu_queries.py b/tests/functional/test_cpu_queries.py
new file mode 100755 (executable)
index 0000000..b1122a0
--- /dev/null
@@ -0,0 +1,37 @@
+#!/usr/bin/env python3
+#
+# Sanity check of query-cpu-* results
+#
+# Copyright (c) 2019 Red Hat, Inc.
+#
+# Author:
+#  Eduardo Habkost <ehabkost@redhat.com>
+#
+# This work is licensed under the terms of the GNU GPL, version 2 or
+# later.  See the COPYING file in the top-level directory.
+
+from qemu_test import QemuSystemTest
+
+class QueryCPUModelExpansion(QemuSystemTest):
+    """
+    Run query-cpu-model-expansion for each CPU model, and validate results
+    """
+
+    def test(self):
+        self.set_machine('none')
+        self.vm.add_args('-S')
+        self.vm.launch()
+
+        cpus = self.vm.cmd('query-cpu-definitions')
+        for c in cpus:
+            self.log.info("Checking CPU: %s", c)
+            self.assertNotIn('', c['unavailable-features'], c['name'])
+
+        for c in cpus:
+            model = {'name': c['name']}
+            e = self.vm.cmd('query-cpu-model-expansion', model=model,
+                            type='full')
+            self.assertEqual(e['model']['name'], c['name'])
+
+if __name__ == '__main__':
+    QemuSystemTest.main()
diff --git a/tests/functional/test_empty_cpu_model.py b/tests/functional/test_empty_cpu_model.py
new file mode 100755 (executable)
index 0000000..0081b06
--- /dev/null
@@ -0,0 +1,24 @@
+#!/usr/bin/env python3
+#
+# Check for crash when using empty -cpu option
+#
+# Copyright (c) 2019 Red Hat, Inc.
+#
+# Author:
+#  Eduardo Habkost <ehabkost@redhat.com>
+#
+# This work is licensed under the terms of the GNU GPL, version 2 or
+# later.  See the COPYING file in the top-level directory.
+from qemu_test import QemuSystemTest
+
+class EmptyCPUModel(QemuSystemTest):
+    def test(self):
+        self.vm.add_args('-S', '-display', 'none', '-machine', 'none', '-cpu', '')
+        self.vm.set_qmp_monitor(enabled=False)
+        self.vm.launch()
+        self.vm.wait()
+        self.assertEqual(self.vm.exitcode(), 1, "QEMU exit code should be 1")
+        self.assertRegex(self.vm.get_log(), r'-cpu option cannot be empty')
+
+if __name__ == '__main__':
+    QemuSystemTest.main()
diff --git a/tests/functional/test_mem_addr_space.py b/tests/functional/test_mem_addr_space.py
new file mode 100755 (executable)
index 0000000..bb0cf06
--- /dev/null
@@ -0,0 +1,314 @@
+#!/usr/bin/env python3
+#
+# Check for crash when using memory beyond the available guest processor
+# address space.
+#
+# Copyright (c) 2023 Red Hat, Inc.
+#
+# Author:
+#  Ani Sinha <anisinha@redhat.com>
+#
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+from qemu_test import QemuSystemTest
+import time
+
+class MemAddrCheck(QemuSystemTest):
+    # after launch, in order to generate the logs from QEMU we need to
+    # wait for some time. Launching and then immediately shutting down
+    # the VM generates empty logs. A delay of 1 second is added for
+    # this reason.
+    DELAY_Q35_BOOT_SEQUENCE = 1
+
+    # first, lets test some 32-bit processors.
+    # for all 32-bit cases, pci64_hole_size is 0.
+    def test_phybits_low_pse36(self):
+        """
+        With pse36 feature ON, a processor has 36 bits of addressing. So it can
+        access up to a maximum of 64GiB of memory. Memory hotplug region begins
+        at 4 GiB boundary when "above_4g_mem_size" is 0 (this would be true when
+        we have 0.5 GiB of VM memory, see pc_q35_init()). This means total
+        hotpluggable memory size is 60 GiB. Per slot, we reserve 1 GiB of memory
+        for dimm alignment for all machines. That leaves total hotpluggable
+        actual memory size of 59 GiB. If the VM is started with 0.5 GiB of
+        memory, maxmem should be set to a maximum value of 59.5 GiB to ensure
+        that the processor can address all memory directly.
+        Note that 64-bit pci hole size is 0 in this case. If maxmem is set to
+        59.6G, QEMU should fail to start with a message "phy-bits are too low".
+        If maxmem is set to 59.5G with all other QEMU parameters identical, QEMU
+        should start fine.
+        """
+        self.vm.add_args('-S', '-machine', 'q35', '-m',
+                         '512,slots=1,maxmem=59.6G',
+                         '-cpu', 'pentium,pse36=on', '-display', 'none',
+                         '-object', 'memory-backend-ram,id=mem1,size=1G',
+                         '-device', 'pc-dimm,id=vm0,memdev=mem1')
+        self.vm.set_qmp_monitor(enabled=False)
+        self.vm.launch()
+        self.vm.wait()
+        self.assertEqual(self.vm.exitcode(), 1, "QEMU exit code should be 1")
+        self.assertRegex(self.vm.get_log(), r'phys-bits too low')
+
+    def test_phybits_low_pae(self):
+        """
+        With pae feature ON, a processor has 36 bits of addressing. So it can
+        access up to a maximum of 64GiB of memory. Rest is the same as the case
+        with pse36 above.
+        """
+        self.vm.add_args('-S', '-machine', 'q35', '-m',
+                         '512,slots=1,maxmem=59.6G',
+                         '-cpu', 'pentium,pae=on', '-display', 'none',
+                         '-object', 'memory-backend-ram,id=mem1,size=1G',
+                         '-device', 'pc-dimm,id=vm0,memdev=mem1')
+        self.vm.set_qmp_monitor(enabled=False)
+        self.vm.launch()
+        self.vm.wait()
+        self.assertEqual(self.vm.exitcode(), 1, "QEMU exit code should be 1")
+        self.assertRegex(self.vm.get_log(), r'phys-bits too low')
+
+    def test_phybits_ok_pentium_pse36(self):
+        """
+        Setting maxmem to 59.5G and making sure that QEMU can start with the
+        same options as the failing case above with pse36 cpu feature.
+        """
+        self.vm.add_args('-machine', 'q35', '-m',
+                         '512,slots=1,maxmem=59.5G',
+                         '-cpu', 'pentium,pse36=on', '-display', 'none',
+                         '-object', 'memory-backend-ram,id=mem1,size=1G',
+                         '-device', 'pc-dimm,id=vm0,memdev=mem1')
+        self.vm.set_qmp_monitor(enabled=False)
+        self.vm.launch()
+        time.sleep(self.DELAY_Q35_BOOT_SEQUENCE)
+        self.vm.shutdown()
+        self.assertNotRegex(self.vm.get_log(), r'phys-bits too low')
+
+    def test_phybits_ok_pentium_pae(self):
+        """
+        Test is same as above but now with pae cpu feature turned on.
+        Setting maxmem to 59.5G and making sure that QEMU can start fine
+        with the same options as the case above.
+        """
+        self.vm.add_args('-machine', 'q35', '-m',
+                         '512,slots=1,maxmem=59.5G',
+                         '-cpu', 'pentium,pae=on', '-display', 'none',
+                         '-object', 'memory-backend-ram,id=mem1,size=1G',
+                         '-device', 'pc-dimm,id=vm0,memdev=mem1')
+        self.vm.set_qmp_monitor(enabled=False)
+        self.vm.launch()
+        time.sleep(self.DELAY_Q35_BOOT_SEQUENCE)
+        self.vm.shutdown()
+        self.assertNotRegex(self.vm.get_log(), r'phys-bits too low')
+
+    def test_phybits_ok_pentium2(self):
+        """
+        Pentium2 has 36 bits of addressing, so its same as pentium
+        with pse36 ON.
+        """
+        self.vm.add_args('-machine', 'q35', '-m',
+                         '512,slots=1,maxmem=59.5G',
+                         '-cpu', 'pentium2', '-display', 'none',
+                         '-object', 'memory-backend-ram,id=mem1,size=1G',
+                         '-device', 'pc-dimm,id=vm0,memdev=mem1')
+        self.vm.set_qmp_monitor(enabled=False)
+        self.vm.launch()
+        time.sleep(self.DELAY_Q35_BOOT_SEQUENCE)
+        self.vm.shutdown()
+        self.assertNotRegex(self.vm.get_log(), r'phys-bits too low')
+
+    def test_phybits_low_nonpse36(self):
+        """
+        Pentium processor has 32 bits of addressing without pse36 or pae
+        so it can access physical address up to 4 GiB. Setting maxmem to
+        4 GiB should make QEMU fail to start with "phys-bits too low"
+        message because the region for memory hotplug is always placed
+        above 4 GiB due to the PCI hole and simplicity.
+        """
+        self.vm.add_args('-S', '-machine', 'q35', '-m',
+                         '512,slots=1,maxmem=4G',
+                         '-cpu', 'pentium', '-display', 'none',
+                         '-object', 'memory-backend-ram,id=mem1,size=1G',
+                         '-device', 'pc-dimm,id=vm0,memdev=mem1')
+        self.vm.set_qmp_monitor(enabled=False)
+        self.vm.launch()
+        self.vm.wait()
+        self.assertEqual(self.vm.exitcode(), 1, "QEMU exit code should be 1")
+        self.assertRegex(self.vm.get_log(), r'phys-bits too low')
+
+    # now lets test some 64-bit CPU cases.
+    def test_phybits_low_tcg_q35_70_amd(self):
+        """
+        For q35 7.1 machines and above, there is a HT window that starts at
+        1024 GiB and ends at 1 TiB - 1. If the max GPA falls in this range,
+        "above_4G" memory is adjusted to start at 1 TiB boundary for AMD cpus
+        in the default case. Lets test without that case for machines 7.0.
+        For q35-7.0 machines, "above 4G" memory starts are 4G.
+        pci64_hole size is 32 GiB. Since TCG_PHYS_ADDR_BITS is defined to
+        be 40, TCG emulated CPUs have maximum of 1 TiB (1024 GiB) of
+        directly addressable memory.
+        Hence, maxmem value at most can be
+        1024 GiB - 4 GiB - 1 GiB per slot for alignment - 32 GiB + 0.5 GiB
+        which is equal to 987.5 GiB. Setting the value to 988 GiB should
+        make QEMU fail with the error message.
+        """
+        self.vm.add_args('-S', '-machine', 'pc-q35-7.0', '-m',
+                         '512,slots=1,maxmem=988G',
+                         '-display', 'none',
+                         '-object', 'memory-backend-ram,id=mem1,size=1G',
+                         '-device', 'pc-dimm,id=vm0,memdev=mem1')
+        self.vm.set_qmp_monitor(enabled=False)
+        self.vm.launch()
+        self.vm.wait()
+        self.assertEqual(self.vm.exitcode(), 1, "QEMU exit code should be 1")
+        self.assertRegex(self.vm.get_log(), r'phys-bits too low')
+
+    def test_phybits_low_tcg_q35_71_amd(self):
+        """
+        AMD_HT_START is defined to be at 1012 GiB. So for q35 machines
+        version > 7.0 and AMD cpus, instead of 1024 GiB limit for 40 bit
+        processor address space, it has to be 1012 GiB , that is 12 GiB
+        less than the case above in order to accommodate HT hole.
+        Make sure QEMU fails when maxmem size is 976 GiB (12 GiB less
+        than 988 GiB).
+        """
+        self.vm.add_args('-S', '-machine', 'pc-q35-7.1', '-m',
+                         '512,slots=1,maxmem=976G',
+                         '-display', 'none',
+                         '-object', 'memory-backend-ram,id=mem1,size=1G',
+                         '-device', 'pc-dimm,id=vm0,memdev=mem1')
+        self.vm.set_qmp_monitor(enabled=False)
+        self.vm.launch()
+        self.vm.wait()
+        self.assertEqual(self.vm.exitcode(), 1, "QEMU exit code should be 1")
+        self.assertRegex(self.vm.get_log(), r'phys-bits too low')
+
+    def test_phybits_ok_tcg_q35_70_amd(self):
+        """
+        Same as q35-7.0 AMD case except that here we check that QEMU can
+        successfully start when maxmem is < 988G.
+        """
+        self.vm.add_args('-S', '-machine', 'pc-q35-7.0', '-m',
+                         '512,slots=1,maxmem=987.5G',
+                         '-display', 'none',
+                         '-object', 'memory-backend-ram,id=mem1,size=1G',
+                         '-device', 'pc-dimm,id=vm0,memdev=mem1')
+        self.vm.set_qmp_monitor(enabled=False)
+        self.vm.launch()
+        time.sleep(self.DELAY_Q35_BOOT_SEQUENCE)
+        self.vm.shutdown()
+        self.assertNotRegex(self.vm.get_log(), r'phys-bits too low')
+
+    def test_phybits_ok_tcg_q35_71_amd(self):
+        """
+        Same as q35-7.1 AMD case except that here we check that QEMU can
+        successfully start when maxmem is < 976G.
+        """
+        self.vm.add_args('-S', '-machine', 'pc-q35-7.1', '-m',
+                         '512,slots=1,maxmem=975.5G',
+                         '-display', 'none',
+                         '-object', 'memory-backend-ram,id=mem1,size=1G',
+                         '-device', 'pc-dimm,id=vm0,memdev=mem1')
+        self.vm.set_qmp_monitor(enabled=False)
+        self.vm.launch()
+        time.sleep(self.DELAY_Q35_BOOT_SEQUENCE)
+        self.vm.shutdown()
+        self.assertNotRegex(self.vm.get_log(), r'phys-bits too low')
+
+    def test_phybits_ok_tcg_q35_71_intel(self):
+        """
+        Same parameters as test_phybits_low_tcg_q35_71_amd() but use
+        Intel cpu instead. QEMU should start fine in this case as
+        "above_4G" memory starts at 4G.
+        """
+        self.vm.add_args('-S', '-cpu', 'Skylake-Server',
+                         '-machine', 'pc-q35-7.1', '-m',
+                         '512,slots=1,maxmem=976G',
+                         '-display', 'none',
+                         '-object', 'memory-backend-ram,id=mem1,size=1G',
+                         '-device', 'pc-dimm,id=vm0,memdev=mem1')
+        self.vm.set_qmp_monitor(enabled=False)
+        self.vm.launch()
+        time.sleep(self.DELAY_Q35_BOOT_SEQUENCE)
+        self.vm.shutdown()
+        self.assertNotRegex(self.vm.get_log(), r'phys-bits too low')
+
+    def test_phybits_low_tcg_q35_71_amd_41bits(self):
+        """
+        AMD processor with 41 bits. Max cpu hw address = 2 TiB.
+        By setting maxram above 1012 GiB  - 32 GiB - 4 GiB = 976 GiB, we can
+        force "above_4G" memory to start at 1 TiB for q35-7.1 machines
+        (max GPA will be above AMD_HT_START which is defined as 1012 GiB).
+
+        With pci_64_hole size at 32 GiB, in this case, maxmem should be 991.5
+        GiB with 1 GiB per slot for alignment and 0.5 GiB as non-hotplug
+        memory for the VM (1024 - 32 - 1 + 0.5). With 992 GiB, QEMU should
+        fail to start.
+        """
+        self.vm.add_args('-S', '-cpu', 'EPYC-v4,phys-bits=41',
+                         '-machine', 'pc-q35-7.1', '-m',
+                         '512,slots=1,maxmem=992G',
+                         '-display', 'none',
+                         '-object', 'memory-backend-ram,id=mem1,size=1G',
+                         '-device', 'pc-dimm,id=vm0,memdev=mem1')
+        self.vm.set_qmp_monitor(enabled=False)
+        self.vm.launch()
+        self.vm.wait()
+        self.assertEqual(self.vm.exitcode(), 1, "QEMU exit code should be 1")
+        self.assertRegex(self.vm.get_log(), r'phys-bits too low')
+
+    def test_phybits_ok_tcg_q35_71_amd_41bits(self):
+        """
+        AMD processor with 41 bits. Max cpu hw address = 2 TiB.
+        Same as above but by setting maxram between 976 GiB and 992 Gib,
+        QEMU should start fine.
+        """
+        self.vm.add_args('-S', '-cpu', 'EPYC-v4,phys-bits=41',
+                         '-machine', 'pc-q35-7.1', '-m',
+                         '512,slots=1,maxmem=990G',
+                         '-display', 'none',
+                         '-object', 'memory-backend-ram,id=mem1,size=1G',
+                         '-device', 'pc-dimm,id=vm0,memdev=mem1')
+        self.vm.set_qmp_monitor(enabled=False)
+        self.vm.launch()
+        time.sleep(self.DELAY_Q35_BOOT_SEQUENCE)
+        self.vm.shutdown()
+        self.assertNotRegex(self.vm.get_log(), r'phys-bits too low')
+
+    def test_phybits_low_tcg_q35_intel_cxl(self):
+        """
+        cxl memory window starts after memory device range. Here, we use 1 GiB
+        of cxl window memory. 4G_mem end aligns at 4G. pci64_hole is 32 GiB and
+        starts after the cxl memory window.
+        So maxmem here should be at most 986 GiB considering all memory boundary
+        alignment constraints with 40 bits (1 TiB) of processor physical bits.
+        """
+        self.vm.add_args('-S', '-cpu', 'Skylake-Server,phys-bits=40',
+                         '-machine', 'q35,cxl=on', '-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')
+        self.vm.set_qmp_monitor(enabled=False)
+        self.vm.launch()
+        self.vm.wait()
+        self.assertEqual(self.vm.exitcode(), 1, "QEMU exit code should be 1")
+        self.assertRegex(self.vm.get_log(), r'phys-bits too low')
+
+    def test_phybits_ok_tcg_q35_intel_cxl(self):
+        """
+        Same as above but here we do not reserve any cxl memory window. Hence,
+        with the exact same parameters as above, QEMU should start fine even
+        with cxl enabled.
+        """
+        self.vm.add_args('-S', '-cpu', 'Skylake-Server,phys-bits=40',
+                         '-machine', 'q35,cxl=on', '-m',
+                         '512,slots=1,maxmem=987G',
+                         '-display', 'none',
+                         '-device', 'pxb-cxl,bus_nr=12,bus=pcie.0,id=cxl.1')
+        self.vm.set_qmp_monitor(enabled=False)
+        self.vm.launch()
+        time.sleep(self.DELAY_Q35_BOOT_SEQUENCE)
+        self.vm.shutdown()
+        self.assertNotRegex(self.vm.get_log(), r'phys-bits too low')
+
+if __name__ == '__main__':
+    QemuSystemTest.main()
diff --git a/tests/functional/test_pc_cpu_hotplug_props.py b/tests/functional/test_pc_cpu_hotplug_props.py
new file mode 100755 (executable)
index 0000000..9d5a37c
--- /dev/null
@@ -0,0 +1,36 @@
+#!/usr/bin/env python3
+#
+# Ensure CPU die-id can be omitted on -device
+#
+#  Copyright (c) 2019 Red Hat Inc
+#
+# Author:
+#  Eduardo Habkost <ehabkost@redhat.com>
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, see <http://www.gnu.org/licenses/>.
+#
+
+from qemu_test import QemuSystemTest
+
+class OmittedCPUProps(QemuSystemTest):
+
+    def test_no_die_id(self):
+        self.vm.add_args('-nodefaults', '-S')
+        self.vm.add_args('-smp', '1,sockets=2,cores=2,threads=2,maxcpus=8')
+        self.vm.add_args('-device', 'qemu64-x86_64-cpu,socket-id=1,core-id=0,thread-id=0')
+        self.vm.launch()
+        self.assertEqual(len(self.vm.cmd('query-cpus-fast')), 2)
+
+if __name__ == '__main__':
+    QemuSystemTest.main()
diff --git a/tests/functional/test_virtio_version.py b/tests/functional/test_virtio_version.py
new file mode 100755 (executable)
index 0000000..eb23060
--- /dev/null
@@ -0,0 +1,177 @@
+#!/usr/bin/env python3
+"""
+Check compatibility of virtio device types
+"""
+# Copyright (c) 2018 Red Hat, Inc.
+#
+# Author:
+#  Eduardo Habkost <ehabkost@redhat.com>
+#
+# 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 sys
+import os
+
+from qemu.machine import QEMUMachine
+from qemu_test import QemuSystemTest
+
+# Virtio Device IDs:
+VIRTIO_NET = 1
+VIRTIO_BLOCK = 2
+VIRTIO_CONSOLE = 3
+VIRTIO_RNG = 4
+VIRTIO_BALLOON = 5
+VIRTIO_RPMSG = 7
+VIRTIO_SCSI = 8
+VIRTIO_9P = 9
+VIRTIO_RPROC_SERIAL = 11
+VIRTIO_CAIF = 12
+VIRTIO_GPU = 16
+VIRTIO_INPUT = 18
+VIRTIO_VSOCK = 19
+VIRTIO_CRYPTO = 20
+
+PCI_VENDOR_ID_REDHAT_QUMRANET = 0x1af4
+
+# Device IDs for legacy/transitional devices:
+PCI_LEGACY_DEVICE_IDS = {
+    VIRTIO_NET:     0x1000,
+    VIRTIO_BLOCK:   0x1001,
+    VIRTIO_BALLOON: 0x1002,
+    VIRTIO_CONSOLE: 0x1003,
+    VIRTIO_SCSI:    0x1004,
+    VIRTIO_RNG:     0x1005,
+    VIRTIO_9P:      0x1009,
+    VIRTIO_VSOCK:   0x1012,
+}
+
+def pci_modern_device_id(virtio_devid):
+    return virtio_devid + 0x1040
+
+def devtype_implements(vm, devtype, implements):
+    return devtype in [d['name'] for d in
+                       vm.cmd('qom-list-types', implements=implements)]
+
+def get_pci_interfaces(vm, devtype):
+    interfaces = ('pci-express-device', 'conventional-pci-device')
+    return [i for i in interfaces if devtype_implements(vm, devtype, i)]
+
+class VirtioVersionCheck(QemuSystemTest):
+    """
+    Check if virtio-version-specific device types result in the
+    same device tree created by `disable-modern` and
+    `disable-legacy`.
+    """
+
+    # just in case there are failures, show larger diff:
+    maxDiff = 4096
+
+    def run_device(self, devtype, opts=None, machine='pc'):
+        """
+        Run QEMU with `-device DEVTYPE`, return device info from `query-pci`
+        """
+        with QEMUMachine(self.qemu_bin) as vm:
+            vm.set_machine(machine)
+            if opts:
+                devtype += ',' + opts
+            vm.add_args('-device', '%s,id=devfortest' % (devtype))
+            vm.add_args('-S')
+            vm.launch()
+
+            pcibuses = vm.cmd('query-pci')
+            alldevs = [dev for bus in pcibuses for dev in bus['devices']]
+            devfortest = [dev for dev in alldevs
+                          if dev['qdev_id'] == 'devfortest']
+            return devfortest[0], get_pci_interfaces(vm, devtype)
+
+
+    def assert_devids(self, dev, devid, non_transitional=False):
+        self.assertEqual(dev['id']['vendor'], PCI_VENDOR_ID_REDHAT_QUMRANET)
+        self.assertEqual(dev['id']['device'], devid)
+        if non_transitional:
+            self.assertTrue(0x1040 <= dev['id']['device'] <= 0x107f)
+            self.assertGreaterEqual(dev['id']['subsystem'], 0x40)
+
+    def check_all_variants(self, qemu_devtype, virtio_devid):
+        """Check if a virtio device type and its variants behave as expected"""
+        # Force modern mode:
+        dev_modern, _ = self.run_device(qemu_devtype,
+                                       'disable-modern=off,disable-legacy=on')
+        self.assert_devids(dev_modern, pci_modern_device_id(virtio_devid),
+                           non_transitional=True)
+
+        # <prefix>-non-transitional device types should be 100% equivalent to
+        # <prefix>,disable-modern=off,disable-legacy=on
+        dev_1_0, nt_ifaces = self.run_device('%s-non-transitional' % (qemu_devtype))
+        self.assertEqual(dev_modern, dev_1_0)
+
+        # Force transitional mode:
+        dev_trans, _ = self.run_device(qemu_devtype,
+                                      'disable-modern=off,disable-legacy=off')
+        self.assert_devids(dev_trans, PCI_LEGACY_DEVICE_IDS[virtio_devid])
+
+        # Force legacy mode:
+        dev_legacy, _ = self.run_device(qemu_devtype,
+                                       'disable-modern=on,disable-legacy=off')
+        self.assert_devids(dev_legacy, PCI_LEGACY_DEVICE_IDS[virtio_devid])
+
+        # No options: default to transitional on PC machine-type:
+        no_opts_pc, generic_ifaces = self.run_device(qemu_devtype)
+        self.assertEqual(dev_trans, no_opts_pc)
+
+        #TODO: check if plugging on a PCI Express bus will make the
+        #      device non-transitional
+        #no_opts_q35 = self.run_device(qemu_devtype, machine='q35')
+        #self.assertEqual(dev_modern, no_opts_q35)
+
+        # <prefix>-transitional device types should be 100% equivalent to
+        # <prefix>,disable-modern=off,disable-legacy=off
+        dev_trans, trans_ifaces = self.run_device('%s-transitional' % (qemu_devtype))
+        self.assertEqual(dev_trans, dev_trans)
+
+        # ensure the interface information is correct:
+        self.assertIn('conventional-pci-device', generic_ifaces)
+        self.assertIn('pci-express-device', generic_ifaces)
+
+        self.assertIn('conventional-pci-device', nt_ifaces)
+        self.assertIn('pci-express-device', nt_ifaces)
+
+        self.assertIn('conventional-pci-device', trans_ifaces)
+        self.assertNotIn('pci-express-device', trans_ifaces)
+
+
+    def test_conventional_devs(self):
+        self.check_all_variants('virtio-net-pci', VIRTIO_NET)
+        # virtio-blk requires 'driver' parameter
+        #self.check_all_variants('virtio-blk-pci', VIRTIO_BLOCK)
+        self.check_all_variants('virtio-serial-pci', VIRTIO_CONSOLE)
+        self.check_all_variants('virtio-rng-pci', VIRTIO_RNG)
+        self.check_all_variants('virtio-balloon-pci', VIRTIO_BALLOON)
+        self.check_all_variants('virtio-scsi-pci', VIRTIO_SCSI)
+        # virtio-9p requires 'fsdev' parameter
+        #self.check_all_variants('virtio-9p-pci', VIRTIO_9P)
+
+    def check_modern_only(self, qemu_devtype, virtio_devid):
+        """Check if a modern-only virtio device type behaves as expected"""
+        # Force modern mode:
+        dev_modern, _ = self.run_device(qemu_devtype,
+                                       'disable-modern=off,disable-legacy=on')
+        self.assert_devids(dev_modern, pci_modern_device_id(virtio_devid),
+                           non_transitional=True)
+
+        # No options: should be modern anyway
+        dev_no_opts, ifaces = self.run_device(qemu_devtype)
+        self.assertEqual(dev_modern, dev_no_opts)
+
+        self.assertIn('conventional-pci-device', ifaces)
+        self.assertIn('pci-express-device', ifaces)
+
+    def test_modern_only_devs(self):
+        self.check_modern_only('virtio-vga', VIRTIO_GPU)
+        self.check_modern_only('virtio-gpu-pci', VIRTIO_GPU)
+        self.check_modern_only('virtio-mouse-pci', VIRTIO_INPUT)
+        self.check_modern_only('virtio-tablet-pci', VIRTIO_INPUT)
+        self.check_modern_only('virtio-keyboard-pci', VIRTIO_INPUT)
+
+if __name__ == '__main__':
+    QemuSystemTest.main()