* -smp cleanpus

* Hyper-V englightenment functionality
 * Documentation cleanups
 -----BEGIN PGP SIGNATURE-----
 
 iQFIBAABCAAyFiEE8TM4V0tmI4mGbHaCv/vSX3jHroMFAmFXQSQUHHBib256aW5p
 QHJlZGhhdC5jb20ACgkQv/vSX3jHroNJUgf/bi96/9B1/6YhZ15l0jzxhtyNaWJ6
 nLtMrAsafbiPM8z3WKQ2BY3hLfRwvPbn8TZkO+mIwvfHP5gQDfYXL8xwW0KmxpPo
 1c8xjV85yqjVMFd2FFvSrLfpUhR8Pduti5zfDLcbFTzjbR08RRRbVjaVNtrm6fpE
 /sfZRl6vC3Znt6e9dM1n5//WDV2yGVEcD9BCbjgnEIf6fBr9pSNAoV/9bd5l+a9M
 kKq+SD3MIozipi96JX02447h1qhfrthAEbYhJc9XBh1Z7Ah6DldHasWiz07+cAp6
 ggwWMJ3p6ss07tgaZ1OlN8ivifRJ1+oFVXZOixAKlFQn6yhXyhZUjEMQdg==
 =3LXK
 -----END PGP SIGNATURE-----

Merge remote-tracking branch 'remotes/bonzini/tags/for-upstream' into staging

* -smp cleanpus
* Hyper-V englightenment functionality
* Documentation cleanups

# gpg: Signature made Fri 01 Oct 2021 01:11:00 PM EDT
# gpg:                using RSA key F13338574B662389866C7682BFFBD25F78C7AE83
# gpg:                issuer "pbonzini@redhat.com"
# gpg: Good signature from "Paolo Bonzini <bonzini@gnu.org>" [full]
# gpg:                 aka "Paolo Bonzini <pbonzini@redhat.com>" [full]

* remotes/bonzini/tags/for-upstream: (29 commits)
  docs: reorganize testing.rst
  docs: move gcov section at the end of testing.rst
  docs: reorganize tcg-plugins.rst
  docs: reorganize qgraph.rst
  docs: put "make" information together in build-system.rst
  docs: move notes inside the body of the document
  docs: name included files ".rst.inc"
  i386: Change the default Hyper-V version to match WS2016
  i386: Make Hyper-V version id configurable
  i386: Implement pseudo 'hv-avic' ('hv-apicv') enlightenment
  i386: Move HV_APIC_ACCESS_RECOMMENDED bit setting to hyperv_fill_cpuids()
  i386: Support KVM_CAP_HYPERV_ENFORCE_CPUID
  i386: Support KVM_CAP_ENFORCE_PV_FEATURE_CPUID
  machine: Put all sanity-check in the generic SMP parser
  machine: Use g_autoptr in machine_set_smp
  machine: Move smp_prefer_sockets to struct SMPCompatProps
  machine: Remove smp_parse callback from MachineClass
  machine: Make smp_parse generic enough for all arches
  machine: Tweak the order of topology members in struct CpuTopology
  machine: Use ms instead of global current_machine in sanity-check
  ...

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
This commit is contained in:
Richard Henderson 2021-10-01 13:44:36 -04:00
commit 5f99210238
26 changed files with 564 additions and 405 deletions

View File

@ -160,6 +160,21 @@ Use ``-display sdl`` instead.
Use ``-display curses`` instead. Use ``-display curses`` instead.
``-smp`` ("parameter=0" SMP configurations) (since 6.2)
'''''''''''''''''''''''''''''''''''''''''''''''''''''''
Specified CPU topology parameters must be greater than zero.
In the SMP configuration, users should either provide a CPU topology
parameter with a reasonable value (greater than zero) or just omit it
and QEMU will compute the missing value.
However, historically it was implicitly allowed for users to provide
a parameter with zero value, which is meaningless and could also possibly
cause unexpected results in the -smp parsing. So support for this kind of
configurations (e.g. -smp 8,sockets=0) is deprecated since 6.2 and will
be removed in the near future, users have to ensure that all the topology
members described with -smp are greater than zero.
Plugin argument passing through ``arg=<string>`` (since 6.1) Plugin argument passing through ``arg=<string>`` (since 6.1)
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''

View File

@ -380,6 +380,16 @@ phony target, while benchmarks are run with ``make bench``. Meson test
suites such as ``unit`` can be ran with ``make check-unit`` too. It is also suites such as ``unit`` can be ran with ``make check-unit`` too. It is also
possible to run tests defined in meson.build with ``meson test``. possible to run tests defined in meson.build with ``meson test``.
Useful make targets
-------------------
``help``
Print a help message for the most common build targets.
``print-VAR``
Print the value of the variable VAR. Useful for debugging the build
system.
Important files for the build system Important files for the build system
==================================== ====================================
@ -473,14 +483,3 @@ Built by Makefile:
meson.build. The rules are produced from Meson's JSON description of meson.build. The rules are produced from Meson's JSON description of
tests (obtained with "meson introspect --tests") through the script tests (obtained with "meson introspect --tests") through the script
scripts/mtest2make.py. scripts/mtest2make.py.
Useful make targets
-------------------
``help``
Print a help message for the most common build targets.
``print-VAR``
Print the value of the variable VAR. Useful for debugging the build
system.

View File

@ -8,6 +8,6 @@ found at::
https://wiki.qemu.org/Testing/CI https://wiki.qemu.org/Testing/CI
.. include:: ci-definitions.rst .. include:: ci-definitions.rst.inc
.. include:: ci-jobs.rst .. include:: ci-jobs.rst.inc
.. include:: ci-runners.rst .. include:: ci-runners.rst.inc

View File

@ -1,3 +1,8 @@
Multi-process QEMU
===================
.. note::
This is the design document for multi-process QEMU. It does not This is the design document for multi-process QEMU. It does not
necessarily reflect the status of the current implementation, which necessarily reflect the status of the current implementation, which
may lack features or be considerably different from what is described may lack features or be considerably different from what is described
@ -7,9 +12,6 @@ the goals and general direction of this feature.
Please refer to the following wiki for latest details: Please refer to the following wiki for latest details:
https://wiki.qemu.org/Features/MultiProcessQEMU https://wiki.qemu.org/Features/MultiProcessQEMU
Multi-process QEMU
===================
QEMU is often used as the hypervisor for virtual machines running in the QEMU is often used as the hypervisor for virtual machines running in the
Oracle cloud. Since one of the advantages of cloud computing is the Oracle cloud. Since one of the advantages of cloud computing is the
ability to run many VMs from different tenants in the same cloud ability to run many VMs from different tenants in the same cloud

View File

@ -1,8 +1,7 @@
.. _qgraph: .. _qgraph:
========================================
Qtest Driver Framework Qtest Driver Framework
======================================== ======================
In order to test a specific driver, plain libqos tests need to In order to test a specific driver, plain libqos tests need to
take care of booting QEMU with the right machine and devices. take care of booting QEMU with the right machine and devices.
@ -31,13 +30,15 @@ so the sdhci-test should only care of linking its qgraph node with
that interface. In this way, if the command line of a sdhci driver that interface. In this way, if the command line of a sdhci driver
is changed, only the respective qgraph driver node has to be adjusted. is changed, only the respective qgraph driver node has to be adjusted.
QGraph concepts
---------------
The graph is composed by nodes that represent machines, drivers, tests The graph is composed by nodes that represent machines, drivers, tests
and edges that define the relationships between them (``CONSUMES``, ``PRODUCES``, and and edges that define the relationships between them (``CONSUMES``, ``PRODUCES``, and
``CONTAINS``). ``CONTAINS``).
Nodes Nodes
^^^^^^ ~~~~~
A node can be of four types: A node can be of four types:
@ -64,7 +65,7 @@ Notes for the nodes:
drivers name, otherwise they won't be discovered drivers name, otherwise they won't be discovered
Edges Edges
^^^^^^ ~~~~~
An edge relation between two nodes (drivers or machines) ``X`` and ``Y`` can be: An edge relation between two nodes (drivers or machines) ``X`` and ``Y`` can be:
@ -73,7 +74,7 @@ An edge relation between two nodes (drivers or machines) ``X`` and ``Y`` can be:
- ``X CONTAINS Y``: ``Y`` is part of ``X`` component - ``X CONTAINS Y``: ``Y`` is part of ``X`` component
Execution steps Execution steps
^^^^^^^^^^^^^^^ ~~~~~~~~~~~~~~~
The basic framework steps are the following: The basic framework steps are the following:
@ -92,8 +93,64 @@ The basic framework steps are the following:
Depending on the QEMU binary used, only some drivers/machines will be Depending on the QEMU binary used, only some drivers/machines will be
available and only test that are reached by them will be executed. available and only test that are reached by them will be executed.
Command line
~~~~~~~~~~~~
Command line is built by using node names and optional arguments
passed by the user when building the edges.
There are three types of command line arguments:
- ``in node`` : created from the node name. For example, machines will
have ``-M <machine>`` to its command line, while devices
``-device <device>``. It is automatically done by the framework.
- ``after node`` : added as additional argument to the node name.
This argument is added optionally when creating edges,
by setting the parameter ``after_cmd_line`` and
``extra_edge_opts`` in ``QOSGraphEdgeOptions``.
The framework automatically adds
a comma before ``extra_edge_opts``,
because it is going to add attributes
after the destination node pointed by
the edge containing these options, and automatically
adds a space before ``after_cmd_line``, because it
adds an additional device, not an attribute.
- ``before node`` : added as additional argument to the node name.
This argument is added optionally when creating edges,
by setting the parameter ``before_cmd_line`` in
``QOSGraphEdgeOptions``. This attribute
is going to add attributes before the destination node
pointed by the edge containing these options. It is
helpful to commands that are not node-representable,
such as ``-fdsev`` or ``-netdev``.
While adding command line in edges is always used, not all nodes names are
used in every path walk: this is because the contained or produced ones
are already added by QEMU, so only nodes that "consumes" will be used to
build the command line. Also, nodes that will have ``{ "abstract" : true }``
as QMP attribute will loose their command line, since they are not proper
devices to be added in QEMU.
Example::
QOSGraphEdgeOptions opts = {
.before_cmd_line = "-drive id=drv0,if=none,file=null-co://,"
"file.read-zeroes=on,format=raw",
.after_cmd_line = "-device scsi-hd,bus=vs0.0,drive=drv0",
opts.extra_device_opts = "id=vs0";
};
qos_node_create_driver("virtio-scsi-device",
virtio_scsi_device_create);
qos_node_consumes("virtio-scsi-device", "virtio-bus", &opts);
Will produce the following command line:
``-drive id=drv0,if=none,file=null-co://, -device virtio-scsi-device,id=vs0 -device scsi-hd,bus=vs0.0,drive=drv0``
Troubleshooting unavailable tests Troubleshooting unavailable tests
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
If there is no path from an available machine to a test then that test will be If there is no path from an available machine to a test then that test will be
unavailable and won't execute. This can happen if a test or driver did not set unavailable and won't execute. This can happen if a test or driver did not set
up its qgraph node correctly. It can also happen if the necessary machine type up its qgraph node correctly. It can also happen if the necessary machine type
@ -151,7 +208,7 @@ Typically this is because the QEMU binary lacks support for the necessary
machine type or device. machine type or device.
Creating a new driver and its interface Creating a new driver and its interface
""""""""""""""""""""""""""""""""""""""""" ---------------------------------------
Here we continue the ``sdhci`` use case, with the following scenario: Here we continue the ``sdhci`` use case, with the following scenario:
@ -489,7 +546,7 @@ or inverting the consumes edge in consumed_by::
arm/raspi2b --contains--> generic-sdhci arm/raspi2b --contains--> generic-sdhci
Adding a new test Adding a new test
""""""""""""""""" -----------------
Given the above setup, adding a new test is very simple. Given the above setup, adding a new test is very simple.
``sdhci-test``, taken from ``tests/qtest/sdhci-test.c``:: ``sdhci-test``, taken from ``tests/qtest/sdhci-test.c``::
@ -565,62 +622,7 @@ and for the binary ``QTEST_QEMU_BINARY=./qemu-system-arm``:
Additional examples are also in ``test-qgraph.c`` Additional examples are also in ``test-qgraph.c``
Command line:
""""""""""""""
Command line is built by using node names and optional arguments
passed by the user when building the edges.
There are three types of command line arguments:
- ``in node`` : created from the node name. For example, machines will
have ``-M <machine>`` to its command line, while devices
``-device <device>``. It is automatically done by the framework.
- ``after node`` : added as additional argument to the node name.
This argument is added optionally when creating edges,
by setting the parameter ``after_cmd_line`` and
``extra_edge_opts`` in ``QOSGraphEdgeOptions``.
The framework automatically adds
a comma before ``extra_edge_opts``,
because it is going to add attributes
after the destination node pointed by
the edge containing these options, and automatically
adds a space before ``after_cmd_line``, because it
adds an additional device, not an attribute.
- ``before node`` : added as additional argument to the node name.
This argument is added optionally when creating edges,
by setting the parameter ``before_cmd_line`` in
``QOSGraphEdgeOptions``. This attribute
is going to add attributes before the destination node
pointed by the edge containing these options. It is
helpful to commands that are not node-representable,
such as ``-fdsev`` or ``-netdev``.
While adding command line in edges is always used, not all nodes names are
used in every path walk: this is because the contained or produced ones
are already added by QEMU, so only nodes that "consumes" will be used to
build the command line. Also, nodes that will have ``{ "abstract" : true }``
as QMP attribute will loose their command line, since they are not proper
devices to be added in QEMU.
Example::
QOSGraphEdgeOptions opts = {
.before_cmd_line = "-drive id=drv0,if=none,file=null-co://,"
"file.read-zeroes=on,format=raw",
.after_cmd_line = "-device scsi-hd,bus=vs0.0,drive=drv0",
opts.extra_device_opts = "id=vs0";
};
qos_node_create_driver("virtio-scsi-device",
virtio_scsi_device_create);
qos_node_consumes("virtio-scsi-device", "virtio-bus", &opts);
Will produce the following command line:
``-drive id=drv0,if=none,file=null-co://, -device virtio-scsi-device,id=vs0 -device scsi-hd,bus=vs0.0,drive=drv0``
Qgraph API reference Qgraph API reference
^^^^^^^^^^^^^^^^^^^^ --------------------
.. kernel-doc:: tests/qtest/libqos/qgraph.h .. kernel-doc:: tests/qtest/libqos/qgraph.h

View File

@ -3,7 +3,6 @@
Copyright (c) 2019, Linaro Limited Copyright (c) 2019, Linaro Limited
Written by Emilio Cota and Alex Bennée Written by Emilio Cota and Alex Bennée
================
QEMU TCG Plugins QEMU TCG Plugins
================ ================
@ -16,60 +15,8 @@ only monitor it passively. However they can do this down to an
individual instruction granularity including potentially subscribing individual instruction granularity including potentially subscribing
to all load and store operations. to all load and store operations.
API Stability
=============
This is a new feature for QEMU and it does allow people to develop
out-of-tree plugins that can be dynamically linked into a running QEMU
process. However the project reserves the right to change or break the
API should it need to do so. The best way to avoid this is to submit
your plugin upstream so they can be updated if/when the API changes.
API versioning
--------------
All plugins need to declare a symbol which exports the plugin API
version they were built against. This can be done simply by::
QEMU_PLUGIN_EXPORT int qemu_plugin_version = QEMU_PLUGIN_VERSION;
The core code will refuse to load a plugin that doesn't export a
``qemu_plugin_version`` symbol or if plugin version is outside of QEMU's
supported range of API versions.
Additionally the ``qemu_info_t`` structure which is passed to the
``qemu_plugin_install`` method of a plugin will detail the minimum and
current API versions supported by QEMU. The API version will be
incremented if new APIs are added. The minimum API version will be
incremented if existing APIs are changed or removed.
Exposure of QEMU internals
--------------------------
The plugin architecture actively avoids leaking implementation details
about how QEMU's translation works to the plugins. While there are
conceptions such as translation time and translation blocks the
details are opaque to plugins. The plugin is able to query select
details of instructions and system configuration only through the
exported *qemu_plugin* functions.
Query Handle Lifetime
---------------------
Each callback provides an opaque anonymous information handle which
can usually be further queried to find out information about a
translation, instruction or operation. The handles themselves are only
valid during the lifetime of the callback so it is important that any
information that is needed is extracted during the callback and saved
by the plugin.
API
===
.. kernel-doc:: include/qemu/qemu-plugin.h
Usage Usage
===== -----
Any QEMU binary with TCG support has plugins enabled by default. Any QEMU binary with TCG support has plugins enabled by default.
Earlier releases needed to be explicitly enabled with:: Earlier releases needed to be explicitly enabled with::
@ -87,8 +34,45 @@ Arguments are plugin specific and can be used to modify their
behaviour. In this case the howvec plugin is being asked to use inline behaviour. In this case the howvec plugin is being asked to use inline
ops to count and break down the hint instructions by type. ops to count and break down the hint instructions by type.
Plugin Life cycle Writing plugins
================= ---------------
API versioning
~~~~~~~~~~~~~~
This is a new feature for QEMU and it does allow people to develop
out-of-tree plugins that can be dynamically linked into a running QEMU
process. However the project reserves the right to change or break the
API should it need to do so. The best way to avoid this is to submit
your plugin upstream so they can be updated if/when the API changes.
All plugins need to declare a symbol which exports the plugin API
version they were built against. This can be done simply by::
QEMU_PLUGIN_EXPORT int qemu_plugin_version = QEMU_PLUGIN_VERSION;
The core code will refuse to load a plugin that doesn't export a
``qemu_plugin_version`` symbol or if plugin version is outside of QEMU's
supported range of API versions.
Additionally the ``qemu_info_t`` structure which is passed to the
``qemu_plugin_install`` method of a plugin will detail the minimum and
current API versions supported by QEMU. The API version will be
incremented if new APIs are added. The minimum API version will be
incremented if existing APIs are changed or removed.
Lifetime of the query handle
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Each callback provides an opaque anonymous information handle which
can usually be further queried to find out information about a
translation, instruction or operation. The handles themselves are only
valid during the lifetime of the callback so it is important that any
information that is needed is extracted during the callback and saved
by the plugin.
Plugin life cycle
~~~~~~~~~~~~~~~~~
First the plugin is loaded and the public qemu_plugin_install function First the plugin is loaded and the public qemu_plugin_install function
is called. The plugin will then register callbacks for various plugin is called. The plugin will then register callbacks for various plugin
@ -111,11 +95,26 @@ callback which can then ensure atomicity itself.
Finally when QEMU exits all the registered *atexit* callbacks are Finally when QEMU exits all the registered *atexit* callbacks are
invoked. invoked.
Exposure of QEMU internals
~~~~~~~~~~~~~~~~~~~~~~~~~~
The plugin architecture actively avoids leaking implementation details
about how QEMU's translation works to the plugins. While there are
conceptions such as translation time and translation blocks the
details are opaque to plugins. The plugin is able to query select
details of instructions and system configuration only through the
exported *qemu_plugin* functions.
API
~~~
.. kernel-doc:: include/qemu/qemu-plugin.h
Internals Internals
========= ---------
Locking Locking
------- ~~~~~~~
We have to ensure we cannot deadlock, particularly under MTTCG. For We have to ensure we cannot deadlock, particularly under MTTCG. For
this we acquire a lock when called from plugin code. We also keep the this we acquire a lock when called from plugin code. We also keep the
@ -142,7 +141,7 @@ requested. The plugin isn't completely uninstalled until the safe work
has executed while all vCPUs are quiescent. has executed while all vCPUs are quiescent.
Example Plugins Example Plugins
=============== ---------------
There are a number of plugins included with QEMU and you are There are a number of plugins included with QEMU and you are
encouraged to contribute your own plugins plugins upstream. There is a encouraged to contribute your own plugins plugins upstream. There is a

View File

@ -1,11 +1,10 @@
===============
Testing in QEMU Testing in QEMU
=============== ===============
This document describes the testing infrastructure in QEMU. This document describes the testing infrastructure in QEMU.
Testing with "make check" Testing with "make check"
========================= -------------------------
The "make check" testing family includes most of the C based tests in QEMU. For The "make check" testing family includes most of the C based tests in QEMU. For
a quick help, run ``make check-help`` from the source tree. a quick help, run ``make check-help`` from the source tree.
@ -24,7 +23,7 @@ expect the executables to exist and will fail with obscure messages if they
cannot find them. cannot find them.
Unit tests Unit tests
---------- ~~~~~~~~~~
Unit tests, which can be invoked with ``make check-unit``, are simple C tests Unit tests, which can be invoked with ``make check-unit``, are simple C tests
that typically link to individual QEMU object files and exercise them by that typically link to individual QEMU object files and exercise them by
@ -67,7 +66,7 @@ and copy the actual command line which executes the unit test, then run
it from the command line. it from the command line.
QTest QTest
----- ~~~~~
QTest is a device emulation testing framework. It can be very useful to test QTest is a device emulation testing framework. It can be very useful to test
device models; it could also control certain aspects of QEMU (such as virtual device models; it could also control certain aspects of QEMU (such as virtual
@ -81,7 +80,7 @@ QTest cases can be executed with
make check-qtest make check-qtest
QAPI schema tests QAPI schema tests
----------------- ~~~~~~~~~~~~~~~~~
The QAPI schema tests validate the QAPI parser used by QMP, by feeding The QAPI schema tests validate the QAPI parser used by QMP, by feeding
predefined input to the parser and comparing the result with the reference predefined input to the parser and comparing the result with the reference
@ -108,33 +107,14 @@ parser (either fixing a bug or extending/modifying the syntax). To do this:
``qapi-schema += foo.json`` ``qapi-schema += foo.json``
check-block check-block
----------- ~~~~~~~~~~~
``make check-block`` runs a subset of the block layer iotests (the tests that ``make check-block`` runs a subset of the block layer iotests (the tests that
are in the "auto" group). are in the "auto" group).
See the "QEMU iotests" section below for more information. See the "QEMU iotests" section below for more information.
GCC gcov support
----------------
``gcov`` is a GCC tool to analyze the testing coverage by
instrumenting the tested code. To use it, configure QEMU with
``--enable-gcov`` option and build. Then run ``make check`` as usual.
If you want to gather coverage information on a single test the ``make
clean-gcda`` target can be used to delete any existing coverage
information before running a single test.
You can generate a HTML coverage report by executing ``make
coverage-html`` which will create
``meson-logs/coveragereport/index.html``.
Further analysis can be conducted by running the ``gcov`` command
directly on the various .gcda output files. Please read the ``gcov``
documentation for more information.
QEMU iotests QEMU iotests
============ ------------
QEMU iotests, under the directory ``tests/qemu-iotests``, is the testing QEMU iotests, under the directory ``tests/qemu-iotests``, is the testing
framework widely used to test block layer related features. It is higher level framework widely used to test block layer related features. It is higher level
@ -171,7 +151,7 @@ More options are supported by the ``./check`` script, run ``./check -h`` for
help. help.
Writing a new test case Writing a new test case
----------------------- ~~~~~~~~~~~~~~~~~~~~~~~
Consider writing a tests case when you are making any changes to the block Consider writing a tests case when you are making any changes to the block
layer. An iotest case is usually the choice for that. There are already many layer. An iotest case is usually the choice for that. There are already many
@ -225,7 +205,8 @@ test failure. If using such devices are explicitly desired, consider adding
``locking=off`` option to disable image locking. ``locking=off`` option to disable image locking.
Debugging a test case Debugging a test case
----------------------- ~~~~~~~~~~~~~~~~~~~~~
The following options to the ``check`` script can be useful when debugging The following options to the ``check`` script can be useful when debugging
a failing test: a failing test:
@ -254,7 +235,7 @@ a failing test:
``$TEST_DIR/qemu-machine-<random_string>``. ``$TEST_DIR/qemu-machine-<random_string>``.
Test case groups Test case groups
---------------- ~~~~~~~~~~~~~~~~
"Tests may belong to one or more test groups, which are defined in the form "Tests may belong to one or more test groups, which are defined in the form
of a comment in the test source file. By convention, test groups are listed of a comment in the test source file. By convention, test groups are listed
@ -304,10 +285,10 @@ Note that the following group names have a special meaning:
.. _container-ref: .. _container-ref:
Container based tests Container based tests
===================== ---------------------
Introduction Introduction
------------ ~~~~~~~~~~~~
The container testing framework in QEMU utilizes public images to The container testing framework in QEMU utilizes public images to
build and test QEMU in predefined and widely accessible Linux build and test QEMU in predefined and widely accessible Linux
@ -322,7 +303,7 @@ The container images are also used to augment the generation of tests
for testing TCG. See :ref:`checktcg-ref` for more details. for testing TCG. See :ref:`checktcg-ref` for more details.
Docker Prerequisites Docker Prerequisites
-------------------- ~~~~~~~~~~~~~~~~~~~~
Install "docker" with the system package manager and start the Docker service Install "docker" with the system package manager and start the Docker service
on your development machine, then make sure you have the privilege to run on your development machine, then make sure you have the privilege to run
@ -353,7 +334,7 @@ exploit the whole host with Docker bind mounting or other privileged
operations. So only do it on development machines. operations. So only do it on development machines.
Podman Prerequisites Podman Prerequisites
-------------------- ~~~~~~~~~~~~~~~~~~~~
Install "podman" with the system package manager. Install "podman" with the system package manager.
@ -365,7 +346,7 @@ Install "podman" with the system package manager.
The last command should print an empty table, to verify the system is ready. The last command should print an empty table, to verify the system is ready.
Quickstart Quickstart
---------- ~~~~~~~~~~
From source tree, type ``make docker-help`` to see the help. Testing From source tree, type ``make docker-help`` to see the help. Testing
can be started without configuring or building QEMU (``configure`` and can be started without configuring or building QEMU (``configure`` and
@ -381,7 +362,7 @@ is downloaded and initialized automatically), in which the ``test-build`` job
is executed. is executed.
Registry Registry
-------- ~~~~~~~~
The QEMU project has a container registry hosted by GitLab at The QEMU project has a container registry hosted by GitLab at
``registry.gitlab.com/qemu-project/qemu`` which will automatically be ``registry.gitlab.com/qemu-project/qemu`` which will automatically be
@ -395,7 +376,7 @@ locally by using the ``NOCACHE`` build option:
make docker-image-debian10 NOCACHE=1 make docker-image-debian10 NOCACHE=1
Images Images
------ ~~~~~~
Along with many other images, the ``centos8`` image is defined in a Dockerfile Along with many other images, the ``centos8`` image is defined in a Dockerfile
in ``tests/docker/dockerfiles/``, called ``centos8.docker``. ``make docker-help`` in ``tests/docker/dockerfiles/``, called ``centos8.docker``. ``make docker-help``
@ -410,7 +391,7 @@ mainly used to do necessary host side setup. One such setup is ``binfmt_misc``,
for example, to make qemu-user powered cross build containers work. for example, to make qemu-user powered cross build containers work.
Tests Tests
----- ~~~~~
Different tests are added to cover various configurations to build and test Different tests are added to cover various configurations to build and test
QEMU. Docker tests are the executables under ``tests/docker`` named QEMU. Docker tests are the executables under ``tests/docker`` named
@ -421,7 +402,7 @@ source and build it.
The full list of tests is printed in the ``make docker-help`` help. The full list of tests is printed in the ``make docker-help`` help.
Debugging a Docker test failure Debugging a Docker test failure
------------------------------- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
When CI tasks, maintainers or yourself report a Docker test failure, follow the When CI tasks, maintainers or yourself report a Docker test failure, follow the
below steps to debug it: below steps to debug it:
@ -438,7 +419,7 @@ below steps to debug it:
the prompt for debug. the prompt for debug.
Options Options
------- ~~~~~~~
Various options can be used to affect how Docker tests are done. The full Various options can be used to affect how Docker tests are done. The full
list is in the ``make docker`` help text. The frequently used ones are: list is in the ``make docker`` help text. The frequently used ones are:
@ -452,7 +433,7 @@ list is in the ``make docker`` help text. The frequently used ones are:
failure" section. failure" section.
Thread Sanitizer Thread Sanitizer
================ ----------------
Thread Sanitizer (TSan) is a tool which can detect data races. QEMU supports Thread Sanitizer (TSan) is a tool which can detect data races. QEMU supports
building and testing with this tool. building and testing with this tool.
@ -462,7 +443,7 @@ For more information on TSan:
https://github.com/google/sanitizers/wiki/ThreadSanitizerCppManual https://github.com/google/sanitizers/wiki/ThreadSanitizerCppManual
Thread Sanitizer in Docker Thread Sanitizer in Docker
--------------------------- ~~~~~~~~~~~~~~~~~~~~~~~~~~
TSan is currently supported in the ubuntu2004 docker. TSan is currently supported in the ubuntu2004 docker.
The test-tsan test will build using TSan and then run make check. The test-tsan test will build using TSan and then run make check.
@ -477,7 +458,7 @@ We recommend using DEBUG=1 to allow launching the test from inside the docker,
and to allow review of the warnings generated by TSan. and to allow review of the warnings generated by TSan.
Building and Testing with TSan Building and Testing with TSan
------------------------------ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
It is possible to build and test with TSan, with a few additional steps. It is possible to build and test with TSan, with a few additional steps.
These steps are normally done automatically in the docker. These steps are normally done automatically in the docker.
@ -516,7 +497,7 @@ This allows for running the test and then checking the warnings afterwards.
If you want TSan to stop and exit with error on warnings, use exitcode=66. If you want TSan to stop and exit with error on warnings, use exitcode=66.
TSan Suppressions TSan Suppressions
----------------- ~~~~~~~~~~~~~~~~~
Keep in mind that for any data race warning, although there might be a data race Keep in mind that for any data race warning, although there might be a data race
detected by TSan, there might be no actual bug here. TSan provides several detected by TSan, there might be no actual bug here. TSan provides several
different mechanisms for suppressing warnings. In general it is recommended different mechanisms for suppressing warnings. In general it is recommended
@ -542,7 +523,7 @@ More information on the file format can be found here under "Blacklist Format":
https://github.com/google/sanitizers/wiki/ThreadSanitizerFlags https://github.com/google/sanitizers/wiki/ThreadSanitizerFlags
TSan Annotations TSan Annotations
---------------- ~~~~~~~~~~~~~~~~
include/qemu/tsan.h defines annotations. See this file for more descriptions include/qemu/tsan.h defines annotations. See this file for more descriptions
of the annotations themselves. Annotations can be used to suppress of the annotations themselves. Annotations can be used to suppress
TSan warnings or give TSan more information so that it can detect proper TSan warnings or give TSan more information so that it can detect proper
@ -559,14 +540,14 @@ The full set of annotations can be found here:
https://github.com/llvm/llvm-project/blob/master/compiler-rt/lib/tsan/rtl/tsan_interface_ann.cpp https://github.com/llvm/llvm-project/blob/master/compiler-rt/lib/tsan/rtl/tsan_interface_ann.cpp
VM testing VM testing
========== ----------
This test suite contains scripts that bootstrap various guest images that have This test suite contains scripts that bootstrap various guest images that have
necessary packages to build QEMU. The basic usage is documented in ``Makefile`` necessary packages to build QEMU. The basic usage is documented in ``Makefile``
help which is displayed with ``make vm-help``. help which is displayed with ``make vm-help``.
Quickstart Quickstart
---------- ~~~~~~~~~~
Run ``make vm-help`` to list available make targets. Invoke a specific make Run ``make vm-help`` to list available make targets. Invoke a specific make
command to run build test in an image. For example, ``make vm-build-freebsd`` command to run build test in an image. For example, ``make vm-build-freebsd``
@ -581,7 +562,7 @@ concerned about attackers taking control of the guest and potentially
exploiting a QEMU security bug to compromise the host. exploiting a QEMU security bug to compromise the host.
QEMU binaries QEMU binaries
------------- ~~~~~~~~~~~~~
By default, qemu-system-x86_64 is searched in $PATH to run the guest. If there By default, qemu-system-x86_64 is searched in $PATH to run the guest. If there
isn't one, or if it is older than 2.10, the test won't work. In this case, isn't one, or if it is older than 2.10, the test won't work. In this case,
@ -590,20 +571,20 @@ provide the QEMU binary in env var: ``QEMU=/path/to/qemu-2.10+``.
Likewise the path to qemu-img can be set in QEMU_IMG environment variable. Likewise the path to qemu-img can be set in QEMU_IMG environment variable.
Make jobs Make jobs
--------- ~~~~~~~~~
The ``-j$X`` option in the make command line is not propagated into the VM, The ``-j$X`` option in the make command line is not propagated into the VM,
specify ``J=$X`` to control the make jobs in the guest. specify ``J=$X`` to control the make jobs in the guest.
Debugging Debugging
--------- ~~~~~~~~~
Add ``DEBUG=1`` and/or ``V=1`` to the make command to allow interactive Add ``DEBUG=1`` and/or ``V=1`` to the make command to allow interactive
debugging and verbose output. If this is not enough, see the next section. debugging and verbose output. If this is not enough, see the next section.
``V=1`` will be propagated down into the make jobs in the guest. ``V=1`` will be propagated down into the make jobs in the guest.
Manual invocation Manual invocation
----------------- ~~~~~~~~~~~~~~~~~
Each guest script is an executable script with the same command line options. Each guest script is an executable script with the same command line options.
For example to work with the netbsd guest, use ``$QEMU_SRC/tests/vm/netbsd``: For example to work with the netbsd guest, use ``$QEMU_SRC/tests/vm/netbsd``:
@ -627,7 +608,7 @@ For example to work with the netbsd guest, use ``$QEMU_SRC/tests/vm/netbsd``:
$ ./netbsd --interactive --image /var/tmp/netbsd.img sh $ ./netbsd --interactive --image /var/tmp/netbsd.img sh
Adding new guests Adding new guests
----------------- ~~~~~~~~~~~~~~~~~
Please look at existing guest scripts for how to add new guests. Please look at existing guest scripts for how to add new guests.
@ -660,7 +641,7 @@ the script's ``main()``.
recommended. recommended.
Image fuzzer testing Image fuzzer testing
==================== --------------------
An image fuzzer was added to exercise format drivers. Currently only qcow2 is An image fuzzer was added to exercise format drivers. Currently only qcow2 is
supported. To start the fuzzer, run supported. To start the fuzzer, run
@ -673,7 +654,7 @@ Alternatively, some command different from "qemu-img info" can be tested, by
changing the ``-c`` option. changing the ``-c`` option.
Acceptance tests using the Avocado Framework Acceptance tests using the Avocado Framework
============================================ --------------------------------------------
The ``tests/acceptance`` directory hosts functional tests, also known The ``tests/acceptance`` directory hosts functional tests, also known
as acceptance level tests. They're usually higher level tests, and as acceptance level tests. They're usually higher level tests, and
@ -712,7 +693,7 @@ Tests based on ``avocado_qemu.Test`` can easily:
- http://avocado-framework.readthedocs.io/en/latest/api/utils/avocado.utils.html - http://avocado-framework.readthedocs.io/en/latest/api/utils/avocado.utils.html
Running tests Running tests
------------- ~~~~~~~~~~~~~
You can run the acceptance tests simply by executing: You can run the acceptance tests simply by executing:
@ -810,7 +791,7 @@ of Avocado or ``make check-acceptance``, and can also be queried using:
tests/venv/bin/avocado list tests/acceptance tests/venv/bin/avocado list tests/acceptance
Manual Installation Manual Installation
------------------- ~~~~~~~~~~~~~~~~~~~
To manually install Avocado and its dependencies, run: To manually install Avocado and its dependencies, run:
@ -823,7 +804,7 @@ Alternatively, follow the instructions on this link:
https://avocado-framework.readthedocs.io/en/latest/guides/user/chapters/installing.html https://avocado-framework.readthedocs.io/en/latest/guides/user/chapters/installing.html
Overview Overview
-------- ~~~~~~~~
The ``tests/acceptance/avocado_qemu`` directory provides the The ``tests/acceptance/avocado_qemu`` directory provides the
``avocado_qemu`` Python module, containing the ``avocado_qemu.Test`` ``avocado_qemu`` Python module, containing the ``avocado_qemu.Test``
@ -859,7 +840,7 @@ in the current directory, tagged as "quick", run:
avocado run -t quick . avocado run -t quick .
The ``avocado_qemu.Test`` base test class The ``avocado_qemu.Test`` base test class
----------------------------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
The ``avocado_qemu.Test`` class has a number of characteristics that The ``avocado_qemu.Test`` class has a number of characteristics that
are worth being mentioned right away. are worth being mentioned right away.
@ -909,7 +890,7 @@ At test "tear down", ``avocado_qemu.Test`` handles all the QEMUMachines
shutdown. shutdown.
The ``avocado_qemu.LinuxTest`` base test class The ``avocado_qemu.LinuxTest`` base test class
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
The ``avocado_qemu.LinuxTest`` is further specialization of the The ``avocado_qemu.LinuxTest`` is further specialization of the
``avocado_qemu.Test`` class, so it contains all the characteristics of ``avocado_qemu.Test`` class, so it contains all the characteristics of
@ -952,7 +933,7 @@ execution of a QEMU binary, giving its users:
a more succinct and intuitive way a more succinct and intuitive way
QEMU binary selection QEMU binary selection
~~~~~~~~~~~~~~~~~~~~~ ^^^^^^^^^^^^^^^^^^^^^
The QEMU binary used for the ``self.vm`` QEMUMachine instance will The QEMU binary used for the ``self.vm`` QEMUMachine instance will
primarily depend on the value of the ``qemu_bin`` parameter. If it's primarily depend on the value of the ``qemu_bin`` parameter. If it's
@ -973,20 +954,23 @@ The resulting ``qemu_bin`` value will be preserved in the
``avocado_qemu.Test`` as an attribute with the same name. ``avocado_qemu.Test`` as an attribute with the same name.
Attribute reference Attribute reference
------------------- ~~~~~~~~~~~~~~~~~~~
Test
^^^^
Besides the attributes and methods that are part of the base Besides the attributes and methods that are part of the base
``avocado.Test`` class, the following attributes are available on any ``avocado.Test`` class, the following attributes are available on any
``avocado_qemu.Test`` instance. ``avocado_qemu.Test`` instance.
vm vm
~~ ''
A QEMUMachine instance, initially configured according to the given A QEMUMachine instance, initially configured according to the given
``qemu_bin`` parameter. ``qemu_bin`` parameter.
arch arch
~~~~ ''''
The architecture can be used on different levels of the stack, e.g. by The architecture can be used on different levels of the stack, e.g. by
the framework or by the test itself. At the framework level, it will the framework or by the test itself. At the framework level, it will
@ -1003,7 +987,7 @@ name. If one is not given explicitly, it will either be set to
``:avocado: tags=arch:VALUE`` tag, it will be set to ``VALUE``. ``:avocado: tags=arch:VALUE`` tag, it will be set to ``VALUE``.
cpu cpu
~~~ '''
The cpu model that will be set to all QEMUMachine instances created The cpu model that will be set to all QEMUMachine instances created
by the test. by the test.
@ -1014,7 +998,7 @@ name. If one is not given explicitly, it will either be set to
``:avocado: tags=cpu:VALUE`` tag, it will be set to ``VALUE``. ``:avocado: tags=cpu:VALUE`` tag, it will be set to ``VALUE``.
machine machine
~~~~~~~ '''''''
The machine type that will be set to all QEMUMachine instances created The machine type that will be set to all QEMUMachine instances created
by the test. by the test.
@ -1025,20 +1009,20 @@ name. If one is not given explicitly, it will either be set to
``:avocado: tags=machine:VALUE`` tag, it will be set to ``VALUE``. ``:avocado: tags=machine:VALUE`` tag, it will be set to ``VALUE``.
qemu_bin qemu_bin
~~~~~~~~ ''''''''
The preserved value of the ``qemu_bin`` parameter or the result of the The preserved value of the ``qemu_bin`` parameter or the result of the
dynamic probe for a QEMU binary in the current working directory or dynamic probe for a QEMU binary in the current working directory or
source tree. source tree.
LinuxTest LinuxTest
~~~~~~~~~ ^^^^^^^^^
Besides the attributes present on the ``avocado_qemu.Test`` base Besides the attributes present on the ``avocado_qemu.Test`` base
class, the ``avocado_qemu.LinuxTest`` adds the following attributes: class, the ``avocado_qemu.LinuxTest`` adds the following attributes:
distro distro
...... ''''''
The name of the Linux distribution used as the guest image for the The name of the Linux distribution used as the guest image for the
test. The name should match the **Provider** column on the list test. The name should match the **Provider** column on the list
@ -1047,7 +1031,7 @@ of images supported by the avocado.utils.vmimage library:
https://avocado-framework.readthedocs.io/en/latest/guides/writer/libs/vmimage.html#supported-images https://avocado-framework.readthedocs.io/en/latest/guides/writer/libs/vmimage.html#supported-images
distro_version distro_version
.............. ''''''''''''''
The version of the Linux distribution as the guest image for the The version of the Linux distribution as the guest image for the
test. The name should match the **Version** column on the list test. The name should match the **Version** column on the list
@ -1056,7 +1040,7 @@ of images supported by the avocado.utils.vmimage library:
https://avocado-framework.readthedocs.io/en/latest/guides/writer/libs/vmimage.html#supported-images https://avocado-framework.readthedocs.io/en/latest/guides/writer/libs/vmimage.html#supported-images
distro_checksum distro_checksum
............... '''''''''''''''
The sha256 hash of the guest image file used for the test. The sha256 hash of the guest image file used for the test.
@ -1065,7 +1049,7 @@ same name), no validation on the integrity of the image will be
performed. performed.
Parameter reference Parameter reference
------------------- ~~~~~~~~~~~~~~~~~~~
To understand how Avocado parameters are accessed by tests, and how To understand how Avocado parameters are accessed by tests, and how
they can be passed to tests, please refer to:: they can be passed to tests, please refer to::
@ -1079,8 +1063,11 @@ like the following:
PARAMS (key=qemu_bin, path=*, default=./qemu-system-x86_64) => './qemu-system-x86_64 PARAMS (key=qemu_bin, path=*, default=./qemu-system-x86_64) => './qemu-system-x86_64
Test
^^^^
arch arch
~~~~ ''''
The architecture that will influence the selection of a QEMU binary The architecture that will influence the selection of a QEMU binary
(when one is not explicitly given). (when one is not explicitly given).
@ -1093,31 +1080,30 @@ This parameter has a direct relation with the ``arch`` attribute. If
not given, it will default to None. not given, it will default to None.
cpu cpu
~~~ '''
The cpu model that will be set to all QEMUMachine instances created The cpu model that will be set to all QEMUMachine instances created
by the test. by the test.
machine machine
~~~~~~~ '''''''
The machine type that will be set to all QEMUMachine instances created The machine type that will be set to all QEMUMachine instances created
by the test. by the test.
qemu_bin qemu_bin
~~~~~~~~ ''''''''
The exact QEMU binary to be used on QEMUMachine. The exact QEMU binary to be used on QEMUMachine.
LinuxTest LinuxTest
~~~~~~~~~ ^^^^^^^^^
Besides the parameters present on the ``avocado_qemu.Test`` base Besides the parameters present on the ``avocado_qemu.Test`` base
class, the ``avocado_qemu.LinuxTest`` adds the following parameters: class, the ``avocado_qemu.LinuxTest`` adds the following parameters:
distro distro
...... ''''''
The name of the Linux distribution used as the guest image for the The name of the Linux distribution used as the guest image for the
test. The name should match the **Provider** column on the list test. The name should match the **Provider** column on the list
@ -1126,7 +1112,7 @@ of images supported by the avocado.utils.vmimage library:
https://avocado-framework.readthedocs.io/en/latest/guides/writer/libs/vmimage.html#supported-images https://avocado-framework.readthedocs.io/en/latest/guides/writer/libs/vmimage.html#supported-images
distro_version distro_version
.............. ''''''''''''''
The version of the Linux distribution as the guest image for the The version of the Linux distribution as the guest image for the
test. The name should match the **Version** column on the list test. The name should match the **Version** column on the list
@ -1135,7 +1121,7 @@ of images supported by the avocado.utils.vmimage library:
https://avocado-framework.readthedocs.io/en/latest/guides/writer/libs/vmimage.html#supported-images https://avocado-framework.readthedocs.io/en/latest/guides/writer/libs/vmimage.html#supported-images
distro_checksum distro_checksum
............... '''''''''''''''
The sha256 hash of the guest image file used for the test. The sha256 hash of the guest image file used for the test.
@ -1143,7 +1129,8 @@ If this value is not set in the code or by this parameter no
validation on the integrity of the image will be performed. validation on the integrity of the image will be performed.
Skipping tests Skipping tests
-------------- ~~~~~~~~~~~~~~
The Avocado framework provides Python decorators which allow for easily skip The Avocado framework provides Python decorators which allow for easily skip
tests running under certain conditions. For example, on the lack of a binary tests running under certain conditions. For example, on the lack of a binary
on the test system or when the running environment is a CI system. For further on the test system or when the running environment is a CI system. For further
@ -1158,7 +1145,7 @@ environment variables became a kind of standard way to enable/disable tests.
Here is a list of the most used variables: Here is a list of the most used variables:
AVOCADO_ALLOW_LARGE_STORAGE AVOCADO_ALLOW_LARGE_STORAGE
~~~~~~~~~~~~~~~~~~~~~~~~~~~ ^^^^^^^^^^^^^^^^^^^^^^^^^^^
Tests which are going to fetch or produce assets considered *large* are not Tests which are going to fetch or produce assets considered *large* are not
going to run unless that ``AVOCADO_ALLOW_LARGE_STORAGE=1`` is exported on going to run unless that ``AVOCADO_ALLOW_LARGE_STORAGE=1`` is exported on
the environment. the environment.
@ -1167,7 +1154,7 @@ The definition of *large* is a bit arbitrary here, but it usually means an
asset which occupies at least 1GB of size on disk when uncompressed. asset which occupies at least 1GB of size on disk when uncompressed.
AVOCADO_ALLOW_UNTRUSTED_CODE AVOCADO_ALLOW_UNTRUSTED_CODE
~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
There are tests which will boot a kernel image or firmware that can be There are tests which will boot a kernel image or firmware that can be
considered not safe to run on the developer's workstation, thus they are considered not safe to run on the developer's workstation, thus they are
skipped by default. The definition of *not safe* is also arbitrary but skipped by default. The definition of *not safe* is also arbitrary but
@ -1178,7 +1165,7 @@ You should export ``AVOCADO_ALLOW_UNTRUSTED_CODE=1`` on the environment in
order to allow tests which make use of those kind of assets. order to allow tests which make use of those kind of assets.
AVOCADO_TIMEOUT_EXPECTED AVOCADO_TIMEOUT_EXPECTED
~~~~~~~~~~~~~~~~~~~~~~~~ ^^^^^^^^^^^^^^^^^^^^^^^^
The Avocado framework has a timeout mechanism which interrupts tests to avoid the The Avocado framework has a timeout mechanism which interrupts tests to avoid the
test suite of getting stuck. The timeout value can be set via test parameter or test suite of getting stuck. The timeout value can be set via test parameter or
property defined in the test class, for further details:: property defined in the test class, for further details::
@ -1192,7 +1179,7 @@ compiled with debug flags. Therefore, the ``AVOCADO_TIMEOUT_EXPECTED`` variable
has been used to determine whether those tests should run or not. has been used to determine whether those tests should run or not.
GITLAB_CI GITLAB_CI
~~~~~~~~~ ^^^^^^^^^
A number of tests are flagged to not run on the GitLab CI. Usually because A number of tests are flagged to not run on the GitLab CI. Usually because
they proved to the flaky or there are constraints on the CI environment which they proved to the flaky or there are constraints on the CI environment which
would make them fail. If you encounter a similar situation then use that would make them fail. If you encounter a similar situation then use that
@ -1205,7 +1192,7 @@ variable as shown on the code snippet below to skip the test:
do_something() do_something()
Uninstalling Avocado Uninstalling Avocado
-------------------- ~~~~~~~~~~~~~~~~~~~~
If you've followed the manual installation instructions above, you can If you've followed the manual installation instructions above, you can
easily uninstall Avocado. Start by listing the packages you have easily uninstall Avocado. Start by listing the packages you have
@ -1223,7 +1210,7 @@ Avocado is installed will be cleaned up as part of ``make check-clean``.
.. _checktcg-ref: .. _checktcg-ref:
Testing with "make check-tcg" Testing with "make check-tcg"
============================= -----------------------------
The check-tcg tests are intended for simple smoke tests of both The check-tcg tests are intended for simple smoke tests of both
linux-user and softmmu TCG functionality. However to build test linux-user and softmmu TCG functionality. However to build test
@ -1256,7 +1243,7 @@ itself.
See :ref:`container-ref` for more details. See :ref:`container-ref` for more details.
Running subset of tests Running subset of tests
----------------------- ~~~~~~~~~~~~~~~~~~~~~~~
You can build the tests for one architecture:: You can build the tests for one architecture::
@ -1270,7 +1257,7 @@ Adding ``V=1`` to the invocation will show the details of how to
invoke QEMU for the test which is useful for debugging tests. invoke QEMU for the test which is useful for debugging tests.
TCG test dependencies TCG test dependencies
--------------------- ~~~~~~~~~~~~~~~~~~~~~
The TCG tests are deliberately very light on dependencies and are The TCG tests are deliberately very light on dependencies and are
either totally bare with minimal gcc lib support (for softmmu tests) either totally bare with minimal gcc lib support (for softmmu tests)
@ -1302,3 +1289,22 @@ exercise as many corner cases as possible. It is a useful test suite
to run to exercise QEMU's linux-user code:: to run to exercise QEMU's linux-user code::
https://linux-test-project.github.io/ https://linux-test-project.github.io/
GCC gcov support
----------------
``gcov`` is a GCC tool to analyze the testing coverage by
instrumenting the tested code. To use it, configure QEMU with
``--enable-gcov`` option and build. Then run the tests as usual.
If you want to gather coverage information on a single test the ``make
clean-gcda`` target can be used to delete any existing coverage
information before running a single test.
You can generate a HTML coverage report by executing ``make
coverage-html`` which will create
``meson-logs/coveragereport/index.html``.
Further analysis can be conducted by running the ``gcov`` command
directly on the various .gcda output files. Please read the ``gcov``
documentation for more information.

View File

@ -189,7 +189,15 @@ enabled.
Requires: hv-vpindex, hv-synic, hv-time, hv-stimer Requires: hv-vpindex, hv-synic, hv-time, hv-stimer
3.17. hv-no-nonarch-coresharing=on/off/auto 3.18. hv-avic (hv-apicv)
=======================
The enlightenment allows to use Hyper-V SynIC with hardware APICv/AVIC enabled.
Normally, Hyper-V SynIC disables these hardware feature and suggests the guest
to use paravirtualized AutoEOI feature.
Note: enabling this feature on old hardware (without APICv/AVIC support) may
have negative effect on guest's performace.
3.19. hv-no-nonarch-coresharing=on/off/auto
=========================================== ===========================================
This enlightenment tells guest OS that virtual processors will never share a This enlightenment tells guest OS that virtual processors will never share a
physical core unless they are reported as sibling SMT threads. This information physical core unless they are reported as sibling SMT threads. This information
@ -203,8 +211,25 @@ When the option is set to 'on' QEMU will always enable the feature, regardless
of host setup. To keep guests secure, this can only be used in conjunction with of host setup. To keep guests secure, this can only be used in conjunction with
exposing correct vCPU topology and vCPU pinning. exposing correct vCPU topology and vCPU pinning.
4. Development features 3.20. hv-version-id-{build,major,minor,spack,sbranch,snumber}
======================== =============================================================
This changes Hyper-V version identification in CPUID 0x40000002.EAX-EDX from the
default (WS2016).
- hv-version-id-build sets 'Build Number' (32 bits)
- hv-version-id-major sets 'Major Version' (16 bits)
- hv-version-id-minor sets 'Minor Version' (16 bits)
- hv-version-id-spack sets 'Service Pack' (32 bits)
- hv-version-id-sbranch sets 'Service Branch' (8 bits)
- hv-version-id-snumber sets 'Service Number' (24 bits)
Note: hv-version-id-* are not enlightenments and thus don't enable Hyper-V
identification when specified without any other enlightenments.
4. Supplementary features
=========================
4.1. hv-passthrough
===================
In some cases (e.g. during development) it may make sense to use QEMU in In some cases (e.g. during development) it may make sense to use QEMU in
'pass-through' mode and give Windows guests all enlightenments currently 'pass-through' mode and give Windows guests all enlightenments currently
supported by KVM. This pass-through mode is enabled by "hv-passthrough" CPU supported by KVM. This pass-through mode is enabled by "hv-passthrough" CPU
@ -215,8 +240,16 @@ values from KVM to QEMU. "hv-passthrough" overrides all other "hv-*" settings on
the command line. Also, enabling this flag effectively prevents migration as the the command line. Also, enabling this flag effectively prevents migration as the
list of enabled enlightenments may differ between target and destination hosts. list of enabled enlightenments may differ between target and destination hosts.
4.2. hv-enforce-cpuid
=====================
By default, KVM allows the guest to use all currently supported Hyper-V
enlightenments when Hyper-V CPUID interface was exposed, regardless of if
some features were not announced in guest visible CPUIDs. 'hv-enforce-cpuid'
feature alters this behavior and only allows the guest to use exposed Hyper-V
enlightenments.
4. Useful links
5. Useful links
================ ================
Hyper-V Top Level Functional specification and other information: Hyper-V Top Level Functional specification and other information:
https://github.com/MicrosoftDocs/Virtualization-Documentation https://github.com/MicrosoftDocs/Virtualization-Documentation

View File

@ -2815,6 +2815,7 @@ static void virt_machine_6_1_options(MachineClass *mc)
virt_machine_6_2_options(mc); virt_machine_6_2_options(mc);
compat_props_add(mc->compat_props, hw_compat_6_1, hw_compat_6_1_len); compat_props_add(mc->compat_props, hw_compat_6_1, hw_compat_6_1_len);
mc->smp_props.prefer_sockets = true;
/* qemu ITS was introduced with 6.2 */ /* qemu ITS was introduced with 6.2 */
vmc->no_tcg_its = true; vmc->no_tcg_its = true;

View File

@ -746,64 +746,163 @@ void machine_set_cpu_numa_node(MachineState *machine,
} }
} }
/*
* Report information of a machine's supported CPU topology hierarchy.
* Topology members will be ordered from the largest to the smallest
* in the string.
*/
static char *cpu_hierarchy_to_string(MachineState *ms)
{
MachineClass *mc = MACHINE_GET_CLASS(ms);
GString *s = g_string_new(NULL);
g_string_append_printf(s, "sockets (%u)", ms->smp.sockets);
if (mc->smp_props.dies_supported) {
g_string_append_printf(s, " * dies (%u)", ms->smp.dies);
}
g_string_append_printf(s, " * cores (%u)", ms->smp.cores);
g_string_append_printf(s, " * threads (%u)", ms->smp.threads);
return g_string_free(s, false);
}
/*
* smp_parse - Generic function used to parse the given SMP configuration
*
* Any missing parameter in "cpus/maxcpus/sockets/cores/threads" will be
* automatically computed based on the provided ones.
*
* In the calculation of omitted sockets/cores/threads: we prefer sockets
* over cores over threads before 6.2, while preferring cores over sockets
* over threads since 6.2.
*
* In the calculation of cpus/maxcpus: When both maxcpus and cpus are omitted,
* maxcpus will be computed from the given parameters and cpus will be set
* equal to maxcpus. When only one of maxcpus and cpus is given then the
* omitted one will be set to its given counterpart's value. Both maxcpus and
* cpus may be specified, but maxcpus must be equal to or greater than cpus.
*
* For compatibility, apart from the parameters that will be computed, newly
* introduced topology members which are likely to be target specific should
* be directly set as 1 if they are omitted (e.g. dies for PC since 4.1).
*/
static void smp_parse(MachineState *ms, SMPConfiguration *config, Error **errp) static void smp_parse(MachineState *ms, SMPConfiguration *config, Error **errp)
{ {
MachineClass *mc = MACHINE_GET_CLASS(ms);
unsigned cpus = config->has_cpus ? config->cpus : 0; unsigned cpus = config->has_cpus ? config->cpus : 0;
unsigned sockets = config->has_sockets ? config->sockets : 0; unsigned sockets = config->has_sockets ? config->sockets : 0;
unsigned dies = config->has_dies ? config->dies : 0;
unsigned cores = config->has_cores ? config->cores : 0; unsigned cores = config->has_cores ? config->cores : 0;
unsigned threads = config->has_threads ? config->threads : 0; unsigned threads = config->has_threads ? config->threads : 0;
unsigned maxcpus = config->has_maxcpus ? config->maxcpus : 0;
if (config->has_dies && config->dies != 0 && config->dies != 1) { /*
* Specified CPU topology parameters must be greater than zero,
* explicit configuration like "cpus=0" is not allowed.
*/
if ((config->has_cpus && config->cpus == 0) ||
(config->has_sockets && config->sockets == 0) ||
(config->has_dies && config->dies == 0) ||
(config->has_cores && config->cores == 0) ||
(config->has_threads && config->threads == 0) ||
(config->has_maxcpus && config->maxcpus == 0)) {
warn_report("Deprecated CPU topology (considered invalid): "
"CPU topology parameters must be greater than zero");
}
/*
* If not supported by the machine, a topology parameter must be
* omitted or specified equal to 1.
*/
if (!mc->smp_props.dies_supported && dies > 1) {
error_setg(errp, "dies not supported by this machine's CPU topology"); error_setg(errp, "dies not supported by this machine's CPU topology");
return; return;
} }
/* compute missing values, prefer sockets over cores over threads */ dies = dies > 0 ? dies : 1;
if (cpus == 0 || sockets == 0) {
/* compute missing values based on the provided ones */
if (cpus == 0 && maxcpus == 0) {
sockets = sockets > 0 ? sockets : 1;
cores = cores > 0 ? cores : 1; cores = cores > 0 ? cores : 1;
threads = threads > 0 ? threads : 1; threads = threads > 0 ? threads : 1;
if (cpus == 0) {
sockets = sockets > 0 ? sockets : 1;
cpus = cores * threads * sockets;
} else { } else {
ms->smp.max_cpus = config->has_maxcpus ? config->maxcpus : cpus; maxcpus = maxcpus > 0 ? maxcpus : cpus;
sockets = ms->smp.max_cpus / (cores * threads);
} if (mc->smp_props.prefer_sockets) {
/* prefer sockets over cores before 6.2 */
if (sockets == 0) {
cores = cores > 0 ? cores : 1;
threads = threads > 0 ? threads : 1;
sockets = maxcpus / (dies * cores * threads);
} else if (cores == 0) { } else if (cores == 0) {
threads = threads > 0 ? threads : 1; threads = threads > 0 ? threads : 1;
cores = cpus / (sockets * threads); cores = maxcpus / (sockets * dies * threads);
cores = cores > 0 ? cores : 1; }
} else if (threads == 0) { } else {
threads = cpus / (cores * sockets); /* prefer cores over sockets since 6.2 */
if (cores == 0) {
sockets = sockets > 0 ? sockets : 1;
threads = threads > 0 ? threads : 1; threads = threads > 0 ? threads : 1;
} else if (sockets * cores * threads < cpus) { cores = maxcpus / (sockets * dies * threads);
error_setg(errp, "cpu topology: " } else if (sockets == 0) {
"sockets (%u) * cores (%u) * threads (%u) < " threads = threads > 0 ? threads : 1;
"smp_cpus (%u)", sockets = maxcpus / (dies * cores * threads);
sockets, cores, threads, cpus); }
return;
} }
ms->smp.max_cpus = config->has_maxcpus ? config->maxcpus : cpus; /* try to calculate omitted threads at last */
if (threads == 0) {
if (ms->smp.max_cpus < cpus) { threads = maxcpus / (sockets * dies * cores);
error_setg(errp, "maxcpus must be equal to or greater than smp"); }
return;
} }
if (sockets * cores * threads != ms->smp.max_cpus) { maxcpus = maxcpus > 0 ? maxcpus : sockets * dies * cores * threads;
error_setg(errp, "Invalid CPU topology: " cpus = cpus > 0 ? cpus : maxcpus;
"sockets (%u) * cores (%u) * threads (%u) "
"!= maxcpus (%u)",
sockets, cores, threads,
ms->smp.max_cpus);
return;
}
ms->smp.cpus = cpus; ms->smp.cpus = cpus;
ms->smp.sockets = sockets;
ms->smp.dies = dies;
ms->smp.cores = cores; ms->smp.cores = cores;
ms->smp.threads = threads; ms->smp.threads = threads;
ms->smp.sockets = sockets; ms->smp.max_cpus = maxcpus;
/* sanity-check of the computed topology */
if (sockets * dies * cores * threads != maxcpus) {
g_autofree char *topo_msg = cpu_hierarchy_to_string(ms);
error_setg(errp, "Invalid CPU topology: "
"product of the hierarchy must match maxcpus: "
"%s != maxcpus (%u)",
topo_msg, maxcpus);
return;
}
if (maxcpus < cpus) {
g_autofree char *topo_msg = cpu_hierarchy_to_string(ms);
error_setg(errp, "Invalid CPU topology: "
"maxcpus must be equal to or greater than smp: "
"%s == maxcpus (%u) < smp_cpus (%u)",
topo_msg, maxcpus, cpus);
return;
}
if (ms->smp.cpus < mc->min_cpus) {
error_setg(errp, "Invalid SMP CPUs %d. The min CPUs "
"supported by machine '%s' is %d",
ms->smp.cpus,
mc->name, mc->min_cpus);
return;
}
if (ms->smp.max_cpus > mc->max_cpus) {
error_setg(errp, "Invalid SMP CPUs %d. The max CPUs "
"supported by machine '%s' is %d",
ms->smp.max_cpus,
mc->name, mc->max_cpus);
return;
}
} }
static void machine_get_smp(Object *obj, Visitor *v, const char *name, static void machine_get_smp(Object *obj, Visitor *v, const char *name,
@ -811,11 +910,11 @@ static void machine_get_smp(Object *obj, Visitor *v, const char *name,
{ {
MachineState *ms = MACHINE(obj); MachineState *ms = MACHINE(obj);
SMPConfiguration *config = &(SMPConfiguration){ SMPConfiguration *config = &(SMPConfiguration){
.has_cores = true, .cores = ms->smp.cores, .has_cpus = true, .cpus = ms->smp.cpus,
.has_sockets = true, .sockets = ms->smp.sockets, .has_sockets = true, .sockets = ms->smp.sockets,
.has_dies = true, .dies = ms->smp.dies, .has_dies = true, .dies = ms->smp.dies,
.has_cores = true, .cores = ms->smp.cores,
.has_threads = true, .threads = ms->smp.threads, .has_threads = true, .threads = ms->smp.threads,
.has_cpus = true, .cpus = ms->smp.cpus,
.has_maxcpus = true, .maxcpus = ms->smp.max_cpus, .has_maxcpus = true, .maxcpus = ms->smp.max_cpus,
}; };
if (!visit_type_SMPConfiguration(v, name, &config, &error_abort)) { if (!visit_type_SMPConfiguration(v, name, &config, &error_abort)) {
@ -826,35 +925,14 @@ static void machine_get_smp(Object *obj, Visitor *v, const char *name,
static void machine_set_smp(Object *obj, Visitor *v, const char *name, static void machine_set_smp(Object *obj, Visitor *v, const char *name,
void *opaque, Error **errp) void *opaque, Error **errp)
{ {
MachineClass *mc = MACHINE_GET_CLASS(obj);
MachineState *ms = MACHINE(obj); MachineState *ms = MACHINE(obj);
SMPConfiguration *config; g_autoptr(SMPConfiguration) config = NULL;
ERRP_GUARD();
if (!visit_type_SMPConfiguration(v, name, &config, errp)) { if (!visit_type_SMPConfiguration(v, name, &config, errp)) {
return; return;
} }
mc->smp_parse(ms, config, errp); smp_parse(ms, config, errp);
if (*errp) {
goto out_free;
}
/* sanity-check smp_cpus and max_cpus against mc */
if (ms->smp.cpus < mc->min_cpus) {
error_setg(errp, "Invalid SMP CPUs %d. The min CPUs "
"supported by machine '%s' is %d",
ms->smp.cpus,
mc->name, mc->min_cpus);
} else if (ms->smp.max_cpus > mc->max_cpus) {
error_setg(errp, "Invalid SMP CPUs %d. The max CPUs "
"supported by machine '%s' is %d",
current_machine->smp.max_cpus,
mc->name, mc->max_cpus);
}
out_free:
qapi_free_SMPConfiguration(config);
} }
static void machine_class_init(ObjectClass *oc, void *data) static void machine_class_init(ObjectClass *oc, void *data)
@ -864,7 +942,6 @@ static void machine_class_init(ObjectClass *oc, void *data)
/* Default 128 MB as guest ram size */ /* Default 128 MB as guest ram size */
mc->default_ram_size = 128 * MiB; mc->default_ram_size = 128 * MiB;
mc->rom_file_has_mr = true; mc->rom_file_has_mr = true;
mc->smp_parse = smp_parse;
/* numa node memory size aligned on 8MB by default. /* numa node memory size aligned on 8MB by default.
* On Linux, each node's border has to be 8MB aligned * On Linux, each node's border has to be 8MB aligned
@ -1028,10 +1105,10 @@ static void machine_initfn(Object *obj)
/* default to mc->default_cpus */ /* default to mc->default_cpus */
ms->smp.cpus = mc->default_cpus; ms->smp.cpus = mc->default_cpus;
ms->smp.max_cpus = mc->default_cpus; ms->smp.max_cpus = mc->default_cpus;
ms->smp.cores = 1;
ms->smp.dies = 1;
ms->smp.threads = 1;
ms->smp.sockets = 1; ms->smp.sockets = 1;
ms->smp.dies = 1;
ms->smp.cores = 1;
ms->smp.threads = 1;
} }
static void machine_finalize(Object *obj) static void machine_finalize(Object *obj)

View File

@ -93,7 +93,11 @@
#include "trace.h" #include "trace.h"
#include CONFIG_DEVICES #include CONFIG_DEVICES
GlobalProperty pc_compat_6_1[] = {}; GlobalProperty pc_compat_6_1[] = {
{ TYPE_X86_CPU, "hv-version-id-build", "0x1bbc" },
{ TYPE_X86_CPU, "hv-version-id-major", "0x0006" },
{ TYPE_X86_CPU, "hv-version-id-minor", "0x0001" },
};
const size_t pc_compat_6_1_len = G_N_ELEMENTS(pc_compat_6_1); const size_t pc_compat_6_1_len = G_N_ELEMENTS(pc_compat_6_1);
GlobalProperty pc_compat_6_0[] = { GlobalProperty pc_compat_6_0[] = {
@ -710,67 +714,6 @@ void pc_acpi_smi_interrupt(void *opaque, int irq, int level)
} }
} }
/*
* This function is very similar to smp_parse()
* in hw/core/machine.c but includes CPU die support.
*/
static void pc_smp_parse(MachineState *ms, SMPConfiguration *config, Error **errp)
{
unsigned cpus = config->has_cpus ? config->cpus : 0;
unsigned sockets = config->has_sockets ? config->sockets : 0;
unsigned dies = config->has_dies ? config->dies : 1;
unsigned cores = config->has_cores ? config->cores : 0;
unsigned threads = config->has_threads ? config->threads : 0;
/* compute missing values, prefer sockets over cores over threads */
if (cpus == 0 || sockets == 0) {
cores = cores > 0 ? cores : 1;
threads = threads > 0 ? threads : 1;
if (cpus == 0) {
sockets = sockets > 0 ? sockets : 1;
cpus = cores * threads * dies * sockets;
} else {
ms->smp.max_cpus = config->has_maxcpus ? config->maxcpus : cpus;
sockets = ms->smp.max_cpus / (cores * threads * dies);
}
} else if (cores == 0) {
threads = threads > 0 ? threads : 1;
cores = cpus / (sockets * dies * threads);
cores = cores > 0 ? cores : 1;
} else if (threads == 0) {
threads = cpus / (cores * dies * sockets);
threads = threads > 0 ? threads : 1;
} else if (sockets * dies * cores * threads < cpus) {
error_setg(errp, "cpu topology: "
"sockets (%u) * dies (%u) * cores (%u) * threads (%u) < "
"smp_cpus (%u)",
sockets, dies, cores, threads, cpus);
return;
}
ms->smp.max_cpus = config->has_maxcpus ? config->maxcpus : cpus;
if (ms->smp.max_cpus < cpus) {
error_setg(errp, "maxcpus must be equal to or greater than smp");
return;
}
if (sockets * dies * cores * threads != ms->smp.max_cpus) {
error_setg(errp, "Invalid CPU topology deprecated: "
"sockets (%u) * dies (%u) * cores (%u) * threads (%u) "
"!= maxcpus (%u)",
sockets, dies, cores, threads,
ms->smp.max_cpus);
return;
}
ms->smp.cpus = cpus;
ms->smp.cores = cores;
ms->smp.threads = threads;
ms->smp.sockets = sockets;
ms->smp.dies = dies;
}
static static
void pc_machine_done(Notifier *notifier, void *data) void pc_machine_done(Notifier *notifier, void *data)
{ {
@ -1734,7 +1677,6 @@ static void pc_machine_class_init(ObjectClass *oc, void *data)
mc->auto_enable_numa_with_memdev = true; mc->auto_enable_numa_with_memdev = true;
mc->has_hotpluggable_cpus = true; mc->has_hotpluggable_cpus = true;
mc->default_boot_order = "cad"; mc->default_boot_order = "cad";
mc->smp_parse = pc_smp_parse;
mc->block_default_type = IF_IDE; mc->block_default_type = IF_IDE;
mc->max_cpus = 255; mc->max_cpus = 255;
mc->reset = pc_machine_reset; mc->reset = pc_machine_reset;
@ -1745,6 +1687,7 @@ static void pc_machine_class_init(ObjectClass *oc, void *data)
hc->unplug = pc_machine_device_unplug_cb; hc->unplug = pc_machine_device_unplug_cb;
mc->default_cpu_type = TARGET_DEFAULT_CPU_TYPE; mc->default_cpu_type = TARGET_DEFAULT_CPU_TYPE;
mc->nvdimm_supported = true; mc->nvdimm_supported = true;
mc->smp_props.dies_supported = true;
mc->default_ram_id = "pc.ram"; mc->default_ram_id = "pc.ram";
object_class_property_add(oc, PC_MACHINE_MAX_RAM_BELOW_4G, "size", object_class_property_add(oc, PC_MACHINE_MAX_RAM_BELOW_4G, "size",

View File

@ -432,6 +432,7 @@ static void pc_i440fx_6_1_machine_options(MachineClass *m)
m->is_default = false; m->is_default = false;
compat_props_add(m->compat_props, hw_compat_6_1, hw_compat_6_1_len); compat_props_add(m->compat_props, hw_compat_6_1, hw_compat_6_1_len);
compat_props_add(m->compat_props, pc_compat_6_1, pc_compat_6_1_len); compat_props_add(m->compat_props, pc_compat_6_1, pc_compat_6_1_len);
m->smp_props.prefer_sockets = true;
} }
DEFINE_I440FX_MACHINE(v6_1, "pc-i440fx-6.1", NULL, DEFINE_I440FX_MACHINE(v6_1, "pc-i440fx-6.1", NULL,

View File

@ -372,6 +372,7 @@ static void pc_q35_6_1_machine_options(MachineClass *m)
m->alias = NULL; m->alias = NULL;
compat_props_add(m->compat_props, hw_compat_6_1, hw_compat_6_1_len); compat_props_add(m->compat_props, hw_compat_6_1, hw_compat_6_1_len);
compat_props_add(m->compat_props, pc_compat_6_1, pc_compat_6_1_len); compat_props_add(m->compat_props, pc_compat_6_1, pc_compat_6_1_len);
m->smp_props.prefer_sockets = true;
} }
DEFINE_Q35_MACHINE(v6_1, "pc-q35-6.1", NULL, DEFINE_Q35_MACHINE(v6_1, "pc-q35-6.1", NULL,

View File

@ -4685,6 +4685,7 @@ static void spapr_machine_6_1_class_options(MachineClass *mc)
spapr_machine_6_2_class_options(mc); spapr_machine_6_2_class_options(mc);
compat_props_add(mc->compat_props, hw_compat_6_1, hw_compat_6_1_len); compat_props_add(mc->compat_props, hw_compat_6_1, hw_compat_6_1_len);
smc->pre_6_2_numa_affinity = true; smc->pre_6_2_numa_affinity = true;
mc->smp_props.prefer_sockets = true;
} }
DEFINE_SPAPR_MACHINE(6_1, "6.1", false); DEFINE_SPAPR_MACHINE(6_1, "6.1", false);

View File

@ -814,6 +814,7 @@ static void ccw_machine_6_1_class_options(MachineClass *mc)
{ {
ccw_machine_6_2_class_options(mc); ccw_machine_6_2_class_options(mc);
compat_props_add(mc->compat_props, hw_compat_6_1, hw_compat_6_1_len); compat_props_add(mc->compat_props, hw_compat_6_1, hw_compat_6_1_len);
mc->smp_props.prefer_sockets = true;
} }
DEFINE_CCW_MACHINE(6_1, "6.1", false); DEFINE_CCW_MACHINE(6_1, "6.1", false);

View File

@ -108,6 +108,16 @@ typedef struct {
CPUArchId cpus[]; CPUArchId cpus[];
} CPUArchIdList; } CPUArchIdList;
/**
* SMPCompatProps:
* @prefer_sockets - whether sockets are preferred over cores in smp parsing
* @dies_supported - whether dies are supported by the machine
*/
typedef struct {
bool prefer_sockets;
bool dies_supported;
} SMPCompatProps;
/** /**
* MachineClass: * MachineClass:
* @deprecation_reason: If set, the machine is marked as deprecated. The * @deprecation_reason: If set, the machine is marked as deprecated. The
@ -169,10 +179,6 @@ typedef struct {
* kvm-type may be NULL if it is not needed. * kvm-type may be NULL if it is not needed.
* @numa_mem_supported: * @numa_mem_supported:
* true if '--numa node.mem' option is supported and false otherwise * true if '--numa node.mem' option is supported and false otherwise
* @smp_parse:
* The function pointer to hook different machine specific functions for
* parsing "smp-opts" from QemuOpts to MachineState::CpuTopology and more
* machine specific topology fields, such as smp_dies for PCMachine.
* @hotplug_allowed: * @hotplug_allowed:
* If the hook is provided, then it'll be called for each device * If the hook is provided, then it'll be called for each device
* hotplug to check whether the device hotplug is allowed. Return * hotplug to check whether the device hotplug is allowed. Return
@ -209,7 +215,6 @@ struct MachineClass {
void (*reset)(MachineState *state); void (*reset)(MachineState *state);
void (*wakeup)(MachineState *state); void (*wakeup)(MachineState *state);
int (*kvm_type)(MachineState *machine, const char *arg); int (*kvm_type)(MachineState *machine, const char *arg);
void (*smp_parse)(MachineState *ms, SMPConfiguration *config, Error **errp);
BlockInterfaceType block_default_type; BlockInterfaceType block_default_type;
int units_per_default_bus; int units_per_default_bus;
@ -247,6 +252,7 @@ struct MachineClass {
bool nvdimm_supported; bool nvdimm_supported;
bool numa_mem_supported; bool numa_mem_supported;
bool auto_enable_numa; bool auto_enable_numa;
SMPCompatProps smp_props;
const char *default_ram_id; const char *default_ram_id;
HotplugHandler *(*get_hotplug_handler)(MachineState *machine, HotplugHandler *(*get_hotplug_handler)(MachineState *machine,
@ -274,17 +280,18 @@ typedef struct DeviceMemoryState {
/** /**
* CpuTopology: * CpuTopology:
* @cpus: the number of present logical processors on the machine * @cpus: the number of present logical processors on the machine
* @cores: the number of cores in one package
* @threads: the number of threads in one core
* @sockets: the number of sockets on the machine * @sockets: the number of sockets on the machine
* @dies: the number of dies in one socket
* @cores: the number of cores in one die
* @threads: the number of threads in one core
* @max_cpus: the maximum number of logical processors on the machine * @max_cpus: the maximum number of logical processors on the machine
*/ */
typedef struct CpuTopology { typedef struct CpuTopology {
unsigned int cpus; unsigned int cpus;
unsigned int sockets;
unsigned int dies; unsigned int dies;
unsigned int cores; unsigned int cores;
unsigned int threads; unsigned int threads;
unsigned int sockets;
unsigned int max_cpus; unsigned int max_cpus;
} CpuTopology; } CpuTopology;

View File

@ -1393,7 +1393,7 @@
# #
# @dies: number of dies per socket in the CPU topology # @dies: number of dies per socket in the CPU topology
# #
# @cores: number of cores per thread in the CPU topology # @cores: number of cores per die in the CPU topology
# #
# @threads: number of threads per core in the CPU topology # @threads: number of threads per core in the CPU topology
# #

View File

@ -220,9 +220,14 @@ SRST
Simulate a SMP system with '\ ``n``\ ' CPUs initially present on Simulate a SMP system with '\ ``n``\ ' CPUs initially present on
the machine type board. On boards supporting CPU hotplug, the optional the machine type board. On boards supporting CPU hotplug, the optional
'\ ``maxcpus``\ ' parameter can be set to enable further CPUs to be '\ ``maxcpus``\ ' parameter can be set to enable further CPUs to be
added at runtime. If omitted the maximum number of CPUs will be added at runtime. When both parameters are omitted, the maximum number
set to match the initial CPU count. Both parameters are subject to of CPUs will be calculated from the provided topology members and the
an upper limit that is determined by the specific machine type chosen. initial CPU count will match the maximum number. When only one of them
is given then the omitted one will be set to its counterpart's value.
Both parameters may be specified, but the maximum number of CPUs must
be equal to or greater than the initial CPU count. Both parameters are
subject to an upper limit that is determined by the specific machine
type chosen.
To control reporting of CPU topology information, the number of sockets, To control reporting of CPU topology information, the number of sockets,
dies per socket, cores per die, and threads per core can be specified. dies per socket, cores per die, and threads per core can be specified.
@ -233,11 +238,14 @@ SRST
of computing the CPU maximum count. of computing the CPU maximum count.
Either the initial CPU count, or at least one of the topology parameters Either the initial CPU count, or at least one of the topology parameters
must be specified. Values for any omitted parameters will be computed must be specified. The specified parameters must be greater than zero,
from those which are given. Historically preference was given to the explicit configuration like "cpus=0" is not allowed. Values for any
coarsest topology parameters when computing missing values (ie sockets omitted parameters will be computed from those which are given.
preferred over cores, which were preferred over threads), however, this Historically preference was given to the coarsest topology parameters
behaviour is considered liable to change. when computing missing values (ie sockets preferred over cores, which
were preferred over threads), however, this behaviour is considered
liable to change. Prior to 6.2 the preference was sockets over cores
over threads. Since 6.2 the preference is cores over sockets over threads.
ERST ERST
DEF("numa", HAS_ARG, QEMU_OPTION_numa, DEF("numa", HAS_ARG, QEMU_OPTION_numa,

View File

@ -6258,10 +6258,6 @@ static void x86_cpu_hyperv_realize(X86CPU *cpu)
cpu->hyperv_interface_id[2] = 0; cpu->hyperv_interface_id[2] = 0;
cpu->hyperv_interface_id[3] = 0; cpu->hyperv_interface_id[3] = 0;
/* Hypervisor system identity */
cpu->hyperv_version_id[0] = 0x00001bbc;
cpu->hyperv_version_id[1] = 0x00060001;
/* Hypervisor implementation limits */ /* Hypervisor implementation limits */
cpu->hyperv_limits[0] = 64; cpu->hyperv_limits[0] = 64;
cpu->hyperv_limits[1] = 0; cpu->hyperv_limits[1] = 0;
@ -6644,6 +6640,8 @@ static void x86_cpu_initfn(Object *obj)
object_property_add_alias(obj, "sse4_1", obj, "sse4.1"); object_property_add_alias(obj, "sse4_1", obj, "sse4.1");
object_property_add_alias(obj, "sse4_2", obj, "sse4.2"); object_property_add_alias(obj, "sse4_2", obj, "sse4.2");
object_property_add_alias(obj, "hv-apicv", obj, "hv-avic");
if (xcc->model) { if (xcc->model) {
x86_cpu_load_model(cpu, xcc->model); x86_cpu_load_model(cpu, xcc->model);
} }
@ -6831,9 +6829,23 @@ static Property x86_cpu_properties[] = {
HYPERV_FEAT_IPI, 0), HYPERV_FEAT_IPI, 0),
DEFINE_PROP_BIT64("hv-stimer-direct", X86CPU, hyperv_features, DEFINE_PROP_BIT64("hv-stimer-direct", X86CPU, hyperv_features,
HYPERV_FEAT_STIMER_DIRECT, 0), HYPERV_FEAT_STIMER_DIRECT, 0),
DEFINE_PROP_BIT64("hv-avic", X86CPU, hyperv_features,
HYPERV_FEAT_AVIC, 0),
DEFINE_PROP_ON_OFF_AUTO("hv-no-nonarch-coresharing", X86CPU, DEFINE_PROP_ON_OFF_AUTO("hv-no-nonarch-coresharing", X86CPU,
hyperv_no_nonarch_cs, ON_OFF_AUTO_OFF), hyperv_no_nonarch_cs, ON_OFF_AUTO_OFF),
DEFINE_PROP_BOOL("hv-passthrough", X86CPU, hyperv_passthrough, false), DEFINE_PROP_BOOL("hv-passthrough", X86CPU, hyperv_passthrough, false),
DEFINE_PROP_BOOL("hv-enforce-cpuid", X86CPU, hyperv_enforce_cpuid, false),
/* WS2008R2 identify by default */
DEFINE_PROP_UINT32("hv-version-id-build", X86CPU, hyperv_ver_id_build,
0x3839),
DEFINE_PROP_UINT16("hv-version-id-major", X86CPU, hyperv_ver_id_major,
0x000A),
DEFINE_PROP_UINT16("hv-version-id-minor", X86CPU, hyperv_ver_id_minor,
0x0000),
DEFINE_PROP_UINT32("hv-version-id-spack", X86CPU, hyperv_ver_id_sp, 0),
DEFINE_PROP_UINT8("hv-version-id-sbranch", X86CPU, hyperv_ver_id_sb, 0),
DEFINE_PROP_UINT32("hv-version-id-snumber", X86CPU, hyperv_ver_id_sn, 0),
DEFINE_PROP_BOOL("check", X86CPU, check_cpuid, true), DEFINE_PROP_BOOL("check", X86CPU, check_cpuid, true),
DEFINE_PROP_BOOL("enforce", X86CPU, enforce_cpuid, false), DEFINE_PROP_BOOL("enforce", X86CPU, enforce_cpuid, false),
@ -6860,6 +6872,8 @@ static Property x86_cpu_properties[] = {
DEFINE_PROP_BOOL("l3-cache", X86CPU, enable_l3_cache, true), DEFINE_PROP_BOOL("l3-cache", X86CPU, enable_l3_cache, true),
DEFINE_PROP_BOOL("kvm-no-smi-migration", X86CPU, kvm_no_smi_migration, DEFINE_PROP_BOOL("kvm-no-smi-migration", X86CPU, kvm_no_smi_migration,
false), false),
DEFINE_PROP_BOOL("kvm-pv-enforce-cpuid", X86CPU, kvm_pv_enforce_cpuid,
false),
DEFINE_PROP_BOOL("vmware-cpuid-freq", X86CPU, vmware_cpuid_freq, true), DEFINE_PROP_BOOL("vmware-cpuid-freq", X86CPU, vmware_cpuid_freq, true),
DEFINE_PROP_BOOL("tcg-cpuid", X86CPU, expose_tcg, true), DEFINE_PROP_BOOL("tcg-cpuid", X86CPU, expose_tcg, true),
DEFINE_PROP_BOOL("x-migrate-smi-count", X86CPU, migrate_smi_count, DEFINE_PROP_BOOL("x-migrate-smi-count", X86CPU, migrate_smi_count,

View File

@ -1056,6 +1056,7 @@ typedef uint64_t FeatureWordArray[FEATURE_WORDS];
#define HYPERV_FEAT_EVMCS 12 #define HYPERV_FEAT_EVMCS 12
#define HYPERV_FEAT_IPI 13 #define HYPERV_FEAT_IPI 13
#define HYPERV_FEAT_STIMER_DIRECT 14 #define HYPERV_FEAT_STIMER_DIRECT 14
#define HYPERV_FEAT_AVIC 15
#ifndef HYPERV_SPINLOCK_NEVER_NOTIFY #ifndef HYPERV_SPINLOCK_NEVER_NOTIFY
#define HYPERV_SPINLOCK_NEVER_NOTIFY 0xFFFFFFFF #define HYPERV_SPINLOCK_NEVER_NOTIFY 0xFFFFFFFF
@ -1716,9 +1717,15 @@ struct X86CPU {
OnOffAuto hyperv_no_nonarch_cs; OnOffAuto hyperv_no_nonarch_cs;
uint32_t hyperv_vendor_id[3]; uint32_t hyperv_vendor_id[3];
uint32_t hyperv_interface_id[4]; uint32_t hyperv_interface_id[4];
uint32_t hyperv_version_id[4];
uint32_t hyperv_limits[3]; uint32_t hyperv_limits[3];
uint32_t hyperv_nested[4]; uint32_t hyperv_nested[4];
bool hyperv_enforce_cpuid;
uint32_t hyperv_ver_id_build;
uint16_t hyperv_ver_id_major;
uint16_t hyperv_ver_id_minor;
uint32_t hyperv_ver_id_sp;
uint8_t hyperv_ver_id_sb;
uint32_t hyperv_ver_id_sn;
bool check_cpuid; bool check_cpuid;
bool enforce_cpuid; bool enforce_cpuid;
@ -1802,6 +1809,9 @@ struct X86CPU {
/* Stop SMI delivery for migration compatibility with old machines */ /* Stop SMI delivery for migration compatibility with old machines */
bool kvm_no_smi_migration; bool kvm_no_smi_migration;
/* Forcefully disable KVM PV features not exposed in guest CPUIDs */
bool kvm_pv_enforce_cpuid;
/* Number of physical address bits supported */ /* Number of physical address bits supported */
uint32_t phys_bits; uint32_t phys_bits;

View File

@ -66,6 +66,7 @@
#define HV_APIC_ACCESS_RECOMMENDED (1u << 3) #define HV_APIC_ACCESS_RECOMMENDED (1u << 3)
#define HV_SYSTEM_RESET_RECOMMENDED (1u << 4) #define HV_SYSTEM_RESET_RECOMMENDED (1u << 4)
#define HV_RELAXED_TIMING_RECOMMENDED (1u << 5) #define HV_RELAXED_TIMING_RECOMMENDED (1u << 5)
#define HV_DEPRECATING_AEOI_RECOMMENDED (1u << 9)
#define HV_CLUSTER_IPI_RECOMMENDED (1u << 10) #define HV_CLUSTER_IPI_RECOMMENDED (1u << 10)
#define HV_EX_PROCESSOR_MASKS_RECOMMENDED (1u << 11) #define HV_EX_PROCESSOR_MASKS_RECOMMENDED (1u << 11)
#define HV_ENLIGHTENED_VMCS_RECOMMENDED (1u << 14) #define HV_ENLIGHTENED_VMCS_RECOMMENDED (1u << 14)

View File

@ -821,9 +821,7 @@ static struct {
.desc = "virtual APIC (hv-vapic)", .desc = "virtual APIC (hv-vapic)",
.flags = { .flags = {
{.func = HV_CPUID_FEATURES, .reg = R_EAX, {.func = HV_CPUID_FEATURES, .reg = R_EAX,
.bits = HV_APIC_ACCESS_AVAILABLE}, .bits = HV_APIC_ACCESS_AVAILABLE}
{.func = HV_CPUID_ENLIGHTMENT_INFO, .reg = R_EAX,
.bits = HV_APIC_ACCESS_RECOMMENDED}
} }
}, },
[HYPERV_FEAT_TIME] = { [HYPERV_FEAT_TIME] = {
@ -926,6 +924,13 @@ static struct {
}, },
.dependencies = BIT(HYPERV_FEAT_STIMER) .dependencies = BIT(HYPERV_FEAT_STIMER)
}, },
[HYPERV_FEAT_AVIC] = {
.desc = "AVIC/APICv support (hv-avic/hv-apicv)",
.flags = {
{.func = HV_CPUID_ENLIGHTMENT_INFO, .reg = R_EAX,
.bits = HV_DEPRECATING_AEOI_RECOMMENDED}
}
},
}; };
static struct kvm_cpuid2 *try_get_hv_cpuid(CPUState *cs, int max, static struct kvm_cpuid2 *try_get_hv_cpuid(CPUState *cs, int max,
@ -1253,14 +1258,18 @@ bool kvm_hyperv_expand_features(X86CPU *cpu, Error **errp)
cpu->hyperv_interface_id[3] = cpu->hyperv_interface_id[3] =
hv_cpuid_get_host(cs, HV_CPUID_INTERFACE, R_EDX); hv_cpuid_get_host(cs, HV_CPUID_INTERFACE, R_EDX);
cpu->hyperv_version_id[0] = cpu->hyperv_ver_id_build =
hv_cpuid_get_host(cs, HV_CPUID_VERSION, R_EAX); hv_cpuid_get_host(cs, HV_CPUID_VERSION, R_EAX);
cpu->hyperv_version_id[1] = cpu->hyperv_ver_id_major =
hv_cpuid_get_host(cs, HV_CPUID_VERSION, R_EBX); hv_cpuid_get_host(cs, HV_CPUID_VERSION, R_EBX) >> 16;
cpu->hyperv_version_id[2] = cpu->hyperv_ver_id_minor =
hv_cpuid_get_host(cs, HV_CPUID_VERSION, R_EBX) & 0xffff;
cpu->hyperv_ver_id_sp =
hv_cpuid_get_host(cs, HV_CPUID_VERSION, R_ECX); hv_cpuid_get_host(cs, HV_CPUID_VERSION, R_ECX);
cpu->hyperv_version_id[3] = cpu->hyperv_ver_id_sb =
hv_cpuid_get_host(cs, HV_CPUID_VERSION, R_EDX); hv_cpuid_get_host(cs, HV_CPUID_VERSION, R_EDX) >> 24;
cpu->hyperv_ver_id_sn =
hv_cpuid_get_host(cs, HV_CPUID_VERSION, R_EDX) & 0xffffff;
cpu->hv_max_vps = hv_cpuid_get_host(cs, HV_CPUID_IMPLEMENT_LIMITS, cpu->hv_max_vps = hv_cpuid_get_host(cs, HV_CPUID_IMPLEMENT_LIMITS,
R_EAX); R_EAX);
@ -1346,10 +1355,12 @@ static int hyperv_fill_cpuids(CPUState *cs,
c = &cpuid_ent[cpuid_i++]; c = &cpuid_ent[cpuid_i++];
c->function = HV_CPUID_VERSION; c->function = HV_CPUID_VERSION;
c->eax = cpu->hyperv_version_id[0]; c->eax = cpu->hyperv_ver_id_build;
c->ebx = cpu->hyperv_version_id[1]; c->ebx = (uint32_t)cpu->hyperv_ver_id_major << 16 |
c->ecx = cpu->hyperv_version_id[2]; cpu->hyperv_ver_id_minor;
c->edx = cpu->hyperv_version_id[3]; c->ecx = cpu->hyperv_ver_id_sp;
c->edx = (uint32_t)cpu->hyperv_ver_id_sb << 24 |
(cpu->hyperv_ver_id_sn & 0xffffff);
c = &cpuid_ent[cpuid_i++]; c = &cpuid_ent[cpuid_i++];
c->function = HV_CPUID_FEATURES; c->function = HV_CPUID_FEATURES;
@ -1366,6 +1377,7 @@ static int hyperv_fill_cpuids(CPUState *cs,
c->ebx |= HV_POST_MESSAGES | HV_SIGNAL_EVENTS; c->ebx |= HV_POST_MESSAGES | HV_SIGNAL_EVENTS;
} }
/* Not exposed by KVM but needed to make CPU hotplug in Windows work */ /* Not exposed by KVM but needed to make CPU hotplug in Windows work */
c->edx |= HV_CPU_DYNAMIC_PARTITIONING_AVAILABLE; c->edx |= HV_CPU_DYNAMIC_PARTITIONING_AVAILABLE;
@ -1374,6 +1386,11 @@ static int hyperv_fill_cpuids(CPUState *cs,
c->eax = hv_build_cpuid_leaf(cs, HV_CPUID_ENLIGHTMENT_INFO, R_EAX); c->eax = hv_build_cpuid_leaf(cs, HV_CPUID_ENLIGHTMENT_INFO, R_EAX);
c->ebx = cpu->hyperv_spinlock_attempts; c->ebx = cpu->hyperv_spinlock_attempts;
if (hyperv_feat_enabled(cpu, HYPERV_FEAT_VAPIC) &&
!hyperv_feat_enabled(cpu, HYPERV_FEAT_AVIC)) {
c->eax |= HV_APIC_ACCESS_RECOMMENDED;
}
if (cpu->hyperv_no_nonarch_cs == ON_OFF_AUTO_ON) { if (cpu->hyperv_no_nonarch_cs == ON_OFF_AUTO_ON) {
c->eax |= HV_NO_NONARCH_CORESHARING; c->eax |= HV_NO_NONARCH_CORESHARING;
} else if (cpu->hyperv_no_nonarch_cs == ON_OFF_AUTO_AUTO) { } else if (cpu->hyperv_no_nonarch_cs == ON_OFF_AUTO_AUTO) {
@ -1531,6 +1548,15 @@ static int hyperv_init_vcpu(X86CPU *cpu)
cpu->hyperv_nested[0] = evmcs_version; cpu->hyperv_nested[0] = evmcs_version;
} }
if (cpu->hyperv_enforce_cpuid) {
ret = kvm_vcpu_enable_cap(cs, KVM_CAP_HYPERV_ENFORCE_CPUID, 0, 1);
if (ret < 0) {
error_report("failed to enable KVM_CAP_HYPERV_ENFORCE_CPUID: %s",
strerror(-ret));
return ret;
}
}
return 0; return 0;
} }
@ -1629,6 +1655,16 @@ int kvm_arch_init_vcpu(CPUState *cs)
cpu_x86_cpuid(env, 0, 0, &limit, &unused, &unused, &unused); cpu_x86_cpuid(env, 0, 0, &limit, &unused, &unused, &unused);
if (cpu->kvm_pv_enforce_cpuid) {
r = kvm_vcpu_enable_cap(cs, KVM_CAP_ENFORCE_PV_FEATURE_CPUID, 0, 1);
if (r < 0) {
fprintf(stderr,
"failed to enable KVM_CAP_ENFORCE_PV_FEATURE_CPUID: %s",
strerror(-r));
abort();
}
}
for (i = 0; i <= limit; i++) { for (i = 0; i <= limit; i++) {
if (cpuid_i == KVM_MAX_CPUID_ENTRIES) { if (cpuid_i == KVM_MAX_CPUID_ENTRIES) {
fprintf(stderr, "unsupported level value: 0x%x\n", limit); fprintf(stderr, "unsupported level value: 0x%x\n", limit);

View File

@ -42,7 +42,8 @@ static void test_def_cpu_split(const void *data)
g_autofree char *s = NULL; g_autofree char *s = NULL;
g_autofree char *cli = NULL; g_autofree char *cli = NULL;
cli = make_cli(data, "-machine smp.cpus=8 -numa node,memdev=ram -numa node"); cli = make_cli(data, "-machine smp.cpus=8,smp.sockets=8 "
"-numa node,memdev=ram -numa node");
qts = qtest_init(cli); qts = qtest_init(cli);
s = qtest_hmp(qts, "info numa"); s = qtest_hmp(qts, "info numa");
@ -265,7 +266,8 @@ static void pc_dynamic_cpu_cfg(const void *data)
QTestState *qs; QTestState *qs;
g_autofree char *cli = NULL; g_autofree char *cli = NULL;
cli = make_cli(data, "-nodefaults --preconfig -machine smp.cpus=2"); cli = make_cli(data, "-nodefaults --preconfig "
"-machine smp.cpus=2,smp.sockets=2");
qs = qtest_init(cli); qs = qtest_init(cli);
/* create 2 numa nodes */ /* create 2 numa nodes */