mirror of https://gitee.com/openkylin/qemu.git
318 lines
15 KiB
ReStructuredText
318 lines
15 KiB
ReStructuredText
================
|
|
ARM CPU Features
|
|
================
|
|
|
|
Examples of probing and using ARM CPU features
|
|
|
|
Introduction
|
|
============
|
|
|
|
CPU features are optional features that a CPU of supporting type may
|
|
choose to implement or not. In QEMU, optional CPU features have
|
|
corresponding boolean CPU proprieties that, when enabled, indicate
|
|
that the feature is implemented, and, conversely, when disabled,
|
|
indicate that it is not implemented. An example of an ARM CPU feature
|
|
is the Performance Monitoring Unit (PMU). CPU types such as the
|
|
Cortex-A15 and the Cortex-A57, which respectively implement ARM
|
|
architecture reference manuals ARMv7-A and ARMv8-A, may both optionally
|
|
implement PMUs. For example, if a user wants to use a Cortex-A15 without
|
|
a PMU, then the `-cpu` parameter should contain `pmu=off` on the QEMU
|
|
command line, i.e. `-cpu cortex-a15,pmu=off`.
|
|
|
|
As not all CPU types support all optional CPU features, then whether or
|
|
not a CPU property exists depends on the CPU type. For example, CPUs
|
|
that implement the ARMv8-A architecture reference manual may optionally
|
|
support the AArch32 CPU feature, which may be enabled by disabling the
|
|
`aarch64` CPU property. A CPU type such as the Cortex-A15, which does
|
|
not implement ARMv8-A, will not have the `aarch64` CPU property.
|
|
|
|
QEMU's support may be limited for some CPU features, only partially
|
|
supporting the feature or only supporting the feature under certain
|
|
configurations. For example, the `aarch64` CPU feature, which, when
|
|
disabled, enables the optional AArch32 CPU feature, is only supported
|
|
when using the KVM accelerator and when running on a host CPU type that
|
|
supports the feature.
|
|
|
|
CPU Feature Probing
|
|
===================
|
|
|
|
Determining which CPU features are available and functional for a given
|
|
CPU type is possible with the `query-cpu-model-expansion` QMP command.
|
|
Below are some examples where `scripts/qmp/qmp-shell` (see the top comment
|
|
block in the script for usage) is used to issue the QMP commands.
|
|
|
|
1. Determine which CPU features are available for the `max` CPU type
|
|
(Note, we started QEMU with qemu-system-aarch64, so `max` is
|
|
implementing the ARMv8-A reference manual in this case)::
|
|
|
|
(QEMU) query-cpu-model-expansion type=full model={"name":"max"}
|
|
{ "return": {
|
|
"model": { "name": "max", "props": {
|
|
"sve1664": true, "pmu": true, "sve1792": true, "sve1920": true,
|
|
"sve128": true, "aarch64": true, "sve1024": true, "sve": true,
|
|
"sve640": true, "sve768": true, "sve1408": true, "sve256": true,
|
|
"sve1152": true, "sve512": true, "sve384": true, "sve1536": true,
|
|
"sve896": true, "sve1280": true, "sve2048": true
|
|
}}}}
|
|
|
|
We see that the `max` CPU type has the `pmu`, `aarch64`, `sve`, and many
|
|
`sve<N>` CPU features. We also see that all the CPU features are
|
|
enabled, as they are all `true`. (The `sve<N>` CPU features are all
|
|
optional SVE vector lengths (see "SVE CPU Properties"). While with TCG
|
|
all SVE vector lengths can be supported, when KVM is in use it's more
|
|
likely that only a few lengths will be supported, if SVE is supported at
|
|
all.)
|
|
|
|
(2) Let's try to disable the PMU::
|
|
|
|
(QEMU) query-cpu-model-expansion type=full model={"name":"max","props":{"pmu":false}}
|
|
{ "return": {
|
|
"model": { "name": "max", "props": {
|
|
"sve1664": true, "pmu": false, "sve1792": true, "sve1920": true,
|
|
"sve128": true, "aarch64": true, "sve1024": true, "sve": true,
|
|
"sve640": true, "sve768": true, "sve1408": true, "sve256": true,
|
|
"sve1152": true, "sve512": true, "sve384": true, "sve1536": true,
|
|
"sve896": true, "sve1280": true, "sve2048": true
|
|
}}}}
|
|
|
|
We see it worked, as `pmu` is now `false`.
|
|
|
|
(3) Let's try to disable `aarch64`, which enables the AArch32 CPU feature::
|
|
|
|
(QEMU) query-cpu-model-expansion type=full model={"name":"max","props":{"aarch64":false}}
|
|
{"error": {
|
|
"class": "GenericError", "desc":
|
|
"'aarch64' feature cannot be disabled unless KVM is enabled and 32-bit EL1 is supported"
|
|
}}
|
|
|
|
It looks like this feature is limited to a configuration we do not
|
|
currently have.
|
|
|
|
(4) Let's disable `sve` and see what happens to all the optional SVE
|
|
vector lengths::
|
|
|
|
(QEMU) query-cpu-model-expansion type=full model={"name":"max","props":{"sve":false}}
|
|
{ "return": {
|
|
"model": { "name": "max", "props": {
|
|
"sve1664": false, "pmu": true, "sve1792": false, "sve1920": false,
|
|
"sve128": false, "aarch64": true, "sve1024": false, "sve": false,
|
|
"sve640": false, "sve768": false, "sve1408": false, "sve256": false,
|
|
"sve1152": false, "sve512": false, "sve384": false, "sve1536": false,
|
|
"sve896": false, "sve1280": false, "sve2048": false
|
|
}}}}
|
|
|
|
As expected they are now all `false`.
|
|
|
|
(5) Let's try probing CPU features for the Cortex-A15 CPU type::
|
|
|
|
(QEMU) query-cpu-model-expansion type=full model={"name":"cortex-a15"}
|
|
{"return": {"model": {"name": "cortex-a15", "props": {"pmu": true}}}}
|
|
|
|
Only the `pmu` CPU feature is available.
|
|
|
|
A note about CPU feature dependencies
|
|
-------------------------------------
|
|
|
|
It's possible for features to have dependencies on other features. I.e.
|
|
it may be possible to change one feature at a time without error, but
|
|
when attempting to change all features at once an error could occur
|
|
depending on the order they are processed. It's also possible changing
|
|
all at once doesn't generate an error, because a feature's dependencies
|
|
are satisfied with other features, but the same feature cannot be changed
|
|
independently without error. For these reasons callers should always
|
|
attempt to make their desired changes all at once in order to ensure the
|
|
collection is valid.
|
|
|
|
A note about CPU models and KVM
|
|
-------------------------------
|
|
|
|
Named CPU models generally do not work with KVM. There are a few cases
|
|
that do work, e.g. using the named CPU model `cortex-a57` with KVM on a
|
|
seattle host, but mostly if KVM is enabled the `host` CPU type must be
|
|
used. This means the guest is provided all the same CPU features as the
|
|
host CPU type has. And, for this reason, the `host` CPU type should
|
|
enable all CPU features that the host has by default. Indeed it's even
|
|
a bit strange to allow disabling CPU features that the host has when using
|
|
the `host` CPU type, but in the absence of CPU models it's the best we can
|
|
do if we want to launch guests without all the host's CPU features enabled.
|
|
|
|
Enabling KVM also affects the `query-cpu-model-expansion` QMP command. The
|
|
affect is not only limited to specific features, as pointed out in example
|
|
(3) of "CPU Feature Probing", but also to which CPU types may be expanded.
|
|
When KVM is enabled, only the `max`, `host`, and current CPU type may be
|
|
expanded. This restriction is necessary as it's not possible to know all
|
|
CPU types that may work with KVM, but it does impose a small risk of users
|
|
experiencing unexpected errors. For example on a seattle, as mentioned
|
|
above, the `cortex-a57` CPU type is also valid when KVM is enabled.
|
|
Therefore a user could use the `host` CPU type for the current type, but
|
|
then attempt to query `cortex-a57`, however that query will fail with our
|
|
restrictions. This shouldn't be an issue though as management layers and
|
|
users have been preferring the `host` CPU type for use with KVM for quite
|
|
some time. Additionally, if the KVM-enabled QEMU instance running on a
|
|
seattle host is using the `cortex-a57` CPU type, then querying `cortex-a57`
|
|
will work.
|
|
|
|
Using CPU Features
|
|
==================
|
|
|
|
After determining which CPU features are available and supported for a
|
|
given CPU type, then they may be selectively enabled or disabled on the
|
|
QEMU command line with that CPU type::
|
|
|
|
$ qemu-system-aarch64 -M virt -cpu max,pmu=off,sve=on,sve128=on,sve256=on
|
|
|
|
The example above disables the PMU and enables the first two SVE vector
|
|
lengths for the `max` CPU type. Note, the `sve=on` isn't actually
|
|
necessary, because, as we observed above with our probe of the `max` CPU
|
|
type, `sve` is already on by default. Also, based on our probe of
|
|
defaults, it would seem we need to disable many SVE vector lengths, rather
|
|
than only enabling the two we want. This isn't the case, because, as
|
|
disabling many SVE vector lengths would be quite verbose, the `sve<N>` CPU
|
|
properties have special semantics (see "SVE CPU Property Parsing
|
|
Semantics").
|
|
|
|
SVE CPU Properties
|
|
==================
|
|
|
|
There are two types of SVE CPU properties: `sve` and `sve<N>`. The first
|
|
is used to enable or disable the entire SVE feature, just as the `pmu`
|
|
CPU property completely enables or disables the PMU. The second type
|
|
is used to enable or disable specific vector lengths, where `N` is the
|
|
number of bits of the length. The `sve<N>` CPU properties have special
|
|
dependencies and constraints, see "SVE CPU Property Dependencies and
|
|
Constraints" below. Additionally, as we want all supported vector lengths
|
|
to be enabled by default, then, in order to avoid overly verbose command
|
|
lines (command lines full of `sve<N>=off`, for all `N` not wanted), we
|
|
provide the parsing semantics listed in "SVE CPU Property Parsing
|
|
Semantics".
|
|
|
|
SVE CPU Property Dependencies and Constraints
|
|
---------------------------------------------
|
|
|
|
1) At least one vector length must be enabled when `sve` is enabled.
|
|
|
|
2) If a vector length `N` is enabled, then, when KVM is enabled, all
|
|
smaller, host supported vector lengths must also be enabled. If
|
|
KVM is not enabled, then only all the smaller, power-of-two vector
|
|
lengths must be enabled. E.g. with KVM if the host supports all
|
|
vector lengths up to 512-bits (128, 256, 384, 512), then if `sve512`
|
|
is enabled, the 128-bit vector length, 256-bit vector length, and
|
|
384-bit vector length must also be enabled. Without KVM, the 384-bit
|
|
vector length would not be required.
|
|
|
|
3) If KVM is enabled then only vector lengths that the host CPU type
|
|
support may be enabled. If SVE is not supported by the host, then
|
|
no `sve*` properties may be enabled.
|
|
|
|
SVE CPU Property Parsing Semantics
|
|
----------------------------------
|
|
|
|
1) If SVE is disabled (`sve=off`), then which SVE vector lengths
|
|
are enabled or disabled is irrelevant to the guest, as the entire
|
|
SVE feature is disabled and that disables all vector lengths for
|
|
the guest. However QEMU will still track any `sve<N>` CPU
|
|
properties provided by the user. If later an `sve=on` is provided,
|
|
then the guest will get only the enabled lengths. If no `sve=on`
|
|
is provided and there are explicitly enabled vector lengths, then
|
|
an error is generated.
|
|
|
|
2) If SVE is enabled (`sve=on`), but no `sve<N>` CPU properties are
|
|
provided, then all supported vector lengths are enabled, which when
|
|
KVM is not in use means including the non-power-of-two lengths, and,
|
|
when KVM is in use, it means all vector lengths supported by the host
|
|
processor.
|
|
|
|
3) If SVE is enabled, then an error is generated when attempting to
|
|
disable the last enabled vector length (see constraint (1) of "SVE
|
|
CPU Property Dependencies and Constraints").
|
|
|
|
4) If one or more vector lengths have been explicitly enabled and at
|
|
at least one of the dependency lengths of the maximum enabled length
|
|
has been explicitly disabled, then an error is generated (see
|
|
constraint (2) of "SVE CPU Property Dependencies and Constraints").
|
|
|
|
5) When KVM is enabled, if the host does not support SVE, then an error
|
|
is generated when attempting to enable any `sve*` properties (see
|
|
constraint (3) of "SVE CPU Property Dependencies and Constraints").
|
|
|
|
6) When KVM is enabled, if the host does support SVE, then an error is
|
|
generated when attempting to enable any vector lengths not supported
|
|
by the host (see constraint (3) of "SVE CPU Property Dependencies and
|
|
Constraints").
|
|
|
|
7) If one or more `sve<N>` CPU properties are set `off`, but no `sve<N>`,
|
|
CPU properties are set `on`, then the specified vector lengths are
|
|
disabled but the default for any unspecified lengths remains enabled.
|
|
When KVM is not enabled, disabling a power-of-two vector length also
|
|
disables all vector lengths larger than the power-of-two length.
|
|
When KVM is enabled, then disabling any supported vector length also
|
|
disables all larger vector lengths (see constraint (2) of "SVE CPU
|
|
Property Dependencies and Constraints").
|
|
|
|
8) If one or more `sve<N>` CPU properties are set to `on`, then they
|
|
are enabled and all unspecified lengths default to disabled, except
|
|
for the required lengths per constraint (2) of "SVE CPU Property
|
|
Dependencies and Constraints", which will even be auto-enabled if
|
|
they were not explicitly enabled.
|
|
|
|
9) If SVE was disabled (`sve=off`), allowing all vector lengths to be
|
|
explicitly disabled (i.e. avoiding the error specified in (3) of
|
|
"SVE CPU Property Parsing Semantics"), then if later an `sve=on` is
|
|
provided an error will be generated. To avoid this error, one must
|
|
enable at least one vector length prior to enabling SVE.
|
|
|
|
SVE CPU Property Examples
|
|
-------------------------
|
|
|
|
1) Disable SVE::
|
|
|
|
$ qemu-system-aarch64 -M virt -cpu max,sve=off
|
|
|
|
2) Implicitly enable all vector lengths for the `max` CPU type::
|
|
|
|
$ qemu-system-aarch64 -M virt -cpu max
|
|
|
|
3) When KVM is enabled, implicitly enable all host CPU supported vector
|
|
lengths with the `host` CPU type::
|
|
|
|
$ qemu-system-aarch64 -M virt,accel=kvm -cpu host
|
|
|
|
4) Only enable the 128-bit vector length::
|
|
|
|
$ qemu-system-aarch64 -M virt -cpu max,sve128=on
|
|
|
|
5) Disable the 512-bit vector length and all larger vector lengths,
|
|
since 512 is a power-of-two. This results in all the smaller,
|
|
uninitialized lengths (128, 256, and 384) defaulting to enabled::
|
|
|
|
$ qemu-system-aarch64 -M virt -cpu max,sve512=off
|
|
|
|
6) Enable the 128-bit, 256-bit, and 512-bit vector lengths::
|
|
|
|
$ qemu-system-aarch64 -M virt -cpu max,sve128=on,sve256=on,sve512=on
|
|
|
|
7) The same as (6), but since the 128-bit and 256-bit vector
|
|
lengths are required for the 512-bit vector length to be enabled,
|
|
then allow them to be auto-enabled::
|
|
|
|
$ qemu-system-aarch64 -M virt -cpu max,sve512=on
|
|
|
|
8) Do the same as (7), but by first disabling SVE and then re-enabling it::
|
|
|
|
$ qemu-system-aarch64 -M virt -cpu max,sve=off,sve512=on,sve=on
|
|
|
|
9) Force errors regarding the last vector length::
|
|
|
|
$ qemu-system-aarch64 -M virt -cpu max,sve128=off
|
|
$ qemu-system-aarch64 -M virt -cpu max,sve=off,sve128=off,sve=on
|
|
|
|
SVE CPU Property Recommendations
|
|
--------------------------------
|
|
|
|
The examples in "SVE CPU Property Examples" exhibit many ways to select
|
|
vector lengths which developers may find useful in order to avoid overly
|
|
verbose command lines. However, the recommended way to select vector
|
|
lengths is to explicitly enable each desired length. Therefore only
|
|
example's (1), (4), and (6) exhibit recommended uses of the properties.
|
|
|