]> git.ipfire.org Git - thirdparty/libvirt.git/commitdiff
virHostCPUGetCPUIDFilterVolatile: Filter out topology data on AMD
authorPeter Krempa <pkrempa@redhat.com>
Mon, 25 Apr 2022 11:55:12 +0000 (13:55 +0200)
committerPeter Krempa <pkrempa@redhat.com>
Mon, 25 Apr 2022 14:38:01 +0000 (16:38 +0200)
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@redhat.com>
Reviewed-by: Jiri Denemark <jdenemar@redhat.com>
Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
src/util/virhostcpu.c

index 9a9fcf11c0fe2af43f9e31fc4baf86855ea994b9..e3f2d6d4b7d1100dec73bebb5715fa1b6c4147d6 100644 (file)
@@ -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;
+        }
     }
 }