]> git.ipfire.org Git - thirdparty/libvirt.git/commitdiff
qemu_capabilities: Fix domain capabilities on AMD CPUs
authorJiri Denemark <jdenemar@redhat.com>
Mon, 25 May 2026 12:31:07 +0000 (14:31 +0200)
committerJiri Denemark <jdenemar@redhat.com>
Tue, 2 Jun 2026 11:45:27 +0000 (13:45 +0200)
The arch-capabilities MSR is not defined on AMD CPUs, but KVM has always
been emulating them. Unfortunately, this may cause Windows to crash so
QEMU (since 10.1, commit d3a24134e37d57abd3e7445842cda2717f49e96d)
decided to mask the MSR by default with some additional compatibility
code for older machine types.

This is all mostly transparent except for probing when we run QEMU
without a machine type and expand the "host" CPU model. With QEMU 10.1
and newer none of the arch-capabilities features will be shown as
enabled, which may cause unexpected issues for users (such as KubeVirt)
that get the list of all supported features from the host-model CPU
definition in domain capabilities to select possible target nodes for
migration. As a result of the change, no AMD host with new QEMU will be
shown as available for incoming migration from older hosts.

Since the features are supported on the host (it's possible to
explicitly enable them), but they should not be enabled by default in
host-model CPU, we only add the to domain capabilities when
VIR_CONNECT_GET_DOMAIN_CAPABILITIES_SUPPORTED_CPU_FEATURES flag is set.

Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
Reviewed-by: Peter Krempa <pkrempa@redhat.com>
src/qemu/qemu_capabilities.c
src/qemu/qemu_driver.c
tests/domaincapsdata/qemu_10.1.0-q35.x86_64-supported.xml
tests/domaincapsdata/qemu_10.2.0-q35.x86_64-supported.xml
tests/domaincapsdata/qemu_11.0.0-q35.x86_64+sgx-supported.xml
tests/domaincapsdata/qemu_11.0.0-q35.x86_64-supported.xml

index 54cf0d624ba01f089f132e68d56ba23ac2e342e7..1c89c0a1de56ad01a82109f4f5e70b7f9c283f8a 100644 (file)
@@ -6657,6 +6657,7 @@ virQEMUCapsFillDomainCPUHostModel(virQEMUCaps *qemuCaps,
 {
     virQEMUCapsHostCPUType cpuType;
     virCPUDef *cpu;
+    virArch arch = domCaps->arch;
 
     if (flags & VIR_CONNECT_GET_DOMAIN_CAPABILITIES_EXPAND_CPU_FEATURES)
         cpuType = VIR_QEMU_CAPS_HOST_CPU_EXPANDED;
@@ -6673,6 +6674,29 @@ virQEMUCapsFillDomainCPUHostModel(virQEMUCaps *qemuCaps,
                                                cpu, VIR_CPU_FEATURE_DISABLE);
     }
 
+    if (flags & VIR_CONNECT_GET_DOMAIN_CAPABILITIES_SUPPORTED_CPU_FEATURES) {
+        uint32_t index = 0x10a; /* arch-capabilities MSR */
+        uint64_t msr = 0;
+
+        /* While the arch-capabilities MSR is not defined on AMD CPUs, KVM has
+         * always been emulating them. Unfortunately, this may cause some
+         * Windows version to crash so QEMU decided to mask the MSR by default.
+         * When asked for all CPU features supported on a host we need to add
+         * the affected features to the host-model.
+         */
+        if (ARCH_IS_X86(arch) &&
+            STREQ_NULLABLE(cpu->vendor, "AMD") &&
+            virCPUCheckFeature(arch, cpu, "arch-capabilities") == 0 &&
+            virHostCPUGetMSRFromKVM(index, &msr) == 0) {
+            g_autoptr(virCPUData) data = virCPUDataNew(arch);
+            virCPUFeaturePolicy policy = VIR_CPU_FEATURE_REQUIRE;
+
+            virCPUx86DataAddMSR(data, index, msr);
+            virCPUUpdateFeatures(arch, cpu, data, policy);
+            virCPUDefUpdateFeature(cpu, "arch-capabilities", policy);
+        }
+    }
+
     virCPUDefSortFeatures(cpu);
     domCaps->cpu.hostModel = cpu;
 }
index f9a04c98e8c5202c2cc6de8744c30256299c56c9..dbb907547689cdfe13e3d1494b76185a0a13eaca 100644 (file)
@@ -16965,7 +16965,8 @@ qemuConnectGetDomainCapabilities(virConnectPtr conn,
     g_autoptr(virDomainCaps) domCaps = NULL;
 
     virCheckFlags(VIR_CONNECT_GET_DOMAIN_CAPABILITIES_DISABLE_DEPRECATED_FEATURES |
-                  VIR_CONNECT_GET_DOMAIN_CAPABILITIES_EXPAND_CPU_FEATURES,
+                  VIR_CONNECT_GET_DOMAIN_CAPABILITIES_EXPAND_CPU_FEATURES |
+                  VIR_CONNECT_GET_DOMAIN_CAPABILITIES_SUPPORTED_CPU_FEATURES,
                   NULL);
 
     if (virConnectGetDomainCapabilitiesEnsureACL(conn) < 0)
index 14beb4b11aff42186d460448d209068dc2a92b81..b235e8cc24917160011736fe81b8cadb5117a0ab 100644 (file)
       <vendor>AMD</vendor>
       <maxphysaddr mode='passthrough' limit='64'/>
       <feature policy='require' name='amd-ssbd'/>
+      <feature policy='require' name='arch-capabilities'/>
       <feature policy='require' name='cmp_legacy'/>
       <feature policy='require' name='flushbyasid'/>
+      <feature policy='require' name='gds-no'/>
       <feature policy='require' name='hypervisor'/>
       <feature policy='require' name='ibpb-brtype'/>
       <feature policy='require' name='invtsc'/>
       <feature policy='require' name='lbrv'/>
       <feature policy='require' name='lfence-always-serializing'/>
+      <feature policy='require' name='mds-no'/>
       <feature policy='require' name='null-sel-clr-base'/>
       <feature policy='require' name='overflow-recov'/>
       <feature policy='require' name='pause-filter'/>
       <feature policy='require' name='pfthreshold'/>
+      <feature policy='require' name='pschange-mc-no'/>
+      <feature policy='require' name='rdctl-no'/>
+      <feature policy='require' name='rfds-no'/>
+      <feature policy='require' name='skip-l1dfl-vmentry'/>
       <feature policy='require' name='ssbd'/>
       <feature policy='require' name='stibp'/>
       <feature policy='require' name='succor'/>
index 7a89f10f8dbb1d70459fe08d3260d4e7abeb38c3..9bd3acc08dacaf0b191fa8230cdd469ec2c1289c 100644 (file)
       <model fallback='forbid'>EPYC-Turin</model>
       <vendor>AMD</vendor>
       <maxphysaddr mode='passthrough' limit='64'/>
+      <feature policy='require' name='arch-capabilities'/>
       <feature policy='require' name='cmp_legacy'/>
       <feature policy='require' name='flush-l1d'/>
+      <feature policy='require' name='gds-no'/>
       <feature policy='require' name='hypervisor'/>
       <feature policy='require' name='invtsc'/>
       <feature policy='disable' name='la57'/>
+      <feature policy='require' name='mds-no'/>
       <feature policy='disable' name='pcid'/>
+      <feature policy='require' name='pschange-mc-no'/>
+      <feature policy='require' name='rdctl-no'/>
       <feature policy='disable' name='rdseed'/>
+      <feature policy='require' name='rfds-no'/>
+      <feature policy='require' name='skip-l1dfl-vmentry'/>
       <feature policy='require' name='spec-ctrl'/>
       <feature policy='require' name='ssbd'/>
       <feature policy='require' name='stibp'/>
index b4a1291d2e4d8427c12627b9b1b81cb9e3d46199..ae04d836527a87be5063848b8f0d0c00622989b1 100644 (file)
       <model fallback='forbid'>EPYC-Turin</model>
       <vendor>AMD</vendor>
       <maxphysaddr mode='passthrough' limit='64'/>
+      <feature policy='require' name='arch-capabilities'/>
       <feature policy='require' name='cet-ss'/>
       <feature policy='require' name='cmp_legacy'/>
       <feature policy='require' name='flush-l1d'/>
+      <feature policy='require' name='gds-no'/>
       <feature policy='require' name='hypervisor'/>
       <feature policy='require' name='invtsc'/>
       <feature policy='disable' name='la57'/>
+      <feature policy='require' name='mds-no'/>
       <feature policy='disable' name='pcid'/>
+      <feature policy='require' name='pschange-mc-no'/>
+      <feature policy='require' name='rdctl-no'/>
       <feature policy='disable' name='rdseed'/>
+      <feature policy='require' name='rfds-no'/>
+      <feature policy='require' name='skip-l1dfl-vmentry'/>
       <feature policy='require' name='spec-ctrl'/>
       <feature policy='require' name='ssbd'/>
       <feature policy='require' name='stibp'/>
index e529e0ccee6dabb4af5b8e38d64038ac6f8db4a4..226afa0fee24f329134540eac5ff1f5e00ddde85 100644 (file)
       <model fallback='forbid'>EPYC-Turin</model>
       <vendor>AMD</vendor>
       <maxphysaddr mode='passthrough' limit='64'/>
+      <feature policy='require' name='arch-capabilities'/>
       <feature policy='require' name='cet-ss'/>
       <feature policy='require' name='cmp_legacy'/>
       <feature policy='require' name='flush-l1d'/>
+      <feature policy='require' name='gds-no'/>
       <feature policy='require' name='hypervisor'/>
       <feature policy='require' name='invtsc'/>
       <feature policy='disable' name='la57'/>
+      <feature policy='require' name='mds-no'/>
       <feature policy='disable' name='pcid'/>
+      <feature policy='require' name='pschange-mc-no'/>
+      <feature policy='require' name='rdctl-no'/>
       <feature policy='disable' name='rdseed'/>
+      <feature policy='require' name='rfds-no'/>
+      <feature policy='require' name='skip-l1dfl-vmentry'/>
       <feature policy='require' name='spec-ctrl'/>
       <feature policy='require' name='ssbd'/>
       <feature policy='require' name='stibp'/>