summaryrefslogtreecommitdiff
path: root/UefiCpuPkg/Library/BaseXApicX2ApicLib/BaseXApicX2ApicLib.c
diff options
context:
space:
mode:
Diffstat (limited to 'UefiCpuPkg/Library/BaseXApicX2ApicLib/BaseXApicX2ApicLib.c')
-rw-r--r--UefiCpuPkg/Library/BaseXApicX2ApicLib/BaseXApicX2ApicLib.c69
1 files changed, 63 insertions, 6 deletions
diff --git a/UefiCpuPkg/Library/BaseXApicX2ApicLib/BaseXApicX2ApicLib.c b/UefiCpuPkg/Library/BaseXApicX2ApicLib/BaseXApicX2ApicLib.c
index bf318e06e4..8c6e8d7415 100644
--- a/UefiCpuPkg/Library/BaseXApicX2ApicLib/BaseXApicX2ApicLib.c
+++ b/UefiCpuPkg/Library/BaseXApicX2ApicLib/BaseXApicX2ApicLib.c
@@ -22,12 +22,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.
@@ -39,8 +67,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)) +
@@ -61,10 +97,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 of the CPU does not support APIC Base Address MSR
+ //
+ return;
+ }
+
ApicBaseMsr.Uint64 = AsmReadMsr64 (MSR_IA32_APIC_BASE_ADDRESS);
ApicBaseMsr.Bits.ApicBaseLow = (UINT32) (BaseAddress >> 12);
@@ -257,7 +300,14 @@ GetApicMode (
VOID
)
{
- MSR_IA32_APIC_BASE ApicBaseMsr;
+ MSR_IA32_APIC_BASE ApicBaseMsr;
+
+ if (!LocalApicBaseAddressMsrSupported ()) {
+ //
+ // If CPU does not support APIC Base Address MSR, then return XAPIC mode
+ //
+ return LOCAL_APIC_MODE_XAPIC;
+ }
ApicBaseMsr.Uint64 = AsmReadMsr64 (MSR_IA32_APIC_BASE_ADDRESS);
//
@@ -288,8 +338,15 @@ SetApicMode (
IN UINTN ApicMode
)
{
- UINTN CurrentMode;
- MSR_IA32_APIC_BASE ApicBaseMsr;
+ UINTN CurrentMode;
+ MSR_IA32_APIC_BASE ApicBaseMsr;
+
+ if (!LocalApicBaseAddressMsrSupported ()) {
+ //
+ // Ignore set request if the CPU does not support APIC Base Address MSR
+ //
+ return;
+ }
CurrentMode = GetApicMode ();
if (CurrentMode == LOCAL_APIC_MODE_XAPIC) {