* -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:
commit
5f99210238
@ -160,6 +160,21 @@ Use ``-display sdl`` 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)
|
||||
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
|
||||
|
@ -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
|
||||
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
|
||||
====================================
|
||||
|
||||
@ -473,14 +483,3 @@ Built by Makefile:
|
||||
meson.build. The rules are produced from Meson's JSON description of
|
||||
tests (obtained with "meson introspect --tests") through the script
|
||||
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.
|
||||
|
@ -8,6 +8,6 @@ found at::
|
||||
|
||||
https://wiki.qemu.org/Testing/CI
|
||||
|
||||
.. include:: ci-definitions.rst
|
||||
.. include:: ci-jobs.rst
|
||||
.. include:: ci-runners.rst
|
||||
.. include:: ci-definitions.rst.inc
|
||||
.. include:: ci-jobs.rst.inc
|
||||
.. include:: ci-runners.rst.inc
|
||||
|
@ -1,15 +1,17 @@
|
||||
This is the design document for multi-process QEMU. It does not
|
||||
necessarily reflect the status of the current implementation, which
|
||||
may lack features or be considerably different from what is described
|
||||
in this document. This document is still useful as a description of
|
||||
the goals and general direction of this feature.
|
||||
|
||||
Please refer to the following wiki for latest details:
|
||||
https://wiki.qemu.org/Features/MultiProcessQEMU
|
||||
|
||||
Multi-process QEMU
|
||||
===================
|
||||
|
||||
.. note::
|
||||
|
||||
This is the design document for multi-process QEMU. It does not
|
||||
necessarily reflect the status of the current implementation, which
|
||||
may lack features or be considerably different from what is described
|
||||
in this document. This document is still useful as a description of
|
||||
the goals and general direction of this feature.
|
||||
|
||||
Please refer to the following wiki for latest details:
|
||||
https://wiki.qemu.org/Features/MultiProcessQEMU
|
||||
|
||||
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
|
||||
ability to run many VMs from different tenants in the same cloud
|
||||
|
@ -1,8 +1,7 @@
|
||||
.. _qgraph:
|
||||
|
||||
========================================
|
||||
Qtest Driver Framework
|
||||
========================================
|
||||
======================
|
||||
|
||||
In order to test a specific driver, plain libqos tests need to
|
||||
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
|
||||
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
|
||||
and edges that define the relationships between them (``CONSUMES``, ``PRODUCES``, and
|
||||
``CONTAINS``).
|
||||
|
||||
|
||||
Nodes
|
||||
^^^^^^
|
||||
~~~~~
|
||||
|
||||
A node can be of four types:
|
||||
|
||||
@ -64,7 +65,7 @@ Notes for the nodes:
|
||||
drivers name, otherwise they won't be discovered
|
||||
|
||||
Edges
|
||||
^^^^^^
|
||||
~~~~~
|
||||
|
||||
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
|
||||
|
||||
Execution steps
|
||||
^^^^^^^^^^^^^^^
|
||||
~~~~~~~~~~~~~~~
|
||||
|
||||
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
|
||||
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
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
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
|
||||
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.
|
||||
|
||||
Creating a new driver and its interface
|
||||
"""""""""""""""""""""""""""""""""""""""""
|
||||
---------------------------------------
|
||||
|
||||
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
|
||||
|
||||
Adding a new test
|
||||
"""""""""""""""""
|
||||
-----------------
|
||||
|
||||
Given the above setup, adding a new test is very simple.
|
||||
``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``
|
||||
|
||||
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
|
||||
^^^^^^^^^^^^^^^^^^^^
|
||||
--------------------
|
||||
|
||||
.. kernel-doc:: tests/qtest/libqos/qgraph.h
|
||||
|
@ -3,7 +3,6 @@
|
||||
Copyright (c) 2019, Linaro Limited
|
||||
Written by Emilio Cota and Alex Bennée
|
||||
|
||||
================
|
||||
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
|
||||
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
|
||||
=====
|
||||
-----
|
||||
|
||||
Any QEMU binary with TCG support has plugins enabled by default.
|
||||
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
|
||||
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
|
||||
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
|
||||
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
|
||||
=========
|
||||
---------
|
||||
|
||||
Locking
|
||||
-------
|
||||
~~~~~~~
|
||||
|
||||
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
|
||||
@ -142,7 +141,7 @@ requested. The plugin isn't completely uninstalled until the safe work
|
||||
has executed while all vCPUs are quiescent.
|
||||
|
||||
Example Plugins
|
||||
===============
|
||||
---------------
|
||||
|
||||
There are a number of plugins included with QEMU and you are
|
||||
encouraged to contribute your own plugins plugins upstream. There is a
|
||||
|
@ -1,11 +1,10 @@
|
||||
===============
|
||||
Testing in QEMU
|
||||
===============
|
||||
|
||||
This document describes the testing infrastructure in QEMU.
|
||||
|
||||
Testing with "make check"
|
||||
=========================
|
||||
-------------------------
|
||||
|
||||
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.
|
||||
@ -24,7 +23,7 @@ expect the executables to exist and will fail with obscure messages if they
|
||||
cannot find them.
|
||||
|
||||
Unit 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
|
||||
@ -67,7 +66,7 @@ and copy the actual command line which executes the unit test, then run
|
||||
it from the command line.
|
||||
|
||||
QTest
|
||||
-----
|
||||
~~~~~
|
||||
|
||||
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
|
||||
@ -81,7 +80,7 @@ QTest cases can be executed with
|
||||
make check-qtest
|
||||
|
||||
QAPI schema tests
|
||||
-----------------
|
||||
~~~~~~~~~~~~~~~~~
|
||||
|
||||
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
|
||||
@ -108,33 +107,14 @@ parser (either fixing a bug or extending/modifying the syntax). To do this:
|
||||
``qapi-schema += foo.json``
|
||||
|
||||
check-block
|
||||
-----------
|
||||
~~~~~~~~~~~
|
||||
|
||||
``make check-block`` runs a subset of the block layer iotests (the tests that
|
||||
are in the "auto" group).
|
||||
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, under the directory ``tests/qemu-iotests``, is the testing
|
||||
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.
|
||||
|
||||
Writing a new test case
|
||||
-----------------------
|
||||
~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
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
|
||||
@ -225,7 +205,8 @@ test failure. If using such devices are explicitly desired, consider adding
|
||||
``locking=off`` option to disable image locking.
|
||||
|
||||
Debugging a test case
|
||||
-----------------------
|
||||
~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The following options to the ``check`` script can be useful when debugging
|
||||
a failing test:
|
||||
|
||||
@ -254,7 +235,7 @@ a failing test:
|
||||
``$TEST_DIR/qemu-machine-<random_string>``.
|
||||
|
||||
Test case groups
|
||||
----------------
|
||||
~~~~~~~~~~~~~~~~
|
||||
|
||||
"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
|
||||
@ -304,10 +285,10 @@ Note that the following group names have a special meaning:
|
||||
.. _container-ref:
|
||||
|
||||
Container based tests
|
||||
=====================
|
||||
---------------------
|
||||
|
||||
Introduction
|
||||
------------
|
||||
~~~~~~~~~~~~
|
||||
|
||||
The container testing framework in QEMU utilizes public images to
|
||||
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.
|
||||
|
||||
Docker Prerequisites
|
||||
--------------------
|
||||
~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
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
|
||||
@ -353,7 +334,7 @@ exploit the whole host with Docker bind mounting or other privileged
|
||||
operations. So only do it on development machines.
|
||||
|
||||
Podman Prerequisites
|
||||
--------------------
|
||||
~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
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.
|
||||
|
||||
Quickstart
|
||||
----------
|
||||
~~~~~~~~~~
|
||||
|
||||
From source tree, type ``make docker-help`` to see the help. Testing
|
||||
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.
|
||||
|
||||
Registry
|
||||
--------
|
||||
~~~~~~~~
|
||||
|
||||
The QEMU project has a container registry hosted by GitLab at
|
||||
``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
|
||||
|
||||
Images
|
||||
------
|
||||
~~~~~~
|
||||
|
||||
Along with many other images, the ``centos8`` image is defined in a Dockerfile
|
||||
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.
|
||||
|
||||
Tests
|
||||
-----
|
||||
~~~~~
|
||||
|
||||
Different tests are added to cover various configurations to build and test
|
||||
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.
|
||||
|
||||
Debugging a Docker test failure
|
||||
-------------------------------
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
When CI tasks, maintainers or yourself report a Docker test failure, follow the
|
||||
below steps to debug it:
|
||||
@ -438,7 +419,7 @@ below steps to debug it:
|
||||
the prompt for debug.
|
||||
|
||||
Options
|
||||
-------
|
||||
~~~~~~~
|
||||
|
||||
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:
|
||||
@ -452,7 +433,7 @@ list is in the ``make docker`` help text. The frequently used ones are:
|
||||
failure" section.
|
||||
|
||||
Thread Sanitizer
|
||||
================
|
||||
----------------
|
||||
|
||||
Thread Sanitizer (TSan) is a tool which can detect data races. QEMU supports
|
||||
building and testing with this tool.
|
||||
@ -462,7 +443,7 @@ For more information on TSan:
|
||||
https://github.com/google/sanitizers/wiki/ThreadSanitizerCppManual
|
||||
|
||||
Thread Sanitizer in Docker
|
||||
---------------------------
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
TSan is currently supported in the ubuntu2004 docker.
|
||||
|
||||
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.
|
||||
|
||||
Building and Testing with TSan
|
||||
------------------------------
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
It is possible to build and test with TSan, with a few additional steps.
|
||||
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.
|
||||
|
||||
TSan Suppressions
|
||||
-----------------
|
||||
~~~~~~~~~~~~~~~~~
|
||||
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
|
||||
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
|
||||
|
||||
TSan Annotations
|
||||
----------------
|
||||
~~~~~~~~~~~~~~~~
|
||||
include/qemu/tsan.h defines annotations. See this file for more descriptions
|
||||
of the annotations themselves. Annotations can be used to suppress
|
||||
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
|
||||
|
||||
VM testing
|
||||
==========
|
||||
----------
|
||||
|
||||
This test suite contains scripts that bootstrap various guest images that have
|
||||
necessary packages to build QEMU. The basic usage is documented in ``Makefile``
|
||||
help which is displayed with ``make vm-help``.
|
||||
|
||||
Quickstart
|
||||
----------
|
||||
~~~~~~~~~~
|
||||
|
||||
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``
|
||||
@ -581,7 +562,7 @@ concerned about attackers taking control of the guest and potentially
|
||||
exploiting a QEMU security bug to compromise the host.
|
||||
|
||||
QEMU binaries
|
||||
-------------
|
||||
~~~~~~~~~~~~~
|
||||
|
||||
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,
|
||||
@ -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.
|
||||
|
||||
Make jobs
|
||||
---------
|
||||
~~~~~~~~~
|
||||
|
||||
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.
|
||||
|
||||
Debugging
|
||||
---------
|
||||
~~~~~~~~~
|
||||
|
||||
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.
|
||||
``V=1`` will be propagated down into the make jobs in the guest.
|
||||
|
||||
Manual invocation
|
||||
-----------------
|
||||
~~~~~~~~~~~~~~~~~
|
||||
|
||||
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``:
|
||||
@ -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
|
||||
|
||||
Adding new guests
|
||||
-----------------
|
||||
~~~~~~~~~~~~~~~~~
|
||||
|
||||
Please look at existing guest scripts for how to add new guests.
|
||||
|
||||
@ -660,7 +641,7 @@ the script's ``main()``.
|
||||
recommended.
|
||||
|
||||
Image fuzzer testing
|
||||
====================
|
||||
--------------------
|
||||
|
||||
An image fuzzer was added to exercise format drivers. Currently only qcow2 is
|
||||
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.
|
||||
|
||||
Acceptance tests using the Avocado Framework
|
||||
============================================
|
||||
--------------------------------------------
|
||||
|
||||
The ``tests/acceptance`` directory hosts functional tests, also known
|
||||
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
|
||||
|
||||
Running tests
|
||||
-------------
|
||||
~~~~~~~~~~~~~
|
||||
|
||||
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
|
||||
|
||||
Manual Installation
|
||||
-------------------
|
||||
~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
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
|
||||
|
||||
Overview
|
||||
--------
|
||||
~~~~~~~~
|
||||
|
||||
The ``tests/acceptance/avocado_qemu`` directory provides the
|
||||
``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 .
|
||||
|
||||
The ``avocado_qemu.Test`` base test class
|
||||
-----------------------------------------
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
The ``avocado_qemu.Test`` class has a number of characteristics that
|
||||
are worth being mentioned right away.
|
||||
@ -909,7 +890,7 @@ At test "tear down", ``avocado_qemu.Test`` handles all the QEMUMachines
|
||||
shutdown.
|
||||
|
||||
The ``avocado_qemu.LinuxTest`` base test class
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
The ``avocado_qemu.LinuxTest`` is further specialization of the
|
||||
``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
|
||||
|
||||
QEMU binary selection
|
||||
~~~~~~~~~~~~~~~~~~~~~
|
||||
^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
The QEMU binary used for the ``self.vm`` QEMUMachine instance will
|
||||
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.
|
||||
|
||||
Attribute reference
|
||||
-------------------
|
||||
~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Test
|
||||
^^^^
|
||||
|
||||
Besides the attributes and methods that are part of the base
|
||||
``avocado.Test`` class, the following attributes are available on any
|
||||
``avocado_qemu.Test`` instance.
|
||||
|
||||
vm
|
||||
~~
|
||||
''
|
||||
|
||||
A QEMUMachine instance, initially configured according to the given
|
||||
``qemu_bin`` parameter.
|
||||
|
||||
arch
|
||||
~~~~
|
||||
''''
|
||||
|
||||
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
|
||||
@ -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``.
|
||||
|
||||
cpu
|
||||
~~~
|
||||
'''
|
||||
|
||||
The cpu model that will be set to all QEMUMachine instances created
|
||||
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``.
|
||||
|
||||
machine
|
||||
~~~~~~~
|
||||
'''''''
|
||||
|
||||
The machine type that will be set to all QEMUMachine instances created
|
||||
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``.
|
||||
|
||||
qemu_bin
|
||||
~~~~~~~~
|
||||
''''''''
|
||||
|
||||
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
|
||||
source tree.
|
||||
|
||||
LinuxTest
|
||||
~~~~~~~~~
|
||||
^^^^^^^^^
|
||||
|
||||
Besides the attributes present on the ``avocado_qemu.Test`` base
|
||||
class, the ``avocado_qemu.LinuxTest`` adds the following attributes:
|
||||
|
||||
distro
|
||||
......
|
||||
''''''
|
||||
|
||||
The name of the Linux distribution used as the guest image for the
|
||||
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
|
||||
|
||||
distro_version
|
||||
..............
|
||||
''''''''''''''
|
||||
|
||||
The version of the Linux distribution as the guest image for the
|
||||
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
|
||||
|
||||
distro_checksum
|
||||
...............
|
||||
'''''''''''''''
|
||||
|
||||
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.
|
||||
|
||||
Parameter reference
|
||||
-------------------
|
||||
~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
To understand how Avocado parameters are accessed by tests, and how
|
||||
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
|
||||
|
||||
Test
|
||||
^^^^
|
||||
|
||||
arch
|
||||
~~~~
|
||||
''''
|
||||
|
||||
The architecture that will influence the selection of a QEMU binary
|
||||
(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.
|
||||
|
||||
cpu
|
||||
~~~
|
||||
'''
|
||||
|
||||
The cpu model that will be set to all QEMUMachine instances created
|
||||
by the test.
|
||||
|
||||
machine
|
||||
~~~~~~~
|
||||
'''''''
|
||||
|
||||
The machine type that will be set to all QEMUMachine instances created
|
||||
by the test.
|
||||
|
||||
|
||||
qemu_bin
|
||||
~~~~~~~~
|
||||
''''''''
|
||||
|
||||
The exact QEMU binary to be used on QEMUMachine.
|
||||
|
||||
LinuxTest
|
||||
~~~~~~~~~
|
||||
^^^^^^^^^
|
||||
|
||||
Besides the parameters present on the ``avocado_qemu.Test`` base
|
||||
class, the ``avocado_qemu.LinuxTest`` adds the following parameters:
|
||||
|
||||
distro
|
||||
......
|
||||
''''''
|
||||
|
||||
The name of the Linux distribution used as the guest image for the
|
||||
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
|
||||
|
||||
distro_version
|
||||
..............
|
||||
''''''''''''''
|
||||
|
||||
The version of the Linux distribution as the guest image for the
|
||||
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
|
||||
|
||||
distro_checksum
|
||||
...............
|
||||
'''''''''''''''
|
||||
|
||||
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.
|
||||
|
||||
Skipping tests
|
||||
--------------
|
||||
~~~~~~~~~~~~~~
|
||||
|
||||
The Avocado framework provides Python decorators which allow for easily skip
|
||||
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
|
||||
@ -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:
|
||||
|
||||
AVOCADO_ALLOW_LARGE_STORAGE
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
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
|
||||
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.
|
||||
|
||||
AVOCADO_ALLOW_UNTRUSTED_CODE
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
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
|
||||
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.
|
||||
|
||||
AVOCADO_TIMEOUT_EXPECTED
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
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
|
||||
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.
|
||||
|
||||
GITLAB_CI
|
||||
~~~~~~~~~
|
||||
^^^^^^^^^
|
||||
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
|
||||
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()
|
||||
|
||||
Uninstalling Avocado
|
||||
--------------------
|
||||
~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
If you've followed the manual installation instructions above, you can
|
||||
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:
|
||||
|
||||
Testing with "make check-tcg"
|
||||
=============================
|
||||
-----------------------------
|
||||
|
||||
The check-tcg tests are intended for simple smoke tests of both
|
||||
linux-user and softmmu TCG functionality. However to build test
|
||||
@ -1256,7 +1243,7 @@ itself.
|
||||
See :ref:`container-ref` for more details.
|
||||
|
||||
Running subset of tests
|
||||
-----------------------
|
||||
~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
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.
|
||||
|
||||
TCG test dependencies
|
||||
---------------------
|
||||
~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The TCG tests are deliberately very light on dependencies and are
|
||||
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::
|
||||
|
||||
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.
|
||||
|
@ -189,7 +189,15 @@ enabled.
|
||||
|
||||
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
|
||||
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
|
||||
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
|
||||
'pass-through' mode and give Windows guests all enlightenments currently
|
||||
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
|
||||
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:
|
||||
https://github.com/MicrosoftDocs/Virtualization-Documentation
|
||||
|
@ -2815,6 +2815,7 @@ static void virt_machine_6_1_options(MachineClass *mc)
|
||||
|
||||
virt_machine_6_2_options(mc);
|
||||
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 */
|
||||
vmc->no_tcg_its = true;
|
||||
|
@ -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)
|
||||
{
|
||||
MachineClass *mc = MACHINE_GET_CLASS(ms);
|
||||
unsigned cpus = config->has_cpus ? config->cpus : 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 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");
|
||||
return;
|
||||
}
|
||||
|
||||
/* compute missing values, prefer sockets over cores over threads */
|
||||
if (cpus == 0 || sockets == 0) {
|
||||
dies = dies > 0 ? dies : 1;
|
||||
|
||||
/* compute missing values based on the provided ones */
|
||||
if (cpus == 0 && maxcpus == 0) {
|
||||
sockets = sockets > 0 ? sockets : 1;
|
||||
cores = cores > 0 ? cores : 1;
|
||||
threads = threads > 0 ? threads : 1;
|
||||
if (cpus == 0) {
|
||||
sockets = sockets > 0 ? sockets : 1;
|
||||
cpus = cores * threads * sockets;
|
||||
} else {
|
||||
maxcpus = maxcpus > 0 ? maxcpus : cpus;
|
||||
|
||||
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) {
|
||||
threads = threads > 0 ? threads : 1;
|
||||
cores = maxcpus / (sockets * dies * threads);
|
||||
}
|
||||
} else {
|
||||
ms->smp.max_cpus = config->has_maxcpus ? config->maxcpus : cpus;
|
||||
sockets = ms->smp.max_cpus / (cores * threads);
|
||||
/* prefer cores over sockets since 6.2 */
|
||||
if (cores == 0) {
|
||||
sockets = sockets > 0 ? sockets : 1;
|
||||
threads = threads > 0 ? threads : 1;
|
||||
cores = maxcpus / (sockets * dies * threads);
|
||||
} else if (sockets == 0) {
|
||||
threads = threads > 0 ? threads : 1;
|
||||
sockets = maxcpus / (dies * cores * threads);
|
||||
}
|
||||
}
|
||||
|
||||
/* try to calculate omitted threads at last */
|
||||
if (threads == 0) {
|
||||
threads = maxcpus / (sockets * dies * cores);
|
||||
}
|
||||
} else if (cores == 0) {
|
||||
threads = threads > 0 ? threads : 1;
|
||||
cores = cpus / (sockets * threads);
|
||||
cores = cores > 0 ? cores : 1;
|
||||
} else if (threads == 0) {
|
||||
threads = cpus / (cores * sockets);
|
||||
threads = threads > 0 ? threads : 1;
|
||||
} else if (sockets * cores * threads < cpus) {
|
||||
error_setg(errp, "cpu topology: "
|
||||
"sockets (%u) * cores (%u) * threads (%u) < "
|
||||
"smp_cpus (%u)",
|
||||
sockets, 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 * cores * threads != ms->smp.max_cpus) {
|
||||
error_setg(errp, "Invalid CPU topology: "
|
||||
"sockets (%u) * cores (%u) * threads (%u) "
|
||||
"!= maxcpus (%u)",
|
||||
sockets, cores, threads,
|
||||
ms->smp.max_cpus);
|
||||
return;
|
||||
}
|
||||
maxcpus = maxcpus > 0 ? maxcpus : sockets * dies * cores * threads;
|
||||
cpus = cpus > 0 ? cpus : maxcpus;
|
||||
|
||||
ms->smp.cpus = cpus;
|
||||
ms->smp.sockets = sockets;
|
||||
ms->smp.dies = dies;
|
||||
ms->smp.cores = cores;
|
||||
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,
|
||||
@ -811,11 +910,11 @@ static void machine_get_smp(Object *obj, Visitor *v, const char *name,
|
||||
{
|
||||
MachineState *ms = MACHINE(obj);
|
||||
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_dies = true, .dies = ms->smp.dies,
|
||||
.has_cores = true, .cores = ms->smp.cores,
|
||||
.has_threads = true, .threads = ms->smp.threads,
|
||||
.has_cpus = true, .cpus = ms->smp.cpus,
|
||||
.has_maxcpus = true, .maxcpus = ms->smp.max_cpus,
|
||||
};
|
||||
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,
|
||||
void *opaque, Error **errp)
|
||||
{
|
||||
MachineClass *mc = MACHINE_GET_CLASS(obj);
|
||||
MachineState *ms = MACHINE(obj);
|
||||
SMPConfiguration *config;
|
||||
ERRP_GUARD();
|
||||
g_autoptr(SMPConfiguration) config = NULL;
|
||||
|
||||
if (!visit_type_SMPConfiguration(v, name, &config, errp)) {
|
||||
return;
|
||||
}
|
||||
|
||||
mc->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);
|
||||
smp_parse(ms, config, errp);
|
||||
}
|
||||
|
||||
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 */
|
||||
mc->default_ram_size = 128 * MiB;
|
||||
mc->rom_file_has_mr = true;
|
||||
mc->smp_parse = smp_parse;
|
||||
|
||||
/* numa node memory size aligned on 8MB by default.
|
||||
* 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 */
|
||||
ms->smp.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.dies = 1;
|
||||
ms->smp.cores = 1;
|
||||
ms->smp.threads = 1;
|
||||
}
|
||||
|
||||
static void machine_finalize(Object *obj)
|
||||
|
69
hw/i386/pc.c
69
hw/i386/pc.c
@ -93,7 +93,11 @@
|
||||
#include "trace.h"
|
||||
#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);
|
||||
|
||||
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
|
||||
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->has_hotpluggable_cpus = true;
|
||||
mc->default_boot_order = "cad";
|
||||
mc->smp_parse = pc_smp_parse;
|
||||
mc->block_default_type = IF_IDE;
|
||||
mc->max_cpus = 255;
|
||||
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;
|
||||
mc->default_cpu_type = TARGET_DEFAULT_CPU_TYPE;
|
||||
mc->nvdimm_supported = true;
|
||||
mc->smp_props.dies_supported = true;
|
||||
mc->default_ram_id = "pc.ram";
|
||||
|
||||
object_class_property_add(oc, PC_MACHINE_MAX_RAM_BELOW_4G, "size",
|
||||
|
@ -432,6 +432,7 @@ static void pc_i440fx_6_1_machine_options(MachineClass *m)
|
||||
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, 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,
|
||||
|
@ -372,6 +372,7 @@ static void pc_q35_6_1_machine_options(MachineClass *m)
|
||||
m->alias = NULL;
|
||||
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);
|
||||
m->smp_props.prefer_sockets = true;
|
||||
}
|
||||
|
||||
DEFINE_Q35_MACHINE(v6_1, "pc-q35-6.1", NULL,
|
||||
|
@ -4685,6 +4685,7 @@ static void spapr_machine_6_1_class_options(MachineClass *mc)
|
||||
spapr_machine_6_2_class_options(mc);
|
||||
compat_props_add(mc->compat_props, hw_compat_6_1, hw_compat_6_1_len);
|
||||
smc->pre_6_2_numa_affinity = true;
|
||||
mc->smp_props.prefer_sockets = true;
|
||||
}
|
||||
|
||||
DEFINE_SPAPR_MACHINE(6_1, "6.1", false);
|
||||
|
@ -814,6 +814,7 @@ static void ccw_machine_6_1_class_options(MachineClass *mc)
|
||||
{
|
||||
ccw_machine_6_2_class_options(mc);
|
||||
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);
|
||||
|
||||
|
@ -108,6 +108,16 @@ typedef struct {
|
||||
CPUArchId cpus[];
|
||||
} 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:
|
||||
* @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.
|
||||
* @numa_mem_supported:
|
||||
* 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:
|
||||
* If the hook is provided, then it'll be called for each device
|
||||
* hotplug to check whether the device hotplug is allowed. Return
|
||||
@ -209,7 +215,6 @@ struct MachineClass {
|
||||
void (*reset)(MachineState *state);
|
||||
void (*wakeup)(MachineState *state);
|
||||
int (*kvm_type)(MachineState *machine, const char *arg);
|
||||
void (*smp_parse)(MachineState *ms, SMPConfiguration *config, Error **errp);
|
||||
|
||||
BlockInterfaceType block_default_type;
|
||||
int units_per_default_bus;
|
||||
@ -247,6 +252,7 @@ struct MachineClass {
|
||||
bool nvdimm_supported;
|
||||
bool numa_mem_supported;
|
||||
bool auto_enable_numa;
|
||||
SMPCompatProps smp_props;
|
||||
const char *default_ram_id;
|
||||
|
||||
HotplugHandler *(*get_hotplug_handler)(MachineState *machine,
|
||||
@ -274,17 +280,18 @@ typedef struct DeviceMemoryState {
|
||||
/**
|
||||
* CpuTopology:
|
||||
* @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
|
||||
* @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
|
||||
*/
|
||||
typedef struct CpuTopology {
|
||||
unsigned int cpus;
|
||||
unsigned int sockets;
|
||||
unsigned int dies;
|
||||
unsigned int cores;
|
||||
unsigned int threads;
|
||||
unsigned int sockets;
|
||||
unsigned int max_cpus;
|
||||
} CpuTopology;
|
||||
|
||||
|
@ -1393,7 +1393,7 @@
|
||||
#
|
||||
# @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
|
||||
#
|
||||
|
@ -220,9 +220,14 @@ SRST
|
||||
Simulate a SMP system with '\ ``n``\ ' CPUs initially present on
|
||||
the machine type board. On boards supporting CPU hotplug, the optional
|
||||
'\ ``maxcpus``\ ' parameter can be set to enable further CPUs to be
|
||||
added at runtime. If omitted the maximum number of CPUs will be
|
||||
set to match the initial CPU count. Both parameters are subject to
|
||||
an upper limit that is determined by the specific machine type chosen.
|
||||
added at runtime. When both parameters are omitted, the maximum number
|
||||
of CPUs will be calculated from the provided topology members and the
|
||||
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,
|
||||
dies per socket, cores per die, and threads per core can be specified.
|
||||
@ -233,11 +238,14 @@ SRST
|
||||
of computing the CPU maximum count.
|
||||
|
||||
Either the initial CPU count, or at least one of the topology parameters
|
||||
must be specified. Values for any omitted parameters will be computed
|
||||
from those which are given. Historically preference was given to the
|
||||
coarsest topology parameters when computing missing values (ie sockets
|
||||
preferred over cores, which were preferred over threads), however, this
|
||||
behaviour is considered liable to change.
|
||||
must be specified. The specified parameters must be greater than zero,
|
||||
explicit configuration like "cpus=0" is not allowed. Values for any
|
||||
omitted parameters will be computed from those which are given.
|
||||
Historically preference was given to the coarsest topology parameters
|
||||
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
|
||||
|
||||
DEF("numa", HAS_ARG, QEMU_OPTION_numa,
|
||||
|
@ -6258,10 +6258,6 @@ static void x86_cpu_hyperv_realize(X86CPU *cpu)
|
||||
cpu->hyperv_interface_id[2] = 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 */
|
||||
cpu->hyperv_limits[0] = 64;
|
||||
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_2", obj, "sse4.2");
|
||||
|
||||
object_property_add_alias(obj, "hv-apicv", obj, "hv-avic");
|
||||
|
||||
if (xcc->model) {
|
||||
x86_cpu_load_model(cpu, xcc->model);
|
||||
}
|
||||
@ -6831,9 +6829,23 @@ static Property x86_cpu_properties[] = {
|
||||
HYPERV_FEAT_IPI, 0),
|
||||
DEFINE_PROP_BIT64("hv-stimer-direct", X86CPU, hyperv_features,
|
||||
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,
|
||||
hyperv_no_nonarch_cs, ON_OFF_AUTO_OFF),
|
||||
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("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("kvm-no-smi-migration", X86CPU, kvm_no_smi_migration,
|
||||
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("tcg-cpuid", X86CPU, expose_tcg, true),
|
||||
DEFINE_PROP_BOOL("x-migrate-smi-count", X86CPU, migrate_smi_count,
|
||||
|
@ -1056,6 +1056,7 @@ typedef uint64_t FeatureWordArray[FEATURE_WORDS];
|
||||
#define HYPERV_FEAT_EVMCS 12
|
||||
#define HYPERV_FEAT_IPI 13
|
||||
#define HYPERV_FEAT_STIMER_DIRECT 14
|
||||
#define HYPERV_FEAT_AVIC 15
|
||||
|
||||
#ifndef HYPERV_SPINLOCK_NEVER_NOTIFY
|
||||
#define HYPERV_SPINLOCK_NEVER_NOTIFY 0xFFFFFFFF
|
||||
@ -1716,9 +1717,15 @@ struct X86CPU {
|
||||
OnOffAuto hyperv_no_nonarch_cs;
|
||||
uint32_t hyperv_vendor_id[3];
|
||||
uint32_t hyperv_interface_id[4];
|
||||
uint32_t hyperv_version_id[4];
|
||||
uint32_t hyperv_limits[3];
|
||||
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 enforce_cpuid;
|
||||
@ -1802,6 +1809,9 @@ struct X86CPU {
|
||||
/* Stop SMI delivery for migration compatibility with old machines */
|
||||
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 */
|
||||
uint32_t phys_bits;
|
||||
|
||||
|
@ -66,6 +66,7 @@
|
||||
#define HV_APIC_ACCESS_RECOMMENDED (1u << 3)
|
||||
#define HV_SYSTEM_RESET_RECOMMENDED (1u << 4)
|
||||
#define HV_RELAXED_TIMING_RECOMMENDED (1u << 5)
|
||||
#define HV_DEPRECATING_AEOI_RECOMMENDED (1u << 9)
|
||||
#define HV_CLUSTER_IPI_RECOMMENDED (1u << 10)
|
||||
#define HV_EX_PROCESSOR_MASKS_RECOMMENDED (1u << 11)
|
||||
#define HV_ENLIGHTENED_VMCS_RECOMMENDED (1u << 14)
|
||||
|
@ -821,9 +821,7 @@ static struct {
|
||||
.desc = "virtual APIC (hv-vapic)",
|
||||
.flags = {
|
||||
{.func = HV_CPUID_FEATURES, .reg = R_EAX,
|
||||
.bits = HV_APIC_ACCESS_AVAILABLE},
|
||||
{.func = HV_CPUID_ENLIGHTMENT_INFO, .reg = R_EAX,
|
||||
.bits = HV_APIC_ACCESS_RECOMMENDED}
|
||||
.bits = HV_APIC_ACCESS_AVAILABLE}
|
||||
}
|
||||
},
|
||||
[HYPERV_FEAT_TIME] = {
|
||||
@ -926,6 +924,13 @@ static struct {
|
||||
},
|
||||
.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,
|
||||
@ -1253,14 +1258,18 @@ bool kvm_hyperv_expand_features(X86CPU *cpu, Error **errp)
|
||||
cpu->hyperv_interface_id[3] =
|
||||
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);
|
||||
cpu->hyperv_version_id[1] =
|
||||
hv_cpuid_get_host(cs, HV_CPUID_VERSION, R_EBX);
|
||||
cpu->hyperv_version_id[2] =
|
||||
cpu->hyperv_ver_id_major =
|
||||
hv_cpuid_get_host(cs, HV_CPUID_VERSION, R_EBX) >> 16;
|
||||
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);
|
||||
cpu->hyperv_version_id[3] =
|
||||
hv_cpuid_get_host(cs, HV_CPUID_VERSION, R_EDX);
|
||||
cpu->hyperv_ver_id_sb =
|
||||
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,
|
||||
R_EAX);
|
||||
@ -1346,10 +1355,12 @@ static int hyperv_fill_cpuids(CPUState *cs,
|
||||
|
||||
c = &cpuid_ent[cpuid_i++];
|
||||
c->function = HV_CPUID_VERSION;
|
||||
c->eax = cpu->hyperv_version_id[0];
|
||||
c->ebx = cpu->hyperv_version_id[1];
|
||||
c->ecx = cpu->hyperv_version_id[2];
|
||||
c->edx = cpu->hyperv_version_id[3];
|
||||
c->eax = cpu->hyperv_ver_id_build;
|
||||
c->ebx = (uint32_t)cpu->hyperv_ver_id_major << 16 |
|
||||
cpu->hyperv_ver_id_minor;
|
||||
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->function = HV_CPUID_FEATURES;
|
||||
@ -1366,6 +1377,7 @@ static int hyperv_fill_cpuids(CPUState *cs,
|
||||
c->ebx |= HV_POST_MESSAGES | HV_SIGNAL_EVENTS;
|
||||
}
|
||||
|
||||
|
||||
/* Not exposed by KVM but needed to make CPU hotplug in Windows work */
|
||||
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->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) {
|
||||
c->eax |= HV_NO_NONARCH_CORESHARING;
|
||||
} 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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@ -1629,6 +1655,16 @@ int kvm_arch_init_vcpu(CPUState *cs)
|
||||
|
||||
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++) {
|
||||
if (cpuid_i == KVM_MAX_CPUID_ENTRIES) {
|
||||
fprintf(stderr, "unsupported level value: 0x%x\n", limit);
|
||||
|
@ -42,7 +42,8 @@ static void test_def_cpu_split(const void *data)
|
||||
g_autofree char *s = 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);
|
||||
|
||||
s = qtest_hmp(qts, "info numa");
|
||||
@ -265,7 +266,8 @@ static void pc_dynamic_cpu_cfg(const void *data)
|
||||
QTestState *qs;
|
||||
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);
|
||||
|
||||
/* create 2 numa nodes */
|
||||
|
Loading…
Reference in New Issue
Block a user