]> git.proxmox.com Git - mirror_edk2.git/commitdiff
UefiCpuPkg/LocalApicLib: fix feature test for Extended Topology CPUID leaf
authorLaszlo Ersek <lersek@redhat.com>
Tue, 22 Nov 2016 11:43:17 +0000 (12:43 +0100)
committerLaszlo Ersek <lersek@redhat.com>
Wed, 23 Nov 2016 20:41:05 +0000 (21:41 +0100)
According to the Intel SDM (325462-060US / September 2016),

> INPUT EAX = 0BH: Returns Extended Topology Information
>
> [...] Software must detect the presence of CPUID leaf 0BH by verifying
> (a) the highest leaf index supported by CPUID is >= 0BH, and
> (b) CPUID.0BH:EBX[15:0] reports a non-zero value. [...]

The LocalApicLib instances in UefiCpuPkg do not perform check (b).

This causes an actual bug in the following OVMF setup:

- Intel W3550 host processor <http://ark.intel.com/products/39720/>,

- the QEMU/KVM guest's VCPU model is set to "host", that is, "the CPU
  visible to the guest should be exactly the same as the host CPU".

In the GetInitialApicId() function, check (a) passes: the CPUID level of
the W3550 is exactly 11 decimal. However, leaf 11 itself is not supported,
therefore EDX is set to zero:

> If a value entered for CPUID.EAX is less than or equal to the maximum
> input value and the leaf is not supported on that processor then 0 is
> returned in all the registers.

Because we don't check (b), we return 0 as initial APIC ID on the BSP and
on all of the APs as well.

Add the missing check.

Cc: Jeff Fan <jeff.fan@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
Reviewed-by: Jeff Fan <jeff.fan@intel.com>
UefiCpuPkg/Library/BaseXApicLib/BaseXApicLib.c
UefiCpuPkg/Library/BaseXApicX2ApicLib/BaseXApicX2ApicLib.c

index 4064049807b72fcc334520339695fdcffd74fe93..f81bbb2252d9e82df9eab00d56b65f8bf9b7e4bb 100644 (file)
@@ -314,12 +314,15 @@ GetInitialApicId (
 \r
   //\r
   // If CPUID Leaf B is supported, \r
+  // And CPUID.0BH:EBX[15:0] reports a non-zero value,\r
   // Then the initial 32-bit APIC ID = CPUID.0BH:EDX\r
   // Else the initial 8-bit APIC ID = CPUID.1:EBX[31:24]\r
   //\r
   if (MaxCpuIdIndex >= CPUID_EXTENDED_TOPOLOGY) {\r
-    AsmCpuidEx (CPUID_EXTENDED_TOPOLOGY, 0, NULL, NULL, NULL, &ApicId);\r
-    return ApicId;\r
+    AsmCpuidEx (CPUID_EXTENDED_TOPOLOGY, 0, NULL, &RegEbx, NULL, &ApicId);\r
+    if ((RegEbx & (BIT16 - 1)) != 0) {\r
+      return ApicId;\r
+    }\r
   }\r
 \r
   AsmCpuid (CPUID_VERSION_INFO, NULL, &RegEbx, NULL, NULL);\r
index 9720d26e60e2044951c01bcb5cfe8e2ca2118a94..e690d2aa144524e703a4002c1145703f1918b87b 100644 (file)
@@ -411,12 +411,15 @@ GetInitialApicId (
     AsmCpuid (CPUID_SIGNATURE, &MaxCpuIdIndex, NULL, NULL, NULL);\r
     //\r
     // If CPUID Leaf B is supported, \r
+    // And CPUID.0BH:EBX[15:0] reports a non-zero value,\r
     // Then the initial 32-bit APIC ID = CPUID.0BH:EDX\r
     // Else the initial 8-bit APIC ID = CPUID.1:EBX[31:24]\r
     //\r
     if (MaxCpuIdIndex >= CPUID_EXTENDED_TOPOLOGY) {\r
-      AsmCpuidEx (CPUID_EXTENDED_TOPOLOGY, 0, NULL, NULL, NULL, &ApicId);\r
-      return ApicId;\r
+      AsmCpuidEx (CPUID_EXTENDED_TOPOLOGY, 0, NULL, &RegEbx, NULL, &ApicId);\r
+      if ((RegEbx & (BIT16 - 1)) != 0) {\r
+        return ApicId;\r
+      }\r
     }\r
     AsmCpuid (CPUID_VERSION_INFO, NULL, &RegEbx, NULL, NULL);\r
     return RegEbx >> 24;\r