* fix WHPX debugging

* misc qga-vss fixes
 * remove the deprecated CPU model 'Icelake-Client'
 * support for x86 architectural LBR
 * remove deprecated properties
 * replace deprecated -soundhw with -audio
 -----BEGIN PGP SIGNATURE-----
 
 iQFIBAABCAAyFiEE8TM4V0tmI4mGbHaCv/vSX3jHroMFAmJ/hZ4UHHBib256aW5p
 QHJlZGhhdC5jb20ACgkQv/vSX3jHroN2Igf/bFs+yluOikt0eFNmXYnshrGBWPXr
 oam0iumPox34vTzZnjpSjF6tJGxHWOgi+wbgIvbwOYHA/ONxx8akW580j+1VhEWa
 X29VyUzjZBffgFtmlF4fM74/ELYm7s4c1a1/D9TpVP6Dr0fSWbMujbx4dfeVstvf
 sONN+A8sVxaNdV9QKPE6BvqfMlPLoCiigrOetf6iY1KuUtkQDF8xDB0MdzdutqAQ
 szAtQ0rrzjxDx9EuGN1SECFM1/riDUbtOOoA9g2C7gGKrx3/iUc6pzrkIcAfWLFK
 xXbH7+6Wynia0cbUxnrvRdY4daMIxm4N3wUvN7szXgF9kxYxeQcsdgGsNA==
 =n4lu
 -----END PGP SIGNATURE-----

Merge tag 'for-upstream' of https://gitlab.com/bonzini/qemu into staging

* fix WHPX debugging
* misc qga-vss fixes
* remove the deprecated CPU model 'Icelake-Client'
* support for x86 architectural LBR
* remove deprecated properties
* replace deprecated -soundhw with -audio

# -----BEGIN PGP SIGNATURE-----
#
# iQFIBAABCAAyFiEE8TM4V0tmI4mGbHaCv/vSX3jHroMFAmJ/hZ4UHHBib256aW5p
# QHJlZGhhdC5jb20ACgkQv/vSX3jHroN2Igf/bFs+yluOikt0eFNmXYnshrGBWPXr
# oam0iumPox34vTzZnjpSjF6tJGxHWOgi+wbgIvbwOYHA/ONxx8akW580j+1VhEWa
# X29VyUzjZBffgFtmlF4fM74/ELYm7s4c1a1/D9TpVP6Dr0fSWbMujbx4dfeVstvf
# sONN+A8sVxaNdV9QKPE6BvqfMlPLoCiigrOetf6iY1KuUtkQDF8xDB0MdzdutqAQ
# szAtQ0rrzjxDx9EuGN1SECFM1/riDUbtOOoA9g2C7gGKrx3/iUc6pzrkIcAfWLFK
# xXbH7+6Wynia0cbUxnrvRdY4daMIxm4N3wUvN7szXgF9kxYxeQcsdgGsNA==
# =n4lu
# -----END PGP SIGNATURE-----
# gpg: Signature made Sat 14 May 2022 03:34:06 AM PDT
# gpg:                using RSA key F13338574B662389866C7682BFFBD25F78C7AE83
# gpg:                issuer "pbonzini@redhat.com"
# gpg: Good signature from "Paolo Bonzini <bonzini@gnu.org>" [undefined]
# gpg:                 aka "Paolo Bonzini <pbonzini@redhat.com>" [undefined]
# gpg: WARNING: This key is not certified with a trusted signature!
# gpg:          There is no indication that the signature belongs to the owner.
# Primary key fingerprint: 46F5 9FBD 57D6 12E7 BFD4  E2F7 7E15 100C CD36 69B1
#      Subkey fingerprint: F133 3857 4B66 2389 866C  7682 BFFB D25F 78C7 AE83

* tag 'for-upstream' of https://gitlab.com/bonzini/qemu: (23 commits)
  configure: remove duplicate help messages
  configure: remove another dead variable
  build: remove useless dependency
  introduce -audio as a replacement for -soundhw
  soundhw: move help handling to vl.c
  soundhw: unify initialization for ISA and PCI soundhw
  soundhw: extract soundhw help to a separate function
  soundhw: remove ability to create multiple soundcards
  rng: make opened property read-only
  crypto: make loaded property read-only
  target/i386: Support Arch LBR in CPUID enumeration
  target/i386: introduce helper to access supported CPUID
  target/i386: Enable Arch LBR migration states in vmstate
  target/i386: Add MSR access interface for Arch LBR
  target/i386: Add XSAVES support for Arch LBR
  target/i386: Enable support for XSAVES based features
  target/i386: Add kvm_get_one_msr helper
  target/i386: Add lbr-fmt vPMU option to support guest LBR
  qdev-properties: Add a new macro with bitmask check for uint64_t property
  i386/cpu: Remove the deprecated cpu model 'Icelake-Client'
  ...

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
This commit is contained in:
Richard Henderson 2022-05-16 14:21:50 -07:00
commit afdb415e67
25 changed files with 600 additions and 457 deletions

View File

@ -165,10 +165,7 @@ ifneq ($(filter $(ninja-targets), $(ninja-cmd-goals)),)
endif endif
endif endif
# Force configure to re-run if the API symbols are updated
ifeq ($(CONFIG_PLUGIN),y) ifeq ($(CONFIG_PLUGIN),y)
config-host.mak: $(SRC_PATH)/plugins/qemu-plugins.symbols
.PHONY: plugins .PHONY: plugins
plugins: plugins:
$(call quiet-command,\ $(call quiet-command,\

View File

@ -2099,13 +2099,19 @@ static void audio_validate_opts(Audiodev *dev, Error **errp)
void audio_parse_option(const char *opt) void audio_parse_option(const char *opt)
{ {
AudiodevListEntry *e;
Audiodev *dev = NULL; Audiodev *dev = NULL;
Visitor *v = qobject_input_visitor_new_str(opt, "driver", &error_fatal); Visitor *v = qobject_input_visitor_new_str(opt, "driver", &error_fatal);
visit_type_Audiodev(v, NULL, &dev, &error_fatal); visit_type_Audiodev(v, NULL, &dev, &error_fatal);
visit_free(v); visit_free(v);
audio_define(dev);
}
void audio_define(Audiodev *dev)
{
AudiodevListEntry *e;
audio_validate_opts(dev, &error_fatal); audio_validate_opts(dev, &error_fatal);
e = g_new0(AudiodevListEntry, 1); e = g_new0(AudiodevListEntry, 1);

View File

@ -168,6 +168,7 @@ void audio_sample_to_uint64(const void *samples, int pos,
void audio_sample_from_uint64(void *samples, int pos, void audio_sample_from_uint64(void *samples, int pos,
uint64_t left, uint64_t right); uint64_t left, uint64_t right);
void audio_define(Audiodev *audio);
void audio_parse_option(const char *opt); void audio_parse_option(const char *opt);
void audio_init_audiodevs(void); void audio_init_audiodevs(void);
void audio_legacy_help(void); void audio_legacy_help(void);

View File

@ -48,24 +48,10 @@ static bool rng_backend_prop_get_opened(Object *obj, Error **errp)
static void rng_backend_complete(UserCreatable *uc, Error **errp) static void rng_backend_complete(UserCreatable *uc, Error **errp)
{ {
object_property_set_bool(OBJECT(uc), "opened", true, errp); RngBackend *s = RNG_BACKEND(uc);
}
static void rng_backend_prop_set_opened(Object *obj, bool value, Error **errp)
{
RngBackend *s = RNG_BACKEND(obj);
RngBackendClass *k = RNG_BACKEND_GET_CLASS(s); RngBackendClass *k = RNG_BACKEND_GET_CLASS(s);
Error *local_err = NULL; Error *local_err = NULL;
if (value == s->opened) {
return;
}
if (!value && s->opened) {
error_setg(errp, QERR_PERMISSION_DENIED);
return;
}
if (k->opened) { if (k->opened) {
k->opened(s, &local_err); k->opened(s, &local_err);
if (local_err) { if (local_err) {
@ -122,7 +108,7 @@ static void rng_backend_class_init(ObjectClass *oc, void *data)
object_class_property_add_bool(oc, "opened", object_class_property_add_bool(oc, "opened",
rng_backend_prop_get_opened, rng_backend_prop_get_opened,
rng_backend_prop_set_opened); NULL);
} }
static const TypeInfo rng_backend_info = { static const TypeInfo rng_backend_info = {

5
configure vendored
View File

@ -1043,10 +1043,6 @@ Advanced options (experts only):
--enable-tsan enable thread sanitizer --enable-tsan enable thread sanitizer
--disable-werror disable compilation abort on warning --disable-werror disable compilation abort on warning
--disable-stack-protector disable compiler-provided stack protection --disable-stack-protector disable compiler-provided stack protection
--audio-drv-list=LIST set audio drivers to try if -audiodev is not used
--block-drv-whitelist=L Same as --block-drv-rw-whitelist=L
--with-trace-file=NAME Full PATH,NAME of file to store traces
Default:trace-<pid>
--cpu=CPU Build for host CPU [$cpu] --cpu=CPU Build for host CPU [$cpu]
--with-coroutine=BACKEND coroutine backend. Supported options: --with-coroutine=BACKEND coroutine backend. Supported options:
ucontext, sigaltstack, windows ucontext, sigaltstack, windows
@ -1992,7 +1988,6 @@ fi
if test "$static" = "yes" ; then if test "$static" = "yes" ; then
echo "CONFIG_STATIC=y" >> $config_host_mak echo "CONFIG_STATIC=y" >> $config_host_mak
fi fi
qemu_version=$(head $source_path/VERSION)
echo "SRC_PATH=$source_path" >> $config_host_mak echo "SRC_PATH=$source_path" >> $config_host_mak
echo "TARGET_DIRS=$target_list" >> $config_host_mak echo "TARGET_DIRS=$target_list" >> $config_host_mak
if test "$modules" = "yes"; then if test "$modules" = "yes"; then

View File

@ -138,36 +138,44 @@ static void qcrypto_secret_decode(const uint8_t *input,
static void static void
qcrypto_secret_prop_set_loaded(Object *obj, qcrypto_secret_complete(UserCreatable *uc, Error **errp)
bool value,
Error **errp)
{ {
QCryptoSecretCommon *secret = QCRYPTO_SECRET_COMMON(obj); QCryptoSecretCommon *secret = QCRYPTO_SECRET_COMMON(uc);
QCryptoSecretCommonClass *sec_class QCryptoSecretCommonClass *sec_class
= QCRYPTO_SECRET_COMMON_GET_CLASS(obj); = QCRYPTO_SECRET_COMMON_GET_CLASS(uc);
if (value) { Error *local_err = NULL;
Error *local_err = NULL; uint8_t *input = NULL;
uint8_t *input = NULL; size_t inputlen = 0;
size_t inputlen = 0; uint8_t *output = NULL;
uint8_t *output = NULL; size_t outputlen = 0;
size_t outputlen = 0;
if (sec_class->load_data) { if (sec_class->load_data) {
sec_class->load_data(secret, &input, &inputlen, &local_err); sec_class->load_data(secret, &input, &inputlen, &local_err);
if (local_err) { if (local_err) {
error_propagate(errp, local_err); error_propagate(errp, local_err);
return;
}
} else {
error_setg(errp, "%s provides no 'load_data' method'",
object_get_typename(obj));
return; return;
} }
} else {
error_setg(errp, "%s provides no 'load_data' method'",
object_get_typename(OBJECT(uc)));
return;
}
if (secret->keyid) { if (secret->keyid) {
qcrypto_secret_decrypt(secret, input, inputlen, qcrypto_secret_decrypt(secret, input, inputlen,
&output, &outputlen, &local_err); &output, &outputlen, &local_err);
g_free(input);
if (local_err) {
error_propagate(errp, local_err);
return;
}
input = output;
inputlen = outputlen;
} else {
if (secret->format == QCRYPTO_SECRET_FORMAT_BASE64) {
qcrypto_secret_decode(input, inputlen,
&output, &outputlen, &local_err);
g_free(input); g_free(input);
if (local_err) { if (local_err) {
error_propagate(errp, local_err); error_propagate(errp, local_err);
@ -175,26 +183,11 @@ qcrypto_secret_prop_set_loaded(Object *obj,
} }
input = output; input = output;
inputlen = outputlen; inputlen = outputlen;
} else {
if (secret->format == QCRYPTO_SECRET_FORMAT_BASE64) {
qcrypto_secret_decode(input, inputlen,
&output, &outputlen, &local_err);
g_free(input);
if (local_err) {
error_propagate(errp, local_err);
return;
}
input = output;
inputlen = outputlen;
}
} }
secret->rawdata = input;
secret->rawlen = inputlen;
} else if (secret->rawdata) {
error_setg(errp, "Cannot unload secret");
return;
} }
secret->rawdata = input;
secret->rawlen = inputlen;
} }
@ -268,13 +261,6 @@ qcrypto_secret_prop_get_keyid(Object *obj,
} }
static void
qcrypto_secret_complete(UserCreatable *uc, Error **errp)
{
object_property_set_bool(OBJECT(uc), "loaded", true, errp);
}
static void static void
qcrypto_secret_finalize(Object *obj) qcrypto_secret_finalize(Object *obj)
{ {
@ -294,7 +280,7 @@ qcrypto_secret_class_init(ObjectClass *oc, void *data)
object_class_property_add_bool(oc, "loaded", object_class_property_add_bool(oc, "loaded",
qcrypto_secret_prop_get_loaded, qcrypto_secret_prop_get_loaded,
qcrypto_secret_prop_set_loaded); NULL);
object_class_property_add_enum(oc, "format", object_class_property_add_enum(oc, "format",
"QCryptoSecretFormat", "QCryptoSecretFormat",
&QCryptoSecretFormat_lookup, &QCryptoSecretFormat_lookup,

View File

@ -119,16 +119,11 @@ qcrypto_tls_creds_anon_unload(QCryptoTLSCredsAnon *creds G_GNUC_UNUSED)
static void static void
qcrypto_tls_creds_anon_prop_set_loaded(Object *obj, qcrypto_tls_creds_anon_complete(UserCreatable *uc, Error **errp)
bool value,
Error **errp)
{ {
QCryptoTLSCredsAnon *creds = QCRYPTO_TLS_CREDS_ANON(obj); QCryptoTLSCredsAnon *creds = QCRYPTO_TLS_CREDS_ANON(uc);
qcrypto_tls_creds_anon_unload(creds); qcrypto_tls_creds_anon_load(creds, errp);
if (value) {
qcrypto_tls_creds_anon_load(creds, errp);
}
} }
@ -163,13 +158,6 @@ qcrypto_tls_creds_anon_prop_get_loaded(Object *obj G_GNUC_UNUSED,
#endif /* ! CONFIG_GNUTLS */ #endif /* ! CONFIG_GNUTLS */
static void
qcrypto_tls_creds_anon_complete(UserCreatable *uc, Error **errp)
{
object_property_set_bool(OBJECT(uc), "loaded", true, errp);
}
static void static void
qcrypto_tls_creds_anon_finalize(Object *obj) qcrypto_tls_creds_anon_finalize(Object *obj)
{ {
@ -188,7 +176,7 @@ qcrypto_tls_creds_anon_class_init(ObjectClass *oc, void *data)
object_class_property_add_bool(oc, "loaded", object_class_property_add_bool(oc, "loaded",
qcrypto_tls_creds_anon_prop_get_loaded, qcrypto_tls_creds_anon_prop_get_loaded,
qcrypto_tls_creds_anon_prop_set_loaded); NULL);
} }

View File

@ -188,16 +188,11 @@ qcrypto_tls_creds_psk_unload(QCryptoTLSCredsPSK *creds G_GNUC_UNUSED)
static void static void
qcrypto_tls_creds_psk_prop_set_loaded(Object *obj, qcrypto_tls_creds_psk_complete(UserCreatable *uc, Error **errp)
bool value,
Error **errp)
{ {
QCryptoTLSCredsPSK *creds = QCRYPTO_TLS_CREDS_PSK(obj); QCryptoTLSCredsPSK *creds = QCRYPTO_TLS_CREDS_PSK(uc);
qcrypto_tls_creds_psk_unload(creds); qcrypto_tls_creds_psk_load(creds, errp);
if (value) {
qcrypto_tls_creds_psk_load(creds, errp);
}
} }
@ -232,13 +227,6 @@ qcrypto_tls_creds_psk_prop_get_loaded(Object *obj G_GNUC_UNUSED,
#endif /* ! CONFIG_GNUTLS */ #endif /* ! CONFIG_GNUTLS */
static void
qcrypto_tls_creds_psk_complete(UserCreatable *uc, Error **errp)
{
object_property_set_bool(OBJECT(uc), "loaded", true, errp);
}
static void static void
qcrypto_tls_creds_psk_finalize(Object *obj) qcrypto_tls_creds_psk_finalize(Object *obj)
{ {
@ -276,7 +264,7 @@ qcrypto_tls_creds_psk_class_init(ObjectClass *oc, void *data)
object_class_property_add_bool(oc, "loaded", object_class_property_add_bool(oc, "loaded",
qcrypto_tls_creds_psk_prop_get_loaded, qcrypto_tls_creds_psk_prop_get_loaded,
qcrypto_tls_creds_psk_prop_set_loaded); NULL);
object_class_property_add_str(oc, "username", object_class_property_add_str(oc, "username",
qcrypto_tls_creds_psk_prop_get_username, qcrypto_tls_creds_psk_prop_get_username,
qcrypto_tls_creds_psk_prop_set_username); qcrypto_tls_creds_psk_prop_set_username);

View File

@ -687,16 +687,11 @@ qcrypto_tls_creds_x509_unload(QCryptoTLSCredsX509 *creds G_GNUC_UNUSED)
static void static void
qcrypto_tls_creds_x509_prop_set_loaded(Object *obj, qcrypto_tls_creds_x509_complete(UserCreatable *uc, Error **errp)
bool value,
Error **errp)
{ {
QCryptoTLSCredsX509 *creds = QCRYPTO_TLS_CREDS_X509(obj); QCryptoTLSCredsX509 *creds = QCRYPTO_TLS_CREDS_X509(uc);
qcrypto_tls_creds_x509_unload(creds); qcrypto_tls_creds_x509_load(creds, errp);
if (value) {
qcrypto_tls_creds_x509_load(creds, errp);
}
} }
@ -814,13 +809,6 @@ qcrypto_tls_creds_x509_reload(QCryptoTLSCreds *creds, Error **errp)
#endif /* ! CONFIG_GNUTLS */ #endif /* ! CONFIG_GNUTLS */
static void
qcrypto_tls_creds_x509_complete(UserCreatable *uc, Error **errp)
{
object_property_set_bool(OBJECT(uc), "loaded", true, errp);
}
static void static void
qcrypto_tls_creds_x509_init(Object *obj) qcrypto_tls_creds_x509_init(Object *obj)
{ {
@ -852,7 +840,7 @@ qcrypto_tls_creds_x509_class_init(ObjectClass *oc, void *data)
object_class_property_add_bool(oc, "loaded", object_class_property_add_bool(oc, "loaded",
qcrypto_tls_creds_x509_prop_get_loaded, qcrypto_tls_creds_x509_prop_get_loaded,
qcrypto_tls_creds_x509_prop_set_loaded); NULL);
object_class_property_add_bool(oc, "sanity-check", object_class_property_add_bool(oc, "sanity-check",
qcrypto_tls_creds_x509_prop_get_sanity, qcrypto_tls_creds_x509_prop_get_sanity,
qcrypto_tls_creds_x509_prop_set_sanity); qcrypto_tls_creds_x509_prop_set_sanity);

View File

@ -39,15 +39,6 @@ should specify an ``audiodev=`` property. Additionally, when using
vnc, you should specify an ``audiodev=`` property if you plan to vnc, you should specify an ``audiodev=`` property if you plan to
transmit audio through the VNC protocol. transmit audio through the VNC protocol.
Creating sound card devices using ``-soundhw`` (since 5.1)
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Sound card devices should be created using ``-device`` instead. The
names are the same for most devices. The exceptions are ``hda`` which
needs two devices (``-device intel-hda -device hda-duplex``) and
``pcspk`` which can be activated using ``-machine
pcspk-audiodev=<name>``.
``-chardev`` backend aliases ``tty`` and ``parport`` (since 6.0) ``-chardev`` backend aliases ``tty`` and ``parport`` (since 6.0)
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
@ -90,25 +81,6 @@ the process listing. This is replaced by the new ``password-secret``
option which lets the password be securely provided on the command option which lets the password be securely provided on the command
line using a ``secret`` object instance. line using a ``secret`` object instance.
``opened`` property of ``rng-*`` objects (since 6.0)
''''''''''''''''''''''''''''''''''''''''''''''''''''
The only effect of specifying ``opened=on`` in the command line or QMP
``object-add`` is that the device is opened immediately, possibly before all
other options have been processed. This will either have no effect (if
``opened`` was the last option) or cause errors. The property is therefore
useless and should not be specified.
``loaded`` property of ``secret`` and ``secret_keyring`` objects (since 6.0)
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
The only effect of specifying ``loaded=on`` in the command line or QMP
``object-add`` is that the secret is loaded immediately, possibly before all
other options have been processed. This will either have no effect (if
``loaded`` was the last option) or cause options to be effectively ignored as
if they were not given. The property is therefore useless and should not be
specified.
``-display sdl,window_close=...`` (since 6.1) ``-display sdl,window_close=...`` (since 6.1)
''''''''''''''''''''''''''''''''''''''''''''' '''''''''''''''''''''''''''''''''''''''''''''
@ -270,12 +242,6 @@ from Linux upstream kernel, declare it deprecated.
System emulator CPUS System emulator CPUS
-------------------- --------------------
``Icelake-Client`` CPU Model (since 5.2)
''''''''''''''''''''''''''''''''''''''''
``Icelake-Client`` CPU Models are deprecated. Use ``Icelake-Server`` CPU
Models instead.
MIPS ``I7200`` CPU Model (since 5.2) MIPS ``I7200`` CPU Model (since 5.2)
'''''''''''''''''''''''''''''''''''' ''''''''''''''''''''''''''''''''''''

View File

@ -355,6 +355,21 @@ The ``-writeconfig`` option was not able to serialize the entire contents
of the QEMU command line. It is thus considered a failed experiment of the QEMU command line. It is thus considered a failed experiment
and removed without a replacement. and removed without a replacement.
``loaded`` property of ``secret`` and ``secret_keyring`` objects (removed in 7.1)
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
The ``loaded=on`` option in the command line or QMP ``object-add`` either had
no effect (if ``loaded`` was the last option) or caused options to be
effectively ignored as if they were not given. The property is therefore
useless and should simply be removed.
``opened`` property of ``rng-*`` objects (removed in 7.1)
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''
The ``opened=on`` option in the command line or QMP ``object-add`` either had
no effect (if ``opened`` was the last option) or caused errors. The property
is therefore useless and should simply be removed.
QEMU Machine Protocol (QMP) commands QEMU Machine Protocol (QMP) commands
------------------------------------ ------------------------------------
@ -557,6 +572,12 @@ Support for this CPU was removed from the upstream Linux kernel, and
there is no available upstream toolchain to build binaries for it. there is no available upstream toolchain to build binaries for it.
Removed without replacement. Removed without replacement.
x86 ``Icelake-Client`` CPU (removed in 7.1)
'''''''''''''''''''''''''''''''''''''''''''
There isn't ever Icelake Client CPU, it is some wrong and imaginary one.
Use ``Icelake-Server`` instead.
System emulator machines System emulator machines
------------------------ ------------------------
@ -633,6 +654,13 @@ tripped up the CI testing and was suspected to be quite broken. For that
reason the maintainers strongly suspected no one actually used it. reason the maintainers strongly suspected no one actually used it.
Creating sound card devices using ``-soundhw`` (removed in 7.1)
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Sound card devices should be created using ``-device`` or ``-audio``.
The exception is ``pcspk`` which can be activated using ``-machine
pcspk-audiodev=<name>``.
TCG introspection features TCG introspection features
-------------------------- --------------------------

View File

@ -1311,17 +1311,16 @@ static const TypeInfo hda_codec_device_type_info = {
* create intel hda controller with codec attached to it, * create intel hda controller with codec attached to it,
* so '-soundhw hda' works. * so '-soundhw hda' works.
*/ */
static int intel_hda_and_codec_init(PCIBus *bus) static int intel_hda_and_codec_init(PCIBus *bus, const char *audiodev)
{ {
DeviceState *controller; DeviceState *controller;
BusState *hdabus; BusState *hdabus;
DeviceState *codec; DeviceState *codec;
warn_report("'-soundhw hda' is deprecated, "
"please use '-device intel-hda -device hda-duplex' instead");
controller = DEVICE(pci_create_simple(bus, -1, "intel-hda")); controller = DEVICE(pci_create_simple(bus, -1, "intel-hda"));
hdabus = QLIST_FIRST(&controller->child_bus); hdabus = QLIST_FIRST(&controller->child_bus);
codec = qdev_new("hda-duplex"); codec = qdev_new("hda-duplex");
qdev_prop_set_string(codec, "audiodev", audiodev);
qdev_realize_and_unref(codec, hdabus, &error_fatal); qdev_realize_and_unref(codec, hdabus, &error_fatal);
return 0; return 0;
} }

View File

@ -25,7 +25,9 @@
#include "qemu/option.h" #include "qemu/option.h"
#include "qemu/help_option.h" #include "qemu/help_option.h"
#include "qemu/error-report.h" #include "qemu/error-report.h"
#include "qapi/error.h"
#include "qom/object.h" #include "qom/object.h"
#include "hw/qdev-properties.h"
#include "hw/isa/isa.h" #include "hw/isa/isa.h"
#include "hw/pci/pci.h" #include "hw/pci/pci.h"
#include "hw/audio/soundhw.h" #include "hw/audio/soundhw.h"
@ -34,16 +36,15 @@ struct soundhw {
const char *name; const char *name;
const char *descr; const char *descr;
const char *typename; const char *typename;
int enabled;
int isa; int isa;
int (*init_pci) (PCIBus *bus); int (*init_pci) (PCIBus *bus, const char *audiodev);
}; };
static struct soundhw soundhw[9]; static struct soundhw soundhw[9];
static int soundhw_count; static int soundhw_count;
void pci_register_soundhw(const char *name, const char *descr, void pci_register_soundhw(const char *name, const char *descr,
int (*init_pci)(PCIBus *bus)) int (*init_pci)(PCIBus *bus, const char *audiodev))
{ {
assert(soundhw_count < ARRAY_SIZE(soundhw) - 1); assert(soundhw_count < ARRAY_SIZE(soundhw) - 1);
soundhw[soundhw_count].name = name; soundhw[soundhw_count].name = name;
@ -64,95 +65,78 @@ void deprecated_register_soundhw(const char *name, const char *descr,
soundhw_count++; soundhw_count++;
} }
void select_soundhw(const char *optarg) void show_valid_soundhw(void)
{ {
struct soundhw *c; struct soundhw *c;
if (is_help_option(optarg)) { if (soundhw_count) {
show_valid_cards: printf("Valid sound card names (comma separated):\n");
for (c = soundhw; c->name; ++c) {
if (soundhw_count) { printf ("%-11s %s\n", c->name, c->descr);
printf("Valid sound card names (comma separated):\n"); }
for (c = soundhw; c->name; ++c) { } else {
printf ("%-11s %s\n", c->name, c->descr); printf("Machine has no user-selectable audio hardware "
} "(it may or may not have always-present audio hardware).\n");
printf("\n-soundhw all will enable all of the above\n");
} else {
printf("Machine has no user-selectable audio hardware "
"(it may or may not have always-present audio hardware).\n");
}
exit(!is_help_option(optarg));
} }
else { }
size_t l;
const char *p;
char *e;
int bad_card = 0;
if (!strcmp(optarg, "all")) { static struct soundhw *selected = NULL;
for (c = soundhw; c->name; ++c) { static const char *audiodev_id;
c->enabled = 1;
} void select_soundhw(const char *optarg, const char *audiodev)
return; {
struct soundhw *c;
if (selected) {
error_setg(&error_fatal, "only one -soundhw option is allowed");
}
for (c = soundhw; c->name; ++c) {
if (g_str_equal(c->name, optarg)) {
selected = c;
audiodev_id = audiodev;
break;
} }
}
p = optarg; if (!c->name) {
while (*p) { error_report("Unknown sound card name `%s'", optarg);
e = strchr(p, ','); show_valid_soundhw();
l = !e ? strlen(p) : (size_t) (e - p); exit(1);
for (c = soundhw; c->name; ++c) {
if (!strncmp(c->name, p, l) && !c->name[l]) {
c->enabled = 1;
break;
}
}
if (!c->name) {
if (l > 80) {
error_report("Unknown sound card name (too big to show)");
}
else {
error_report("Unknown sound card name `%.*s'",
(int) l, p);
}
bad_card = 1;
}
p += l + (e != NULL);
}
if (bad_card) {
goto show_valid_cards;
}
} }
} }
void soundhw_init(void) void soundhw_init(void)
{ {
struct soundhw *c; struct soundhw *c = selected;
ISABus *isa_bus = (ISABus *) object_resolve_path_type("", TYPE_ISA_BUS, NULL); ISABus *isa_bus = (ISABus *) object_resolve_path_type("", TYPE_ISA_BUS, NULL);
PCIBus *pci_bus = (PCIBus *) object_resolve_path_type("", TYPE_PCI_BUS, NULL); PCIBus *pci_bus = (PCIBus *) object_resolve_path_type("", TYPE_PCI_BUS, NULL);
BusState *bus;
for (c = soundhw; c->name; ++c) { if (!c) {
if (c->enabled) { return;
if (c->typename) { }
warn_report("'-soundhw %s' is deprecated, " if (c->isa) {
"please use '-device %s' instead", if (!isa_bus) {
c->name, c->typename); error_report("ISA bus not available for %s", c->name);
if (c->isa) { exit(1);
isa_create_simple(isa_bus, c->typename);
} else {
pci_create_simple(pci_bus, -1, c->typename);
}
} else {
assert(!c->isa);
if (!pci_bus) {
error_report("PCI bus not available for %s", c->name);
exit(1);
}
c->init_pci(pci_bus);
}
} }
bus = BUS(isa_bus);
} else {
if (!pci_bus) {
error_report("PCI bus not available for %s", c->name);
exit(1);
}
bus = BUS(pci_bus);
}
if (c->typename) {
DeviceState *dev = qdev_new(c->typename);
qdev_prop_set_string(dev, "audiodev", audiodev_id);
qdev_realize_and_unref(dev, bus, &error_fatal);
} else {
assert(!c->isa);
c->init_pci(pci_bus, audiodev_id);
} }
} }

View File

@ -428,6 +428,25 @@ const PropertyInfo qdev_prop_int64 = {
.set_default_value = qdev_propinfo_set_default_value_int, .set_default_value = qdev_propinfo_set_default_value_int,
}; };
static void set_uint64_checkmask(Object *obj, Visitor *v, const char *name,
void *opaque, Error **errp)
{
Property *prop = opaque;
uint64_t *ptr = object_field_prop_ptr(obj, prop);
visit_type_uint64(v, name, ptr, errp);
if (*ptr & ~prop->bitmask) {
error_setg(errp, "Property value for '%s' has bits outside mask '0x%" PRIx64 "'",
name, prop->bitmask);
}
}
const PropertyInfo qdev_prop_uint64_checkmask = {
.name = "uint64",
.get = get_uint64,
.set = set_uint64_checkmask,
};
/* --- string --- */ /* --- string --- */
static void release_string(Object *obj, const char *name, void *opaque) static void release_string(Object *obj, const char *name, void *opaque)

View File

@ -2,11 +2,12 @@
#define HW_SOUNDHW_H #define HW_SOUNDHW_H
void pci_register_soundhw(const char *name, const char *descr, void pci_register_soundhw(const char *name, const char *descr,
int (*init_pci)(PCIBus *bus)); int (*init_pci)(PCIBus *bus, const char *audiodev));
void deprecated_register_soundhw(const char *name, const char *descr, void deprecated_register_soundhw(const char *name, const char *descr,
int isa, const char *typename); int isa, const char *typename);
void soundhw_init(void); void soundhw_init(void);
void select_soundhw(const char *optarg); void show_valid_soundhw(void);
void select_soundhw(const char *optarg, const char *audiodev);
#endif #endif

View File

@ -17,6 +17,7 @@ struct Property {
const PropertyInfo *info; const PropertyInfo *info;
ptrdiff_t offset; ptrdiff_t offset;
uint8_t bitnr; uint8_t bitnr;
uint64_t bitmask;
bool set_default; bool set_default;
union { union {
int64_t i; int64_t i;
@ -54,6 +55,7 @@ extern const PropertyInfo qdev_prop_uint16;
extern const PropertyInfo qdev_prop_uint32; extern const PropertyInfo qdev_prop_uint32;
extern const PropertyInfo qdev_prop_int32; extern const PropertyInfo qdev_prop_int32;
extern const PropertyInfo qdev_prop_uint64; extern const PropertyInfo qdev_prop_uint64;
extern const PropertyInfo qdev_prop_uint64_checkmask;
extern const PropertyInfo qdev_prop_int64; extern const PropertyInfo qdev_prop_int64;
extern const PropertyInfo qdev_prop_size; extern const PropertyInfo qdev_prop_size;
extern const PropertyInfo qdev_prop_string; extern const PropertyInfo qdev_prop_string;
@ -103,6 +105,16 @@ extern const PropertyInfo qdev_prop_link;
.set_default = true, \ .set_default = true, \
.defval.u = (bool)_defval) .defval.u = (bool)_defval)
/**
* The DEFINE_PROP_UINT64_CHECKMASK macro checks a user-supplied value
* against corresponding bitmask, rejects the value if it violates.
* The default value is set in instance_init().
*/
#define DEFINE_PROP_UINT64_CHECKMASK(_name, _state, _field, _bitmask) \
DEFINE_PROP(_name, _state, _field, qdev_prop_uint64_checkmask, uint64_t, \
.bitmask = (_bitmask), \
.set_default = false)
#define PROP_ARRAY_LEN_PREFIX "len-" #define PROP_ARRAY_LEN_PREFIX "len-"
/** /**

View File

@ -661,6 +661,30 @@ SRST
(deprecated) environment variables. (deprecated) environment variables.
ERST ERST
DEF("audio", HAS_ARG, QEMU_OPTION_audio,
"-audio [driver=]driver,model=value[,prop[=value][,...]]\n"
" specifies the audio backend and device to use;\n"
" apart from 'model', options are the same as for -audiodev.\n"
" use '-audio model=help' to show possible devices.\n",
QEMU_ARCH_ALL)
SRST
``-audio [driver=]driver,model=value[,prop[=value][,...]]``
This option is a shortcut for configuring both the guest audio
hardware and the host audio backend in one go.
The host backend options are the same as with the corresponding
``-audiodev`` options below. The guest hardware model can be set with
``model=modelname``. Use ``model=help`` to list the available device
types.
The following two example do exactly the same, to show how ``-audio``
can be used to shorten the command line length:
.. parsed-literal::
|qemu_system| -audiodev pa,id=pa -device sb16,audiodev=pa
|qemu_system| -audio pa,model=sb16
ERST
DEF("audiodev", HAS_ARG, QEMU_OPTION_audiodev, DEF("audiodev", HAS_ARG, QEMU_OPTION_audiodev,
"-audiodev [driver=]driver,id=id[,prop[=value][,...]]\n" "-audiodev [driver=]driver,id=id[,prop[=value][,...]]\n"
" specifies the audio backend to use\n" " specifies the audio backend to use\n"
@ -892,33 +916,6 @@ SRST
``qemu.wav``. ``qemu.wav``.
ERST ERST
DEF("soundhw", HAS_ARG, QEMU_OPTION_soundhw,
"-soundhw c1,... enable audio support\n"
" and only specified sound cards (comma separated list)\n"
" use '-soundhw help' to get the list of supported cards\n"
" use '-soundhw all' to enable all of them\n", QEMU_ARCH_ALL)
SRST
``-soundhw card1[,card2,...] or -soundhw all``
Enable audio and selected sound hardware. Use 'help' to print all
available sound hardware. For example:
.. parsed-literal::
|qemu_system_x86| -soundhw sb16,adlib disk.img
|qemu_system_x86| -soundhw es1370 disk.img
|qemu_system_x86| -soundhw ac97 disk.img
|qemu_system_x86| -soundhw hda disk.img
|qemu_system_x86| -soundhw all disk.img
|qemu_system_x86| -soundhw help
Note that Linux's i810\_audio OSS kernel (for AC97) module might
require manually specifying clocking.
::
modprobe i810_audio clocking=48000
ERST
DEF("device", HAS_ARG, QEMU_OPTION_device, DEF("device", HAS_ARG, QEMU_OPTION_device,
"-device driver[,prop[=value][,...]]\n" "-device driver[,prop[=value][,...]]\n"
" add device (based on driver)\n" " add device (based on driver)\n"

View File

@ -7,7 +7,7 @@ link_args = cc.get_supported_link_arguments([
qga_vss = shared_module( qga_vss = shared_module(
'qga-vss', 'qga-vss',
['requester.cpp', 'provider.cpp', 'install.cpp'], ['requester.cpp', 'provider.cpp', 'install.cpp', genh],
name_prefix: '', name_prefix: '',
cpp_args: ['-Wno-unknown-pragmas', '-Wno-delete-non-virtual-dtor', '-Wno-non-virtual-dtor'], cpp_args: ['-Wno-unknown-pragmas', '-Wno-delete-non-virtual-dtor', '-Wno-non-virtual-dtor'],
link_args: link_args, link_args: link_args,

View File

@ -354,12 +354,12 @@ void requester_freeze(int *num_vols, void *mountpoints, ErrorSet *errset)
if (FAILED(hr)) { if (FAILED(hr)) {
err_set(errset, hr, "failed to add %S to snapshot set", err_set(errset, hr, "failed to add %S to snapshot set",
volume_name_wchar); volume_name_wchar);
delete volume_name_wchar; delete[] volume_name_wchar;
goto out; goto out;
} }
num_mount_points++; num_mount_points++;
delete volume_name_wchar; delete[] volume_name_wchar;
} }
if (num_mount_points == 0) { if (num_mount_points == 0) {

View File

@ -116,6 +116,8 @@
#include "crypto/init.h" #include "crypto/init.h"
#include "sysemu/replay.h" #include "sysemu/replay.h"
#include "qapi/qapi-events-run-state.h" #include "qapi/qapi-events-run-state.h"
#include "qapi/qapi-types-audio.h"
#include "qapi/qapi-visit-audio.h"
#include "qapi/qapi-visit-block-core.h" #include "qapi/qapi-visit-block-core.h"
#include "qapi/qapi-visit-compat.h" #include "qapi/qapi-visit-compat.h"
#include "qapi/qapi-visit-ui.h" #include "qapi/qapi-visit-ui.h"
@ -2930,9 +2932,33 @@ void qemu_init(int argc, char **argv, char **envp)
case QEMU_OPTION_audiodev: case QEMU_OPTION_audiodev:
audio_parse_option(optarg); audio_parse_option(optarg);
break; break;
case QEMU_OPTION_soundhw: case QEMU_OPTION_audio: {
select_soundhw (optarg); QDict *dict = keyval_parse(optarg, "driver", NULL, &error_fatal);
char *model;
Audiodev *dev = NULL;
Visitor *v;
if (!qdict_haskey(dict, "id")) {
qdict_put_str(dict, "id", "audiodev0");
}
if (!qdict_haskey(dict, "model")) {
error_setg(&error_fatal, "Parameter 'model' is missing");
}
model = g_strdup(qdict_get_str(dict, "model"));
qdict_del(dict, "model");
if (is_help_option(model)) {
show_valid_soundhw();
exit(0);
}
v = qobject_input_visitor_new_keyval(QOBJECT(dict));
qobject_unref(dict);
visit_type_Audiodev(v, NULL, &dev, &error_fatal);
visit_free(v);
audio_define(dev);
select_soundhw(model, dev->id);
g_free(model);
break; break;
}
case QEMU_OPTION_h: case QEMU_OPTION_h:
help(0); help(0);
break; break;

View File

@ -855,7 +855,7 @@ FeatureWordInfo feature_word_info[FEATURE_WORDS] = {
"fsrm", NULL, NULL, NULL, "fsrm", NULL, NULL, NULL,
"avx512-vp2intersect", NULL, "md-clear", NULL, "avx512-vp2intersect", NULL, "md-clear", NULL,
NULL, NULL, "serialize", NULL, NULL, NULL, "serialize", NULL,
"tsx-ldtrk", NULL, NULL /* pconfig */, NULL, "tsx-ldtrk", NULL, NULL /* pconfig */, "arch-lbr",
NULL, NULL, "amx-bf16", "avx512-fp16", NULL, NULL, "amx-bf16", "avx512-fp16",
"amx-tile", "amx-int8", "spec-ctrl", "stibp", "amx-tile", "amx-int8", "spec-ctrl", "stibp",
NULL, "arch-capabilities", "core-capability", "ssbd", NULL, "arch-capabilities", "core-capability", "ssbd",
@ -937,6 +937,34 @@ FeatureWordInfo feature_word_info[FEATURE_WORDS] = {
}, },
.tcg_features = TCG_XSAVE_FEATURES, .tcg_features = TCG_XSAVE_FEATURES,
}, },
[FEAT_XSAVE_XSS_LO] = {
.type = CPUID_FEATURE_WORD,
.feat_names = {
NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL,
},
.cpuid = {
.eax = 0xD,
.needs_ecx = true,
.ecx = 1,
.reg = R_ECX,
},
},
[FEAT_XSAVE_XSS_HI] = {
.type = CPUID_FEATURE_WORD,
.cpuid = {
.eax = 0xD,
.needs_ecx = true,
.ecx = 1,
.reg = R_EDX
},
},
[FEAT_6_EAX] = { [FEAT_6_EAX] = {
.type = CPUID_FEATURE_WORD, .type = CPUID_FEATURE_WORD,
.feat_names = { .feat_names = {
@ -952,7 +980,7 @@ FeatureWordInfo feature_word_info[FEATURE_WORDS] = {
.cpuid = { .eax = 6, .reg = R_EAX, }, .cpuid = { .eax = 6, .reg = R_EAX, },
.tcg_features = TCG_6_EAX_FEATURES, .tcg_features = TCG_6_EAX_FEATURES,
}, },
[FEAT_XSAVE_COMP_LO] = { [FEAT_XSAVE_XCR0_LO] = {
.type = CPUID_FEATURE_WORD, .type = CPUID_FEATURE_WORD,
.cpuid = { .cpuid = {
.eax = 0xD, .eax = 0xD,
@ -965,7 +993,7 @@ FeatureWordInfo feature_word_info[FEATURE_WORDS] = {
XSTATE_OPMASK_MASK | XSTATE_ZMM_Hi256_MASK | XSTATE_Hi16_ZMM_MASK | XSTATE_OPMASK_MASK | XSTATE_ZMM_Hi256_MASK | XSTATE_Hi16_ZMM_MASK |
XSTATE_PKRU_MASK, XSTATE_PKRU_MASK,
}, },
[FEAT_XSAVE_COMP_HI] = { [FEAT_XSAVE_XCR0_HI] = {
.type = CPUID_FEATURE_WORD, .type = CPUID_FEATURE_WORD,
.cpuid = { .cpuid = {
.eax = 0xD, .eax = 0xD,
@ -1382,6 +1410,9 @@ static const X86RegisterInfo32 x86_reg_info_32[CPU_NB_REGS32] = {
}; };
#undef REGISTER #undef REGISTER
/* CPUID feature bits available in XSS */
#define CPUID_XSTATE_XSS_MASK (XSTATE_ARCH_LBR_MASK)
ExtSaveArea x86_ext_save_areas[XSAVE_STATE_AREA_COUNT] = { ExtSaveArea x86_ext_save_areas[XSAVE_STATE_AREA_COUNT] = {
[XSTATE_FP_BIT] = { [XSTATE_FP_BIT] = {
/* x87 FP state component is always enabled if XSAVE is supported */ /* x87 FP state component is always enabled if XSAVE is supported */
@ -1414,6 +1445,10 @@ ExtSaveArea x86_ext_save_areas[XSAVE_STATE_AREA_COUNT] = {
[XSTATE_PKRU_BIT] = [XSTATE_PKRU_BIT] =
{ .feature = FEAT_7_0_ECX, .bits = CPUID_7_0_ECX_PKU, { .feature = FEAT_7_0_ECX, .bits = CPUID_7_0_ECX_PKU,
.size = sizeof(XSavePKRU) }, .size = sizeof(XSavePKRU) },
[XSTATE_ARCH_LBR_BIT] = {
.feature = FEAT_7_0_EDX, .bits = CPUID_7_0_EDX_ARCH_LBR,
.offset = 0 /*supervisor mode component, offset = 0 */,
.size = sizeof(XSavesArchLBR) },
[XSTATE_XTILE_CFG_BIT] = { [XSTATE_XTILE_CFG_BIT] = {
.feature = FEAT_7_0_EDX, .bits = CPUID_7_0_EDX_AMX_TILE, .feature = FEAT_7_0_EDX, .bits = CPUID_7_0_EDX_AMX_TILE,
.size = sizeof(XSaveXTILECFG), .size = sizeof(XSaveXTILECFG),
@ -1424,15 +1459,18 @@ ExtSaveArea x86_ext_save_areas[XSAVE_STATE_AREA_COUNT] = {
}, },
}; };
static uint32_t xsave_area_size(uint64_t mask) static uint32_t xsave_area_size(uint64_t mask, bool compacted)
{ {
uint64_t ret = x86_ext_save_areas[0].size;
const ExtSaveArea *esa;
uint32_t offset = 0;
int i; int i;
uint64_t ret = 0;
for (i = 0; i < ARRAY_SIZE(x86_ext_save_areas); i++) { for (i = 2; i < ARRAY_SIZE(x86_ext_save_areas); i++) {
const ExtSaveArea *esa = &x86_ext_save_areas[i]; esa = &x86_ext_save_areas[i];
if ((mask >> i) & 1) { if ((mask >> i) & 1) {
ret = MAX(ret, esa->offset + esa->size); offset = compacted ? ret : esa->offset;
ret = MAX(ret, offset + esa->size);
} }
} }
return ret; return ret;
@ -1443,10 +1481,10 @@ static inline bool accel_uses_host_cpuid(void)
return kvm_enabled() || hvf_enabled(); return kvm_enabled() || hvf_enabled();
} }
static inline uint64_t x86_cpu_xsave_components(X86CPU *cpu) static inline uint64_t x86_cpu_xsave_xcr0_components(X86CPU *cpu)
{ {
return ((uint64_t)cpu->env.features[FEAT_XSAVE_COMP_HI]) << 32 | return ((uint64_t)cpu->env.features[FEAT_XSAVE_XCR0_HI]) << 32 |
cpu->env.features[FEAT_XSAVE_COMP_LO]; cpu->env.features[FEAT_XSAVE_XCR0_LO];
} }
/* Return name of 32-bit register, from a R_* constant */ /* Return name of 32-bit register, from a R_* constant */
@ -1458,6 +1496,12 @@ static const char *get_register_name_32(unsigned int reg)
return x86_reg_info_32[reg].name; return x86_reg_info_32[reg].name;
} }
static inline uint64_t x86_cpu_xsave_xss_components(X86CPU *cpu)
{
return ((uint64_t)cpu->env.features[FEAT_XSAVE_XSS_HI]) << 32 |
cpu->env.features[FEAT_XSAVE_XSS_LO];
}
/* /*
* Returns the set of feature flags that are supported and migratable by * Returns the set of feature flags that are supported and migratable by
* QEMU, for a given FeatureWord. * QEMU, for a given FeatureWord.
@ -3258,128 +3302,6 @@ static const X86CPUDefinition builtin_x86_defs[] = {
{ /* end of list */ } { /* end of list */ }
} }
}, },
{
.name = "Icelake-Client",
.level = 0xd,
.vendor = CPUID_VENDOR_INTEL,
.family = 6,
.model = 126,
.stepping = 0,
.features[FEAT_1_EDX] =
CPUID_VME | CPUID_SSE2 | CPUID_SSE | CPUID_FXSR | CPUID_MMX |
CPUID_CLFLUSH | CPUID_PSE36 | CPUID_PAT | CPUID_CMOV | CPUID_MCA |
CPUID_PGE | CPUID_MTRR | CPUID_SEP | CPUID_APIC | CPUID_CX8 |
CPUID_MCE | CPUID_PAE | CPUID_MSR | CPUID_TSC | CPUID_PSE |
CPUID_DE | CPUID_FP87,
.features[FEAT_1_ECX] =
CPUID_EXT_AVX | CPUID_EXT_XSAVE | CPUID_EXT_AES |
CPUID_EXT_POPCNT | CPUID_EXT_X2APIC | CPUID_EXT_SSE42 |
CPUID_EXT_SSE41 | CPUID_EXT_CX16 | CPUID_EXT_SSSE3 |
CPUID_EXT_PCLMULQDQ | CPUID_EXT_SSE3 |
CPUID_EXT_TSC_DEADLINE_TIMER | CPUID_EXT_FMA | CPUID_EXT_MOVBE |
CPUID_EXT_PCID | CPUID_EXT_F16C | CPUID_EXT_RDRAND,
.features[FEAT_8000_0001_EDX] =
CPUID_EXT2_LM | CPUID_EXT2_RDTSCP | CPUID_EXT2_NX |
CPUID_EXT2_SYSCALL,
.features[FEAT_8000_0001_ECX] =
CPUID_EXT3_ABM | CPUID_EXT3_LAHF_LM | CPUID_EXT3_3DNOWPREFETCH,
.features[FEAT_8000_0008_EBX] =
CPUID_8000_0008_EBX_WBNOINVD,
.features[FEAT_7_0_EBX] =
CPUID_7_0_EBX_FSGSBASE | CPUID_7_0_EBX_BMI1 |
CPUID_7_0_EBX_HLE | CPUID_7_0_EBX_AVX2 | CPUID_7_0_EBX_SMEP |
CPUID_7_0_EBX_BMI2 | CPUID_7_0_EBX_ERMS | CPUID_7_0_EBX_INVPCID |
CPUID_7_0_EBX_RTM | CPUID_7_0_EBX_RDSEED | CPUID_7_0_EBX_ADX |
CPUID_7_0_EBX_SMAP,
.features[FEAT_7_0_ECX] =
CPUID_7_0_ECX_AVX512_VBMI | CPUID_7_0_ECX_UMIP | CPUID_7_0_ECX_PKU |
CPUID_7_0_ECX_AVX512_VBMI2 | CPUID_7_0_ECX_GFNI |
CPUID_7_0_ECX_VAES | CPUID_7_0_ECX_VPCLMULQDQ |
CPUID_7_0_ECX_AVX512VNNI | CPUID_7_0_ECX_AVX512BITALG |
CPUID_7_0_ECX_AVX512_VPOPCNTDQ,
.features[FEAT_7_0_EDX] =
CPUID_7_0_EDX_SPEC_CTRL | CPUID_7_0_EDX_SPEC_CTRL_SSBD,
/* XSAVES is added in version 3 */
.features[FEAT_XSAVE] =
CPUID_XSAVE_XSAVEOPT | CPUID_XSAVE_XSAVEC |
CPUID_XSAVE_XGETBV1,
.features[FEAT_6_EAX] =
CPUID_6_EAX_ARAT,
/* Missing: Mode-based execute control (XS/XU), processor tracing, TSC scaling */
.features[FEAT_VMX_BASIC] = MSR_VMX_BASIC_INS_OUTS |
MSR_VMX_BASIC_TRUE_CTLS,
.features[FEAT_VMX_ENTRY_CTLS] = VMX_VM_ENTRY_IA32E_MODE |
VMX_VM_ENTRY_LOAD_IA32_PERF_GLOBAL_CTRL | VMX_VM_ENTRY_LOAD_IA32_PAT |
VMX_VM_ENTRY_LOAD_DEBUG_CONTROLS | VMX_VM_ENTRY_LOAD_IA32_EFER,
.features[FEAT_VMX_EPT_VPID_CAPS] = MSR_VMX_EPT_EXECONLY |
MSR_VMX_EPT_PAGE_WALK_LENGTH_4 | MSR_VMX_EPT_WB | MSR_VMX_EPT_2MB |
MSR_VMX_EPT_1GB | MSR_VMX_EPT_INVEPT |
MSR_VMX_EPT_INVEPT_SINGLE_CONTEXT | MSR_VMX_EPT_INVEPT_ALL_CONTEXT |
MSR_VMX_EPT_INVVPID | MSR_VMX_EPT_INVVPID_SINGLE_ADDR |
MSR_VMX_EPT_INVVPID_SINGLE_CONTEXT | MSR_VMX_EPT_INVVPID_ALL_CONTEXT |
MSR_VMX_EPT_INVVPID_SINGLE_CONTEXT_NOGLOBALS | MSR_VMX_EPT_AD_BITS,
.features[FEAT_VMX_EXIT_CTLS] =
VMX_VM_EXIT_ACK_INTR_ON_EXIT | VMX_VM_EXIT_SAVE_DEBUG_CONTROLS |
VMX_VM_EXIT_LOAD_IA32_PERF_GLOBAL_CTRL |
VMX_VM_EXIT_LOAD_IA32_PAT | VMX_VM_EXIT_LOAD_IA32_EFER |
VMX_VM_EXIT_SAVE_IA32_PAT | VMX_VM_EXIT_SAVE_IA32_EFER |
VMX_VM_EXIT_SAVE_VMX_PREEMPTION_TIMER,
.features[FEAT_VMX_MISC] = MSR_VMX_MISC_ACTIVITY_HLT |
MSR_VMX_MISC_STORE_LMA | MSR_VMX_MISC_VMWRITE_VMEXIT,
.features[FEAT_VMX_PINBASED_CTLS] = VMX_PIN_BASED_EXT_INTR_MASK |
VMX_PIN_BASED_NMI_EXITING | VMX_PIN_BASED_VIRTUAL_NMIS |
VMX_PIN_BASED_VMX_PREEMPTION_TIMER,
.features[FEAT_VMX_PROCBASED_CTLS] = VMX_CPU_BASED_VIRTUAL_INTR_PENDING |
VMX_CPU_BASED_USE_TSC_OFFSETING | VMX_CPU_BASED_HLT_EXITING |
VMX_CPU_BASED_INVLPG_EXITING | VMX_CPU_BASED_MWAIT_EXITING |
VMX_CPU_BASED_RDPMC_EXITING | VMX_CPU_BASED_RDTSC_EXITING |
VMX_CPU_BASED_CR8_LOAD_EXITING | VMX_CPU_BASED_CR8_STORE_EXITING |
VMX_CPU_BASED_TPR_SHADOW | VMX_CPU_BASED_MOV_DR_EXITING |
VMX_CPU_BASED_UNCOND_IO_EXITING | VMX_CPU_BASED_USE_IO_BITMAPS |
VMX_CPU_BASED_MONITOR_EXITING | VMX_CPU_BASED_PAUSE_EXITING |
VMX_CPU_BASED_VIRTUAL_NMI_PENDING | VMX_CPU_BASED_USE_MSR_BITMAPS |
VMX_CPU_BASED_CR3_LOAD_EXITING | VMX_CPU_BASED_CR3_STORE_EXITING |
VMX_CPU_BASED_MONITOR_TRAP_FLAG |
VMX_CPU_BASED_ACTIVATE_SECONDARY_CONTROLS,
.features[FEAT_VMX_SECONDARY_CTLS] =
VMX_SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES |
VMX_SECONDARY_EXEC_WBINVD_EXITING | VMX_SECONDARY_EXEC_ENABLE_EPT |
VMX_SECONDARY_EXEC_DESC | VMX_SECONDARY_EXEC_RDTSCP |
VMX_SECONDARY_EXEC_ENABLE_VPID | VMX_SECONDARY_EXEC_UNRESTRICTED_GUEST |
VMX_SECONDARY_EXEC_RDRAND_EXITING | VMX_SECONDARY_EXEC_ENABLE_INVPCID |
VMX_SECONDARY_EXEC_ENABLE_VMFUNC | VMX_SECONDARY_EXEC_SHADOW_VMCS |
VMX_SECONDARY_EXEC_RDSEED_EXITING | VMX_SECONDARY_EXEC_ENABLE_PML,
.features[FEAT_VMX_VMFUNC] = MSR_VMX_VMFUNC_EPT_SWITCHING,
.xlevel = 0x80000008,
.model_id = "Intel Core Processor (Icelake)",
.versions = (X86CPUVersionDefinition[]) {
{
.version = 1,
.note = "deprecated"
},
{
.version = 2,
.note = "no TSX, deprecated",
.alias = "Icelake-Client-noTSX",
.props = (PropValue[]) {
{ "hle", "off" },
{ "rtm", "off" },
{ /* end of list */ }
},
},
{
.version = 3,
.note = "no TSX, XSAVES, deprecated",
.props = (PropValue[]) {
{ "xsaves", "on" },
{ "vmx-xsaves", "on" },
{ /* end of list */ }
},
},
{ /* end of list */ }
},
.deprecation_note = "use Icelake-Server instead"
},
{ {
.name = "Icelake-Server", .name = "Icelake-Server",
.level = 0xd, .level = 0xd,
@ -4633,8 +4555,8 @@ static const char *x86_cpu_feature_name(FeatureWord w, int bitnr)
/* XSAVE components are automatically enabled by other features, /* XSAVE components are automatically enabled by other features,
* so return the original feature name instead * so return the original feature name instead
*/ */
if (w == FEAT_XSAVE_COMP_LO || w == FEAT_XSAVE_COMP_HI) { if (w == FEAT_XSAVE_XCR0_LO || w == FEAT_XSAVE_XCR0_HI) {
int comp = (w == FEAT_XSAVE_COMP_HI) ? bitnr + 32 : bitnr; int comp = (w == FEAT_XSAVE_XCR0_HI) ? bitnr + 32 : bitnr;
if (comp < ARRAY_SIZE(x86_ext_save_areas) && if (comp < ARRAY_SIZE(x86_ext_save_areas) &&
x86_ext_save_areas[comp].bits) { x86_ext_save_areas[comp].bits) {
@ -5022,6 +4944,28 @@ uint64_t x86_cpu_get_supported_feature_word(FeatureWord w,
return r; return r;
} }
static void x86_cpu_get_supported_cpuid(uint32_t func, uint32_t index,
uint32_t *eax, uint32_t *ebx,
uint32_t *ecx, uint32_t *edx)
{
if (kvm_enabled()) {
*eax = kvm_arch_get_supported_cpuid(kvm_state, func, index, R_EAX);
*ebx = kvm_arch_get_supported_cpuid(kvm_state, func, index, R_EBX);
*ecx = kvm_arch_get_supported_cpuid(kvm_state, func, index, R_ECX);
*edx = kvm_arch_get_supported_cpuid(kvm_state, func, index, R_EDX);
} else if (hvf_enabled()) {
*eax = hvf_get_supported_cpuid(func, index, R_EAX);
*ebx = hvf_get_supported_cpuid(func, index, R_EBX);
*ecx = hvf_get_supported_cpuid(func, index, R_ECX);
*edx = hvf_get_supported_cpuid(func, index, R_EDX);
} else {
*eax = 0;
*ebx = 0;
*ecx = 0;
*edx = 0;
}
}
static void x86_cpu_get_cache_cpuid(uint32_t func, uint32_t index, static void x86_cpu_get_cache_cpuid(uint32_t func, uint32_t index,
uint32_t *eax, uint32_t *ebx, uint32_t *eax, uint32_t *ebx,
uint32_t *ecx, uint32_t *edx) uint32_t *ecx, uint32_t *edx)
@ -5437,18 +5381,8 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count,
break; break;
case 0xA: case 0xA:
/* Architectural Performance Monitoring Leaf */ /* Architectural Performance Monitoring Leaf */
if (kvm_enabled() && cpu->enable_pmu) { if (accel_uses_host_cpuid() && cpu->enable_pmu) {
KVMState *s = cs->kvm_state; x86_cpu_get_supported_cpuid(0xA, count, eax, ebx, ecx, edx);
*eax = kvm_arch_get_supported_cpuid(s, 0xA, count, R_EAX);
*ebx = kvm_arch_get_supported_cpuid(s, 0xA, count, R_EBX);
*ecx = kvm_arch_get_supported_cpuid(s, 0xA, count, R_ECX);
*edx = kvm_arch_get_supported_cpuid(s, 0xA, count, R_EDX);
} else if (hvf_enabled() && cpu->enable_pmu) {
*eax = hvf_get_supported_cpuid(0xA, count, R_EAX);
*ebx = hvf_get_supported_cpuid(0xA, count, R_EBX);
*ecx = hvf_get_supported_cpuid(0xA, count, R_ECX);
*edx = hvf_get_supported_cpuid(0xA, count, R_EDX);
} else { } else {
*eax = 0; *eax = 0;
*ebx = 0; *ebx = 0;
@ -5486,6 +5420,13 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count,
assert(!(*eax & ~0x1f)); assert(!(*eax & ~0x1f));
*ebx &= 0xffff; /* The count doesn't need to be reliable. */ *ebx &= 0xffff; /* The count doesn't need to be reliable. */
break; break;
case 0x1C:
if (accel_uses_host_cpuid() && cpu->enable_pmu &&
(env->features[FEAT_7_0_EDX] & CPUID_7_0_EDX_ARCH_LBR)) {
x86_cpu_get_supported_cpuid(0x1C, 0, eax, ebx, ecx, edx);
*edx = 0;
}
break;
case 0x1F: case 0x1F:
/* V2 Extended Topology Enumeration Leaf */ /* V2 Extended Topology Enumeration Leaf */
if (env->nr_dies < 2) { if (env->nr_dies < 2) {
@ -5530,25 +5471,47 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count,
} }
if (count == 0) { if (count == 0) {
*ecx = xsave_area_size(x86_cpu_xsave_components(cpu)); *ecx = xsave_area_size(x86_cpu_xsave_xcr0_components(cpu), false);
*eax = env->features[FEAT_XSAVE_COMP_LO]; *eax = env->features[FEAT_XSAVE_XCR0_LO];
*edx = env->features[FEAT_XSAVE_COMP_HI]; *edx = env->features[FEAT_XSAVE_XCR0_HI];
/* /*
* The initial value of xcr0 and ebx == 0, On host without kvm * The initial value of xcr0 and ebx == 0, On host without kvm
* commit 412a3c41(e.g., CentOS 6), the ebx's value always == 0 * commit 412a3c41(e.g., CentOS 6), the ebx's value always == 0
* even through guest update xcr0, this will crash some legacy guest * even through guest update xcr0, this will crash some legacy guest
* (e.g., CentOS 6), So set ebx == ecx to workaroud it. * (e.g., CentOS 6), So set ebx == ecx to workaroud it.
*/ */
*ebx = kvm_enabled() ? *ecx : xsave_area_size(env->xcr0); *ebx = kvm_enabled() ? *ecx : xsave_area_size(env->xcr0, false);
} else if (count == 1) { } else if (count == 1) {
uint64_t xstate = x86_cpu_xsave_xcr0_components(cpu) |
x86_cpu_xsave_xss_components(cpu);
*eax = env->features[FEAT_XSAVE]; *eax = env->features[FEAT_XSAVE];
*ebx = xsave_area_size(xstate, true);
*ecx = env->features[FEAT_XSAVE_XSS_LO];
*edx = env->features[FEAT_XSAVE_XSS_HI];
if (kvm_enabled() && cpu->enable_pmu &&
(env->features[FEAT_7_0_EDX] & CPUID_7_0_EDX_ARCH_LBR) &&
(*eax & CPUID_XSAVE_XSAVES)) {
*ecx |= XSTATE_ARCH_LBR_MASK;
} else {
*ecx &= ~XSTATE_ARCH_LBR_MASK;
}
} else if (count == 0xf &&
accel_uses_host_cpuid() && cpu->enable_pmu &&
(env->features[FEAT_7_0_EDX] & CPUID_7_0_EDX_ARCH_LBR)) {
x86_cpu_get_supported_cpuid(0xD, count, eax, ebx, ecx, edx);
} else if (count < ARRAY_SIZE(x86_ext_save_areas)) { } else if (count < ARRAY_SIZE(x86_ext_save_areas)) {
if ((x86_cpu_xsave_components(cpu) >> count) & 1) { const ExtSaveArea *esa = &x86_ext_save_areas[count];
const ExtSaveArea *esa = &x86_ext_save_areas[count];
if (x86_cpu_xsave_xcr0_components(cpu) & (1ULL << count)) {
*eax = esa->size; *eax = esa->size;
*ebx = esa->offset; *ebx = esa->offset;
*ecx = esa->ecx & *ecx = esa->ecx &
(ESA_FEATURE_ALIGN64_MASK | ESA_FEATURE_XFD_MASK); (ESA_FEATURE_ALIGN64_MASK | ESA_FEATURE_XFD_MASK);
} else if (x86_cpu_xsave_xss_components(cpu) & (1ULL << count)) {
*eax = esa->size;
*ebx = 0;
*ecx = 1;
} }
} }
break; break;
@ -5588,10 +5551,7 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count,
* supports. Features can be further restricted by userspace, but not * supports. Features can be further restricted by userspace, but not
* made more permissive. * made more permissive.
*/ */
*eax = kvm_arch_get_supported_cpuid(cs->kvm_state, 0x12, count, R_EAX); x86_cpu_get_supported_cpuid(0x12, index, eax, ebx, ecx, edx);
*ebx = kvm_arch_get_supported_cpuid(cs->kvm_state, 0x12, count, R_EBX);
*ecx = kvm_arch_get_supported_cpuid(cs->kvm_state, 0x12, count, R_ECX);
*edx = kvm_arch_get_supported_cpuid(cs->kvm_state, 0x12, count, R_EDX);
if (count == 0) { if (count == 0) {
*eax &= env->features[FEAT_SGX_12_0_EAX]; *eax &= env->features[FEAT_SGX_12_0_EAX];
@ -5599,8 +5559,8 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count,
} else { } else {
*eax &= env->features[FEAT_SGX_12_1_EAX]; *eax &= env->features[FEAT_SGX_12_1_EAX];
*ebx &= 0; /* ebx reserve */ *ebx &= 0; /* ebx reserve */
*ecx &= env->features[FEAT_XSAVE_COMP_LO]; *ecx &= env->features[FEAT_XSAVE_XSS_LO];
*edx &= env->features[FEAT_XSAVE_COMP_HI]; *edx &= env->features[FEAT_XSAVE_XSS_HI];
/* FP and SSE are always allowed regardless of XSAVE/XCR0. */ /* FP and SSE are always allowed regardless of XSAVE/XCR0. */
*ecx |= XSTATE_FP_MASK | XSTATE_SSE_MASK; *ecx |= XSTATE_FP_MASK | XSTATE_SSE_MASK;
@ -5996,6 +5956,9 @@ static void x86_cpu_reset(DeviceState *dev)
} }
for (i = 2; i < ARRAY_SIZE(x86_ext_save_areas); i++) { for (i = 2; i < ARRAY_SIZE(x86_ext_save_areas); i++) {
const ExtSaveArea *esa = &x86_ext_save_areas[i]; const ExtSaveArea *esa = &x86_ext_save_areas[i];
if (!((1 << i) & CPUID_XSTATE_XCR0_MASK)) {
continue;
}
if (env->features[esa->feature] & esa->bits) { if (env->features[esa->feature] & esa->bits) {
xcr0 |= 1ull << i; xcr0 |= 1ull << i;
} }
@ -6110,8 +6073,8 @@ static void x86_cpu_enable_xsave_components(X86CPU *cpu)
static bool request_perm; static bool request_perm;
if (!(env->features[FEAT_1_ECX] & CPUID_EXT_XSAVE)) { if (!(env->features[FEAT_1_ECX] & CPUID_EXT_XSAVE)) {
env->features[FEAT_XSAVE_COMP_LO] = 0; env->features[FEAT_XSAVE_XCR0_LO] = 0;
env->features[FEAT_XSAVE_COMP_HI] = 0; env->features[FEAT_XSAVE_XCR0_HI] = 0;
return; return;
} }
@ -6129,8 +6092,10 @@ static void x86_cpu_enable_xsave_components(X86CPU *cpu)
request_perm = true; request_perm = true;
} }
env->features[FEAT_XSAVE_COMP_LO] = mask; env->features[FEAT_XSAVE_XCR0_LO] = mask & CPUID_XSTATE_XCR0_MASK;
env->features[FEAT_XSAVE_COMP_HI] = mask >> 32; env->features[FEAT_XSAVE_XCR0_HI] = mask >> 32;
env->features[FEAT_XSAVE_XSS_LO] = mask & CPUID_XSTATE_XSS_MASK;
env->features[FEAT_XSAVE_XSS_HI] = mask >> 32;
} }
/***** Steps involved on loading and filtering CPUID data /***** Steps involved on loading and filtering CPUID data
@ -6397,6 +6362,7 @@ static void x86_cpu_realizefn(DeviceState *dev, Error **errp)
CPUX86State *env = &cpu->env; CPUX86State *env = &cpu->env;
Error *local_err = NULL; Error *local_err = NULL;
static bool ht_warned; static bool ht_warned;
unsigned requested_lbr_fmt;
if (cpu->apic_id == UNASSIGNED_APIC_ID) { if (cpu->apic_id == UNASSIGNED_APIC_ID) {
error_setg(errp, "apic-id property was not initialized properly"); error_setg(errp, "apic-id property was not initialized properly");
@ -6414,6 +6380,42 @@ static void x86_cpu_realizefn(DeviceState *dev, Error **errp)
goto out; goto out;
} }
/*
* Override env->features[FEAT_PERF_CAPABILITIES].LBR_FMT
* with user-provided setting.
*/
if (cpu->lbr_fmt != ~PERF_CAP_LBR_FMT) {
if ((cpu->lbr_fmt & PERF_CAP_LBR_FMT) != cpu->lbr_fmt) {
error_setg(errp, "invalid lbr-fmt");
return;
}
env->features[FEAT_PERF_CAPABILITIES] &= ~PERF_CAP_LBR_FMT;
env->features[FEAT_PERF_CAPABILITIES] |= cpu->lbr_fmt;
}
/*
* vPMU LBR is supported when 1) KVM is enabled 2) Option pmu=on and
* 3)vPMU LBR format matches that of host setting.
*/
requested_lbr_fmt =
env->features[FEAT_PERF_CAPABILITIES] & PERF_CAP_LBR_FMT;
if (requested_lbr_fmt && kvm_enabled()) {
uint64_t host_perf_cap =
x86_cpu_get_supported_feature_word(FEAT_PERF_CAPABILITIES, false);
unsigned host_lbr_fmt = host_perf_cap & PERF_CAP_LBR_FMT;
if (!cpu->enable_pmu) {
error_setg(errp, "vPMU: LBR is unsupported without pmu=on");
return;
}
if (requested_lbr_fmt != host_lbr_fmt) {
error_setg(errp, "vPMU: the lbr-fmt value (0x%x) does not match "
"the host value (0x%x).",
requested_lbr_fmt, host_lbr_fmt);
return;
}
}
x86_cpu_filter_features(cpu, cpu->check_cpuid || cpu->enforce_cpuid); x86_cpu_filter_features(cpu, cpu->check_cpuid || cpu->enforce_cpuid);
if (cpu->enforce_cpuid && x86_cpu_have_filtered_features(cpu)) { if (cpu->enforce_cpuid && x86_cpu_have_filtered_features(cpu)) {
@ -6766,6 +6768,8 @@ static void x86_cpu_initfn(Object *obj)
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"); object_property_add_alias(obj, "hv-apicv", obj, "hv-avic");
cpu->lbr_fmt = ~PERF_CAP_LBR_FMT;
object_property_add_alias(obj, "lbr_fmt", obj, "lbr-fmt");
if (xcc->model) { if (xcc->model) {
x86_cpu_load_model(cpu, xcc->model); x86_cpu_load_model(cpu, xcc->model);
@ -6920,6 +6924,7 @@ static Property x86_cpu_properties[] = {
#endif #endif
DEFINE_PROP_INT32("node-id", X86CPU, node_id, CPU_UNSET_NUMA_NODE_ID), DEFINE_PROP_INT32("node-id", X86CPU, node_id, CPU_UNSET_NUMA_NODE_ID),
DEFINE_PROP_BOOL("pmu", X86CPU, enable_pmu, false), DEFINE_PROP_BOOL("pmu", X86CPU, enable_pmu, false),
DEFINE_PROP_UINT64_CHECKMASK("lbr-fmt", X86CPU, lbr_fmt, PERF_CAP_LBR_FMT),
DEFINE_PROP_UINT32("hv-spinlocks", X86CPU, hyperv_spinlock_attempts, DEFINE_PROP_UINT32("hv-spinlocks", X86CPU, hyperv_spinlock_attempts,
HYPERV_SPINLOCK_NEVER_NOTIFY), HYPERV_SPINLOCK_NEVER_NOTIFY),

View File

@ -386,10 +386,16 @@ typedef enum X86Seg {
#define ARCH_CAP_TSX_CTRL_MSR (1<<7) #define ARCH_CAP_TSX_CTRL_MSR (1<<7)
#define MSR_IA32_PERF_CAPABILITIES 0x345 #define MSR_IA32_PERF_CAPABILITIES 0x345
#define PERF_CAP_LBR_FMT 0x3f
#define MSR_IA32_TSX_CTRL 0x122 #define MSR_IA32_TSX_CTRL 0x122
#define MSR_IA32_TSCDEADLINE 0x6e0 #define MSR_IA32_TSCDEADLINE 0x6e0
#define MSR_IA32_PKRS 0x6e1 #define MSR_IA32_PKRS 0x6e1
#define MSR_ARCH_LBR_CTL 0x000014ce
#define MSR_ARCH_LBR_DEPTH 0x000014cf
#define MSR_ARCH_LBR_FROM_0 0x00001500
#define MSR_ARCH_LBR_TO_0 0x00001600
#define MSR_ARCH_LBR_INFO_0 0x00001200
#define FEATURE_CONTROL_LOCKED (1<<0) #define FEATURE_CONTROL_LOCKED (1<<0)
#define FEATURE_CONTROL_VMXON_ENABLED_INSIDE_SMX (1ULL << 1) #define FEATURE_CONTROL_VMXON_ENABLED_INSIDE_SMX (1ULL << 1)
@ -543,6 +549,7 @@ typedef enum X86Seg {
#define XSTATE_ZMM_Hi256_BIT 6 #define XSTATE_ZMM_Hi256_BIT 6
#define XSTATE_Hi16_ZMM_BIT 7 #define XSTATE_Hi16_ZMM_BIT 7
#define XSTATE_PKRU_BIT 9 #define XSTATE_PKRU_BIT 9
#define XSTATE_ARCH_LBR_BIT 15
#define XSTATE_XTILE_CFG_BIT 17 #define XSTATE_XTILE_CFG_BIT 17
#define XSTATE_XTILE_DATA_BIT 18 #define XSTATE_XTILE_DATA_BIT 18
@ -555,6 +562,7 @@ typedef enum X86Seg {
#define XSTATE_ZMM_Hi256_MASK (1ULL << XSTATE_ZMM_Hi256_BIT) #define XSTATE_ZMM_Hi256_MASK (1ULL << XSTATE_ZMM_Hi256_BIT)
#define XSTATE_Hi16_ZMM_MASK (1ULL << XSTATE_Hi16_ZMM_BIT) #define XSTATE_Hi16_ZMM_MASK (1ULL << XSTATE_Hi16_ZMM_BIT)
#define XSTATE_PKRU_MASK (1ULL << XSTATE_PKRU_BIT) #define XSTATE_PKRU_MASK (1ULL << XSTATE_PKRU_BIT)
#define XSTATE_ARCH_LBR_MASK (1ULL << XSTATE_ARCH_LBR_BIT)
#define XSTATE_XTILE_CFG_MASK (1ULL << XSTATE_XTILE_CFG_BIT) #define XSTATE_XTILE_CFG_MASK (1ULL << XSTATE_XTILE_CFG_BIT)
#define XSTATE_XTILE_DATA_MASK (1ULL << XSTATE_XTILE_DATA_BIT) #define XSTATE_XTILE_DATA_MASK (1ULL << XSTATE_XTILE_DATA_BIT)
@ -567,6 +575,14 @@ typedef enum X86Seg {
#define ESA_FEATURE_XFD_MASK (1U << ESA_FEATURE_XFD_BIT) #define ESA_FEATURE_XFD_MASK (1U << ESA_FEATURE_XFD_BIT)
/* CPUID feature bits available in XCR0 */
#define CPUID_XSTATE_XCR0_MASK (XSTATE_FP_MASK | XSTATE_SSE_MASK | \
XSTATE_YMM_MASK | XSTATE_BNDREGS_MASK | \
XSTATE_BNDCSR_MASK | XSTATE_OPMASK_MASK | \
XSTATE_ZMM_Hi256_MASK | \
XSTATE_Hi16_ZMM_MASK | XSTATE_PKRU_MASK | \
XSTATE_XTILE_CFG_MASK | XSTATE_XTILE_DATA_MASK)
/* CPUID feature words */ /* CPUID feature words */
typedef enum FeatureWord { typedef enum FeatureWord {
FEAT_1_EDX, /* CPUID[1].EDX */ FEAT_1_EDX, /* CPUID[1].EDX */
@ -585,8 +601,8 @@ typedef enum FeatureWord {
FEAT_SVM, /* CPUID[8000_000A].EDX */ FEAT_SVM, /* CPUID[8000_000A].EDX */
FEAT_XSAVE, /* CPUID[EAX=0xd,ECX=1].EAX */ FEAT_XSAVE, /* CPUID[EAX=0xd,ECX=1].EAX */
FEAT_6_EAX, /* CPUID[6].EAX */ FEAT_6_EAX, /* CPUID[6].EAX */
FEAT_XSAVE_COMP_LO, /* CPUID[EAX=0xd,ECX=0].EAX */ FEAT_XSAVE_XCR0_LO, /* CPUID[EAX=0xd,ECX=0].EAX */
FEAT_XSAVE_COMP_HI, /* CPUID[EAX=0xd,ECX=0].EDX */ FEAT_XSAVE_XCR0_HI, /* CPUID[EAX=0xd,ECX=0].EDX */
FEAT_ARCH_CAPABILITIES, FEAT_ARCH_CAPABILITIES,
FEAT_CORE_CAPABILITY, FEAT_CORE_CAPABILITY,
FEAT_PERF_CAPABILITIES, FEAT_PERF_CAPABILITIES,
@ -603,6 +619,8 @@ typedef enum FeatureWord {
FEAT_SGX_12_0_EAX, /* CPUID[EAX=0x12,ECX=0].EAX (SGX) */ FEAT_SGX_12_0_EAX, /* CPUID[EAX=0x12,ECX=0].EAX (SGX) */
FEAT_SGX_12_0_EBX, /* CPUID[EAX=0x12,ECX=0].EBX (SGX MISCSELECT[31:0]) */ FEAT_SGX_12_0_EBX, /* CPUID[EAX=0x12,ECX=0].EBX (SGX MISCSELECT[31:0]) */
FEAT_SGX_12_1_EAX, /* CPUID[EAX=0x12,ECX=1].EAX (SGX ATTRIBUTES[31:0]) */ FEAT_SGX_12_1_EAX, /* CPUID[EAX=0x12,ECX=1].EAX (SGX ATTRIBUTES[31:0]) */
FEAT_XSAVE_XSS_LO, /* CPUID[EAX=0xd,ECX=1].ECX */
FEAT_XSAVE_XSS_HI, /* CPUID[EAX=0xd,ECX=1].EDX */
FEATURE_WORDS, FEATURE_WORDS,
} FeatureWord; } FeatureWord;
@ -859,6 +877,8 @@ uint64_t x86_cpu_get_supported_feature_word(FeatureWord w,
#define CPUID_7_0_EDX_SERIALIZE (1U << 14) #define CPUID_7_0_EDX_SERIALIZE (1U << 14)
/* TSX Suspend Load Address Tracking instruction */ /* TSX Suspend Load Address Tracking instruction */
#define CPUID_7_0_EDX_TSX_LDTRK (1U << 16) #define CPUID_7_0_EDX_TSX_LDTRK (1U << 16)
/* Architectural LBRs */
#define CPUID_7_0_EDX_ARCH_LBR (1U << 19)
/* AVX512_FP16 instruction */ /* AVX512_FP16 instruction */
#define CPUID_7_0_EDX_AVX512_FP16 (1U << 23) #define CPUID_7_0_EDX_AVX512_FP16 (1U << 23)
/* AMX tile (two-dimensional register) */ /* AMX tile (two-dimensional register) */
@ -1365,6 +1385,24 @@ typedef struct XSaveXTILEDATA {
uint8_t xtiledata[8][1024]; uint8_t xtiledata[8][1024];
} XSaveXTILEDATA; } XSaveXTILEDATA;
typedef struct {
uint64_t from;
uint64_t to;
uint64_t info;
} LBREntry;
#define ARCH_LBR_NR_ENTRIES 32
/* Ext. save area 19: Supervisor mode Arch LBR state */
typedef struct XSavesArchLBR {
uint64_t lbr_ctl;
uint64_t lbr_depth;
uint64_t ler_from;
uint64_t ler_to;
uint64_t ler_info;
LBREntry lbr_records[ARCH_LBR_NR_ENTRIES];
} XSavesArchLBR;
QEMU_BUILD_BUG_ON(sizeof(XSaveAVX) != 0x100); QEMU_BUILD_BUG_ON(sizeof(XSaveAVX) != 0x100);
QEMU_BUILD_BUG_ON(sizeof(XSaveBNDREG) != 0x40); QEMU_BUILD_BUG_ON(sizeof(XSaveBNDREG) != 0x40);
QEMU_BUILD_BUG_ON(sizeof(XSaveBNDCSR) != 0x40); QEMU_BUILD_BUG_ON(sizeof(XSaveBNDCSR) != 0x40);
@ -1374,6 +1412,7 @@ QEMU_BUILD_BUG_ON(sizeof(XSaveHi16_ZMM) != 0x400);
QEMU_BUILD_BUG_ON(sizeof(XSavePKRU) != 0x8); QEMU_BUILD_BUG_ON(sizeof(XSavePKRU) != 0x8);
QEMU_BUILD_BUG_ON(sizeof(XSaveXTILECFG) != 0x40); QEMU_BUILD_BUG_ON(sizeof(XSaveXTILECFG) != 0x40);
QEMU_BUILD_BUG_ON(sizeof(XSaveXTILEDATA) != 0x2000); QEMU_BUILD_BUG_ON(sizeof(XSaveXTILEDATA) != 0x2000);
QEMU_BUILD_BUG_ON(sizeof(XSavesArchLBR) != 0x328);
typedef struct ExtSaveArea { typedef struct ExtSaveArea {
uint32_t feature, bits; uint32_t feature, bits;
@ -1616,6 +1655,11 @@ typedef struct CPUArchState {
uint64_t msr_xfd; uint64_t msr_xfd;
uint64_t msr_xfd_err; uint64_t msr_xfd_err;
/* Per-VCPU Arch LBR MSRs */
uint64_t msr_lbr_ctl;
uint64_t msr_lbr_depth;
LBREntry lbr_records[ARCH_LBR_NR_ENTRIES];
/* exception/interrupt handling */ /* exception/interrupt handling */
int error_code; int error_code;
int exception_is_int; int exception_is_int;
@ -1810,6 +1854,15 @@ struct ArchCPU {
*/ */
bool enable_pmu; bool enable_pmu;
/*
* Enable LBR_FMT bits of IA32_PERF_CAPABILITIES MSR.
* This can't be initialized with a default because it doesn't have
* stable ABI support yet. It is only allowed to pass all LBR_FMT bits
* returned by kvm_arch_get_supported_msr_feature()(which depends on both
* host CPU and kernel capabilities) to the guest.
*/
uint64_t lbr_fmt;
/* LMCE support can be enabled/disabled via cpu option 'lmce=on/off'. It is /* LMCE support can be enabled/disabled via cpu option 'lmce=on/off'. It is
* disabled by default to avoid breaking migration between QEMU with * disabled by default to avoid breaking migration between QEMU with
* different LMCE configurations. * different LMCE configurations.

View File

@ -141,6 +141,7 @@ static struct kvm_msr_list *kvm_feature_msrs;
#define BUS_LOCK_SLICE_TIME 1000000000ULL /* ns */ #define BUS_LOCK_SLICE_TIME 1000000000ULL /* ns */
static RateLimit bus_lock_ratelimit_ctrl; static RateLimit bus_lock_ratelimit_ctrl;
static int kvm_get_one_msr(X86CPU *cpu, int index, uint64_t *value);
int kvm_has_pit_state2(void) int kvm_has_pit_state2(void)
{ {
@ -211,28 +212,21 @@ static int kvm_get_tsc(CPUState *cs)
{ {
X86CPU *cpu = X86_CPU(cs); X86CPU *cpu = X86_CPU(cs);
CPUX86State *env = &cpu->env; CPUX86State *env = &cpu->env;
struct { uint64_t value;
struct kvm_msrs info;
struct kvm_msr_entry entries[1];
} msr_data = {};
int ret; int ret;
if (env->tsc_valid) { if (env->tsc_valid) {
return 0; return 0;
} }
memset(&msr_data, 0, sizeof(msr_data));
msr_data.info.nmsrs = 1;
msr_data.entries[0].index = MSR_IA32_TSC;
env->tsc_valid = !runstate_is_running(); env->tsc_valid = !runstate_is_running();
ret = kvm_vcpu_ioctl(CPU(cpu), KVM_GET_MSRS, &msr_data); ret = kvm_get_one_msr(cpu, MSR_IA32_TSC, &value);
if (ret < 0) { if (ret < 0) {
return ret; return ret;
} }
assert(ret == 1); env->tsc = value;
env->tsc = msr_data.entries[0].data;
return 0; return 0;
} }
@ -1566,21 +1560,14 @@ static int hyperv_init_vcpu(X86CPU *cpu)
* the kernel doesn't support setting vp_index; assert that its value * the kernel doesn't support setting vp_index; assert that its value
* is in sync * is in sync
*/ */
struct { uint64_t value;
struct kvm_msrs info;
struct kvm_msr_entry entries[1];
} msr_data = {
.info.nmsrs = 1,
.entries[0].index = HV_X64_MSR_VP_INDEX,
};
ret = kvm_vcpu_ioctl(cs, KVM_GET_MSRS, &msr_data); ret = kvm_get_one_msr(cpu, HV_X64_MSR_VP_INDEX, &value);
if (ret < 0) { if (ret < 0) {
return ret; return ret;
} }
assert(ret == 1);
if (msr_data.entries[0].data != hyperv_vp_index(CPU(cpu))) { if (value != hyperv_vp_index(CPU(cpu))) {
error_report("kernel's vp_index != QEMU's vp_index"); error_report("kernel's vp_index != QEMU's vp_index");
return -ENXIO; return -ENXIO;
} }
@ -2839,6 +2826,25 @@ static int kvm_put_one_msr(X86CPU *cpu, int index, uint64_t value)
return kvm_vcpu_ioctl(CPU(cpu), KVM_SET_MSRS, cpu->kvm_msr_buf); return kvm_vcpu_ioctl(CPU(cpu), KVM_SET_MSRS, cpu->kvm_msr_buf);
} }
static int kvm_get_one_msr(X86CPU *cpu, int index, uint64_t *value)
{
int ret;
struct {
struct kvm_msrs info;
struct kvm_msr_entry entries[1];
} msr_data = {
.info.nmsrs = 1,
.entries[0].index = index,
};
ret = kvm_vcpu_ioctl(CPU(cpu), KVM_GET_MSRS, &msr_data);
if (ret < 0) {
return ret;
}
assert(ret == 1);
*value = msr_data.entries[0].data;
return ret;
}
void kvm_put_apicbase(X86CPU *cpu, uint64_t value) void kvm_put_apicbase(X86CPU *cpu, uint64_t value)
{ {
int ret; int ret;
@ -3361,6 +3367,38 @@ static int kvm_put_msrs(X86CPU *cpu, int level)
env->msr_xfd_err); env->msr_xfd_err);
} }
if (kvm_enabled() && cpu->enable_pmu &&
(env->features[FEAT_7_0_EDX] & CPUID_7_0_EDX_ARCH_LBR)) {
uint64_t depth;
int i, ret;
/*
* Only migrate Arch LBR states when: 1) Arch LBR is enabled
* for migrated vcpu. 2) the host Arch LBR depth equals that
* of source guest's, this is to avoid mismatch of guest/host
* config for the msr hence avoid unexpected misbehavior.
*/
ret = kvm_get_one_msr(cpu, MSR_ARCH_LBR_DEPTH, &depth);
if (ret == 1 && (env->msr_lbr_ctl & 0x1) && !!depth &&
depth == env->msr_lbr_depth) {
kvm_msr_entry_add(cpu, MSR_ARCH_LBR_CTL, env->msr_lbr_ctl);
kvm_msr_entry_add(cpu, MSR_ARCH_LBR_DEPTH, env->msr_lbr_depth);
for (i = 0; i < ARCH_LBR_NR_ENTRIES; i++) {
if (!env->lbr_records[i].from) {
continue;
}
kvm_msr_entry_add(cpu, MSR_ARCH_LBR_FROM_0 + i,
env->lbr_records[i].from);
kvm_msr_entry_add(cpu, MSR_ARCH_LBR_TO_0 + i,
env->lbr_records[i].to);
kvm_msr_entry_add(cpu, MSR_ARCH_LBR_INFO_0 + i,
env->lbr_records[i].info);
}
}
}
/* Note: MSR_IA32_FEATURE_CONTROL is written separately, see /* Note: MSR_IA32_FEATURE_CONTROL is written separately, see
* kvm_put_msr_feature_control. */ * kvm_put_msr_feature_control. */
} }
@ -3761,6 +3799,26 @@ static int kvm_get_msrs(X86CPU *cpu)
kvm_msr_entry_add(cpu, MSR_IA32_XFD_ERR, 0); kvm_msr_entry_add(cpu, MSR_IA32_XFD_ERR, 0);
} }
if (kvm_enabled() && cpu->enable_pmu &&
(env->features[FEAT_7_0_EDX] & CPUID_7_0_EDX_ARCH_LBR)) {
uint64_t ctl, depth;
int i, ret2;
ret = kvm_get_one_msr(cpu, MSR_ARCH_LBR_CTL, &ctl);
ret2 = kvm_get_one_msr(cpu, MSR_ARCH_LBR_DEPTH, &depth);
if (ret == 1 && ret2 == 1 && (ctl & 0x1) &&
depth == ARCH_LBR_NR_ENTRIES) {
kvm_msr_entry_add(cpu, MSR_ARCH_LBR_CTL, 0);
kvm_msr_entry_add(cpu, MSR_ARCH_LBR_DEPTH, 0);
for (i = 0; i < ARCH_LBR_NR_ENTRIES; i++) {
kvm_msr_entry_add(cpu, MSR_ARCH_LBR_FROM_0 + i, 0);
kvm_msr_entry_add(cpu, MSR_ARCH_LBR_TO_0 + i, 0);
kvm_msr_entry_add(cpu, MSR_ARCH_LBR_INFO_0 + i, 0);
}
}
}
ret = kvm_vcpu_ioctl(CPU(cpu), KVM_GET_MSRS, cpu->kvm_msr_buf); ret = kvm_vcpu_ioctl(CPU(cpu), KVM_GET_MSRS, cpu->kvm_msr_buf);
if (ret < 0) { if (ret < 0) {
return ret; return ret;
@ -4066,6 +4124,21 @@ static int kvm_get_msrs(X86CPU *cpu)
case MSR_IA32_XFD_ERR: case MSR_IA32_XFD_ERR:
env->msr_xfd_err = msrs[i].data; env->msr_xfd_err = msrs[i].data;
break; break;
case MSR_ARCH_LBR_CTL:
env->msr_lbr_ctl = msrs[i].data;
break;
case MSR_ARCH_LBR_DEPTH:
env->msr_lbr_depth = msrs[i].data;
break;
case MSR_ARCH_LBR_FROM_0 ... MSR_ARCH_LBR_FROM_0 + 31:
env->lbr_records[index - MSR_ARCH_LBR_FROM_0].from = msrs[i].data;
break;
case MSR_ARCH_LBR_TO_0 ... MSR_ARCH_LBR_TO_0 + 31:
env->lbr_records[index - MSR_ARCH_LBR_TO_0].to = msrs[i].data;
break;
case MSR_ARCH_LBR_INFO_0 ... MSR_ARCH_LBR_INFO_0 + 31:
env->lbr_records[index - MSR_ARCH_LBR_INFO_0].info = msrs[i].data;
break;
} }
} }

View File

@ -136,6 +136,22 @@ static const VMStateDescription vmstate_mtrr_var = {
#define VMSTATE_MTRR_VARS(_field, _state, _n, _v) \ #define VMSTATE_MTRR_VARS(_field, _state, _n, _v) \
VMSTATE_STRUCT_ARRAY(_field, _state, _n, _v, vmstate_mtrr_var, MTRRVar) VMSTATE_STRUCT_ARRAY(_field, _state, _n, _v, vmstate_mtrr_var, MTRRVar)
static const VMStateDescription vmstate_lbr_records_var = {
.name = "lbr_records_var",
.version_id = 1,
.minimum_version_id = 1,
.fields = (VMStateField[]) {
VMSTATE_UINT64(from, LBREntry),
VMSTATE_UINT64(to, LBREntry),
VMSTATE_UINT64(info, LBREntry),
VMSTATE_END_OF_LIST()
}
};
#define VMSTATE_LBR_VARS(_field, _state, _n, _v) \
VMSTATE_STRUCT_ARRAY(_field, _state, _n, _v, vmstate_lbr_records_var, \
LBREntry)
typedef struct x86_FPReg_tmp { typedef struct x86_FPReg_tmp {
FPReg *parent; FPReg *parent;
uint64_t tmp_mant; uint64_t tmp_mant;
@ -1525,6 +1541,27 @@ static const VMStateDescription vmstate_amx_xtile = {
}; };
#endif #endif
static bool arch_lbr_needed(void *opaque)
{
X86CPU *cpu = opaque;
CPUX86State *env = &cpu->env;
return !!(env->features[FEAT_7_0_EDX] & CPUID_7_0_EDX_ARCH_LBR);
}
static const VMStateDescription vmstate_arch_lbr = {
.name = "cpu/arch_lbr",
.version_id = 1,
.minimum_version_id = 1,
.needed = arch_lbr_needed,
.fields = (VMStateField[]) {
VMSTATE_UINT64(env.msr_lbr_ctl, X86CPU),
VMSTATE_UINT64(env.msr_lbr_depth, X86CPU),
VMSTATE_LBR_VARS(env.lbr_records, X86CPU, ARCH_LBR_NR_ENTRIES, 1),
VMSTATE_END_OF_LIST()
}
};
const VMStateDescription vmstate_x86_cpu = { const VMStateDescription vmstate_x86_cpu = {
.name = "cpu", .name = "cpu",
.version_id = 12, .version_id = 12,
@ -1668,6 +1705,7 @@ const VMStateDescription vmstate_x86_cpu = {
#ifdef TARGET_X86_64 #ifdef TARGET_X86_64
&vmstate_amx_xtile, &vmstate_amx_xtile,
#endif #endif
&vmstate_arch_lbr,
NULL NULL
} }
}; };

View File

@ -373,6 +373,8 @@ static int whpx_set_tsc(CPUState *cpu)
* *
* This mechanism is described in section 10.8.6.1 of Volume 3 of Intel 64 * This mechanism is described in section 10.8.6.1 of Volume 3 of Intel 64
* and IA-32 Architectures Software Developer's Manual. * and IA-32 Architectures Software Developer's Manual.
*
* The functions below translate the value of CR8 to TPR and vice versa.
*/ */
static uint64_t whpx_apic_tpr_to_cr8(uint64_t tpr) static uint64_t whpx_apic_tpr_to_cr8(uint64_t tpr)
@ -380,6 +382,11 @@ static uint64_t whpx_apic_tpr_to_cr8(uint64_t tpr)
return tpr >> 4; return tpr >> 4;
} }
static uint64_t whpx_cr8_to_apic_tpr(uint64_t cr8)
{
return cr8 << 4;
}
static void whpx_set_registers(CPUState *cpu, int level) static void whpx_set_registers(CPUState *cpu, int level)
{ {
struct whpx_state *whpx = &whpx_global; struct whpx_state *whpx = &whpx_global;
@ -687,7 +694,7 @@ static void whpx_get_registers(CPUState *cpu)
tpr = vcxt.values[idx++].Reg64; tpr = vcxt.values[idx++].Reg64;
if (tpr != vcpu->tpr) { if (tpr != vcpu->tpr) {
vcpu->tpr = tpr; vcpu->tpr = tpr;
cpu_set_apic_tpr(x86_cpu->apic_state, tpr); cpu_set_apic_tpr(x86_cpu->apic_state, whpx_cr8_to_apic_tpr(tpr));
} }
/* 8 Debug Registers - Skipped */ /* 8 Debug Registers - Skipped */
@ -1547,7 +1554,7 @@ static void whpx_vcpu_pre_run(CPUState *cpu)
} }
/* Sync the TPR to the CR8 if was modified during the intercept */ /* Sync the TPR to the CR8 if was modified during the intercept */
tpr = cpu_get_apic_tpr(x86_cpu->apic_state); tpr = whpx_apic_tpr_to_cr8(cpu_get_apic_tpr(x86_cpu->apic_state));
if (tpr != vcpu->tpr) { if (tpr != vcpu->tpr) {
vcpu->tpr = tpr; vcpu->tpr = tpr;
reg_values[reg_count].Reg64 = tpr; reg_values[reg_count].Reg64 = tpr;
@ -1596,7 +1603,7 @@ static void whpx_vcpu_post_run(CPUState *cpu)
if (vcpu->tpr != tpr) { if (vcpu->tpr != tpr) {
vcpu->tpr = tpr; vcpu->tpr = tpr;
qemu_mutex_lock_iothread(); qemu_mutex_lock_iothread();
cpu_set_apic_tpr(x86_cpu->apic_state, vcpu->tpr); cpu_set_apic_tpr(x86_cpu->apic_state, whpx_cr8_to_apic_tpr(vcpu->tpr));
qemu_mutex_unlock_iothread(); qemu_mutex_unlock_iothread();
} }