[PATCH 7/7] virHostCPUGetCPUIDFilterVolatile: Filter out topology data on AMD

Peter Krempa pkrempa at redhat.com
Mon Apr 25 13:28:31 UTC 2022


AMD cpus report Core (compute unit) identifiers of the cpu running the
instruction under leaf 0x8000001e. This data is not needed for libvirt
and actually breaks caching of the qemu capabilities where we check that
all of the CPU flags to be identical.

Mask out all of leaf 0x8000001e.

Signed-off-by: Peter Krempa <pkrempa at redhat.com>
---
 src/util/virhostcpu.c | 43 +++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 43 insertions(+)

diff --git a/src/util/virhostcpu.c b/src/util/virhostcpu.c
index 9a9fcf11c0..e3f2d6d4b7 100644
--- a/src/util/virhostcpu.c
+++ b/src/util/virhostcpu.c
@@ -1324,11 +1324,13 @@ virHostCPUGetMSR(unsigned long index,
  *
  * Currently filtered fields:
  * - local APIC ID
+ * - topology ids and information on AMD cpus
  */
 static void
 virHostCPUGetCPUIDFilterVolatile(struct kvm_cpuid2 *kvm_cpuid)
 {
     size_t i;
+    bool isAMD = false;

     for (i = 0; i < kvm_cpuid->nent; ++i) {
         struct kvm_cpuid_entry2 *entry = &kvm_cpuid->entries[i];
@@ -1338,6 +1340,47 @@ virHostCPUGetCPUIDFilterVolatile(struct kvm_cpuid2 *kvm_cpuid)
             entry->ebx &= 0x00ffffff;
         if (entry->function == 0x0b)
             entry->edx &= 0xffffff00;
+
+        /* Match AMD hosts */
+        if (entry->function == 0x00 && entry->index == 0x00 &&
+            entry->ebx == 0x68747541 && /* Auth */
+            entry->edx == 0x69746e65 && /* enti */
+            entry->ecx == 0x444d4163)   /* cAMD */
+            isAMD = true;
+
+        /* AMD APIC ID and topology information:
+         *
+         * Leaf 0x8000001e
+         *
+         * CPUID Fn8000_001E_EAX Extended APIC ID
+         *  31:0 ExtendedApicId: extended APIC ID.
+         *
+         * CPUID Fn8000_001E_EBX Compute Unit Identifiers
+         *  31:10 Reserved.
+         *  9:8   CoresPerComputeUnit: cores per compute unit.
+         *        The number of cores per compute unit is CoresPerComputeUnit+1.
+         *  7:0   ComputeUnitId: compute unit ID. Identifies the processor compute unit ID.
+         *
+         * CPUID Fn8000_001E_ECX Node Identifiers
+         *  31:11 Reserved.
+         *  10:8  NodesPerProcessor. Specifies the number of nodes per processor.
+         *          000b      1  node per processor
+         *          001b      2  nodes per processor
+         *          111b-010b Reserved
+         *  7:0   NodeId. Specifies the node ID.
+         *
+         * CPUID Fn8000_001E_EDX Reserved
+         *  31:0 Reserved.
+         *
+         * For libvirt none of this information seems to be interesting, thus
+         * we clear all of it including reserved bits for future-proofing.
+         */
+        if (isAMD && entry->function == 0x8000001e) {
+            entry->eax = 0x00;
+            entry->ebx = 0x00;
+            entry->ecx = 0x00;
+            entry->edx = 0x00;
+        }
     }
 }

-- 
2.35.1



More information about the libvir-list mailing list