summaryrefslogtreecommitdiffstats
path: root/UefiCpuPkg
diff options
context:
space:
mode:
authorLaszlo Ersek <lersek@redhat.com>2016-11-22 13:58:54 +0100
committerLaszlo Ersek <lersek@redhat.com>2016-11-23 21:41:24 +0100
commit1cbd8330898964a465ebb91421b951595398d56b (patch)
treecdf80e7b1c0b39b515ed8a266b866b780f6d23f7 /UefiCpuPkg
parent4af3ae1463796ef7b2ecf2bfe8b390e72817212c (diff)
downloadedk2-1cbd8330898964a465ebb91421b951595398d56b.tar.gz
edk2-1cbd8330898964a465ebb91421b951595398d56b.tar.bz2
edk2-1cbd8330898964a465ebb91421b951595398d56b.zip
UefiCpuPkg/MpInitLib: fix feature test for Extended Topology CPUID leaf
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 "GetApicId" sections in the Ia32 and X64 "MpFuncs.nasm" files 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". Under "GetApicId", 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), the "GetProcessorNumber" section of the code is reached with an initial APIC ID of 0 in EDX on all of the APs. Given that "GetProcessorNumber" searches the "MP_CPU_EXCHANGE_INFO.CpuInfo[*].InitialApicId" fields for a match, all APs enter ApWakeupFunction() with an identical "NumApsExecuting" parameter. This results in unpredictable guest behavior (crashes, reboots, hangs etc). Reorganize the "GetApicId" section and add the missing check in both assembly files. 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>
Diffstat (limited to 'UefiCpuPkg')
-rw-r--r--UefiCpuPkg/Library/MpInitLib/Ia32/MpFuncs.nasm21
-rw-r--r--UefiCpuPkg/Library/MpInitLib/X64/MpFuncs.nasm21
2 files changed, 24 insertions, 18 deletions
diff --git a/UefiCpuPkg/Library/MpInitLib/Ia32/MpFuncs.nasm b/UefiCpuPkg/Library/MpInitLib/Ia32/MpFuncs.nasm
index 64e51d87ae..9067f78070 100644
--- a/UefiCpuPkg/Library/MpInitLib/Ia32/MpFuncs.nasm
+++ b/UefiCpuPkg/Library/MpInitLib/Ia32/MpFuncs.nasm
@@ -154,21 +154,24 @@ GetApicId:
mov eax, 0
cpuid
cmp eax, 0bh
- jnb X2Apic
+ jb NoX2Apic ; CPUID level below CPUID_EXTENDED_TOPOLOGY
+
+ mov eax, 0bh
+ xor ecx, ecx
+ cpuid
+ test ebx, 0ffffh
+ jz NoX2Apic ; CPUID.0BH:EBX[15:0] is zero
+
+ ; Processor is x2APIC capable; 32-bit x2APIC ID is already in EDX
+ jmp GetProcessorNumber
+
+NoX2Apic:
; Processor is not x2APIC capable, so get 8-bit APIC ID
mov eax, 1
cpuid
shr ebx, 24
mov edx, ebx
- jmp GetProcessorNumber
-X2Apic:
- ; Processor is x2APIC capable, so get 32-bit x2APIC ID
- mov eax, 0bh
- xor ecx, ecx
- cpuid
- ; edx save x2APIC ID
-
GetProcessorNumber:
;
; Get processor number for this AP
diff --git a/UefiCpuPkg/Library/MpInitLib/X64/MpFuncs.nasm b/UefiCpuPkg/Library/MpInitLib/X64/MpFuncs.nasm
index aaabb50c54..e7e7d8086d 100644
--- a/UefiCpuPkg/Library/MpInitLib/X64/MpFuncs.nasm
+++ b/UefiCpuPkg/Library/MpInitLib/X64/MpFuncs.nasm
@@ -158,21 +158,24 @@ GetApicId:
mov eax, 0
cpuid
cmp eax, 0bh
- jnb X2Apic
+ jb NoX2Apic ; CPUID level below CPUID_EXTENDED_TOPOLOGY
+
+ mov eax, 0bh
+ xor ecx, ecx
+ cpuid
+ test ebx, 0ffffh
+ jz NoX2Apic ; CPUID.0BH:EBX[15:0] is zero
+
+ ; Processor is x2APIC capable; 32-bit x2APIC ID is already in EDX
+ jmp GetProcessorNumber
+
+NoX2Apic:
; Processor is not x2APIC capable, so get 8-bit APIC ID
mov eax, 1
cpuid
shr ebx, 24
mov edx, ebx
- jmp GetProcessorNumber
-X2Apic:
- ; Processor is x2APIC capable, so get 32-bit x2APIC ID
- mov eax, 0bh
- xor ecx, ecx
- cpuid
- ; edx save x2APIC ID
-
GetProcessorNumber:
;
; Get processor number for this AP