* -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.
|
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)
|
||||||
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
|
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
|
||||||
|
@ -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.
|
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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.
|
||||||
|
@ -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
|
||||||
|
@ -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;
|
||||||
|
@ -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)
|
||||||
|
69
hw/i386/pc.c
69
hw/i386/pc.c
@ -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",
|
||||||
|
@ -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,
|
||||||
|
@ -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,
|
||||||
|
@ -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);
|
||||||
|
@ -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);
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
@ -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
|
||||||
#
|
#
|
||||||
|
@ -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,
|
||||||
|
@ -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,
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
@ -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)
|
||||||
|
@ -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);
|
||||||
|
@ -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 */
|
||||||
|
Loading…
Reference in New Issue
Block a user