From a3d3de8e1d4aff1343066e351020de9a6294c102 Mon Sep 17 00:00:00 2001
From: Paolo Bonzini <pbonzini@redhat.com>
Date: Wed, 9 Aug 2023 10:13:43 +0200
Subject: [PATCH 01/14] configure: fix and complete detection of tricore tools

The tricore tools are not detected when they are installed in
the host system, only if they are taken from an external
container.  For this reason the build-tricore-softmmu job
was not running the TCG tests.

In addition the container provides all tools, not just as/ld/gcc,
so there is no need to special case tricore.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 configure | 5 +----
 1 file changed, 1 insertion(+), 4 deletions(-)

diff --git a/configure b/configure
index 133f4e3235..f2bd8858d6 100755
--- a/configure
+++ b/configure
@@ -1271,6 +1271,7 @@ fi
 : ${cross_prefix_sh4="sh4-linux-gnu-"}
 : ${cross_prefix_sparc64="sparc64-linux-gnu-"}
 : ${cross_prefix_sparc="$cross_prefix_sparc64"}
+: ${cross_prefix_tricore="tricore-"}
 : ${cross_prefix_x86_64="x86_64-linux-gnu-"}
 
 : ${cross_cc_aarch64_be="$cross_cc_aarch64"}
@@ -1458,10 +1459,6 @@ probe_target_compiler() {
       tricore)
         container_image=debian-tricore-cross
         container_cross_prefix=tricore-
-        container_cross_as=tricore-as
-        container_cross_ld=tricore-ld
-        container_cross_cc=tricore-gcc
-        break
         ;;
       x86_64)
         container_image=debian-amd64-cross

From 87f77f58d897314f0726374ce8f9cdf44ccd9c5b Mon Sep 17 00:00:00 2001
From: Paolo Bonzini <pbonzini@redhat.com>
Date: Tue, 8 Aug 2023 16:02:57 +0200
Subject: [PATCH 02/14] dockerfiles: bump tricore cross compiler container to
 Debian 11

With the release of version 12 on June 10, 2023, Debian 10 is
not supported anymore.  Modify the cross compiler container to
build on a newer version.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 tests/docker/dockerfiles/debian-tricore-cross.docker | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/tests/docker/dockerfiles/debian-tricore-cross.docker b/tests/docker/dockerfiles/debian-tricore-cross.docker
index 269bfa8d42..5bd1963fb5 100644
--- a/tests/docker/dockerfiles/debian-tricore-cross.docker
+++ b/tests/docker/dockerfiles/debian-tricore-cross.docker
@@ -9,7 +9,7 @@
 #
 # SPDX-License-Identifier: GPL-2.0-or-later
 #
-FROM docker.io/library/debian:buster-slim
+FROM docker.io/library/debian:11-slim
 
 MAINTAINER Philippe Mathieu-Daudé <f4bug@amsat.org>
 

From 67b9a83daf384f3dc24e83f22da40e34da49021d Mon Sep 17 00:00:00 2001
From: Paolo Bonzini <pbonzini@redhat.com>
Date: Tue, 8 Aug 2023 13:25:09 +0200
Subject: [PATCH 03/14] python: mkvenv: tweak the matching of --diagnose to
 depspecs

Move the matching between the "absent" array and dep_specs[0] inside
the loop, preparing for the possibility of having multiple canaries
among the installed packages.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 python/scripts/mkvenv.py | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/python/scripts/mkvenv.py b/python/scripts/mkvenv.py
index a47f1eaf5d..399659b22f 100644
--- a/python/scripts/mkvenv.py
+++ b/python/scripts/mkvenv.py
@@ -806,6 +806,7 @@ def _do_ensure(
     """
     absent = []
     present = []
+    canary = None
     for spec in dep_specs:
         matcher = distlib.version.LegacyMatcher(spec)
         ver = _get_version(matcher.name)
@@ -817,6 +818,8 @@ def _do_ensure(
             or not matcher.match(distlib.version.LegacyVersion(ver))
         ):
             absent.append(spec)
+            if spec == dep_specs[0]:
+                canary = prog
         else:
             logger.info("found %s %s", matcher.name, ver)
             present.append(matcher.name)
@@ -839,7 +842,7 @@ def _do_ensure(
             absent[0],
             online,
             wheels_dir,
-            prog if absent[0] == dep_specs[0] else None,
+            canary,
         )
 
     return None

From 0f1ec0705b92b79e5e5f69bed236639dae67d312 Mon Sep 17 00:00:00 2001
From: Paolo Bonzini <pbonzini@redhat.com>
Date: Tue, 8 Aug 2023 09:47:25 +0200
Subject: [PATCH 04/14] python: mkvenv: introduce TOML-like representation of
 dependencies

We would like to place all Python dependencies in the same file, so that
we can add more information without having long and complex command lines.
The plan is to have a TOML file with one entry per package, for example

  [avocado]
  avocado-framework = {
    accepted = "(>=88.1, <93.0)",
    installed = "88.1",
    canary = "avocado"
  }

Each TOML section will thus be a dictionary of dictionaries.  Modify
mkvenv.py's workhorse function, _do_ensure, to already operate on such
a data structure.  The "ensure" subcommand is modified to separate the
depspec into a name and a version part, and use the result (plus the
--diagnose argument) to build a dictionary for each command line argument.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 python/scripts/mkvenv.py | 77 +++++++++++++++++++++++++++++++---------
 1 file changed, 61 insertions(+), 16 deletions(-)

diff --git a/python/scripts/mkvenv.py b/python/scripts/mkvenv.py
index 399659b22f..96f506d7e2 100644
--- a/python/scripts/mkvenv.py
+++ b/python/scripts/mkvenv.py
@@ -46,6 +46,9 @@ options:
 
 """
 
+# The duplication between importlib and pkg_resources does not help
+# pylint: disable=too-many-lines
+
 # Copyright (C) 2022-2023 Red Hat, Inc.
 #
 # Authors:
@@ -69,6 +72,7 @@ import sysconfig
 from types import SimpleNamespace
 from typing import (
     Any,
+    Dict,
     Iterator,
     Optional,
     Sequence,
@@ -786,43 +790,67 @@ def pip_install(
     )
 
 
+def _make_version_constraint(info: Dict[str, str], install: bool) -> str:
+    """
+    Construct the version constraint part of a PEP 508 dependency
+    specification (for example '>=0.61.5') from the accepted and
+    installed keys of the provided dictionary.
+
+    :param info: A dictionary corresponding to a TOML key-value list.
+    :param install: True generates install constraints, False generates
+        presence constraints
+    """
+    if install and "installed" in info:
+        return "==" + info["installed"]
+
+    dep_spec = info.get("accepted", "")
+    dep_spec = dep_spec.strip()
+    # Double check that they didn't just use a version number
+    if dep_spec and dep_spec[0] not in "!~><=(":
+        raise Ouch(
+            "invalid dependency specifier " + dep_spec + " in dependency file"
+        )
+
+    return dep_spec
+
+
 def _do_ensure(
-    dep_specs: Sequence[str],
+    group: Dict[str, Dict[str, str]],
     online: bool = False,
     wheels_dir: Optional[Union[str, Path]] = None,
-    prog: Optional[str] = None,
 ) -> Optional[Tuple[str, bool]]:
     """
-    Use pip to ensure we have the package specified by @dep_specs.
+    Use pip to ensure we have the packages specified in @group.
 
-    If the package is already installed, do nothing. If online and
+    If the packages are already installed, do nothing. If online and
     wheels_dir are both provided, prefer packages found in wheels_dir
     first before connecting to PyPI.
 
-    :param dep_specs:
-        PEP 508 dependency specifications. e.g. ['meson>=0.61.5'].
+    :param group: A dictionary of dictionaries, corresponding to a
+        section in a pythondeps.toml file.
     :param online: If True, fall back to PyPI.
     :param wheels_dir: If specified, search this path for packages.
     """
     absent = []
     present = []
     canary = None
-    for spec in dep_specs:
-        matcher = distlib.version.LegacyMatcher(spec)
-        ver = _get_version(matcher.name)
+    for name, info in group.items():
+        constraint = _make_version_constraint(info, False)
+        matcher = distlib.version.LegacyMatcher(name + constraint)
+        ver = _get_version(name)
         if (
             ver is None
             # Always pass installed package to pip, so that they can be
             # updated if the requested version changes
-            or not _is_system_package(matcher.name)
+            or not _is_system_package(name)
             or not matcher.match(distlib.version.LegacyVersion(ver))
         ):
-            absent.append(spec)
-            if spec == dep_specs[0]:
-                canary = prog
+            absent.append(name + _make_version_constraint(info, True))
+            if len(absent) == 1:
+                canary = info.get("canary", None)
         else:
-            logger.info("found %s %s", matcher.name, ver)
-            present.append(matcher.name)
+            logger.info("found %s %s", name, ver)
+            present.append(name)
 
     if present:
         generate_console_scripts(present)
@@ -875,7 +903,24 @@ def ensure(
     if not HAVE_DISTLIB:
         raise Ouch("a usable distlib could not be found, please install it")
 
-    result = _do_ensure(dep_specs, online, wheels_dir, prog)
+    # Convert the depspecs to a dictionary, as if they came
+    # from a section in a pythondeps.toml file
+    group: Dict[str, Dict[str, str]] = {}
+    for spec in dep_specs:
+        name = distlib.version.LegacyMatcher(spec).name
+        group[name] = {}
+
+        spec = spec.strip()
+        pos = len(name)
+        ver = spec[pos:].strip()
+        if ver:
+            group[name]["accepted"] = ver
+
+        if prog:
+            group[name]["canary"] = prog
+            prog = None
+
+    result = _do_ensure(group, online, wheels_dir)
     if result:
         # Well, that's not good.
         if result[1]:

From 71ed611cd47d961e1897721d7d002ffb498221d4 Mon Sep 17 00:00:00 2001
From: Paolo Bonzini <pbonzini@redhat.com>
Date: Tue, 8 Aug 2023 10:03:42 +0200
Subject: [PATCH 05/14] python: mkvenv: add ensuregroup command

Introduce a new subcommand that retrieves the packages to be installed
from a TOML file. This allows being more flexible in using the system
version of a package, while at the same time using a known-good version
when installing the package.  This is important for packages that
sometimes have backwards-incompatible changes or that depend on
specific versions of their dependencies.

Compared to JSON, TOML is more human readable and easier to edit.  A
parser is available in 3.11 but also available as a small (12k) package
for older versions, tomli.  While tomli is bundled with pip, this is only
true of recent versions of pip.  Of all the supported OSes pretty much
only FreeBSD has a recent enough version of pip while staying on Python
<3.11.  So we cannot use the same trick that is in place for distlib.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 python/scripts/mkvenv.py | 126 ++++++++++++++++++++++++++++++++++++++-
 python/setup.cfg         |   6 ++
 pythondeps.toml          |  17 ++++++
 3 files changed, 148 insertions(+), 1 deletion(-)
 create mode 100644 pythondeps.toml

diff --git a/python/scripts/mkvenv.py b/python/scripts/mkvenv.py
index 96f506d7e2..02bcd9a8c9 100644
--- a/python/scripts/mkvenv.py
+++ b/python/scripts/mkvenv.py
@@ -14,6 +14,8 @@ Commands:
     post_init
               post-venv initialization
     ensure    Ensure that the specified package is installed.
+    ensuregroup
+              Ensure that the specified package group is installed.
 
 --------------------------------------------------
 
@@ -44,6 +46,19 @@ options:
   --online    Install packages from PyPI, if necessary.
   --dir DIR   Path to vendored packages where we may install from.
 
+--------------------------------------------------
+
+usage: mkvenv ensuregroup [-h] [--online] [--dir DIR] file group...
+
+positional arguments:
+  file        pointer to a TOML file
+  group       section name in the TOML file
+
+options:
+  -h, --help  show this help message and exit
+  --online    Install packages from PyPI, if necessary.
+  --dir DIR   Path to vendored packages where we may install from.
+
 """
 
 # The duplication between importlib and pkg_resources does not help
@@ -99,6 +114,18 @@ except ImportError:
     except ImportError:
         HAVE_DISTLIB = False
 
+# Try to load tomllib, with a fallback to tomli.
+# HAVE_TOMLLIB is checked below, just-in-time, so that mkvenv does not fail
+# outside the venv or before a potential call to ensurepip in checkpip().
+HAVE_TOMLLIB = True
+try:
+    import tomllib
+except ImportError:
+    try:
+        import tomli as tomllib
+    except ImportError:
+        HAVE_TOMLLIB = False
+
 # Do not add any mandatory dependencies from outside the stdlib:
 # This script *must* be usable standalone!
 
@@ -837,6 +864,7 @@ def _do_ensure(
     for name, info in group.items():
         constraint = _make_version_constraint(info, False)
         matcher = distlib.version.LegacyMatcher(name + constraint)
+        print(f"mkvenv: checking for {matcher}", file=sys.stderr)
         ver = _get_version(name)
         if (
             ver is None
@@ -898,7 +926,6 @@ def ensure(
         be presented to the user. e.g., 'sphinx-build' can be used as a
         bellwether for the presence of 'sphinx'.
     """
-    print(f"mkvenv: checking for {', '.join(dep_specs)}", file=sys.stderr)
 
     if not HAVE_DISTLIB:
         raise Ouch("a usable distlib could not be found, please install it")
@@ -928,6 +955,64 @@ def ensure(
         raise SystemExit(f"\n{result[0]}\n\n")
 
 
+def _parse_groups(file: str) -> Dict[str, Dict[str, Any]]:
+    if not HAVE_TOMLLIB:
+        if sys.version_info < (3, 11):
+            raise Ouch("found no usable tomli, please install it")
+
+        raise Ouch(
+            "Python >=3.11 does not have tomllib... what have you done!?"
+        )
+
+    try:
+        # Use loads() to support both tomli v1.2.x (Ubuntu 22.04,
+        # Debian bullseye-backports) and v2.0.x
+        with open(file, "r", encoding="ascii") as depfile:
+            contents = depfile.read()
+            return tomllib.loads(contents)  # type: ignore
+    except tomllib.TOMLDecodeError as exc:
+        raise Ouch(f"parsing {file} failed: {exc}") from exc
+
+
+def ensure_group(
+    file: str,
+    groups: Sequence[str],
+    online: bool = False,
+    wheels_dir: Optional[Union[str, Path]] = None,
+) -> None:
+    """
+    Use pip to ensure we have the package specified by @dep_specs.
+
+    If the package is already installed, do nothing. If online and
+    wheels_dir are both provided, prefer packages found in wheels_dir
+    first before connecting to PyPI.
+
+    :param dep_specs:
+        PEP 508 dependency specifications. e.g. ['meson>=0.61.5'].
+    :param online: If True, fall back to PyPI.
+    :param wheels_dir: If specified, search this path for packages.
+    """
+
+    if not HAVE_DISTLIB:
+        raise Ouch("found no usable distlib, please install it")
+
+    parsed_deps = _parse_groups(file)
+
+    to_install: Dict[str, Dict[str, str]] = {}
+    for group in groups:
+        try:
+            to_install.update(parsed_deps[group])
+        except KeyError as exc:
+            raise Ouch(f"group {group} not defined") from exc
+
+    result = _do_ensure(to_install, online, wheels_dir)
+    if result:
+        # Well, that's not good.
+        if result[1]:
+            raise Ouch(result[0])
+        raise SystemExit(f"\n{result[0]}\n\n")
+
+
 def post_venv_setup() -> None:
     """
     This is intended to be run *inside the venv* after it is created.
@@ -955,6 +1040,37 @@ def _add_post_init_subcommand(subparsers: Any) -> None:
     subparsers.add_parser("post_init", help="post-venv initialization")
 
 
+def _add_ensuregroup_subcommand(subparsers: Any) -> None:
+    subparser = subparsers.add_parser(
+        "ensuregroup",
+        help="Ensure that the specified package group is installed.",
+    )
+    subparser.add_argument(
+        "--online",
+        action="store_true",
+        help="Install packages from PyPI, if necessary.",
+    )
+    subparser.add_argument(
+        "--dir",
+        type=str,
+        action="store",
+        help="Path to vendored packages where we may install from.",
+    )
+    subparser.add_argument(
+        "file",
+        type=str,
+        action="store",
+        help=("Path to a TOML file describing package groups"),
+    )
+    subparser.add_argument(
+        "group",
+        type=str,
+        action="store",
+        help="One or more package group names",
+        nargs="+",
+    )
+
+
 def _add_ensure_subcommand(subparsers: Any) -> None:
     subparser = subparsers.add_parser(
         "ensure", help="Ensure that the specified package is installed."
@@ -1012,6 +1128,7 @@ def main() -> int:
     _add_create_subcommand(subparsers)
     _add_post_init_subcommand(subparsers)
     _add_ensure_subcommand(subparsers)
+    _add_ensuregroup_subcommand(subparsers)
 
     args = parser.parse_args()
     try:
@@ -1030,6 +1147,13 @@ def main() -> int:
                 wheels_dir=args.dir,
                 prog=args.diagnose,
             )
+        if args.command == "ensuregroup":
+            ensure_group(
+                file=args.file,
+                groups=args.group,
+                online=args.online,
+                wheels_dir=args.dir,
+            )
         logger.debug("mkvenv.py %s: exiting", args.command)
     except Ouch as exc:
         print("\n*** Ouch! ***\n", file=sys.stderr)
diff --git a/python/setup.cfg b/python/setup.cfg
index 5d7e95f5d2..e74b58a8c2 100644
--- a/python/setup.cfg
+++ b/python/setup.cfg
@@ -94,6 +94,12 @@ allow_subclassing_any = True
 [mypy-fuse]
 ignore_missing_imports = True
 
+[mypy-tomli]
+ignore_missing_imports = True
+
+[mypy-tomllib]
+ignore_missing_imports = True
+
 [mypy-urwid]
 ignore_missing_imports = True
 
diff --git a/pythondeps.toml b/pythondeps.toml
new file mode 100644
index 0000000000..362f63ff2c
--- /dev/null
+++ b/pythondeps.toml
@@ -0,0 +1,17 @@
+# This file describes Python package requirements to be
+# installed in the pyvenv Python virtual environment.
+#
+# Packages are placed in groups, which are installed using
+# the ensuregroup subcommand of python/scripts/mkvenv.py.
+# Each group forms a TOML section and each entry in the
+# section is a TOML key-value list describing a package.
+# All fields are optional; valid fields are:
+#
+# - accepted: accepted versions when using a system package
+# - installed: fixed version to install in the virtual environment
+#              if a system package is not found; if not specified,
+#              the minimum and maximum
+# - canary: if specified, use this program name to present more
+#           precise error diagnostics to the user.  For example,
+#           'sphinx-build' can be used as a bellwether for the
+#           presence of 'sphinx' in the system.

From dcb8541b0b726e18af7bb32acc6eea383d3b75af Mon Sep 17 00:00:00 2001
From: Paolo Bonzini <pbonzini@redhat.com>
Date: Tue, 8 Aug 2023 15:31:22 +0200
Subject: [PATCH 06/14] lcitool: bump libvirt-ci submodule and regenerate

This brings in a newer version of the pipewire mapping, so rename it.

Python 3.9 and 3.10 do not seem to work in OpenSUSE LEAP 15.5 (weird,
because 3.9 persisted from 15.3 to 15.4) so bump the Python runtime
version to 3.11.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 .../dockerfiles/debian-amd64-cross.docker     |  2 +-
 .../dockerfiles/debian-arm64-cross.docker     |  2 +-
 .../dockerfiles/debian-armel-cross.docker     |  2 +-
 .../dockerfiles/debian-armhf-cross.docker     |  2 +-
 .../dockerfiles/debian-mips64el-cross.docker  |  2 +-
 .../dockerfiles/debian-mipsel-cross.docker    |  2 +-
 .../dockerfiles/debian-ppc64el-cross.docker   |  2 +-
 .../dockerfiles/debian-riscv64-cross.docker   |  2 +-
 .../dockerfiles/debian-s390x-cross.docker     |  2 +-
 .../dockerfiles/fedora-win32-cross.docker     |  2 +-
 .../dockerfiles/fedora-win64-cross.docker     |  2 +-
 tests/docker/dockerfiles/opensuse-leap.docker | 22 +++++++++----------
 tests/lcitool/libvirt-ci                      |  2 +-
 tests/lcitool/mappings.yml                    | 12 +++++-----
 tests/lcitool/projects/qemu.yml               |  2 +-
 tests/lcitool/targets/opensuse-leap-15.yml    |  4 ++--
 16 files changed, 32 insertions(+), 32 deletions(-)

diff --git a/tests/docker/dockerfiles/debian-amd64-cross.docker b/tests/docker/dockerfiles/debian-amd64-cross.docker
index b7bdc01243..b9871f9c8c 100644
--- a/tests/docker/dockerfiles/debian-amd64-cross.docker
+++ b/tests/docker/dockerfiles/debian-amd64-cross.docker
@@ -1,6 +1,6 @@
 # THIS FILE WAS AUTO-GENERATED
 #
-#  $ lcitool dockerfile --layers all --cross x86_64 debian-11 qemu
+#  $ lcitool dockerfile --layers all --cross-arch x86_64 debian-11 qemu
 #
 # https://gitlab.com/libvirt/libvirt-ci
 
diff --git a/tests/docker/dockerfiles/debian-arm64-cross.docker b/tests/docker/dockerfiles/debian-arm64-cross.docker
index 68165c2f23..3504c771a7 100644
--- a/tests/docker/dockerfiles/debian-arm64-cross.docker
+++ b/tests/docker/dockerfiles/debian-arm64-cross.docker
@@ -1,6 +1,6 @@
 # THIS FILE WAS AUTO-GENERATED
 #
-#  $ lcitool dockerfile --layers all --cross aarch64 debian-11 qemu
+#  $ lcitool dockerfile --layers all --cross-arch aarch64 debian-11 qemu
 #
 # https://gitlab.com/libvirt/libvirt-ci
 
diff --git a/tests/docker/dockerfiles/debian-armel-cross.docker b/tests/docker/dockerfiles/debian-armel-cross.docker
index 2fb65308c7..6d11c9510f 100644
--- a/tests/docker/dockerfiles/debian-armel-cross.docker
+++ b/tests/docker/dockerfiles/debian-armel-cross.docker
@@ -1,6 +1,6 @@
 # THIS FILE WAS AUTO-GENERATED
 #
-#  $ lcitool dockerfile --layers all --cross armv6l debian-11 qemu
+#  $ lcitool dockerfile --layers all --cross-arch armv6l debian-11 qemu
 #
 # https://gitlab.com/libvirt/libvirt-ci
 
diff --git a/tests/docker/dockerfiles/debian-armhf-cross.docker b/tests/docker/dockerfiles/debian-armhf-cross.docker
index df77ccb57b..37ae575cf7 100644
--- a/tests/docker/dockerfiles/debian-armhf-cross.docker
+++ b/tests/docker/dockerfiles/debian-armhf-cross.docker
@@ -1,6 +1,6 @@
 # THIS FILE WAS AUTO-GENERATED
 #
-#  $ lcitool dockerfile --layers all --cross armv7l debian-11 qemu
+#  $ lcitool dockerfile --layers all --cross-arch armv7l debian-11 qemu
 #
 # https://gitlab.com/libvirt/libvirt-ci
 
diff --git a/tests/docker/dockerfiles/debian-mips64el-cross.docker b/tests/docker/dockerfiles/debian-mips64el-cross.docker
index 63a3d7aa3b..26ed730165 100644
--- a/tests/docker/dockerfiles/debian-mips64el-cross.docker
+++ b/tests/docker/dockerfiles/debian-mips64el-cross.docker
@@ -1,6 +1,6 @@
 # THIS FILE WAS AUTO-GENERATED
 #
-#  $ lcitool dockerfile --layers all --cross mips64el debian-11 qemu
+#  $ lcitool dockerfile --layers all --cross-arch mips64el debian-11 qemu
 #
 # https://gitlab.com/libvirt/libvirt-ci
 
diff --git a/tests/docker/dockerfiles/debian-mipsel-cross.docker b/tests/docker/dockerfiles/debian-mipsel-cross.docker
index ac87bbb095..ade2f37ed1 100644
--- a/tests/docker/dockerfiles/debian-mipsel-cross.docker
+++ b/tests/docker/dockerfiles/debian-mipsel-cross.docker
@@ -1,6 +1,6 @@
 # THIS FILE WAS AUTO-GENERATED
 #
-#  $ lcitool dockerfile --layers all --cross mipsel debian-11 qemu
+#  $ lcitool dockerfile --layers all --cross-arch mipsel debian-11 qemu
 #
 # https://gitlab.com/libvirt/libvirt-ci
 
diff --git a/tests/docker/dockerfiles/debian-ppc64el-cross.docker b/tests/docker/dockerfiles/debian-ppc64el-cross.docker
index def11f1693..08dcffa0a8 100644
--- a/tests/docker/dockerfiles/debian-ppc64el-cross.docker
+++ b/tests/docker/dockerfiles/debian-ppc64el-cross.docker
@@ -1,6 +1,6 @@
 # THIS FILE WAS AUTO-GENERATED
 #
-#  $ lcitool dockerfile --layers all --cross ppc64le debian-11 qemu
+#  $ lcitool dockerfile --layers all --cross-arch ppc64le debian-11 qemu
 #
 # https://gitlab.com/libvirt/libvirt-ci
 
diff --git a/tests/docker/dockerfiles/debian-riscv64-cross.docker b/tests/docker/dockerfiles/debian-riscv64-cross.docker
index a2d879ee1f..a26637ec4f 100644
--- a/tests/docker/dockerfiles/debian-riscv64-cross.docker
+++ b/tests/docker/dockerfiles/debian-riscv64-cross.docker
@@ -1,6 +1,6 @@
 # THIS FILE WAS AUTO-GENERATED
 #
-#  $ lcitool dockerfile --layers all --cross riscv64 debian-sid qemu-minimal
+#  $ lcitool dockerfile --layers all --cross-arch riscv64 debian-sid qemu-minimal
 #
 # https://gitlab.com/libvirt/libvirt-ci
 
diff --git a/tests/docker/dockerfiles/debian-s390x-cross.docker b/tests/docker/dockerfiles/debian-s390x-cross.docker
index 80028e1eea..48a2c10fdb 100644
--- a/tests/docker/dockerfiles/debian-s390x-cross.docker
+++ b/tests/docker/dockerfiles/debian-s390x-cross.docker
@@ -1,6 +1,6 @@
 # THIS FILE WAS AUTO-GENERATED
 #
-#  $ lcitool dockerfile --layers all --cross s390x debian-11 qemu
+#  $ lcitool dockerfile --layers all --cross-arch s390x debian-11 qemu
 #
 # https://gitlab.com/libvirt/libvirt-ci
 
diff --git a/tests/docker/dockerfiles/fedora-win32-cross.docker b/tests/docker/dockerfiles/fedora-win32-cross.docker
index e3dfd68bed..afa988574f 100644
--- a/tests/docker/dockerfiles/fedora-win32-cross.docker
+++ b/tests/docker/dockerfiles/fedora-win32-cross.docker
@@ -1,6 +1,6 @@
 # THIS FILE WAS AUTO-GENERATED
 #
-#  $ lcitool dockerfile --layers all --cross mingw32 fedora-38 qemu
+#  $ lcitool dockerfile --layers all --cross-arch mingw32 fedora-38 qemu
 #
 # https://gitlab.com/libvirt/libvirt-ci
 
diff --git a/tests/docker/dockerfiles/fedora-win64-cross.docker b/tests/docker/dockerfiles/fedora-win64-cross.docker
index 0e15c9643a..cf93a0ca60 100644
--- a/tests/docker/dockerfiles/fedora-win64-cross.docker
+++ b/tests/docker/dockerfiles/fedora-win64-cross.docker
@@ -1,6 +1,6 @@
 # THIS FILE WAS AUTO-GENERATED
 #
-#  $ lcitool dockerfile --layers all --cross mingw64 fedora-38 qemu
+#  $ lcitool dockerfile --layers all --cross-arch mingw64 fedora-38 qemu
 #
 # https://gitlab.com/libvirt/libvirt-ci
 
diff --git a/tests/docker/dockerfiles/opensuse-leap.docker b/tests/docker/dockerfiles/opensuse-leap.docker
index 37c83e5e4e..fef8d5a2e4 100644
--- a/tests/docker/dockerfiles/opensuse-leap.docker
+++ b/tests/docker/dockerfiles/opensuse-leap.docker
@@ -4,7 +4,7 @@
 #
 # https://gitlab.com/libvirt/libvirt-ci
 
-FROM registry.opensuse.org/opensuse/leap:15.4
+FROM registry.opensuse.org/opensuse/leap:15.5
 
 RUN zypper update -y && \
     zypper install -y \
@@ -90,9 +90,9 @@ RUN zypper update -y && \
            pcre-devel-static \
            pipewire-devel \
            pkgconfig \
-           python39-base \
-           python39-pip \
-           python39-setuptools \
+           python311-base \
+           python311-pip \
+           python311-setuptools \
            rdma-core-devel \
            sed \
            snappy-devel \
@@ -125,18 +125,18 @@ RUN zypper update -y && \
     ln -s /usr/bin/ccache /usr/libexec/ccache-wrappers/g++ && \
     ln -s /usr/bin/ccache /usr/libexec/ccache-wrappers/gcc
 
-RUN /usr/bin/pip3.9 install \
-                    PyYAML \
-                    meson==0.63.2 \
-                    pillow \
-                    sphinx \
-                    sphinx-rtd-theme
+RUN /usr/bin/pip3.11 install \
+                     PyYAML \
+                     meson==0.63.2 \
+                     pillow \
+                     sphinx \
+                     sphinx-rtd-theme
 
 ENV CCACHE_WRAPPERSDIR "/usr/libexec/ccache-wrappers"
 ENV LANG "en_US.UTF-8"
 ENV MAKE "/usr/bin/make"
 ENV NINJA "/usr/bin/ninja"
-ENV PYTHON "/usr/bin/python3.9"
+ENV PYTHON "/usr/bin/python3.11"
 # As a final step configure the user (if env is defined)
 ARG USER
 ARG UID
diff --git a/tests/lcitool/libvirt-ci b/tests/lcitool/libvirt-ci
index 9bff3b763b..bbd55b4d18 160000
--- a/tests/lcitool/libvirt-ci
+++ b/tests/lcitool/libvirt-ci
@@ -1 +1 @@
-Subproject commit 9bff3b763b5531a1490e238bfbf77306dc3a6dbb
+Subproject commit bbd55b4d18cce8f89b5167675e434a6941315634
diff --git a/tests/lcitool/mappings.yml b/tests/lcitool/mappings.yml
index 454963f07b..3c554099ed 100644
--- a/tests/lcitool/mappings.yml
+++ b/tests/lcitool/mappings.yml
@@ -9,7 +9,7 @@ mappings:
 
   python3:
     CentOSStream8: python38
-    OpenSUSELeap15: python39-base
+    OpenSUSELeap15: python311-base
 
   python3-PyYAML:
     CentOSStream8: python38-PyYAML
@@ -17,7 +17,7 @@ mappings:
 
   python3-devel:
     CentOSStream8: python38-devel
-    OpenSUSELeap15: python39-devel
+    OpenSUSELeap15: python311-devel
 
   python3-docutils:
     CentOSStream8:
@@ -37,7 +37,7 @@ mappings:
 
   python3-pip:
     CentOSStream8: python38-pip
-    OpenSUSELeap15: python39-pip
+    OpenSUSELeap15: python311-pip
 
   python3-pillow:
     CentOSStream8:
@@ -49,7 +49,7 @@ mappings:
 
   python3-setuptools:
     CentOSStream8: python38-setuptools
-    OpenSUSELeap15: python39-setuptools
+    OpenSUSELeap15: python311-setuptools
 
   python3-sphinx:
     CentOSStream8:
@@ -61,11 +61,11 @@ mappings:
 
   python3-venv:
     CentOSStream8: python38
-    OpenSUSELeap15: python39-base
+    OpenSUSELeap15: python311-base
 
   python3-wheel:
     CentOSStream8: python38-wheel
-    OpenSUSELeap15: python39-pip
+    OpenSUSELeap15: python311-pip
 
 pypi_mappings:
   # Request more recent version
diff --git a/tests/lcitool/projects/qemu.yml b/tests/lcitool/projects/qemu.yml
index d452a891ee..2d31cf792a 100644
--- a/tests/lcitool/projects/qemu.yml
+++ b/tests/lcitool/projects/qemu.yml
@@ -85,7 +85,7 @@ packages:
  - pam
  - pcre-static
  - pixman
- - pipewire
+ - libpipewire-dev
  - pkg-config
  - pulseaudio
  - python3
diff --git a/tests/lcitool/targets/opensuse-leap-15.yml b/tests/lcitool/targets/opensuse-leap-15.yml
index 683016e007..c2d87f6cb4 100644
--- a/tests/lcitool/targets/opensuse-leap-15.yml
+++ b/tests/lcitool/targets/opensuse-leap-15.yml
@@ -1,3 +1,3 @@
 paths:
-  pip3: /usr/bin/pip3.9
-  python: /usr/bin/python3.9
+  pip3: /usr/bin/pip3.11
+  python: /usr/bin/python3.11

From 7c3fb52bcdaef85b15a91b3ca4d1516f9d9b5402 Mon Sep 17 00:00:00 2001
From: Paolo Bonzini <pbonzini@redhat.com>
Date: Tue, 8 Aug 2023 20:28:25 +0200
Subject: [PATCH 07/14] configure: never use PyPI for Meson

Since there is a vendored copy, there is no point in choosing online
operation.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 configure | 6 ------
 1 file changed, 6 deletions(-)

diff --git a/configure b/configure
index f2bd8858d6..f13f0662b9 100755
--- a/configure
+++ b/configure
@@ -1018,13 +1018,7 @@ fi
 python="$python -B"
 mkvenv="$python ${source_path}/python/scripts/mkvenv.py"
 
-mkvenv_flags=""
-if test "$download" = "enabled" ; then
-    mkvenv_flags="--online"
-fi
-
 if ! $mkvenv ensure \
-     $mkvenv_flags \
      --dir "${source_path}/python/wheels" \
      --diagnose "meson" \
      "meson>=0.63.0" ;

From edc2107895007d621fe474d58bcb99036c8e55d2 Mon Sep 17 00:00:00 2001
From: Paolo Bonzini <pbonzini@redhat.com>
Date: Tue, 8 Aug 2023 20:19:43 +0200
Subject: [PATCH 08/14] python: use vendored tomli

Debian only introduced tomli in the bookworm release.  Use a
vendored wheel to avoid requiring a package that is only in
bullseye-backports and is also absent in Ubuntu 20.04.

While at it, fix an issue in the vendor.py scripts which does
not add a newline after each package and hash.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 configure                                  |   6 ++++++
 python/scripts/vendor.py                   |   5 ++++-
 python/wheels/tomli-2.0.1-py3-none-any.whl | Bin 0 -> 12757 bytes
 3 files changed, 10 insertions(+), 1 deletion(-)
 create mode 100644 python/wheels/tomli-2.0.1-py3-none-any.whl

diff --git a/configure b/configure
index f13f0662b9..347153702c 100755
--- a/configure
+++ b/configure
@@ -1018,6 +1018,12 @@ fi
 python="$python -B"
 mkvenv="$python ${source_path}/python/scripts/mkvenv.py"
 
+# Finish preparing the virtual environment using vendored .whl files
+
+if $python -c 'import sys; sys.exit(sys.version_info >= (3,11))'; then
+    $mkvenv ensure --dir "${source_path}/python/wheels" \
+        'tomli>=1.2.0' || exit 1
+fi
 if ! $mkvenv ensure \
      --dir "${source_path}/python/wheels" \
      --diagnose "meson" \
diff --git a/python/scripts/vendor.py b/python/scripts/vendor.py
index 34486a51f4..7627487117 100755
--- a/python/scripts/vendor.py
+++ b/python/scripts/vendor.py
@@ -43,13 +43,16 @@ def main() -> int:
     packages = {
         "meson==0.63.3":
         "d677b809c4895dcbaac9bf6c43703fcb3609a4b24c6057c78f828590049cf43a",
+
+        "tomli==2.0.1":
+        "939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc",
     }
 
     vendor_dir = Path(__file__, "..", "..", "wheels").resolve()
 
     with tempfile.NamedTemporaryFile(mode="w", encoding="utf-8") as file:
         for dep_spec, checksum in packages.items():
-            file.write(f"{dep_spec} --hash=sha256:{checksum}")
+            print(f"{dep_spec} --hash=sha256:{checksum}", file=file)
         file.flush()
 
         cli_args = [
diff --git a/python/wheels/tomli-2.0.1-py3-none-any.whl b/python/wheels/tomli-2.0.1-py3-none-any.whl
new file mode 100644
index 0000000000000000000000000000000000000000..29670b98d16e2bc770d4fea718582e1dc0dd8aca
GIT binary patch
literal 12757
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

literal 0
HcmV?d00001


From c853c4d08728f8e7fa6965e8508ed826b5461f04 Mon Sep 17 00:00:00 2001
From: Paolo Bonzini <pbonzini@redhat.com>
Date: Tue, 8 Aug 2023 11:23:48 +0200
Subject: [PATCH 09/14] configure: switch to ensuregroup

Using the new ensuregroup command, the desired versions of meson and
sphinx can be placed in pythondeps.toml rather than configure.

The meson.install entry in pythondeps.toml matches the version that is
found in python/wheels.  This ensures that mkvenv.py uses the bundled
wheel even if PyPI is enabled; thus not introducing warnings or errors
from versions that are more recent than the one used in CI.

The sphinx entries match what is shipped in Fedora 38.  It's the
last release that has support for older versions of Python (sphinx 6.0
requires Python 3.8) and especially docutils (of which sphinx 6.0 requires
version 0.18).  This is important because Ubuntu 20.04 has docutils 0.14
and Debian 11 has docutils 0.16.

"mkvenv.py ensure" is only used to bootstrap tomli.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 configure       | 14 ++++----------
 pythondeps.toml |  8 ++++++++
 2 files changed, 12 insertions(+), 10 deletions(-)

diff --git a/configure b/configure
index 347153702c..e4d42d640e 100755
--- a/configure
+++ b/configure
@@ -1024,13 +1024,8 @@ if $python -c 'import sys; sys.exit(sys.version_info >= (3,11))'; then
     $mkvenv ensure --dir "${source_path}/python/wheels" \
         'tomli>=1.2.0' || exit 1
 fi
-if ! $mkvenv ensure \
-     --dir "${source_path}/python/wheels" \
-     --diagnose "meson" \
-     "meson>=0.63.0" ;
-then
-    exit 1
-fi
+$mkvenv ensuregroup --dir "${source_path}/python/wheels" \
+     ${source_path}/pythondeps.toml meson || exit 1
 
 # At this point, we expect Meson to be installed and available.
 # We expect mkvenv or pip to have created pyvenv/bin/meson for us.
@@ -1047,10 +1042,9 @@ if test "$download" = "enabled" -a "$docs" = "enabled" ; then
 fi
 
 if test "$docs" != "disabled" ; then
-    if ! $mkvenv ensure \
+    if ! $mkvenv ensuregroup \
          $mkvenv_flags \
-         --diagnose "sphinx-build" \
-         "sphinx>=1.6.0" "sphinx-rtd-theme>=0.5.0";
+         ${source_path}/pythondeps.toml docs;
     then
         if test "$docs" = "enabled" ; then
             exit 1
diff --git a/pythondeps.toml b/pythondeps.toml
index 362f63ff2c..6be31dba30 100644
--- a/pythondeps.toml
+++ b/pythondeps.toml
@@ -15,3 +15,11 @@
 #           precise error diagnostics to the user.  For example,
 #           'sphinx-build' can be used as a bellwether for the
 #           presence of 'sphinx' in the system.
+
+[meson]
+# The install key should match the version in python/wheels/
+meson = { accepted = ">=0.63.0", installed = "0.63.3", canary = "meson" }
+
+[docs]
+sphinx = { accepted = ">=1.6", installed = "5.3.0", canary = "sphinx-build" }
+sphinx_rtd_theme = { accepted = ">=0.5", installed = "1.1.1" }

From c03f57fd5bf72588a05750f14202f63be7ddbd0c Mon Sep 17 00:00:00 2001
From: Paolo Bonzini <pbonzini@redhat.com>
Date: Tue, 8 Aug 2023 11:28:08 +0200
Subject: [PATCH 10/14] Revert "tests: Use separate virtual environment for
 avocado"

This reverts commit e8e4298feadae7924cf7600bb3bcc5b0a8d7cbe9.

ensuregroup allows to specify both the acceptable versions of avocado,
and a locked version to be used when avocado is not installed as a system
pacakge.  This lets us install avocado in pyvenv/ using "mkvenv.py" and
reuse the distro package on Fedora and CentOS Stream (the only distros
where it's available).

ensuregroup's usage of "(>=..., <=...)" constraints when evaluating
the distro package, and "==" constraints when installing it from PyPI,
makes it possible to avoid conflicts between the known-good version and
a package plugins included in the distro.

This is because package plugins have "==" constraints on the version
that is included in the distro, and, using "pip install avocado==88.1"
on a venv that includes system packages will result in an error:

   avocado-framework-plugin-varianter-yaml-to-mux 98.0 requires avocado-framework==98.0, but you have avocado-framework 88.1 which is incompatible.
   avocado-framework-plugin-result-html 98.0 requires avocado-framework==98.0, but you have avocado-framework 88.1 which is incompatible.

But at the same time, if the venv does not include a system distribution
of avocado then we can install a known-good version and stick to LTS
releases.

Resolves: https://gitlab.com/qemu-project/qemu/-/issues/1663
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 .gitlab-ci.d/buildtest.yml                    |  6 +++---
 docs/devel/acpi-bits.rst                      |  6 +++---
 docs/devel/testing.rst                        | 14 +++++++-------
 python/scripts/mkvenv.py                      | 13 +++++--------
 pythondeps.toml                               |  7 +++++++
 .../org.centos/stream/8/x86_64/test-avocado   |  4 ++--
 scripts/device-crash-test                     |  2 +-
 tests/Makefile.include                        | 19 ++++++++-----------
 tests/requirements.txt                        |  6 ------
 tests/vm/Makefile.include                     |  2 +-
 10 files changed, 37 insertions(+), 42 deletions(-)
 delete mode 100644 tests/requirements.txt

diff --git a/.gitlab-ci.d/buildtest.yml b/.gitlab-ci.d/buildtest.yml
index 77dc83a6be..aee9101507 100644
--- a/.gitlab-ci.d/buildtest.yml
+++ b/.gitlab-ci.d/buildtest.yml
@@ -103,7 +103,7 @@ crash-test-debian:
   script:
     - cd build
     - make NINJA=":" check-venv
-    - tests/venv/bin/python3 scripts/device-crash-test -q --tcg-only ./qemu-system-i386
+    - pyvenv/bin/python3 scripts/device-crash-test -q --tcg-only ./qemu-system-i386
 
 build-system-fedora:
   extends:
@@ -146,8 +146,8 @@ crash-test-fedora:
   script:
     - cd build
     - make NINJA=":" check-venv
-    - tests/venv/bin/python3 scripts/device-crash-test -q ./qemu-system-ppc
-    - tests/venv/bin/python3 scripts/device-crash-test -q ./qemu-system-riscv32
+    - pyvenv/bin/python3 scripts/device-crash-test -q ./qemu-system-ppc
+    - pyvenv/bin/python3 scripts/device-crash-test -q ./qemu-system-riscv32
 
 build-system-centos:
   extends:
diff --git a/docs/devel/acpi-bits.rst b/docs/devel/acpi-bits.rst
index 22e2580200..9677b0098f 100644
--- a/docs/devel/acpi-bits.rst
+++ b/docs/devel/acpi-bits.rst
@@ -61,19 +61,19 @@ Under ``tests/avocado/`` as the root we have:
    ::
 
      $ make check-venv (needed only the first time to create the venv)
-     $ ./tests/venv/bin/avocado run -t acpi tests/avocado
+     $ ./pyvenv/bin/avocado run -t acpi tests/avocado
 
    The above will run all acpi avocado tests including this one.
    In order to run the individual tests, perform the following:
    ::
 
-     $ ./tests/venv/bin/avocado run tests/avocado/acpi-bits.py --tap -
+     $ ./pyvenv/bin/avocado run tests/avocado/acpi-bits.py --tap -
 
    The above will produce output in tap format. You can omit "--tap -" in the
    end and it will produce output like the following:
    ::
 
-      $ ./tests/venv/bin/avocado run tests/avocado/acpi-bits.py
+      $ ./pyvenv/bin/avocado run tests/avocado/acpi-bits.py
       Fetching asset from tests/avocado/acpi-bits.py:AcpiBitsTest.test_acpi_smbios_bits
       JOB ID     : eab225724da7b64c012c65705dc2fa14ab1defef
       JOB LOG    : /home/anisinha/avocado/job-results/job-2022-10-10T17.58-eab2257/job.log
diff --git a/docs/devel/testing.rst b/docs/devel/testing.rst
index b6ad21bed1..5d1fc0aa95 100644
--- a/docs/devel/testing.rst
+++ b/docs/devel/testing.rst
@@ -894,9 +894,9 @@ You can run the avocado tests simply by executing:
 
   make check-avocado
 
-This involves the automatic creation of Python virtual environment
-within the build tree (at ``tests/venv``) which will have all the
-right dependencies, and will save tests results also within the
+This involves the automatic installation, from PyPI, of all the
+necessary avocado-framework dependencies into the QEMU venv within the
+build tree (at ``./pyvenv``). Test results are also saved within the
 build tree (at ``tests/results``).
 
 Note: the build environment must be using a Python 3 stack, and have
@@ -953,7 +953,7 @@ may be invoked by running:
 
  .. code::
 
-  tests/venv/bin/avocado run $OPTION1 $OPTION2 tests/avocado/
+  pyvenv/bin/avocado run $OPTION1 $OPTION2 tests/avocado/
 
 Note that if ``make check-avocado`` was not executed before, it is
 possible to create the Python virtual environment with the dependencies
@@ -968,20 +968,20 @@ a test file. To run tests from a single file within the build tree, use:
 
  .. code::
 
-  tests/venv/bin/avocado run tests/avocado/$TESTFILE
+  pyvenv/bin/avocado run tests/avocado/$TESTFILE
 
 To run a single test within a test file, use:
 
  .. code::
 
-  tests/venv/bin/avocado run tests/avocado/$TESTFILE:$TESTCLASS.$TESTNAME
+  pyvenv/bin/avocado run tests/avocado/$TESTFILE:$TESTCLASS.$TESTNAME
 
 Valid test names are visible in the output from any previous execution
 of Avocado or ``make check-avocado``, and can also be queried using:
 
  .. code::
 
-  tests/venv/bin/avocado list tests/avocado
+  pyvenv/bin/avocado list tests/avocado
 
 Manual Installation
 ~~~~~~~~~~~~~~~~~~~
diff --git a/python/scripts/mkvenv.py b/python/scripts/mkvenv.py
index 02bcd9a8c9..4f2349fbb6 100644
--- a/python/scripts/mkvenv.py
+++ b/python/scripts/mkvenv.py
@@ -964,14 +964,11 @@ def _parse_groups(file: str) -> Dict[str, Dict[str, Any]]:
             "Python >=3.11 does not have tomllib... what have you done!?"
         )
 
-    try:
-        # Use loads() to support both tomli v1.2.x (Ubuntu 22.04,
-        # Debian bullseye-backports) and v2.0.x
-        with open(file, "r", encoding="ascii") as depfile:
-            contents = depfile.read()
-            return tomllib.loads(contents)  # type: ignore
-    except tomllib.TOMLDecodeError as exc:
-        raise Ouch(f"parsing {file} failed: {exc}") from exc
+    # Use loads() to support both tomli v1.2.x (Ubuntu 22.04,
+    # Debian bullseye-backports) and v2.0.x
+    with open(file, "r", encoding="ascii") as depfile:
+        contents = depfile.read()
+        return tomllib.loads(contents)  # type: ignore
 
 
 def ensure_group(
diff --git a/pythondeps.toml b/pythondeps.toml
index 6be31dba30..0a35ebcf9f 100644
--- a/pythondeps.toml
+++ b/pythondeps.toml
@@ -23,3 +23,10 @@ meson = { accepted = ">=0.63.0", installed = "0.63.3", canary = "meson" }
 [docs]
 sphinx = { accepted = ">=1.6", installed = "5.3.0", canary = "sphinx-build" }
 sphinx_rtd_theme = { accepted = ">=0.5", installed = "1.1.1" }
+
+[avocado]
+# Note that qemu.git/python/ is always implicitly installed.
+# Prefer an LTS version when updating the accepted versions of
+# avocado-framework, for example right now the limit is 92.x.
+avocado-framework = { accepted = "(>=88.1, <93.0)", installed = "88.1", canary = "avocado" }
+pycdlib = { accepted = ">=1.11.0" }
diff --git a/scripts/ci/org.centos/stream/8/x86_64/test-avocado b/scripts/ci/org.centos/stream/8/x86_64/test-avocado
index e0443fc8ae..73e7a1a312 100755
--- a/scripts/ci/org.centos/stream/8/x86_64/test-avocado
+++ b/scripts/ci/org.centos/stream/8/x86_64/test-avocado
@@ -4,7 +4,7 @@
 # KVM and x86_64, or tests that are generic enough to be valid for all
 # targets. Such a test list can be generated with:
 #
-# ./tests/venv/bin/avocado list --filter-by-tags-include-empty \
+# ./pyvenv/bin/avocado list --filter-by-tags-include-empty \
 #   --filter-by-tags-include-empty-key -t accel:kvm,arch:x86_64 \
 #   tests/avocado/
 #
@@ -22,7 +22,7 @@
 #   - tests/avocado/virtio_check_params.py:VirtioMaxSegSettingsCheck.test_machine_types
 #
 make get-vm-images
-./tests/venv/bin/avocado run \
+./pyvenv/bin/avocado run \
     --job-results-dir=tests/results/ \
     tests/avocado/boot_linux.py:BootLinuxX8664.test_pc_i440fx_kvm \
     tests/avocado/boot_linux.py:BootLinuxX8664.test_pc_q35_kvm \
diff --git a/scripts/device-crash-test b/scripts/device-crash-test
index b74d887331..353aa575d7 100755
--- a/scripts/device-crash-test
+++ b/scripts/device-crash-test
@@ -43,7 +43,7 @@ except ModuleNotFoundError as exc:
     print(f"Module '{exc.name}' not found.")
     print("  Try 'make check-venv' from your build directory,")
     print("  and then one way to run this script is like so:")
-    print(f'  > $builddir/tests/venv/bin/python3 "{path}"')
+    print(f'  > $builddir/pyvenv/bin/python3 "{path}"')
     sys.exit(1)
 
 logger = logging.getLogger('device-crash-test')
diff --git a/tests/Makefile.include b/tests/Makefile.include
index 9422ddaece..985cda7a94 100644
--- a/tests/Makefile.include
+++ b/tests/Makefile.include
@@ -89,10 +89,8 @@ distclean-tcg: $(DISTCLEAN_TCG_TARGET_RULES)
 # Build up our target list from the filtered list of ninja targets
 TARGETS=$(patsubst libqemu-%.fa, %, $(filter libqemu-%.fa, $(ninja-targets)))
 
-TESTS_VENV_DIR=$(BUILD_DIR)/tests/venv
-TESTS_VENV_REQ=$(SRC_PATH)/tests/requirements.txt
+TESTS_VENV_TOKEN=$(BUILD_DIR)/pyvenv/tests.group
 TESTS_RESULTS_DIR=$(BUILD_DIR)/tests/results
-TESTS_PYTHON=$(TESTS_VENV_DIR)/bin/python3
 ifndef AVOCADO_TESTS
 	AVOCADO_TESTS=tests/avocado
 endif
@@ -108,20 +106,19 @@ else
 endif
 
 quiet-venv-pip = $(quiet-@)$(call quiet-command-run, \
-    $(TESTS_PYTHON) -m pip -q --disable-pip-version-check $1, \
+    $(PYTHON) -m pip -q --disable-pip-version-check $1, \
     "VENVPIP","$1")
 
-$(TESTS_VENV_DIR): $(TESTS_VENV_REQ)
-	$(call quiet-command, $(PYTHON) -m venv $@, VENV, $@)
+$(TESTS_VENV_TOKEN): $(SRC_PATH)/pythondeps.toml
 	$(call quiet-venv-pip,install -e "$(SRC_PATH)/python/")
-	$(call quiet-venv-pip,install -r $(TESTS_VENV_REQ))
+	$(PYTHON) python/scripts/mkvenv.py ensuregroup --online $< avocado
 	$(call quiet-command, touch $@)
 
 $(TESTS_RESULTS_DIR):
 	$(call quiet-command, mkdir -p $@, \
             MKDIR, $@)
 
-check-venv: $(TESTS_VENV_DIR)
+check-venv: $(TESTS_VENV_TOKEN)
 
 FEDORA_31_ARCHES_TARGETS=$(patsubst %-softmmu,%, $(filter %-softmmu,$(TARGETS)))
 FEDORA_31_ARCHES_CANDIDATES=$(patsubst ppc64,ppc64le,$(FEDORA_31_ARCHES_TARGETS))
@@ -131,7 +128,7 @@ FEDORA_31_DOWNLOAD=$(filter $(FEDORA_31_ARCHES),$(FEDORA_31_ARCHES_CANDIDATES))
 # download one specific Fedora 31 image
 get-vm-image-fedora-31-%: check-venv
 	$(call quiet-command, \
-             $(TESTS_PYTHON) -m avocado vmimage get \
+             $(PYTHON) -m avocado vmimage get \
              --distro=fedora --distro-version=31 --arch=$*, \
 	"AVOCADO", "Downloading avocado tests VM image for $*")
 
@@ -140,7 +137,7 @@ get-vm-images: check-venv $(patsubst %,get-vm-image-fedora-31-%, $(FEDORA_31_DOW
 
 check-avocado: check-venv $(TESTS_RESULTS_DIR) get-vm-images
 	$(call quiet-command, \
-            $(TESTS_PYTHON) -m avocado \
+            $(PYTHON) -m avocado \
             --show=$(AVOCADO_SHOW) run --job-results-dir=$(TESTS_RESULTS_DIR) \
             $(if $(AVOCADO_TAGS),, --filter-by-tags-include-empty \
 			--filter-by-tags-include-empty-key) \
@@ -163,7 +160,7 @@ check:
 check-build: run-ninja
 
 check-clean:
-	rm -rf $(TESTS_VENV_DIR) $(TESTS_RESULTS_DIR)
+	rm -rf $(TESTS_RESULTS_DIR)
 
 clean: check-clean clean-tcg
 distclean: distclean-tcg
diff --git a/tests/requirements.txt b/tests/requirements.txt
deleted file mode 100644
index 0ba561b6bd..0000000000
--- a/tests/requirements.txt
+++ /dev/null
@@ -1,6 +0,0 @@
-# Add Python module requirements, one per line, to be installed
-# in the tests/venv Python virtual environment. For more info,
-# refer to: https://pip.pypa.io/en/stable/user_guide/#id1
-# Note that qemu.git/python/ is always implicitly installed.
-avocado-framework==88.1
-pycdlib==1.11.0
diff --git a/tests/vm/Makefile.include b/tests/vm/Makefile.include
index c2a8ca1c17..f0f5d32fb0 100644
--- a/tests/vm/Makefile.include
+++ b/tests/vm/Makefile.include
@@ -5,7 +5,7 @@ ifeq ($(realpath $(SRC_PATH)),$(realpath .))
 VM_PYTHON = PYTHONPATH=$(SRC_PATH)/python /usr/bin/env python3
 VM_VENV =
 else
-VM_PYTHON = $(TESTS_PYTHON)
+VM_PYTHON = $(PYTHON)
 VM_VENV = check-venv
 endif
 

From 7ace219303e28cc67852e1d193437cd1f367b5c8 Mon Sep 17 00:00:00 2001
From: Paolo Bonzini <pbonzini@redhat.com>
Date: Tue, 8 Aug 2023 23:35:47 +0200
Subject: [PATCH 11/14] tests/docker: add python3-tomli dependency to
 containers

Instead of having CI pick tomli from the vendored wheel at configure
time, place it in the containers.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 .gitlab-ci.d/cirrus/freebsd-13.vars              |  2 +-
 .gitlab-ci.d/cirrus/macos-12.vars                |  2 +-
 tests/docker/dockerfiles/centos8.docker          |  3 ++-
 .../dockerfiles/debian-all-test-cross.docker     |  7 ++++++-
 .../docker/dockerfiles/debian-amd64-cross.docker |  4 ++++
 tests/docker/dockerfiles/debian-amd64.docker     |  4 ++++
 .../docker/dockerfiles/debian-arm64-cross.docker |  4 ++++
 .../docker/dockerfiles/debian-armel-cross.docker |  4 ++++
 .../docker/dockerfiles/debian-armhf-cross.docker |  4 ++++
 .../dockerfiles/debian-hexagon-cross.docker      |  6 +++++-
 .../dockerfiles/debian-mips64el-cross.docker     |  4 ++++
 .../dockerfiles/debian-mipsel-cross.docker       |  4 ++++
 .../dockerfiles/debian-ppc64el-cross.docker      |  4 ++++
 .../docker/dockerfiles/debian-s390x-cross.docker |  4 ++++
 .../dockerfiles/debian-tricore-cross.docker      |  2 ++
 .../docker/dockerfiles/fedora-i386-cross.docker  |  1 +
 tests/docker/dockerfiles/ubuntu2004.docker       |  4 +++-
 tests/docker/dockerfiles/ubuntu2204.docker       |  1 +
 tests/lcitool/mappings.yml                       | 16 ++++++++++++++++
 tests/lcitool/projects/qemu.yml                  |  1 +
 tests/vm/generated/freebsd.json                  |  1 +
 21 files changed, 76 insertions(+), 6 deletions(-)

diff --git a/.gitlab-ci.d/cirrus/freebsd-13.vars b/.gitlab-ci.d/cirrus/freebsd-13.vars
index facb649f5b..3785afca36 100644
--- a/.gitlab-ci.d/cirrus/freebsd-13.vars
+++ b/.gitlab-ci.d/cirrus/freebsd-13.vars
@@ -11,6 +11,6 @@ MAKE='/usr/local/bin/gmake'
 NINJA='/usr/local/bin/ninja'
 PACKAGING_COMMAND='pkg'
 PIP3='/usr/local/bin/pip-3.8'
-PKGS='alsa-lib bash bison bzip2 ca_root_nss capstone4 ccache cmocka ctags curl cyrus-sasl dbus diffutils dtc flex fusefs-libs3 gettext git glib gmake gnutls gsed gtk3 json-c libepoxy libffi libgcrypt libjpeg-turbo libnfs libslirp libspice-server libssh libtasn1 llvm lzo2 meson mtools ncurses nettle ninja opencv pixman pkgconf png py39-numpy py39-pillow py39-pip py39-sphinx py39-sphinx_rtd_theme py39-yaml python3 rpm2cpio sdl2 sdl2_image snappy sndio socat spice-protocol tesseract usbredir virglrenderer vte3 xorriso zstd'
+PKGS='alsa-lib bash bison bzip2 ca_root_nss capstone4 ccache cmocka ctags curl cyrus-sasl dbus diffutils dtc flex fusefs-libs3 gettext git glib gmake gnutls gsed gtk3 json-c libepoxy libffi libgcrypt libjpeg-turbo libnfs libslirp libspice-server libssh libtasn1 llvm lzo2 meson mtools ncurses nettle ninja opencv pixman pkgconf png py39-numpy py39-pillow py39-pip py39-sphinx py39-sphinx_rtd_theme py39-tomli py39-yaml python3 rpm2cpio sdl2 sdl2_image snappy sndio socat spice-protocol tesseract usbredir virglrenderer vte3 xorriso zstd'
 PYPI_PKGS=''
 PYTHON='/usr/local/bin/python3'
diff --git a/.gitlab-ci.d/cirrus/macos-12.vars b/.gitlab-ci.d/cirrus/macos-12.vars
index ceb294e153..80eadaab29 100644
--- a/.gitlab-ci.d/cirrus/macos-12.vars
+++ b/.gitlab-ci.d/cirrus/macos-12.vars
@@ -12,5 +12,5 @@ NINJA='/opt/homebrew/bin/ninja'
 PACKAGING_COMMAND='brew'
 PIP3='/opt/homebrew/bin/pip3'
 PKGS='bash bc bison bzip2 capstone ccache cmocka ctags curl dbus diffutils dtc flex gcovr gettext git glib gnu-sed gnutls gtk+3 jemalloc jpeg-turbo json-c libepoxy libffi libgcrypt libiscsi libnfs libpng libslirp libssh libtasn1 libusb llvm lzo make meson mtools ncurses nettle ninja pixman pkg-config python3 rpm2cpio sdl2 sdl2_image snappy socat sparse spice-protocol tesseract usbredir vde vte3 xorriso zlib zstd'
-PYPI_PKGS='PyYAML numpy pillow sphinx sphinx-rtd-theme'
+PYPI_PKGS='PyYAML numpy pillow sphinx sphinx-rtd-theme tomli'
 PYTHON='/opt/homebrew/bin/python3'
diff --git a/tests/docker/dockerfiles/centos8.docker b/tests/docker/dockerfiles/centos8.docker
index da7dc818fb..fc1830966f 100644
--- a/tests/docker/dockerfiles/centos8.docker
+++ b/tests/docker/dockerfiles/centos8.docker
@@ -133,7 +133,8 @@ RUN /usr/bin/pip3.8 install \
                     meson==0.63.2 \
                     pillow \
                     sphinx \
-                    sphinx-rtd-theme
+                    sphinx-rtd-theme \
+                    tomli
 
 ENV CCACHE_WRAPPERSDIR "/usr/libexec/ccache-wrappers"
 ENV LANG "en_US.UTF-8"
diff --git a/tests/docker/dockerfiles/debian-all-test-cross.docker b/tests/docker/dockerfiles/debian-all-test-cross.docker
index f9f401544a..54e957d5e7 100644
--- a/tests/docker/dockerfiles/debian-all-test-cross.docker
+++ b/tests/docker/dockerfiles/debian-all-test-cross.docker
@@ -58,7 +58,12 @@ RUN DEBIAN_FRONTEND=noninteractive eatmydata \
         libc6-dev-sh4-cross \
         gcc-sparc64-linux-gnu \
         libc6-dev-sparc64-cross \
-        python3-venv
+        python3-pip \
+        python3-setuptools \
+        python3-venv \
+        python3-wheel
+
+RUN /usr/bin/pip3 install tomli
 
 ENV QEMU_CONFIGURE_OPTS --disable-system --disable-docs --disable-tools
 ENV DEF_TARGET_LIST aarch64-linux-user,alpha-linux-user,arm-linux-user,hppa-linux-user,i386-linux-user,m68k-linux-user,mips-linux-user,mips64-linux-user,mips64el-linux-user,mipsel-linux-user,ppc-linux-user,ppc64-linux-user,ppc64le-linux-user,riscv64-linux-user,s390x-linux-user,sh4-linux-user,sparc64-linux-user
diff --git a/tests/docker/dockerfiles/debian-amd64-cross.docker b/tests/docker/dockerfiles/debian-amd64-cross.docker
index b9871f9c8c..b66b9cc191 100644
--- a/tests/docker/dockerfiles/debian-amd64-cross.docker
+++ b/tests/docker/dockerfiles/debian-amd64-cross.docker
@@ -47,9 +47,11 @@ RUN export DEBIAN_FRONTEND=noninteractive && \
                       python3-opencv \
                       python3-pillow \
                       python3-pip \
+                      python3-setuptools \
                       python3-sphinx \
                       python3-sphinx-rtd-theme \
                       python3-venv \
+                      python3-wheel \
                       python3-yaml \
                       rpm2cpio \
                       sed \
@@ -65,6 +67,8 @@ RUN export DEBIAN_FRONTEND=noninteractive && \
     sed -Ei 's,^# (en_US\.UTF-8 .*)$,\1,' /etc/locale.gen && \
     dpkg-reconfigure locales
 
+RUN /usr/bin/pip3 install tomli
+
 ENV CCACHE_WRAPPERSDIR "/usr/libexec/ccache-wrappers"
 ENV LANG "en_US.UTF-8"
 ENV MAKE "/usr/bin/make"
diff --git a/tests/docker/dockerfiles/debian-amd64.docker b/tests/docker/dockerfiles/debian-amd64.docker
index 6d2fa38e3e..02262bc70e 100644
--- a/tests/docker/dockerfiles/debian-amd64.docker
+++ b/tests/docker/dockerfiles/debian-amd64.docker
@@ -115,9 +115,11 @@ RUN export DEBIAN_FRONTEND=noninteractive && \
                       python3-opencv \
                       python3-pillow \
                       python3-pip \
+                      python3-setuptools \
                       python3-sphinx \
                       python3-sphinx-rtd-theme \
                       python3-venv \
+                      python3-wheel \
                       python3-yaml \
                       rpm2cpio \
                       sed \
@@ -143,6 +145,8 @@ RUN export DEBIAN_FRONTEND=noninteractive && \
     ln -s /usr/bin/ccache /usr/libexec/ccache-wrappers/g++ && \
     ln -s /usr/bin/ccache /usr/libexec/ccache-wrappers/gcc
 
+RUN /usr/bin/pip3 install tomli
+
 ENV CCACHE_WRAPPERSDIR "/usr/libexec/ccache-wrappers"
 ENV LANG "en_US.UTF-8"
 ENV MAKE "/usr/bin/make"
diff --git a/tests/docker/dockerfiles/debian-arm64-cross.docker b/tests/docker/dockerfiles/debian-arm64-cross.docker
index 3504c771a7..a0a968b8c6 100644
--- a/tests/docker/dockerfiles/debian-arm64-cross.docker
+++ b/tests/docker/dockerfiles/debian-arm64-cross.docker
@@ -47,9 +47,11 @@ RUN export DEBIAN_FRONTEND=noninteractive && \
                       python3-opencv \
                       python3-pillow \
                       python3-pip \
+                      python3-setuptools \
                       python3-sphinx \
                       python3-sphinx-rtd-theme \
                       python3-venv \
+                      python3-wheel \
                       python3-yaml \
                       rpm2cpio \
                       sed \
@@ -65,6 +67,8 @@ RUN export DEBIAN_FRONTEND=noninteractive && \
     sed -Ei 's,^# (en_US\.UTF-8 .*)$,\1,' /etc/locale.gen && \
     dpkg-reconfigure locales
 
+RUN /usr/bin/pip3 install tomli
+
 ENV CCACHE_WRAPPERSDIR "/usr/libexec/ccache-wrappers"
 ENV LANG "en_US.UTF-8"
 ENV MAKE "/usr/bin/make"
diff --git a/tests/docker/dockerfiles/debian-armel-cross.docker b/tests/docker/dockerfiles/debian-armel-cross.docker
index 6d11c9510f..f1fc34a28a 100644
--- a/tests/docker/dockerfiles/debian-armel-cross.docker
+++ b/tests/docker/dockerfiles/debian-armel-cross.docker
@@ -47,9 +47,11 @@ RUN export DEBIAN_FRONTEND=noninteractive && \
                       python3-opencv \
                       python3-pillow \
                       python3-pip \
+                      python3-setuptools \
                       python3-sphinx \
                       python3-sphinx-rtd-theme \
                       python3-venv \
+                      python3-wheel \
                       python3-yaml \
                       rpm2cpio \
                       sed \
@@ -65,6 +67,8 @@ RUN export DEBIAN_FRONTEND=noninteractive && \
     sed -Ei 's,^# (en_US\.UTF-8 .*)$,\1,' /etc/locale.gen && \
     dpkg-reconfigure locales
 
+RUN /usr/bin/pip3 install tomli
+
 ENV CCACHE_WRAPPERSDIR "/usr/libexec/ccache-wrappers"
 ENV LANG "en_US.UTF-8"
 ENV MAKE "/usr/bin/make"
diff --git a/tests/docker/dockerfiles/debian-armhf-cross.docker b/tests/docker/dockerfiles/debian-armhf-cross.docker
index 37ae575cf7..a278578211 100644
--- a/tests/docker/dockerfiles/debian-armhf-cross.docker
+++ b/tests/docker/dockerfiles/debian-armhf-cross.docker
@@ -47,9 +47,11 @@ RUN export DEBIAN_FRONTEND=noninteractive && \
                       python3-opencv \
                       python3-pillow \
                       python3-pip \
+                      python3-setuptools \
                       python3-sphinx \
                       python3-sphinx-rtd-theme \
                       python3-venv \
+                      python3-wheel \
                       python3-yaml \
                       rpm2cpio \
                       sed \
@@ -65,6 +67,8 @@ RUN export DEBIAN_FRONTEND=noninteractive && \
     sed -Ei 's,^# (en_US\.UTF-8 .*)$,\1,' /etc/locale.gen && \
     dpkg-reconfigure locales
 
+RUN /usr/bin/pip3 install tomli
+
 ENV CCACHE_WRAPPERSDIR "/usr/libexec/ccache-wrappers"
 ENV LANG "en_US.UTF-8"
 ENV MAKE "/usr/bin/make"
diff --git a/tests/docker/dockerfiles/debian-hexagon-cross.docker b/tests/docker/dockerfiles/debian-hexagon-cross.docker
index c2cfb6a5d0..153fc7cfb3 100644
--- a/tests/docker/dockerfiles/debian-hexagon-cross.docker
+++ b/tests/docker/dockerfiles/debian-hexagon-cross.docker
@@ -21,11 +21,15 @@ RUN apt-get update && \
         flex \
         git \
         ninja-build \
-        python3-venv && \
+        python3-pip \
+        python3-setuptools \
+        python3-venv \
+        python3-wheel && \
 # Install QEMU build deps for use in CI
     DEBIAN_FRONTEND=noninteractive eatmydata \
     apt build-dep -yy --arch-only qemu
 
+RUN /usr/bin/pip3 install tomli
 
 ENV TOOLCHAIN_INSTALL /opt
 ENV TOOLCHAIN_RELEASE 16.0.0
diff --git a/tests/docker/dockerfiles/debian-mips64el-cross.docker b/tests/docker/dockerfiles/debian-mips64el-cross.docker
index 26ed730165..17d3e01ecc 100644
--- a/tests/docker/dockerfiles/debian-mips64el-cross.docker
+++ b/tests/docker/dockerfiles/debian-mips64el-cross.docker
@@ -47,9 +47,11 @@ RUN export DEBIAN_FRONTEND=noninteractive && \
                       python3-opencv \
                       python3-pillow \
                       python3-pip \
+                      python3-setuptools \
                       python3-sphinx \
                       python3-sphinx-rtd-theme \
                       python3-venv \
+                      python3-wheel \
                       python3-yaml \
                       rpm2cpio \
                       sed \
@@ -65,6 +67,8 @@ RUN export DEBIAN_FRONTEND=noninteractive && \
     sed -Ei 's,^# (en_US\.UTF-8 .*)$,\1,' /etc/locale.gen && \
     dpkg-reconfigure locales
 
+RUN /usr/bin/pip3 install tomli
+
 ENV CCACHE_WRAPPERSDIR "/usr/libexec/ccache-wrappers"
 ENV LANG "en_US.UTF-8"
 ENV MAKE "/usr/bin/make"
diff --git a/tests/docker/dockerfiles/debian-mipsel-cross.docker b/tests/docker/dockerfiles/debian-mipsel-cross.docker
index ade2f37ed1..5fcd641f15 100644
--- a/tests/docker/dockerfiles/debian-mipsel-cross.docker
+++ b/tests/docker/dockerfiles/debian-mipsel-cross.docker
@@ -47,9 +47,11 @@ RUN export DEBIAN_FRONTEND=noninteractive && \
                       python3-opencv \
                       python3-pillow \
                       python3-pip \
+                      python3-setuptools \
                       python3-sphinx \
                       python3-sphinx-rtd-theme \
                       python3-venv \
+                      python3-wheel \
                       python3-yaml \
                       rpm2cpio \
                       sed \
@@ -65,6 +67,8 @@ RUN export DEBIAN_FRONTEND=noninteractive && \
     sed -Ei 's,^# (en_US\.UTF-8 .*)$,\1,' /etc/locale.gen && \
     dpkg-reconfigure locales
 
+RUN /usr/bin/pip3 install tomli
+
 ENV CCACHE_WRAPPERSDIR "/usr/libexec/ccache-wrappers"
 ENV LANG "en_US.UTF-8"
 ENV MAKE "/usr/bin/make"
diff --git a/tests/docker/dockerfiles/debian-ppc64el-cross.docker b/tests/docker/dockerfiles/debian-ppc64el-cross.docker
index 08dcffa0a8..30e5efa986 100644
--- a/tests/docker/dockerfiles/debian-ppc64el-cross.docker
+++ b/tests/docker/dockerfiles/debian-ppc64el-cross.docker
@@ -47,9 +47,11 @@ RUN export DEBIAN_FRONTEND=noninteractive && \
                       python3-opencv \
                       python3-pillow \
                       python3-pip \
+                      python3-setuptools \
                       python3-sphinx \
                       python3-sphinx-rtd-theme \
                       python3-venv \
+                      python3-wheel \
                       python3-yaml \
                       rpm2cpio \
                       sed \
@@ -65,6 +67,8 @@ RUN export DEBIAN_FRONTEND=noninteractive && \
     sed -Ei 's,^# (en_US\.UTF-8 .*)$,\1,' /etc/locale.gen && \
     dpkg-reconfigure locales
 
+RUN /usr/bin/pip3 install tomli
+
 ENV CCACHE_WRAPPERSDIR "/usr/libexec/ccache-wrappers"
 ENV LANG "en_US.UTF-8"
 ENV MAKE "/usr/bin/make"
diff --git a/tests/docker/dockerfiles/debian-s390x-cross.docker b/tests/docker/dockerfiles/debian-s390x-cross.docker
index 48a2c10fdb..ee6db7b526 100644
--- a/tests/docker/dockerfiles/debian-s390x-cross.docker
+++ b/tests/docker/dockerfiles/debian-s390x-cross.docker
@@ -47,9 +47,11 @@ RUN export DEBIAN_FRONTEND=noninteractive && \
                       python3-opencv \
                       python3-pillow \
                       python3-pip \
+                      python3-setuptools \
                       python3-sphinx \
                       python3-sphinx-rtd-theme \
                       python3-venv \
+                      python3-wheel \
                       python3-yaml \
                       rpm2cpio \
                       sed \
@@ -65,6 +67,8 @@ RUN export DEBIAN_FRONTEND=noninteractive && \
     sed -Ei 's,^# (en_US\.UTF-8 .*)$,\1,' /etc/locale.gen && \
     dpkg-reconfigure locales
 
+RUN /usr/bin/pip3 install tomli
+
 ENV CCACHE_WRAPPERSDIR "/usr/libexec/ccache-wrappers"
 ENV LANG "en_US.UTF-8"
 ENV MAKE "/usr/bin/make"
diff --git a/tests/docker/dockerfiles/debian-tricore-cross.docker b/tests/docker/dockerfiles/debian-tricore-cross.docker
index 5bd1963fb5..c597f8e16b 100644
--- a/tests/docker/dockerfiles/debian-tricore-cross.docker
+++ b/tests/docker/dockerfiles/debian-tricore-cross.docker
@@ -36,6 +36,8 @@ RUN apt update && \
        python3-wheel \
        python3-venv
 
+RUN /usr/bin/pip3 install tomli
+
 RUN curl -#SL https://github.com/bkoppelmann/package_940/releases/download/tricore-toolchain-9.40/tricore-toolchain-9.4.0.tar.gz \
     | tar -xzC /usr/local/
 
diff --git a/tests/docker/dockerfiles/fedora-i386-cross.docker b/tests/docker/dockerfiles/fedora-i386-cross.docker
index 14c1fb2c93..b59a9115c4 100644
--- a/tests/docker/dockerfiles/fedora-i386-cross.docker
+++ b/tests/docker/dockerfiles/fedora-i386-cross.docker
@@ -24,6 +24,7 @@ ENV PACKAGES \
     nettle-devel.i686 \
     pcre-devel.i686 \
     pixman-devel.i686 \
+    python3-tomli \
     sysprof-capture-devel.i686 \
     zlib-devel.i686
 
diff --git a/tests/docker/dockerfiles/ubuntu2004.docker b/tests/docker/dockerfiles/ubuntu2004.docker
index 8f864d19e6..4180cd8674 100644
--- a/tests/docker/dockerfiles/ubuntu2004.docker
+++ b/tests/docker/dockerfiles/ubuntu2004.docker
@@ -141,7 +141,9 @@ RUN export DEBIAN_FRONTEND=noninteractive && \
     ln -s /usr/bin/ccache /usr/libexec/ccache-wrappers/g++ && \
     ln -s /usr/bin/ccache /usr/libexec/ccache-wrappers/gcc
 
-RUN /usr/bin/pip3 install meson==0.63.2
+RUN /usr/bin/pip3 install \
+                            meson==0.63.2 \
+                            tomli
 
 ENV CCACHE_WRAPPERSDIR "/usr/libexec/ccache-wrappers"
 ENV LANG "en_US.UTF-8"
diff --git a/tests/docker/dockerfiles/ubuntu2204.docker b/tests/docker/dockerfiles/ubuntu2204.docker
index 8f939870ae..88493f00f6 100644
--- a/tests/docker/dockerfiles/ubuntu2204.docker
+++ b/tests/docker/dockerfiles/ubuntu2204.docker
@@ -117,6 +117,7 @@ RUN export DEBIAN_FRONTEND=noninteractive && \
                       python3-pip \
                       python3-sphinx \
                       python3-sphinx-rtd-theme \
+                      python3-tomli \
                       python3-venv \
                       python3-yaml \
                       rpm2cpio \
diff --git a/tests/lcitool/mappings.yml b/tests/lcitool/mappings.yml
index 3c554099ed..0b908882f1 100644
--- a/tests/lcitool/mappings.yml
+++ b/tests/lcitool/mappings.yml
@@ -59,6 +59,15 @@ mappings:
     CentOSStream8:
     OpenSUSELeap15:
 
+  python3-tomli:
+    # test using tomllib
+    apk:
+    Fedora:
+    Debian12:
+    OpenSUSELeap15:
+    # Not available for Python 3.8
+    CentOSStream8:
+
   python3-venv:
     CentOSStream8: python38
     OpenSUSELeap15: python311-base
@@ -75,3 +84,10 @@ pypi_mappings:
   # Drop packages that need devel headers
   python3-numpy:
     OpenSUSELeap15:
+
+  # see above
+  python3-tomli:
+    apk:
+    Fedora:
+    Debian12:
+    OpenSUSELeap15:
diff --git a/tests/lcitool/projects/qemu.yml b/tests/lcitool/projects/qemu.yml
index 2d31cf792a..584f78cb7f 100644
--- a/tests/lcitool/projects/qemu.yml
+++ b/tests/lcitool/projects/qemu.yml
@@ -96,6 +96,7 @@ packages:
  - python3-pip
  - python3-sphinx
  - python3-sphinx-rtd-theme
+ - python3-tomli
  - python3-venv
  - rpm2cpio
  - sdl2
diff --git a/tests/vm/generated/freebsd.json b/tests/vm/generated/freebsd.json
index 7c435cf23e..2d5895ebed 100644
--- a/tests/vm/generated/freebsd.json
+++ b/tests/vm/generated/freebsd.json
@@ -56,6 +56,7 @@
     "py39-pip",
     "py39-sphinx",
     "py39-sphinx_rtd_theme",
+    "py39-tomli",
     "py39-yaml",
     "python3",
     "rpm2cpio",

From 33cc88261c352445d31599054653d759f20531c1 Mon Sep 17 00:00:00 2001
From: Ake Koomsin <ake@igel.co.jp>
Date: Mon, 7 Aug 2023 18:33:40 +0900
Subject: [PATCH 12/14] target/i386: add support for
 VMX_SECONDARY_EXEC_ENABLE_USER_WAIT_PAUSE

Current QEMU can expose waitpkg to guests when it is available. However,
VMX_SECONDARY_EXEC_ENABLE_USER_WAIT_PAUSE is still not recognized and
masked by QEMU. This can lead to an unexpected situation when a L1
hypervisor wants to expose waitpkg to a L2 guest. The L1 hypervisor can
assume that VMX_SECONDARY_EXEC_ENABLE_USER_WAIT_PAUSE exists as waitpkg is
available. The L1 hypervisor then can accidentally expose waitpkg to the
L2 guest. This will cause invalid opcode exception in the L2 guest when
it executes waitpkg related instructions.

This patch adds VMX_SECONDARY_EXEC_ENABLE_USER_WAIT_PAUSE support, and
sets up dependency between the bit and CPUID_7_0_ECX_WAITPKG. QEMU should
not expose waitpkg feature if VMX_SECONDARY_EXEC_ENABLE_USER_WAIT_PAUSE is
not available to avoid unexpected invalid opcode exception in L2 guests.

Signed-off-by: Ake Koomsin <ake@igel.co.jp>
Message-ID: <20230807093339.32091-2-ake@igel.co.jp>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 target/i386/cpu.c | 6 +++++-
 target/i386/cpu.h | 1 +
 2 files changed, 6 insertions(+), 1 deletion(-)

diff --git a/target/i386/cpu.c b/target/i386/cpu.c
index 97ad229d8b..00f913b638 100644
--- a/target/i386/cpu.c
+++ b/target/i386/cpu.c
@@ -1228,7 +1228,7 @@ FeatureWordInfo feature_word_info[FEATURE_WORDS] = {
             "vmx-invpcid-exit", "vmx-vmfunc", "vmx-shadow-vmcs", "vmx-encls-exit",
             "vmx-rdseed-exit", "vmx-pml", NULL, NULL,
             "vmx-xsaves", NULL, NULL, NULL,
-            NULL, "vmx-tsc-scaling", NULL, NULL,
+            NULL, "vmx-tsc-scaling", "vmx-enable-user-wait-pause", NULL,
             NULL, NULL, NULL, NULL,
         },
         .msr = {
@@ -1545,6 +1545,10 @@ static FeatureDep feature_dependencies[] = {
         .from = { FEAT_8000_0001_ECX,       CPUID_EXT3_SVM },
         .to = { FEAT_SVM,                   ~0ull },
     },
+    {
+        .from = { FEAT_VMX_SECONDARY_CTLS,  VMX_SECONDARY_EXEC_ENABLE_USER_WAIT_PAUSE },
+        .to = { FEAT_7_0_ECX,               CPUID_7_0_ECX_WAITPKG },
+    },
 };
 
 typedef struct X86RegisterInfo32 {
diff --git a/target/i386/cpu.h b/target/i386/cpu.h
index e0771a1043..a6000e93bd 100644
--- a/target/i386/cpu.h
+++ b/target/i386/cpu.h
@@ -1111,6 +1111,7 @@ uint64_t x86_cpu_get_supported_feature_word(FeatureWord w,
 #define VMX_SECONDARY_EXEC_ENABLE_PML               0x00020000
 #define VMX_SECONDARY_EXEC_XSAVES                   0x00100000
 #define VMX_SECONDARY_EXEC_TSC_SCALING              0x02000000
+#define VMX_SECONDARY_EXEC_ENABLE_USER_WAIT_PAUSE   0x04000000
 
 #define VMX_PIN_BASED_EXT_INTR_MASK                 0x00000001
 #define VMX_PIN_BASED_NMI_EXITING                   0x00000008

From a04f33727cea092dc71be32745e8964f62fb8104 Mon Sep 17 00:00:00 2001
From: Paolo Bonzini <pbonzini@redhat.com>
Date: Mon, 7 Aug 2023 11:22:08 +0200
Subject: [PATCH 13/14] configure: fix container_hosts misspellings and
 duplications

container_hosts is matched against $cpu, so it must contain QEMU
canonical architecture names, not Debian architecture names.
Also do not set $container_hosts inside the loop, since it is
already set before.

Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 configure | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/configure b/configure
index e4d42d640e..08bf24b689 100755
--- a/configure
+++ b/configure
@@ -1352,7 +1352,7 @@ probe_target_compiler() {
     sh4) container_hosts=x86_64 ;;
     sparc64) container_hosts=x86_64 ;;
     tricore) container_hosts=x86_64 ;;
-    x86_64) container_hosts="aarch64 ppc64el x86_64" ;;
+    x86_64) container_hosts="aarch64 ppc64le x86_64" ;;
     xtensa*) container_hosts=x86_64 ;;
   esac
 
@@ -1459,7 +1459,6 @@ probe_target_compiler() {
         container_cross_prefix=x86_64-linux-gnu-
         ;;
       xtensa*)
-        container_hosts=x86_64
         container_image=debian-xtensa-cross
 
         # default to the dc232b cpu

From 29a8238510df27080b0ffa92c58400412ce19daa Mon Sep 17 00:00:00 2001
From: Paolo Bonzini <pbonzini@redhat.com>
Date: Mon, 7 Aug 2023 14:17:43 +0200
Subject: [PATCH 14/14] configure: remove unnecessary mkdir -p

It is already included in the symlink shell function.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 configure | 1 -
 1 file changed, 1 deletion(-)

diff --git a/configure b/configure
index 08bf24b689..b9bd008592 100755
--- a/configure
+++ b/configure
@@ -1775,7 +1775,6 @@ fi
 for target in $target_list; do
     target_dir="$target"
     target_name=$(echo $target | cut -d '-' -f 1)$EXESUF
-    mkdir -p "$target_dir"
     case $target in
         *-user) symlink "../qemu-$target_name" "$target_dir/qemu-$target_name" ;;
         *) symlink "../qemu-system-$target_name" "$target_dir/qemu-system-$target_name" ;;