From e9cd66d0859f63ec6aab2b1ac863fe72b65fe474 Mon Sep 17 00:00:00 2001 From: Michael Kinney Date: Mon, 27 Apr 2015 19:48:00 +0000 Subject: MdePkg/BaseXApicX2ApicLib: Support IA32 processors without MSR_IA32_APIC_BASE_ADDRESS Use Family from CPUID 01 to detect support for the Local APIC Base Address MSR (MSR_IA32_APIC_BASE_ADDRESS). If this MSR is not supported, then use Local APIC Base Address from the PCD PcdCpuLocalApicBaseAddress. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Michael Kinney Reviewed-by: Jordan Justen git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@17217 6f19259b-4bc3-4df7-8a09-765794883524 --- .../BaseXApicX2ApicLib/BaseXApicX2ApicLib.c | 69 ++++++++++++++++++++-- .../BaseXApicX2ApicLib/BaseXApicX2ApicLib.inf | 7 ++- 2 files changed, 67 insertions(+), 9 deletions(-) (limited to 'UefiCpuPkg') 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,11 +22,39 @@ #include #include #include +#include // // 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. @@ -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) { diff --git a/UefiCpuPkg/Library/BaseXApicX2ApicLib/BaseXApicX2ApicLib.inf b/UefiCpuPkg/Library/BaseXApicX2ApicLib/BaseXApicX2ApicLib.inf index 1e0e98433d..53e186858f 100644 --- a/UefiCpuPkg/Library/BaseXApicX2ApicLib/BaseXApicX2ApicLib.inf +++ b/UefiCpuPkg/Library/BaseXApicX2ApicLib/BaseXApicX2ApicLib.inf @@ -21,7 +21,7 @@ MODULE_UNI_FILE = BaseXApicX2ApicLib.uni FILE_GUID = 967B6E05-F10D-4c10-8BF7-365291CA143F MODULE_TYPE = BASE - VERSION_STRING = 1.0 + VERSION_STRING = 1.1 LIBRARY_CLASS = LocalApicLib # @@ -42,7 +42,8 @@ DebugLib TimerLib IoLib + PcdLib [Pcd] - gUefiCpuPkgTokenSpaceGuid.PcdCpuInitIpiDelayInMicroSeconds ## SOMETIMES_CONSUMES - + gUefiCpuPkgTokenSpaceGuid.PcdCpuInitIpiDelayInMicroSeconds ## SOMETIMES_CONSUMES + gUefiCpuPkgTokenSpaceGuid.PcdCpuLocalApicBaseAddress ## SOMETIMES_CONSUMES -- cgit v1.2.3