summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--UefiCpuPkg/Library/BaseXApicLib/BaseXApicLib.c66
-rw-r--r--UefiCpuPkg/Library/BaseXApicLib/BaseXApicLib.inf6
2 files changed, 61 insertions, 11 deletions
diff --git a/UefiCpuPkg/Library/BaseXApicLib/BaseXApicLib.c b/UefiCpuPkg/Library/BaseXApicLib/BaseXApicLib.c
index 6f8cd2eb9b..f219b07888 100644
--- a/UefiCpuPkg/Library/BaseXApicLib/BaseXApicLib.c
+++ b/UefiCpuPkg/Library/BaseXApicLib/BaseXApicLib.c
@@ -3,7 +3,7 @@
This local APIC library instance supports xAPIC mode only.
- Copyright (c) 2010 - 2014, Intel Corporation. All rights reserved.<BR>
+ Copyright (c) 2010 - 2015, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
@@ -21,12 +21,40 @@
#include <Library/LocalApicLib.h>
#include <Library/IoLib.h>
#include <Library/TimerLib.h>
+#include <Library/PcdLib.h>
//
// Library internal functions
//
/**
+ Determine if the CPU supports the Local APIC Base Address MSR.
+
+ @retval TRUE The CPU supports the Local APIC Base Address MSR.
+ @retval FALSE The CPU does not support the Local APIC Base Address MSR.
+
+**/
+BOOLEAN
+LocalApicBaseAddressMsrSupported (
+ VOID
+ )
+{
+ UINT32 RegEax;
+ UINTN FamilyId;
+
+ AsmCpuid (1, &RegEax, NULL, NULL, NULL);
+ FamilyId = BitFieldRead32 (RegEax, 8, 11);
+ if (FamilyId == 0x04 || FamilyId == 0x05) {
+ //
+ // CPUs with a FamilyId of 0x04 or 0x05 do not support the
+ // Local APIC Base Address MSR
+ //
+ return FALSE;
+ }
+ return TRUE;
+}
+
+/**
Retrieve the base address of local APIC.
@return The base address of local APIC.
@@ -38,8 +66,16 @@ GetLocalApicBaseAddress (
VOID
)
{
- MSR_IA32_APIC_BASE ApicBaseMsr;
-
+ MSR_IA32_APIC_BASE ApicBaseMsr;
+
+ if (!LocalApicBaseAddressMsrSupported ()) {
+ //
+ // If CPU does not support Local APIC Base Address MSR, then retrieve
+ // Local APIC Base Address from PCD
+ //
+ return PcdGet32 (PcdCpuLocalApicBaseAddress);
+ }
+
ApicBaseMsr.Uint64 = AsmReadMsr64 (MSR_IA32_APIC_BASE_ADDRESS);
return (UINTN)(LShiftU64 ((UINT64) ApicBaseMsr.Bits.ApicBaseHigh, 32)) +
@@ -60,10 +96,17 @@ SetLocalApicBaseAddress (
IN UINTN BaseAddress
)
{
- MSR_IA32_APIC_BASE ApicBaseMsr;
+ MSR_IA32_APIC_BASE ApicBaseMsr;
ASSERT ((BaseAddress & (SIZE_4KB - 1)) == 0);
+ if (!LocalApicBaseAddressMsrSupported ()) {
+ //
+ // Ignore set request if the CPU does not support APIC Base Address MSR
+ //
+ return;
+ }
+
ApicBaseMsr.Uint64 = AsmReadMsr64 (MSR_IA32_APIC_BASE_ADDRESS);
ApicBaseMsr.Bits.ApicBaseLow = (UINT32) (BaseAddress >> 12);
@@ -202,14 +245,19 @@ GetApicMode (
{
DEBUG_CODE (
{
- MSR_IA32_APIC_BASE ApicBaseMsr;
+ MSR_IA32_APIC_BASE ApicBaseMsr;
- ApicBaseMsr.Uint64 = AsmReadMsr64 (MSR_IA32_APIC_BASE_ADDRESS);
//
- // Local APIC should have been enabled
+ // Check to see if the CPU supports the APIC Base Address MSR
//
- ASSERT (ApicBaseMsr.Bits.En != 0);
- ASSERT (ApicBaseMsr.Bits.Extd == 0);
+ if (LocalApicBaseAddressMsrSupported ()) {
+ ApicBaseMsr.Uint64 = AsmReadMsr64 (MSR_IA32_APIC_BASE_ADDRESS);
+ //
+ // Local APIC should have been enabled
+ //
+ ASSERT (ApicBaseMsr.Bits.En != 0);
+ ASSERT (ApicBaseMsr.Bits.Extd == 0);
+ }
}
);
return LOCAL_APIC_MODE_XAPIC;
diff --git a/UefiCpuPkg/Library/BaseXApicLib/BaseXApicLib.inf b/UefiCpuPkg/Library/BaseXApicLib/BaseXApicLib.inf
index 120e6e50e9..7dd2714af3 100644
--- a/UefiCpuPkg/Library/BaseXApicLib/BaseXApicLib.inf
+++ b/UefiCpuPkg/Library/BaseXApicLib/BaseXApicLib.inf
@@ -21,7 +21,7 @@
MODULE_UNI_FILE = BaseXApicLib.uni
FILE_GUID = D87CA0A8-1AC2-439b-90F8-EF4A2AC88DAF
MODULE_TYPE = BASE
- VERSION_STRING = 1.0
+ VERSION_STRING = 1.1
LIBRARY_CLASS = LocalApicLib
#
@@ -42,6 +42,8 @@
DebugLib
TimerLib
IoLib
+ PcdLib
[Pcd]
- gUefiCpuPkgTokenSpaceGuid.PcdCpuInitIpiDelayInMicroSeconds ## SOMETIMES_CONSUMES
+ gUefiCpuPkgTokenSpaceGuid.PcdCpuInitIpiDelayInMicroSeconds ## SOMETIMES_CONSUMES
+ gUefiCpuPkgTokenSpaceGuid.PcdCpuLocalApicBaseAddress ## SOMETIMES_CONSUMES