]> git.proxmox.com Git - mirror_edk2.git/commitdiff
Add Local APIC Library class defining APIs for common Local APIC operations. Add...
authorrsun3 <rsun3@6f19259b-4bc3-4df7-8a09-765794883524>
Mon, 23 Aug 2010 06:34:39 +0000 (06:34 +0000)
committerrsun3 <rsun3@6f19259b-4bc3-4df7-8a09-765794883524>
Mon, 23 Aug 2010 06:34:39 +0000 (06:34 +0000)
git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@10814 6f19259b-4bc3-4df7-8a09-765794883524

UefiCpuPkg/Include/Library/LocalApicLib.h [new file with mode: 0644]
UefiCpuPkg/Include/Register/LocalApic.h [new file with mode: 0644]
UefiCpuPkg/Library/BaseXApicLib/BaseXApicLib.c [new file with mode: 0644]
UefiCpuPkg/Library/BaseXApicLib/BaseXApicLib.inf [new file with mode: 0644]
UefiCpuPkg/Library/BaseXApicX2ApicLib/BaseXApicX2ApicLib.c [new file with mode: 0644]
UefiCpuPkg/Library/BaseXApicX2ApicLib/BaseXApicX2ApicLib.inf [new file with mode: 0644]
UefiCpuPkg/UefiCpuPkg.dec
UefiCpuPkg/UefiCpuPkg.dsc

diff --git a/UefiCpuPkg/Include/Library/LocalApicLib.h b/UefiCpuPkg/Include/Library/LocalApicLib.h
new file mode 100644 (file)
index 0000000..58e3474
--- /dev/null
@@ -0,0 +1,270 @@
+/** @file\r
+  Public include file for Local APIC library.\r
+\r
+  Local APIC library assumes local APIC is enabled. It does not\r
+  handles cases where local APIC is disabled.\r
+\r
+  Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>\r
+  This program and the accompanying materials\r
+  are licensed and made available under the terms and conditions of the BSD License\r
+  which accompanies this distribution.  The full text of the license may be found at\r
+  http://opensource.org/licenses/bsd-license.php\r
+\r
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#ifndef __LOCAL_APIC_LIB_H__\r
+#define __LOCAL_APIC_LIB_H__\r
+\r
+#define LOCAL_APIC_MODE_XAPIC   0x1  ///< xAPIC mode.\r
+#define LOCAL_APIC_MODE_X2APIC  0x2  ///< x2APIC mode.\r
+\r
+/**\r
+  Get the current local APIC mode.\r
+\r
+  If local APIC is disabled, then ASSERT.\r
+\r
+  @retval LOCAL_APIC_MODE_XAPIC  current APIC mode is xAPIC.\r
+  @retval LOCAL_APIC_MODE_X2APIC current APIC mode is x2APIC.\r
+**/\r
+UINTN\r
+EFIAPI\r
+GetApicMode (\r
+  VOID\r
+  );\r
+\r
+/**\r
+  Set the current local APIC mode.\r
+\r
+  If the specified local APIC mode is not valid, then ASSERT.\r
+  If the specified local APIC mode can't be set as current, then ASSERT.\r
+\r
+  @param ApicMode APIC mode to be set.\r
+**/\r
+VOID\r
+EFIAPI\r
+SetApicMode (\r
+  IN UINTN  ApicMode\r
+  );\r
+\r
+/**\r
+  Get the initial local APIC ID of the executing processor assigned by hardware upon power on or reset.\r
+\r
+  In xAPIC mode, the initial local APIC ID is 8-bit, and may be different from current APIC ID.\r
+  In x2APIC mode, the local APIC ID can't be changed and there is no concept of initial APIC ID. In this case, \r
+  the 32-bit local APIC ID is returned as initial APIC ID.\r
+\r
+  @return  32-bit initial local APIC ID of the executing processor.\r
+**/\r
+UINT32\r
+EFIAPI\r
+GetInitialApicId (\r
+  VOID\r
+  );\r
+\r
+/**\r
+  Get the local APIC ID of the executing processor.\r
+\r
+  @return  32-bit local APIC ID of the executing processor.\r
+**/\r
+UINT32\r
+EFIAPI\r
+GetApicId (\r
+  VOID\r
+  );\r
+\r
+/**\r
+  Send a SMI IPI to a specified target processor.\r
+\r
+  This function returns after the IPI has been accepted by the target processor. \r
+\r
+  @param  ApicId   Specify the local APIC ID of the target processor.\r
+**/\r
+VOID\r
+EFIAPI\r
+SendSmiIpi (\r
+  IN UINT32          ApicId\r
+  );\r
+\r
+/**\r
+  Send a SMI IPI to all processors excluding self.\r
+\r
+  This function returns after the IPI has been accepted by the target processors. \r
+**/\r
+VOID\r
+EFIAPI\r
+SendSmiIpiAllExcludingSelf (\r
+  VOID\r
+  );\r
+\r
+/**\r
+  Send an INIT IPI to a specified target processor.\r
+\r
+  This function returns after the IPI has been accepted by the target processor. \r
+\r
+  @param  ApicId   Specify the local APIC ID of the target processor.\r
+**/\r
+VOID\r
+EFIAPI\r
+SendInitIpi (\r
+  IN UINT32          ApicId\r
+  );\r
+\r
+/**\r
+  Send an INIT IPI to all processors excluding self.\r
+\r
+  This function returns after the IPI has been accepted by the target processors. \r
+**/\r
+VOID\r
+EFIAPI\r
+SendInitIpiAllExcludingSelf (\r
+  VOID\r
+  );\r
+\r
+/**\r
+  Send an INIT-Start-up-Start-up IPI sequence to a specified target processor.\r
+\r
+  This function returns after the IPI has been accepted by the target processor. \r
+\r
+  if StartupRoutine >= 1M, then ASSERT.\r
+  if StartupRoutine is not multiple of 4K, then ASSERT.\r
+\r
+  @param  ApicId          Specify the local APIC ID of the target processor.\r
+  @param  StartupRoutine  Points to a start-up routine which is below 1M physical\r
+                          address and 4K aligned.\r
+**/\r
+VOID\r
+EFIAPI\r
+SendInitSipiSipi (\r
+  IN UINT32          ApicId,\r
+  IN UINT32          StartupRoutine\r
+  );\r
+\r
+/**\r
+  Send an INIT-Start-up-Start-up IPI sequence to all processors excluding self.\r
+\r
+  This function returns after the IPI has been accepted by the target processors. \r
+\r
+  if StartupRoutine >= 1M, then ASSERT.\r
+  if StartupRoutine is not multiple of 4K, then ASSERT.\r
+\r
+  @param  StartupRoutine    Points to a start-up routine which is below 1M physical\r
+                            address and 4K aligned.\r
+**/\r
+VOID\r
+EFIAPI\r
+SendInitSipiSipiAllExcludingSelf (\r
+  IN UINT32          StartupRoutine\r
+  );\r
+\r
+/**\r
+  Programming Virtual Wire Mode.\r
+\r
+  This function programs the local APIC for virtual wire mode following\r
+  the example described in chapter A.3 of the MP 1.4 spec.\r
+\r
+  IOxAPIC is not involved in this type of virtual wire mode.\r
+**/\r
+VOID\r
+EFIAPI\r
+ProgramVirtualWireMode (\r
+  VOID\r
+  );\r
+\r
+/**\r
+  Get the divide value from the DCR (Divide Configuration Register) by which\r
+  the processor's bus clock is divided to form the time base for the APIC timer.\r
+\r
+  @return The divide value is one of 1,2,4,8,16,32,64,128.\r
+**/\r
+UINTN\r
+EFIAPI\r
+GetApicTimerDivisor (\r
+  VOID\r
+  );\r
+\r
+/**\r
+  Read the initial count value from the init-count register.\r
+\r
+  @return The initial count value read from the init-count register.\r
+**/\r
+UINT32\r
+EFIAPI\r
+GetApicTimerInitCount (\r
+  VOID\r
+  );\r
+\r
+/**\r
+  Read the current count value from the current-count register.\r
+\r
+  @return The current count value read from the current-count register.\r
+**/\r
+UINT32\r
+EFIAPI\r
+GetApicTimerCurrentCount (\r
+  VOID\r
+  );\r
+\r
+/**\r
+  Initialize the local APIC timer.\r
+\r
+  The local APIC timer is initialized and enabled.\r
+\r
+  @param DivideValue   The divide value for the DCR. It is one of 1,2,4,8,16,32,64,128.\r
+                       If it is 0, then use the current divide value in the DCR.\r
+  @param InitCount     The initial count value.\r
+  @param PeriodicMode  If TRUE, timer mode is peridoic. Othewise, timer mode is one-shot.\r
+  @param Vector        The timer interrupt vector number.\r
+**/\r
+VOID\r
+EFIAPI\r
+InitializeApicTimer (\r
+  IN UINTN   DivideValue,\r
+  IN UINT32  InitCount,\r
+  IN BOOLEAN PeriodicMode,\r
+  IN UINT8   Vector\r
+  );\r
+\r
+/**\r
+  Enable the local APIC timer interrupt.\r
+**/\r
+VOID\r
+EFIAPI\r
+EnableApicTimerInterrupt (\r
+  VOID\r
+  );\r
+\r
+/**\r
+  Disable the local APIC timer interrupt.\r
+**/\r
+VOID\r
+EFIAPI\r
+DisableApicTimerInterrupt (\r
+  VOID\r
+  );\r
+\r
+/**\r
+  Get the local APIC timer interrupt state.\r
+\r
+  @retval TRUE  The local APIC timer interrupt is enabled.\r
+  @retval FALSE The local APIC timer interrupt is disabled.\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+GetApicTimerInterruptState (\r
+  VOID\r
+  );\r
+\r
+/**\r
+  Send EOI to the local APIC.\r
+**/\r
+VOID\r
+EFIAPI\r
+SendApicEoi (\r
+  VOID\r
+  );\r
+\r
+#endif\r
+\r
diff --git a/UefiCpuPkg/Include/Register/LocalApic.h b/UefiCpuPkg/Include/Register/LocalApic.h
new file mode 100644 (file)
index 0000000..7535ef5
--- /dev/null
@@ -0,0 +1,167 @@
+/** @file\r
+  IA32 Local APIC Definitions.\r
+\r
+  Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>\r
+  This program and the accompanying materials\r
+  are licensed and made available under the terms and conditions of the BSD License\r
+  which accompanies this distribution.  The full text of the license may be found at\r
+  http://opensource.org/licenses/bsd-license.php\r
+\r
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#ifndef __LOCAL_APIC_H__\r
+#define __LOCAL_APIC_H__\r
+\r
+//\r
+// Definitions for IA32 architectural MSRs\r
+//\r
+#define MSR_IA32_APIC_BASE_ADDRESS              0x1B\r
+\r
+//\r
+// Definitions for CPUID instruction\r
+//\r
+#define CPUID_VERSION_INFO                      0x1\r
+#define CPUID_EXTENDED_FUNCTION                 0x80000000\r
+#define CPUID_VIR_PHY_ADDRESS_SIZE              0x80000008\r
+\r
+//\r
+// Definition for Local APIC registers and related values\r
+//\r
+#define XAPIC_ID_OFFSET                         0x0\r
+#define XAPIC_EOI_OFFSET                        0x0b0\r
+#define XAPIC_ICR_DFR_OFFSET                    0x0e0\r
+#define XAPIC_SPURIOUS_VECTOR_OFFSET            0x0f0\r
+#define XAPIC_ICR_LOW_OFFSET                    0x300\r
+#define XAPIC_ICR_HIGH_OFFSET                   0x310\r
+#define XAPIC_LVT_TIMER_OFFSET                  0x320\r
+#define XAPIC_LINT0_VECTOR_OFFSET               0x350\r
+#define XAPIC_LINT1_VECTOR_OFFSET               0x360\r
+#define XAPIC_TIMER_INIT_COUNT_OFFSET           0x380\r
+#define XAPIC_TIMER_CURRENT_COUNT_OFFSET        0x390\r
+#define XAPIC_TIMER_DIVIDE_CONFIGURATION_OFFSET 0x3E0\r
+\r
+#define X2APIC_MSR_BASE_ADDRESS                 0x800\r
+#define X2APIC_MSR_ICR_ADDRESS                  0x830\r
+\r
+#define LOCAL_APIC_DELIVERY_MODE_FIXED           0\r
+#define LOCAL_APIC_DELIVERY_MODE_LOWEST_PRIORITY 1\r
+#define LOCAL_APIC_DELIVERY_MODE_SMI             2\r
+#define LOCAL_APIC_DELIVERY_MODE_NMI             4\r
+#define LOCAL_APIC_DELIVERY_MODE_INIT            5\r
+#define LOCAL_APIC_DELIVERY_MODE_STARTUP         6\r
+#define LOCAL_APIC_DELIVERY_MODE_EXTINT          7\r
+\r
+#define LOCAL_APIC_DESTINATION_SHORTHAND_NO_SHORTHAND       0\r
+#define LOCAL_APIC_DESTINATION_SHORTHAND_SELF               1\r
+#define LOCAL_APIC_DESTINATION_SHORTHAND_ALL_INCLUDING_SELF 2\r
+#define LOCAL_APIC_DESTINATION_SHORTHAND_ALL_EXCLUDING_SELF 3\r
+\r
+typedef union {\r
+  struct {\r
+    UINT64  Reserved0:8;   ///< Reserved.\r
+    UINT64  Bsp:1;         ///< Processor is BSP.\r
+    UINT64  Reserved1:1;   ///< Reserved.\r
+    UINT64  Extd:1;        ///< Enable x2APIC mode.\r
+    UINT64  En:1;          ///< xAPIC global enable/disable.\r
+    UINT64  ApicBase:52;   ///< APIC Base physical address. The actual field width depends on physical address width.\r
+  } Bits;\r
+  UINT64    Uint64;\r
+} MSR_IA32_APIC_BASE;\r
+\r
+//\r
+// Low half of Interrupt Command Register (ICR).\r
+//\r
+typedef union {\r
+  struct {\r
+    UINT32  Vector:8;                ///< The vector number of the interrupt being sent.\r
+    UINT32  DeliveryMode:3;          ///< Specifies the type of IPI to be sent.\r
+    UINT32  DestinationMode:1;       ///< 0: physical destination mode, 1: logical destination mode.\r
+    UINT32  DeliveryStatus:1;        ///< Indicates the IPI delivery status. This field is reserved in x2APIC mode.\r
+    UINT32  Reserved0:1;             ///< Reserved.\r
+    UINT32  Level:1;                 ///< 0 for the INIT level de-assert delivery mode. Otherwise 1.\r
+    UINT32  TriggerMode:1;           ///< 0: edge, 1: level when using the INIT level de-assert delivery mode.\r
+    UINT32  Reserved1:2;             ///< Reserved.\r
+    UINT32  DestinationShorthand:2;  ///< A shorthand notation to specify the destination of the interrupt.\r
+    UINT32  Reserved2:12;            ///< Reserved.\r
+  } Bits;\r
+  UINT32    Uint32;\r
+} LOCAL_APIC_ICR_LOW;\r
+\r
+//\r
+// High half of Interrupt Command Register (ICR)\r
+//\r
+typedef union {\r
+  struct {\r
+    UINT32  Reserved0:24;   ///< Reserved.\r
+    UINT32  Destination:8;  ///< Specifies the target processor or processors in xAPIC mode.\r
+  } Bits;\r
+  UINT32    Uint32;         ///< Destination field expanded to 32-bit in x2APIC mode.\r
+} LOCAL_APIC_ICR_HIGH;\r
+\r
+//\r
+// Spurious-Interrupt Vector Register (SVR)\r
+//\r
+typedef union {\r
+  struct {\r
+    UINT32  SpuriousVector:8;           ///< Spurious Vector.\r
+    UINT32  SoftwareEnable:1;           ///< APIC Software Enable/Disable.\r
+    UINT32  FocusProcessorChecking:1;   ///< Focus Processor Checking.\r
+    UINT32  Reserved0:2;                ///< Reserved.\r
+    UINT32  EoiBroadcastSuppression:1;  ///< EOI-Broadcast Suppression.\r
+    UINT32  Reserved1:19;               ///< Reserved.\r
+  } Bits;\r
+  UINT32    Uint32;\r
+} LOCAL_APIC_SVR;\r
+\r
+//\r
+// Divide Configuration Register (DCR)\r
+//\r
+typedef union {\r
+  struct {\r
+    UINT32  DivideValue1:2;  ///< Low 2 bits of the divide value.\r
+    UINT32  Reserved0:1;     ///< Always 0.\r
+    UINT32  DivideValue2:1;  ///< Highest 1 bit of the divide value.\r
+    UINT32  Reserved1:28;    ///< Reserved.\r
+  } Bits;\r
+  UINT32    Uint32;\r
+} LOCAL_APIC_DCR;\r
+\r
+//\r
+// LVT Timer Register\r
+//\r
+typedef union {\r
+  struct {\r
+    UINT32  Vector:8;          ///< The vector number of the interrupt being sent.\r
+    UINT32  Reserved0:4;       ///< Reserved.\r
+    UINT32  DeliveryStatus:1;  ///< 0: Idle, 1: send pending.\r
+    UINT32  Reserved1:3;       ///< Reserved.\r
+    UINT32  Mask:1;            ///< 0: Not masked, 1: Masked.\r
+    UINT32  TimerMode:1;       ///< 0: One-shot, 1: Periodic.\r
+    UINT32  Reserved2:14;      ///< Reserved.\r
+  } Bits;\r
+  UINT32    Uint32;\r
+} LOCAL_APIC_LVT_TIMER;\r
+\r
+//\r
+// LVT LINT0/LINT1 Register\r
+//\r
+typedef union {\r
+  struct {\r
+    UINT32  Vector:8;            ///< The vector number of the interrupt being sent.\r
+    UINT32  DeliveryMode:3;      ///< Specifies the type of interrupt to be sent.\r
+    UINT32  Reserved0:1;         ///< Reserved.\r
+    UINT32  DeliveryStatus:1;    ///< 0: Idle, 1: send pending.\r
+    UINT32  InputPinPolarity:1;  ///< Interrupt Input Pin Polarity.\r
+    UINT32  RemoteIrr:1;         ///< RO. Set when the local APIC accepts the interrupt and reset when an EOI is received.\r
+    UINT32  TriggerMode:1;       ///< 0:edge, 1:level.\r
+    UINT32  Mask:1;              ///< 0: Not masked, 1: Masked.\r
+    UINT32  Reserved1:15;        ///< Reserved.\r
+  } Bits;\r
+  UINT32    Uint32;\r
+} LOCAL_APIC_LVT_LINT;\r
+\r
+#endif\r
+\r
diff --git a/UefiCpuPkg/Library/BaseXApicLib/BaseXApicLib.c b/UefiCpuPkg/Library/BaseXApicLib/BaseXApicLib.c
new file mode 100644 (file)
index 0000000..16dbd4b
--- /dev/null
@@ -0,0 +1,574 @@
+/** @file\r
+  Local APIC Library.\r
+\r
+  This local APIC library instance supports xAPIC mode only.\r
+\r
+  Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>\r
+  This program and the accompanying materials\r
+  are licensed and made available under the terms and conditions of the BSD License\r
+  which accompanies this distribution.  The full text of the license may be found at\r
+  http://opensource.org/licenses/bsd-license.php\r
+\r
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include <Register/LocalApic.h>\r
+\r
+#include <Library/BaseLib.h>\r
+#include <Library/DebugLib.h>\r
+#include <Library/LocalApicLib.h>\r
+#include <Library/IoLib.h>\r
+#include <Library/TimerLib.h>\r
+#include <Library/PcdLib.h>\r
+\r
+//\r
+// Library internal functions\r
+//\r
+\r
+/**\r
+  Read from a local APIC register.\r
+\r
+  This function reads from a local APIC register either in xAPIC or x2APIC mode.\r
+  It is required that in xAPIC mode wider registers (64-bit or 256-bit) must be\r
+  accessed using multiple 32-bit loads or stores, so this function only performs\r
+  32-bit read.\r
+\r
+  @param  MmioOffset  The MMIO offset of the local APIC register in xAPIC mode.\r
+                      It must be 16-byte aligned.\r
+\r
+  @return 32-bit      Value read from the register.\r
+**/\r
+UINT32\r
+EFIAPI\r
+ReadLocalApicReg (\r
+  IN UINTN  MmioOffset\r
+  )\r
+{\r
+  ASSERT ((MmioOffset & 0xf) == 0);\r
+  ASSERT (GetApicMode () == LOCAL_APIC_MODE_XAPIC);\r
+\r
+  return MmioRead32 (PcdGet32 (PcdCpuLocalApicBaseAddress) + MmioOffset);\r
+}\r
+\r
+/**\r
+  Write to a local APIC register.\r
+\r
+  This function writes to a local APIC register either in xAPIC or x2APIC mode.\r
+  It is required that in xAPIC mode wider registers (64-bit or 256-bit) must be\r
+  accessed using multiple 32-bit loads or stores, so this function only performs\r
+  32-bit write.\r
+\r
+  if the register index is invalid or unsupported in current APIC mode, then ASSERT.\r
+\r
+  @param  MmioOffset  The MMIO offset of the local APIC register in xAPIC mode.\r
+                      It must be 16-byte aligned.\r
+  @param  Value       Value to be written to the register.\r
+**/\r
+VOID\r
+EFIAPI\r
+WriteLocalApicReg (\r
+  IN UINTN  MmioOffset,\r
+  IN UINT32 Value\r
+  )\r
+{\r
+  ASSERT ((MmioOffset & 0xf) == 0);\r
+  ASSERT (GetApicMode () == LOCAL_APIC_MODE_XAPIC);\r
+\r
+  MmioWrite32 (PcdGet32 (PcdCpuLocalApicBaseAddress) + MmioOffset, Value);\r
+}\r
+\r
+/**\r
+  Send an IPI by writing to ICR.\r
+\r
+  This function returns after the IPI has been accepted by the target processor. \r
+\r
+  @param  IcrLow 32-bit value to be written to the low half of ICR.\r
+  @param  ApicId APIC ID of the target processor if this IPI is targeted for a specific processor.\r
+**/\r
+VOID\r
+SendIpi (\r
+  IN UINT32          IcrLow,\r
+  IN UINT32          ApicId\r
+  )\r
+{\r
+  LOCAL_APIC_ICR_LOW IcrLowReg;\r
+\r
+  ASSERT (GetApicMode () == LOCAL_APIC_MODE_XAPIC);\r
+  ASSERT (ApicId <= 0xff);\r
+\r
+  //\r
+  // For xAPIC, the act of writing to the low doubleword of the ICR causes the IPI to be sent.\r
+  //\r
+  WriteLocalApicReg (XAPIC_ICR_HIGH_OFFSET, ApicId << 24);\r
+  WriteLocalApicReg (XAPIC_ICR_LOW_OFFSET, IcrLow);\r
+  do {\r
+    IcrLowReg.Uint32 = ReadLocalApicReg (XAPIC_ICR_LOW_OFFSET);\r
+  } while (IcrLowReg.Bits.DeliveryStatus != 0);\r
+}\r
+\r
+//\r
+// Library API implementation functions\r
+//\r
+\r
+/**\r
+  Get the current local APIC mode.\r
+\r
+  If local APIC is disabled, then ASSERT.\r
+\r
+  @retval LOCAL_APIC_MODE_XAPIC  current APIC mode is xAPIC.\r
+  @retval LOCAL_APIC_MODE_X2APIC current APIC mode is x2APIC.\r
+**/\r
+UINTN\r
+EFIAPI\r
+GetApicMode (\r
+  VOID\r
+  )\r
+{\r
+  DEBUG_CODE (\r
+    {\r
+      MSR_IA32_APIC_BASE ApicBaseMsr;\r
+\r
+      ApicBaseMsr.Uint64 = AsmReadMsr64 (MSR_IA32_APIC_BASE_ADDRESS);\r
+      //\r
+      // Local APIC should have been enabled\r
+      //\r
+      ASSERT (ApicBaseMsr.Bits.En != 0);\r
+      ASSERT (ApicBaseMsr.Bits.Extd == 0);\r
+    }\r
+  );\r
+  return LOCAL_APIC_MODE_XAPIC;\r
+}\r
+\r
+/**\r
+  Set the current local APIC mode.\r
+\r
+  If the specified local APIC mode is not valid, then ASSERT.\r
+  If the specified local APIC mode can't be set as current, then ASSERT.\r
+\r
+  @param ApicMode APIC mode to be set.\r
+**/\r
+VOID\r
+EFIAPI\r
+SetApicMode (\r
+  IN UINTN  ApicMode\r
+  )\r
+{\r
+  ASSERT (ApicMode == LOCAL_APIC_MODE_XAPIC);\r
+  ASSERT (GetApicMode () == LOCAL_APIC_MODE_XAPIC);\r
+}\r
+\r
+/**\r
+  Get the initial local APIC ID of the executing processor assigned by hardware upon power on or reset.\r
+\r
+  In xAPIC mode, the initial local APIC ID is 8-bit, and may be different from current APIC ID.\r
+  In x2APIC mode, the local APIC ID can't be changed and there is no concept of initial APIC ID. In this case, \r
+  the 32-bit local APIC ID is returned as initial APIC ID.\r
+\r
+  @return  32-bit initial local APIC ID of the executing processor.\r
+**/\r
+UINT32\r
+EFIAPI\r
+GetInitialApicId (\r
+  VOID\r
+  )\r
+{\r
+  UINT32 RegEbx;\r
+\r
+  ASSERT (GetApicMode () == LOCAL_APIC_MODE_XAPIC);\r
+\r
+  AsmCpuid (CPUID_VERSION_INFO, NULL, &RegEbx, NULL, NULL);\r
+  return RegEbx >> 24;\r
+}\r
+\r
+/**\r
+  Get the local APIC ID of the executing processor.\r
+\r
+  @return  32-bit local APIC ID of the executing processor.\r
+**/\r
+UINT32\r
+EFIAPI\r
+GetApicId (\r
+  VOID\r
+  )\r
+{\r
+  UINT32 ApicId;\r
+\r
+  ASSERT (GetApicMode () == LOCAL_APIC_MODE_XAPIC);\r
+\r
+  ApicId = ReadLocalApicReg (XAPIC_ID_OFFSET);\r
+  ApicId >>= 24;\r
+  return ApicId;\r
+}\r
+\r
+/**\r
+  Send a SMI IPI to a specified target processor.\r
+\r
+  This function returns after the IPI has been accepted by the target processor. \r
+\r
+  @param  ApicId   Specify the local APIC ID of the target processor.\r
+**/\r
+VOID\r
+EFIAPI\r
+SendSmiIpi (\r
+  IN UINT32          ApicId\r
+  )\r
+{\r
+  LOCAL_APIC_ICR_LOW IcrLow;\r
+\r
+  IcrLow.Uint32 = 0;\r
+  IcrLow.Bits.DeliveryMode = LOCAL_APIC_DELIVERY_MODE_SMI;\r
+  IcrLow.Bits.Level = 1;\r
+  SendIpi (IcrLow.Uint32, ApicId);\r
+}\r
+\r
+/**\r
+  Send a SMI IPI to all processors excluding self.\r
+\r
+  This function returns after the IPI has been accepted by the target processors. \r
+**/\r
+VOID\r
+EFIAPI\r
+SendSmiIpiAllExcludingSelf (\r
+  VOID\r
+  )\r
+{\r
+  LOCAL_APIC_ICR_LOW IcrLow;\r
+\r
+  IcrLow.Uint32 = 0;\r
+  IcrLow.Bits.DeliveryMode = LOCAL_APIC_DELIVERY_MODE_SMI;\r
+  IcrLow.Bits.Level = 1;\r
+  IcrLow.Bits.DestinationShorthand = LOCAL_APIC_DESTINATION_SHORTHAND_ALL_EXCLUDING_SELF;\r
+  SendIpi (IcrLow.Uint32, 0);\r
+}\r
+\r
+/**\r
+  Send an INIT IPI to a specified target processor.\r
+\r
+  This function returns after the IPI has been accepted by the target processor. \r
+\r
+  @param  ApicId   Specify the local APIC ID of the target processor.\r
+**/\r
+VOID\r
+EFIAPI\r
+SendInitIpi (\r
+  IN UINT32          ApicId\r
+  )\r
+{\r
+  LOCAL_APIC_ICR_LOW IcrLow;\r
+\r
+  IcrLow.Uint32 = 0;\r
+  IcrLow.Bits.DeliveryMode = LOCAL_APIC_DELIVERY_MODE_INIT;\r
+  IcrLow.Bits.Level = 1;\r
+  SendIpi (IcrLow.Uint32, ApicId);\r
+}\r
+\r
+/**\r
+  Send an INIT IPI to all processors excluding self.\r
+\r
+  This function returns after the IPI has been accepted by the target processors. \r
+**/\r
+VOID\r
+EFIAPI\r
+SendInitIpiAllExcludingSelf (\r
+  VOID\r
+  )\r
+{\r
+  LOCAL_APIC_ICR_LOW IcrLow;\r
+\r
+  IcrLow.Uint32 = 0;\r
+  IcrLow.Bits.DeliveryMode = LOCAL_APIC_DELIVERY_MODE_INIT;\r
+  IcrLow.Bits.Level = 1;\r
+  IcrLow.Bits.DestinationShorthand = LOCAL_APIC_DESTINATION_SHORTHAND_ALL_EXCLUDING_SELF;\r
+  SendIpi (IcrLow.Uint32, 0);\r
+}\r
+\r
+/**\r
+  Send an INIT-Start-up-Start-up IPI sequence to a specified target processor.\r
+\r
+  This function returns after the IPI has been accepted by the target processor. \r
+\r
+  if StartupRoutine >= 1M, then ASSERT.\r
+  if StartupRoutine is not multiple of 4K, then ASSERT.\r
+\r
+  @param  ApicId          Specify the local APIC ID of the target processor.\r
+  @param  StartupRoutine  Points to a start-up routine which is below 1M physical\r
+                          address and 4K aligned.\r
+**/\r
+VOID\r
+EFIAPI\r
+SendInitSipiSipi (\r
+  IN UINT32          ApicId,\r
+  IN UINT32          StartupRoutine\r
+  )\r
+{\r
+  LOCAL_APIC_ICR_LOW IcrLow;\r
+\r
+  ASSERT (StartupRoutine < 0x100000);\r
+  ASSERT ((StartupRoutine & 0xfff) == 0);\r
+\r
+  SendInitIpi (ApicId);\r
+  MicroSecondDelay (10);\r
+  IcrLow.Uint32 = 0;\r
+  IcrLow.Bits.Vector = (StartupRoutine >> 12);\r
+  IcrLow.Bits.DeliveryMode = LOCAL_APIC_DELIVERY_MODE_STARTUP;\r
+  IcrLow.Bits.Level = 1;\r
+  SendIpi (IcrLow.Uint32, ApicId);\r
+  MicroSecondDelay (200);\r
+  SendIpi (IcrLow.Uint32, ApicId);\r
+}\r
+\r
+/**\r
+  Send an INIT-Start-up-Start-up IPI sequence to all processors excluding self.\r
+\r
+  This function returns after the IPI has been accepted by the target processors. \r
+\r
+  if StartupRoutine >= 1M, then ASSERT.\r
+  if StartupRoutine is not multiple of 4K, then ASSERT.\r
+\r
+  @param  StartupRoutine    Points to a start-up routine which is below 1M physical\r
+                            address and 4K aligned.\r
+**/\r
+VOID\r
+EFIAPI\r
+SendInitSipiSipiAllExcludingSelf (\r
+  IN UINT32          StartupRoutine\r
+  )\r
+{\r
+  LOCAL_APIC_ICR_LOW IcrLow;\r
+\r
+  ASSERT (StartupRoutine < 0x100000);\r
+  ASSERT ((StartupRoutine & 0xfff) == 0);\r
+\r
+  SendInitIpiAllExcludingSelf ();\r
+  MicroSecondDelay (10);\r
+  IcrLow.Uint32 = 0;\r
+  IcrLow.Bits.Vector = (StartupRoutine >> 12);\r
+  IcrLow.Bits.DeliveryMode = LOCAL_APIC_DELIVERY_MODE_STARTUP;\r
+  IcrLow.Bits.Level = 1;\r
+  IcrLow.Bits.DestinationShorthand = LOCAL_APIC_DESTINATION_SHORTHAND_ALL_EXCLUDING_SELF;\r
+  SendIpi (IcrLow.Uint32, 0);\r
+  MicroSecondDelay (200);\r
+  SendIpi (IcrLow.Uint32, 0);\r
+}\r
+\r
+/**\r
+  Programming Virtual Wire Mode.\r
+\r
+  This function programs the local APIC for virtual wire mode following\r
+  the example described in chapter A.3 of the MP 1.4 spec.\r
+\r
+  IOxAPIC is not involved in this type of virtual wire mode.\r
+**/\r
+VOID\r
+EFIAPI\r
+ProgramVirtualWireMode (\r
+  VOID\r
+  )\r
+{\r
+  LOCAL_APIC_SVR      Svr;\r
+  LOCAL_APIC_LVT_LINT Lint;\r
+\r
+  //\r
+  // Enable the APIC via SVR and set the spurious interrupt to use Int 00F.\r
+  //\r
+  Svr.Uint32 = ReadLocalApicReg (XAPIC_SPURIOUS_VECTOR_OFFSET);\r
+  Svr.Bits.SpuriousVector = 0xf;\r
+  Svr.Bits.SoftwareEnable = 1;\r
+  WriteLocalApicReg (XAPIC_SPURIOUS_VECTOR_OFFSET, Svr.Uint32);\r
+\r
+  //\r
+  // Program the LINT0 vector entry as ExtInt. Not masked, edge, active high.\r
+  //\r
+  Lint.Uint32 = ReadLocalApicReg (XAPIC_LINT0_VECTOR_OFFSET);\r
+  Lint.Bits.DeliveryMode = LOCAL_APIC_DELIVERY_MODE_EXTINT;\r
+  Lint.Bits.InputPinPolarity = 0;\r
+  Lint.Bits.TriggerMode = 0;\r
+  Lint.Bits.Mask = 0;\r
+  WriteLocalApicReg (XAPIC_LINT0_VECTOR_OFFSET, Lint.Uint32);\r
+\r
+  //\r
+  // Program the LINT0 vector entry as NMI. Not masked, edge, active high.\r
+  //\r
+  Lint.Uint32 = ReadLocalApicReg (XAPIC_LINT1_VECTOR_OFFSET);\r
+  Lint.Bits.DeliveryMode = LOCAL_APIC_DELIVERY_MODE_NMI;\r
+  Lint.Bits.InputPinPolarity = 0;\r
+  Lint.Bits.TriggerMode = 0;\r
+  Lint.Bits.Mask = 0;\r
+  WriteLocalApicReg (XAPIC_LINT1_VECTOR_OFFSET, Lint.Uint32);\r
+}\r
+\r
+/**\r
+  Get the divide value from the DCR (Divide Configuration Register) by which\r
+  the processor's bus clock is divided to form the time base for the APIC timer.\r
+\r
+  @return The divide value is one of 1,2,4,8,16,32,64,128.\r
+**/\r
+UINTN\r
+EFIAPI\r
+GetApicTimerDivisor (\r
+  VOID\r
+  )\r
+{\r
+  UINT32         DivideValue;\r
+  LOCAL_APIC_DCR Dcr;\r
+\r
+  Dcr.Uint32 = ReadLocalApicReg (XAPIC_TIMER_DIVIDE_CONFIGURATION_OFFSET);\r
+  DivideValue = Dcr.Bits.DivideValue1 | (Dcr.Bits.DivideValue2 << 2);\r
+  DivideValue = (DivideValue + 1) & 0x7;\r
+  return ((UINTN)1) << DivideValue;\r
+}\r
+\r
+/**\r
+  Read the initial count value from the init-count register.\r
+\r
+  @return The initial count value read from the init-count register.\r
+**/\r
+UINT32\r
+EFIAPI\r
+GetApicTimerInitCount (\r
+  VOID\r
+  )\r
+{\r
+  return ReadLocalApicReg (XAPIC_TIMER_INIT_COUNT_OFFSET);\r
+}\r
+\r
+/**\r
+  Read the current count value from the current-count register.\r
+\r
+  @return The current count value read from the current-count register.\r
+**/\r
+UINT32\r
+EFIAPI\r
+GetApicTimerCurrentCount (\r
+  VOID\r
+  )\r
+{\r
+  return ReadLocalApicReg (XAPIC_TIMER_CURRENT_COUNT_OFFSET);\r
+}\r
+\r
+/**\r
+  Initialize the local APIC timer.\r
+\r
+  The local APIC timer is initialized and enabled.\r
+\r
+  @param DivideValue   The divide value for the DCR. It is one of 1,2,4,8,16,32,64,128.\r
+                       If it is 0, then use the current divide value in the DCR.\r
+  @param InitCount     The initial count value.\r
+  @param PeriodicMode  If TRUE, timer mode is peridoic. Othewise, timer mode is one-shot.\r
+  @param Vector        The timer interrupt vector number.\r
+**/\r
+VOID\r
+EFIAPI\r
+InitializeApicTimer (\r
+  IN UINTN   DivideValue,\r
+  IN UINT32  InitCount,\r
+  IN BOOLEAN PeriodicMode,\r
+  IN UINT8   Vector\r
+  )\r
+{\r
+  LOCAL_APIC_SVR       Svr;\r
+  LOCAL_APIC_DCR       Dcr;\r
+  LOCAL_APIC_LVT_TIMER LvtTimer;\r
+  UINT32               Divisor;\r
+\r
+  //\r
+  // Ensure local APIC is in software-enabled state.\r
+  //\r
+  Svr.Uint32 = ReadLocalApicReg (XAPIC_SPURIOUS_VECTOR_OFFSET);\r
+  Svr.Bits.SoftwareEnable = 1;\r
+  WriteLocalApicReg (XAPIC_SPURIOUS_VECTOR_OFFSET, Svr.Uint32);\r
+\r
+  //\r
+  // Program init-count register.\r
+  //\r
+  WriteLocalApicReg (XAPIC_TIMER_INIT_COUNT_OFFSET, InitCount);\r
+\r
+  if (DivideValue != 0) {\r
+    ASSERT (DivideValue <= 128);\r
+    ASSERT (DivideValue == GetPowerOfTwo32((UINT32)DivideValue));\r
+    Divisor = (UINT32)((HighBitSet32 ((UINT32)DivideValue) - 1) & 0x7);\r
+\r
+    Dcr.Uint32 = ReadLocalApicReg (XAPIC_TIMER_DIVIDE_CONFIGURATION_OFFSET);\r
+    Dcr.Bits.DivideValue1 = (Divisor & 0x3);\r
+    Dcr.Bits.DivideValue2 = (Divisor >> 2);\r
+    WriteLocalApicReg (XAPIC_TIMER_DIVIDE_CONFIGURATION_OFFSET, Dcr.Uint32); \r
+  }\r
+\r
+  //\r
+  // Enable APIC timer interrupt with specified timer mode.\r
+  //\r
+  LvtTimer.Uint32 = ReadLocalApicReg (XAPIC_LVT_TIMER_OFFSET);\r
+  if (PeriodicMode) {\r
+    LvtTimer.Bits.TimerMode = 1;\r
+  } else {\r
+    LvtTimer.Bits.TimerMode = 0;\r
+  }\r
+  LvtTimer.Bits.Mask = 0;\r
+  LvtTimer.Bits.Vector = Vector;\r
+  WriteLocalApicReg (XAPIC_LVT_TIMER_OFFSET, LvtTimer.Uint32);\r
+}\r
+\r
+/**\r
+  Enable the local APIC timer interrupt.\r
+**/\r
+VOID\r
+EFIAPI\r
+EnableApicTimerInterrupt (\r
+  VOID\r
+  )\r
+{\r
+  LOCAL_APIC_LVT_TIMER LvtTimer;\r
+\r
+  LvtTimer.Uint32 = ReadLocalApicReg (XAPIC_LVT_TIMER_OFFSET);\r
+  LvtTimer.Bits.Mask = 0;\r
+  WriteLocalApicReg (XAPIC_LVT_TIMER_OFFSET, LvtTimer.Uint32);\r
+}\r
+\r
+/**\r
+  Disable the local APIC timer interrupt.\r
+**/\r
+VOID\r
+EFIAPI\r
+DisableApicTimerInterrupt (\r
+  VOID\r
+  )\r
+{\r
+  LOCAL_APIC_LVT_TIMER LvtTimer;\r
+\r
+  LvtTimer.Uint32 = ReadLocalApicReg (XAPIC_LVT_TIMER_OFFSET);\r
+  LvtTimer.Bits.Mask = 1;\r
+  WriteLocalApicReg (XAPIC_LVT_TIMER_OFFSET, LvtTimer.Uint32);\r
+}\r
+\r
+/**\r
+  Get the local APIC timer interrupt state.\r
+\r
+  @retval TRUE  The local APIC timer interrupt is enabled.\r
+  @retval FALSE The local APIC timer interrupt is disabled.\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+GetApicTimerInterruptState (\r
+  VOID\r
+  )\r
+{\r
+  LOCAL_APIC_LVT_TIMER LvtTimer;\r
+\r
+  LvtTimer.Uint32 = ReadLocalApicReg (XAPIC_LVT_TIMER_OFFSET);\r
+  return (BOOLEAN)(LvtTimer.Bits.Mask == 0);\r
+}\r
+\r
+/**\r
+  Send EOI to the local APIC.\r
+**/\r
+VOID\r
+EFIAPI\r
+SendApicEoi (\r
+  VOID\r
+  )\r
+{\r
+  WriteLocalApicReg (XAPIC_EOI_OFFSET, 0);\r
+}\r
+\r
diff --git a/UefiCpuPkg/Library/BaseXApicLib/BaseXApicLib.inf b/UefiCpuPkg/Library/BaseXApicLib/BaseXApicLib.inf
new file mode 100644 (file)
index 0000000..470e029
--- /dev/null
@@ -0,0 +1,46 @@
+## @file\r
+#  Component description file for CPU Local APIC Library.\r
+#\r
+#  This library instance supports xAPIC mode only.\r
+#\r
+#  Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>\r
+#  This program and the accompanying materials\r
+#  are licensed and made available under the terms and conditions of the BSD License\r
+#  which accompanies this distribution.  The full text of the license may be found at\r
+#  http://opensource.org/licenses/bsd-license.php\r
+#  \r
+#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+#  \r
+##\r
+\r
+[Defines]\r
+  INF_VERSION                    = 0x00010005\r
+  BASE_NAME                      = BaseXApicLib\r
+  FILE_GUID                      = D87CA0A8-1AC2-439b-90F8-EF4A2AC88DAF\r
+  MODULE_TYPE                    = BASE\r
+  VERSION_STRING                 = 1.0\r
+  LIBRARY_CLASS                  = LocalApicLib \r
+\r
+#\r
+# The following information is for reference only and not required by the build tools.\r
+#\r
+#  VALID_ARCHITECTURES           = IA32 X64\r
+#\r
+\r
+[Sources]\r
+  BaseXApicLib.c\r
+\r
+[Packages]\r
+  MdePkg/MdePkg.dec\r
+  UefiCpuPkg/UefiCpuPkg.dec\r
+\r
+[LibraryClasses]\r
+  BaseLib\r
+  DebugLib\r
+  TimerLib\r
+  IoLib\r
+\r
+[Pcd]\r
+  gUefiCpuPkgTokenSpaceGuid.PcdCpuLocalApicBaseAddress\r
+\r
diff --git a/UefiCpuPkg/Library/BaseXApicX2ApicLib/BaseXApicX2ApicLib.c b/UefiCpuPkg/Library/BaseXApicX2ApicLib/BaseXApicX2ApicLib.c
new file mode 100644 (file)
index 0000000..bff66ee
--- /dev/null
@@ -0,0 +1,657 @@
+/** @file\r
+  Local APIC Library.\r
+\r
+  This local APIC library instance supports x2APIC capable processors\r
+  which have xAPIC and x2APIC modes.\r
+\r
+  Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>\r
+  This program and the accompanying materials\r
+  are licensed and made available under the terms and conditions of the BSD License\r
+  which accompanies this distribution.  The full text of the license may be found at\r
+  http://opensource.org/licenses/bsd-license.php\r
+\r
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include <Register/LocalApic.h>\r
+\r
+#include <Library/BaseLib.h>\r
+#include <Library/DebugLib.h>\r
+#include <Library/LocalApicLib.h>\r
+#include <Library/IoLib.h>\r
+#include <Library/TimerLib.h>\r
+#include <Library/PcdLib.h>\r
+\r
+//\r
+// Library internal functions\r
+//\r
+\r
+/**\r
+  Read from a local APIC register.\r
+\r
+  This function reads from a local APIC register either in xAPIC or x2APIC mode.\r
+  It is required that in xAPIC mode wider registers (64-bit or 256-bit) must be\r
+  accessed using multiple 32-bit loads or stores, so this function only performs\r
+  32-bit read.\r
+\r
+  @param  MmioOffset  The MMIO offset of the local APIC register in xAPIC mode.\r
+                      It must be 16-byte aligned.\r
+\r
+  @return 32-bit      Value read from the register.\r
+**/\r
+UINT32\r
+EFIAPI\r
+ReadLocalApicReg (\r
+  IN UINTN  MmioOffset\r
+  )\r
+{\r
+  UINT32 MsrIndex;\r
+\r
+  ASSERT ((MmioOffset & 0xf) == 0);\r
+\r
+  if (GetApicMode () == LOCAL_APIC_MODE_XAPIC) {\r
+    return MmioRead32 (PcdGet32 (PcdCpuLocalApicBaseAddress) + MmioOffset);\r
+  } else {\r
+    //\r
+    // DFR is not supported in x2APIC mode.\r
+    //\r
+    ASSERT (MmioOffset != XAPIC_ICR_DFR_OFFSET);\r
+    //\r
+    // Note that in x2APIC mode, ICR is a 64-bit MSR that needs special treatment. It\r
+    // is not supported in this function for simplicity.\r
+    //\r
+    ASSERT (MmioOffset != XAPIC_ICR_HIGH_OFFSET);\r
+\r
+    MsrIndex = (UINT32)(MmioOffset >> 4) + X2APIC_MSR_BASE_ADDRESS;\r
+    return AsmReadMsr32 (MsrIndex);\r
+  }\r
+}\r
+\r
+/**\r
+  Write to a local APIC register.\r
+\r
+  This function writes to a local APIC register either in xAPIC or x2APIC mode.\r
+  It is required that in xAPIC mode wider registers (64-bit or 256-bit) must be\r
+  accessed using multiple 32-bit loads or stores, so this function only performs\r
+  32-bit write.\r
+\r
+  if the register index is invalid or unsupported in current APIC mode, then ASSERT.\r
+\r
+  @param  MmioOffset  The MMIO offset of the local APIC register in xAPIC mode.\r
+                      It must be 16-byte aligned.\r
+  @param  Value       Value to be written to the register.\r
+**/\r
+VOID\r
+EFIAPI\r
+WriteLocalApicReg (\r
+  IN UINTN  MmioOffset,\r
+  IN UINT32 Value\r
+  )\r
+{\r
+  UINT32 MsrIndex;\r
+\r
+  ASSERT ((MmioOffset & 0xf) == 0);\r
+\r
+  if (GetApicMode () == LOCAL_APIC_MODE_XAPIC) {\r
+    MmioWrite32 (PcdGet32 (PcdCpuLocalApicBaseAddress) + MmioOffset, Value);\r
+  } else {\r
+    //\r
+    // DFR is not supported in x2APIC mode.\r
+    //\r
+    ASSERT (MmioOffset != XAPIC_ICR_DFR_OFFSET);\r
+    //\r
+    // Note that in x2APIC mode, ICR is a 64-bit MSR that needs special treatment. It\r
+    // is not supported in this function for simplicity.\r
+    //\r
+    ASSERT (MmioOffset != XAPIC_ICR_HIGH_OFFSET);\r
+    ASSERT (MmioOffset != XAPIC_ICR_LOW_OFFSET);\r
+\r
+    MsrIndex =  (UINT32)(MmioOffset >> 4) + X2APIC_MSR_BASE_ADDRESS;\r
+    //\r
+    // The serializing semantics of WRMSR are relaxed when writing to the APIC registers.\r
+    // Use memory fence here to force the serializing semantics to be consisent with xAPIC mode.\r
+    //\r
+    MemoryFence ();\r
+    AsmWriteMsr32 (MsrIndex, Value);\r
+  }\r
+}\r
+\r
+/**\r
+  Send an IPI by writing to ICR.\r
+\r
+  This function returns after the IPI has been accepted by the target processor. \r
+\r
+  @param  IcrLow 32-bit value to be written to the low half of ICR.\r
+  @param  ApicId APIC ID of the target processor if this IPI is targeted for a specific processor.\r
+**/\r
+VOID\r
+SendIpi (\r
+  IN UINT32          IcrLow,\r
+  IN UINT32          ApicId\r
+  )\r
+{\r
+  UINT64             MsrValue;\r
+  LOCAL_APIC_ICR_LOW IcrLowReg;\r
+\r
+  if (GetApicMode () == LOCAL_APIC_MODE_XAPIC) {\r
+    ASSERT (ApicId <= 0xff);\r
+\r
+    //\r
+    // For xAPIC, the act of writing to the low doubleword of the ICR causes the IPI to be sent.\r
+    //\r
+    MmioWrite32 (PcdGet32 (PcdCpuLocalApicBaseAddress) + XAPIC_ICR_HIGH_OFFSET, ApicId << 24);\r
+    MmioWrite32 (PcdGet32 (PcdCpuLocalApicBaseAddress) + XAPIC_ICR_LOW_OFFSET, IcrLow);\r
+    do {\r
+      IcrLowReg.Uint32 = MmioRead32 (PcdGet32 (PcdCpuLocalApicBaseAddress) + XAPIC_ICR_LOW_OFFSET);\r
+    } while (IcrLowReg.Bits.DeliveryStatus != 0);\r
+  } else {\r
+    //\r
+    // For x2APIC, A single MSR write to the Interrupt Command Register is required for dispatching an \r
+    // interrupt in x2APIC mode.\r
+    //\r
+    MsrValue = (((UINT64)ApicId) << 32) | IcrLow;\r
+    AsmWriteMsr64 (X2APIC_MSR_ICR_ADDRESS, MsrValue);\r
+  }\r
+}\r
+\r
+//\r
+// Library API implementation functions\r
+//\r
+\r
+/**\r
+  Get the current local APIC mode.\r
+\r
+  If local APIC is disabled, then ASSERT.\r
+\r
+  @retval LOCAL_APIC_MODE_XAPIC  current APIC mode is xAPIC.\r
+  @retval LOCAL_APIC_MODE_X2APIC current APIC mode is x2APIC.\r
+**/\r
+UINTN\r
+EFIAPI\r
+GetApicMode (\r
+  VOID\r
+  )\r
+{\r
+  MSR_IA32_APIC_BASE ApicBaseMsr;\r
+\r
+  ApicBaseMsr.Uint64 = AsmReadMsr64 (MSR_IA32_APIC_BASE_ADDRESS);\r
+  //\r
+  // Local APIC should have been enabled\r
+  //\r
+  ASSERT (ApicBaseMsr.Bits.En != 0);\r
+  if (ApicBaseMsr.Bits.Extd != 0) {\r
+    return LOCAL_APIC_MODE_X2APIC;\r
+  } else {\r
+    return LOCAL_APIC_MODE_XAPIC;\r
+  }\r
+}\r
+\r
+/**\r
+  Set the current local APIC mode.\r
+\r
+  If the specified local APIC mode is not valid, then ASSERT.\r
+  If the specified local APIC mode can't be set as current, then ASSERT.\r
+\r
+  @param ApicMode APIC mode to be set.\r
+**/\r
+VOID\r
+EFIAPI\r
+SetApicMode (\r
+  IN UINTN  ApicMode\r
+  )\r
+{\r
+  UINTN              CurrentMode;\r
+  MSR_IA32_APIC_BASE ApicBaseMsr;\r
+\r
+  CurrentMode = GetApicMode ();\r
+  if (CurrentMode == LOCAL_APIC_MODE_XAPIC) {\r
+    switch (ApicMode) {\r
+      case LOCAL_APIC_MODE_XAPIC:\r
+        break;\r
+      case LOCAL_APIC_MODE_X2APIC:\r
+        ApicBaseMsr.Uint64 = AsmReadMsr64 (MSR_IA32_APIC_BASE_ADDRESS);\r
+        ApicBaseMsr.Bits.Extd = 1;\r
+        AsmWriteMsr64 (MSR_IA32_APIC_BASE_ADDRESS, ApicBaseMsr.Uint64);\r
+        break;\r
+      default:\r
+        ASSERT (FALSE);\r
+    }\r
+  } else {\r
+    switch (ApicMode) {\r
+      case LOCAL_APIC_MODE_XAPIC:\r
+        //\r
+        //  Transition from x2APIC mode to xAPIC mode is a two-step process:\r
+        //    x2APIC -> Local APIC disabled -> xAPIC\r
+        //\r
+        ApicBaseMsr.Uint64 = AsmReadMsr64 (MSR_IA32_APIC_BASE_ADDRESS);\r
+        ApicBaseMsr.Bits.Extd = 0;\r
+        ApicBaseMsr.Bits.En = 0;\r
+        AsmWriteMsr64 (MSR_IA32_APIC_BASE_ADDRESS, ApicBaseMsr.Uint64);\r
+        ApicBaseMsr.Bits.En = 1;\r
+        AsmWriteMsr64 (MSR_IA32_APIC_BASE_ADDRESS, ApicBaseMsr.Uint64);\r
+        break;\r
+      case LOCAL_APIC_MODE_X2APIC:\r
+        break;\r
+      default:\r
+        ASSERT (FALSE);\r
+    }\r
+  }\r
+}\r
+\r
+/**\r
+  Get the initial local APIC ID of the executing processor assigned by hardware upon power on or reset.\r
+\r
+  In xAPIC mode, the initial local APIC ID is 8-bit, and may be different from current APIC ID.\r
+  In x2APIC mode, the local APIC ID can't be changed and there is no concept of initial APIC ID. In this case, \r
+  the 32-bit local APIC ID is returned as initial APIC ID.\r
+\r
+  @return  32-bit initial local APIC ID of the executing processor.\r
+**/\r
+UINT32\r
+EFIAPI\r
+GetInitialApicId (\r
+  VOID\r
+  )\r
+{\r
+  UINT32 RegEbx;\r
+\r
+  if (GetApicMode () == LOCAL_APIC_MODE_XAPIC) {\r
+    AsmCpuid (CPUID_VERSION_INFO, NULL, &RegEbx, NULL, NULL);\r
+    return RegEbx >> 24;\r
+  } else {\r
+    return GetApicId ();\r
+  }\r
+}\r
+\r
+/**\r
+  Get the local APIC ID of the executing processor.\r
+\r
+  @return  32-bit local APIC ID of the executing processor.\r
+**/\r
+UINT32\r
+EFIAPI\r
+GetApicId (\r
+  VOID\r
+  )\r
+{\r
+  UINT32 ApicId;\r
+\r
+  ApicId = ReadLocalApicReg (XAPIC_ID_OFFSET);\r
+  if (GetApicMode () == LOCAL_APIC_MODE_XAPIC) {\r
+    ApicId >>= 24;\r
+  }\r
+  return ApicId;\r
+}\r
+\r
+/**\r
+  Send a SMI IPI to a specified target processor.\r
+\r
+  This function returns after the IPI has been accepted by the target processor. \r
+\r
+  @param  ApicId   Specify the local APIC ID of the target processor.\r
+**/\r
+VOID\r
+EFIAPI\r
+SendSmiIpi (\r
+  IN UINT32          ApicId\r
+  )\r
+{\r
+  LOCAL_APIC_ICR_LOW IcrLow;\r
+\r
+  IcrLow.Uint32 = 0;\r
+  IcrLow.Bits.DeliveryMode = LOCAL_APIC_DELIVERY_MODE_SMI;\r
+  IcrLow.Bits.Level = 1;\r
+  SendIpi (IcrLow.Uint32, ApicId);\r
+}\r
+\r
+/**\r
+  Send a SMI IPI to all processors excluding self.\r
+\r
+  This function returns after the IPI has been accepted by the target processors. \r
+**/\r
+VOID\r
+EFIAPI\r
+SendSmiIpiAllExcludingSelf (\r
+  VOID\r
+  )\r
+{\r
+  LOCAL_APIC_ICR_LOW IcrLow;\r
+\r
+  IcrLow.Uint32 = 0;\r
+  IcrLow.Bits.DeliveryMode = LOCAL_APIC_DELIVERY_MODE_SMI;\r
+  IcrLow.Bits.Level = 1;\r
+  IcrLow.Bits.DestinationShorthand = LOCAL_APIC_DESTINATION_SHORTHAND_ALL_EXCLUDING_SELF;\r
+  SendIpi (IcrLow.Uint32, 0);\r
+}\r
+\r
+/**\r
+  Send an INIT IPI to a specified target processor.\r
+\r
+  This function returns after the IPI has been accepted by the target processor. \r
+\r
+  @param  ApicId   Specify the local APIC ID of the target processor.\r
+**/\r
+VOID\r
+EFIAPI\r
+SendInitIpi (\r
+  IN UINT32          ApicId\r
+  )\r
+{\r
+  LOCAL_APIC_ICR_LOW IcrLow;\r
+\r
+  IcrLow.Uint32 = 0;\r
+  IcrLow.Bits.DeliveryMode = LOCAL_APIC_DELIVERY_MODE_INIT;\r
+  IcrLow.Bits.Level = 1;\r
+  SendIpi (IcrLow.Uint32, ApicId);\r
+}\r
+\r
+/**\r
+  Send an INIT IPI to all processors excluding self.\r
+\r
+  This function returns after the IPI has been accepted by the target processors. \r
+**/\r
+VOID\r
+EFIAPI\r
+SendInitIpiAllExcludingSelf (\r
+  VOID\r
+  )\r
+{\r
+  LOCAL_APIC_ICR_LOW IcrLow;\r
+\r
+  IcrLow.Uint32 = 0;\r
+  IcrLow.Bits.DeliveryMode = LOCAL_APIC_DELIVERY_MODE_INIT;\r
+  IcrLow.Bits.Level = 1;\r
+  IcrLow.Bits.DestinationShorthand = LOCAL_APIC_DESTINATION_SHORTHAND_ALL_EXCLUDING_SELF;\r
+  SendIpi (IcrLow.Uint32, 0);\r
+}\r
+\r
+/**\r
+  Send an INIT-Start-up-Start-up IPI sequence to a specified target processor.\r
+\r
+  This function returns after the IPI has been accepted by the target processor. \r
+\r
+  if StartupRoutine >= 1M, then ASSERT.\r
+  if StartupRoutine is not multiple of 4K, then ASSERT.\r
+\r
+  @param  ApicId          Specify the local APIC ID of the target processor.\r
+  @param  StartupRoutine  Points to a start-up routine which is below 1M physical\r
+                          address and 4K aligned.\r
+**/\r
+VOID\r
+EFIAPI\r
+SendInitSipiSipi (\r
+  IN UINT32          ApicId,\r
+  IN UINT32          StartupRoutine\r
+  )\r
+{\r
+  LOCAL_APIC_ICR_LOW IcrLow;\r
+\r
+  ASSERT (StartupRoutine < 0x100000);\r
+  ASSERT ((StartupRoutine & 0xfff) == 0);\r
+\r
+  SendInitIpi (ApicId);\r
+  MicroSecondDelay (10);\r
+  IcrLow.Uint32 = 0;\r
+  IcrLow.Bits.Vector = (StartupRoutine >> 12);\r
+  IcrLow.Bits.DeliveryMode = LOCAL_APIC_DELIVERY_MODE_STARTUP;\r
+  IcrLow.Bits.Level = 1;\r
+  SendIpi (IcrLow.Uint32, ApicId);\r
+  MicroSecondDelay (200);\r
+  SendIpi (IcrLow.Uint32, ApicId);\r
+}\r
+\r
+/**\r
+  Send an INIT-Start-up-Start-up IPI sequence to all processors excluding self.\r
+\r
+  This function returns after the IPI has been accepted by the target processors. \r
+\r
+  if StartupRoutine >= 1M, then ASSERT.\r
+  if StartupRoutine is not multiple of 4K, then ASSERT.\r
+\r
+  @param  StartupRoutine    Points to a start-up routine which is below 1M physical\r
+                            address and 4K aligned.\r
+**/\r
+VOID\r
+EFIAPI\r
+SendInitSipiSipiAllExcludingSelf (\r
+  IN UINT32          StartupRoutine\r
+  )\r
+{\r
+  LOCAL_APIC_ICR_LOW IcrLow;\r
+\r
+  ASSERT (StartupRoutine < 0x100000);\r
+  ASSERT ((StartupRoutine & 0xfff) == 0);\r
+\r
+  SendInitIpiAllExcludingSelf ();\r
+  MicroSecondDelay (10);\r
+  IcrLow.Uint32 = 0;\r
+  IcrLow.Bits.Vector = (StartupRoutine >> 12);\r
+  IcrLow.Bits.DeliveryMode = LOCAL_APIC_DELIVERY_MODE_STARTUP;\r
+  IcrLow.Bits.Level = 1;\r
+  IcrLow.Bits.DestinationShorthand = LOCAL_APIC_DESTINATION_SHORTHAND_ALL_EXCLUDING_SELF;\r
+  SendIpi (IcrLow.Uint32, 0);\r
+  MicroSecondDelay (200);\r
+  SendIpi (IcrLow.Uint32, 0);\r
+}\r
+\r
+/**\r
+  Programming Virtual Wire Mode.\r
+\r
+  This function programs the local APIC for virtual wire mode following\r
+  the example described in chapter A.3 of the MP 1.4 spec.\r
+\r
+  IOxAPIC is not involved in this type of virtual wire mode.\r
+**/\r
+VOID\r
+EFIAPI\r
+ProgramVirtualWireMode (\r
+  VOID\r
+  )\r
+{\r
+  LOCAL_APIC_SVR      Svr;\r
+  LOCAL_APIC_LVT_LINT Lint;\r
+\r
+  //\r
+  // Enable the APIC via SVR and set the spurious interrupt to use Int 00F.\r
+  //\r
+  Svr.Uint32 = ReadLocalApicReg (XAPIC_SPURIOUS_VECTOR_OFFSET);\r
+  Svr.Bits.SpuriousVector = 0xf;\r
+  Svr.Bits.SoftwareEnable = 1;\r
+  WriteLocalApicReg (XAPIC_SPURIOUS_VECTOR_OFFSET, Svr.Uint32);\r
+\r
+  //\r
+  // Program the LINT0 vector entry as ExtInt. Not masked, edge, active high.\r
+  //\r
+  Lint.Uint32 = ReadLocalApicReg (XAPIC_LINT0_VECTOR_OFFSET);\r
+  Lint.Bits.DeliveryMode = LOCAL_APIC_DELIVERY_MODE_EXTINT;\r
+  Lint.Bits.InputPinPolarity = 0;\r
+  Lint.Bits.TriggerMode = 0;\r
+  Lint.Bits.Mask = 0;\r
+  WriteLocalApicReg (XAPIC_LINT0_VECTOR_OFFSET, Lint.Uint32);\r
+\r
+  //\r
+  // Program the LINT0 vector entry as NMI. Not masked, edge, active high.\r
+  //\r
+  Lint.Uint32 = ReadLocalApicReg (XAPIC_LINT1_VECTOR_OFFSET);\r
+  Lint.Bits.DeliveryMode = LOCAL_APIC_DELIVERY_MODE_NMI;\r
+  Lint.Bits.InputPinPolarity = 0;\r
+  Lint.Bits.TriggerMode = 0;\r
+  Lint.Bits.Mask = 0;\r
+  WriteLocalApicReg (XAPIC_LINT1_VECTOR_OFFSET, Lint.Uint32);\r
+}\r
+\r
+/**\r
+  Get the divide value from the DCR (Divide Configuration Register) by which\r
+  the processor's bus clock is divided to form the time base for the APIC timer.\r
+\r
+  @return The divide value is one of 1,2,4,8,16,32,64,128.\r
+**/\r
+UINTN\r
+EFIAPI\r
+GetApicTimerDivisor (\r
+  VOID\r
+  )\r
+{\r
+  UINT32         DivideValue;\r
+  LOCAL_APIC_DCR Dcr;\r
+\r
+  Dcr.Uint32 = ReadLocalApicReg (XAPIC_TIMER_DIVIDE_CONFIGURATION_OFFSET);\r
+  DivideValue = Dcr.Bits.DivideValue1 | (Dcr.Bits.DivideValue2 << 2);\r
+  DivideValue = (DivideValue + 1) & 0x7;\r
+  return ((UINTN)1) << DivideValue;\r
+}\r
+\r
+/**\r
+  Read the initial count value from the init-count register.\r
+\r
+  @return The initial count value read from the init-count register.\r
+**/\r
+UINT32\r
+EFIAPI\r
+GetApicTimerInitCount (\r
+  VOID\r
+  )\r
+{\r
+  return ReadLocalApicReg (XAPIC_TIMER_INIT_COUNT_OFFSET);\r
+}\r
+\r
+/**\r
+  Read the current count value from the current-count register.\r
+\r
+  @return The current count value read from the current-count register.\r
+**/\r
+UINT32\r
+EFIAPI\r
+GetApicTimerCurrentCount (\r
+  VOID\r
+  )\r
+{\r
+  return ReadLocalApicReg (XAPIC_TIMER_CURRENT_COUNT_OFFSET);\r
+}\r
+\r
+/**\r
+  Initialize the local APIC timer.\r
+\r
+  The local APIC timer is initialized and enabled.\r
+\r
+  @param DivideValue   The divide value for the DCR. It is one of 1,2,4,8,16,32,64,128.\r
+                       If it is 0, then use the current divide value in the DCR.\r
+  @param InitCount     The initial count value.\r
+  @param PeriodicMode  If TRUE, timer mode is peridoic. Othewise, timer mode is one-shot.\r
+  @param Vector        The timer interrupt vector number.\r
+**/\r
+VOID\r
+EFIAPI\r
+InitializeApicTimer (\r
+  IN UINTN   DivideValue,\r
+  IN UINT32  InitCount,\r
+  IN BOOLEAN PeriodicMode,\r
+  IN UINT8   Vector\r
+  )\r
+{\r
+  LOCAL_APIC_SVR       Svr;\r
+  LOCAL_APIC_DCR       Dcr;\r
+  LOCAL_APIC_LVT_TIMER LvtTimer;\r
+  UINT32               Divisor;\r
+\r
+  //\r
+  // Ensure local APIC is in software-enabled state.\r
+  //\r
+  Svr.Uint32 = ReadLocalApicReg (XAPIC_SPURIOUS_VECTOR_OFFSET);\r
+  Svr.Bits.SoftwareEnable = 1;\r
+  WriteLocalApicReg (XAPIC_SPURIOUS_VECTOR_OFFSET, Svr.Uint32);\r
+\r
+  //\r
+  // Program init-count register.\r
+  //\r
+  WriteLocalApicReg (XAPIC_TIMER_INIT_COUNT_OFFSET, InitCount);\r
+\r
+  if (DivideValue != 0) {\r
+    ASSERT (DivideValue <= 128);\r
+    ASSERT (DivideValue == GetPowerOfTwo32((UINT32)DivideValue));\r
+    Divisor = (UINT32)((HighBitSet32 ((UINT32)DivideValue) - 1) & 0x7);\r
+\r
+    Dcr.Uint32 = ReadLocalApicReg (XAPIC_TIMER_DIVIDE_CONFIGURATION_OFFSET);\r
+    Dcr.Bits.DivideValue1 = (Divisor & 0x3);\r
+    Dcr.Bits.DivideValue2 = (Divisor >> 2);\r
+    WriteLocalApicReg (XAPIC_TIMER_DIVIDE_CONFIGURATION_OFFSET, Dcr.Uint32); \r
+  }\r
+\r
+  //\r
+  // Enable APIC timer interrupt with specified timer mode.\r
+  //\r
+  LvtTimer.Uint32 = ReadLocalApicReg (XAPIC_LVT_TIMER_OFFSET);\r
+  if (PeriodicMode) {\r
+    LvtTimer.Bits.TimerMode = 1;\r
+  } else {\r
+    LvtTimer.Bits.TimerMode = 0;\r
+  }\r
+  LvtTimer.Bits.Mask = 0;\r
+  LvtTimer.Bits.Vector = Vector;\r
+  WriteLocalApicReg (XAPIC_LVT_TIMER_OFFSET, LvtTimer.Uint32);\r
+}\r
+\r
+/**\r
+  Enable the local APIC timer interrupt.\r
+**/\r
+VOID\r
+EFIAPI\r
+EnableApicTimerInterrupt (\r
+  VOID\r
+  )\r
+{\r
+  LOCAL_APIC_LVT_TIMER LvtTimer;\r
+\r
+  LvtTimer.Uint32 = ReadLocalApicReg (XAPIC_LVT_TIMER_OFFSET);\r
+  LvtTimer.Bits.Mask = 0;\r
+  WriteLocalApicReg (XAPIC_LVT_TIMER_OFFSET, LvtTimer.Uint32);\r
+}\r
+\r
+/**\r
+  Disable the local APIC timer interrupt.\r
+**/\r
+VOID\r
+EFIAPI\r
+DisableApicTimerInterrupt (\r
+  VOID\r
+  )\r
+{\r
+  LOCAL_APIC_LVT_TIMER LvtTimer;\r
+\r
+  LvtTimer.Uint32 = ReadLocalApicReg (XAPIC_LVT_TIMER_OFFSET);\r
+  LvtTimer.Bits.Mask = 1;\r
+  WriteLocalApicReg (XAPIC_LVT_TIMER_OFFSET, LvtTimer.Uint32);\r
+}\r
+\r
+/**\r
+  Get the local APIC timer interrupt state.\r
+\r
+  @retval TRUE  The local APIC timer interrupt is enabled.\r
+  @retval FALSE The local APIC timer interrupt is disabled.\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+GetApicTimerInterruptState (\r
+  VOID\r
+  )\r
+{\r
+  LOCAL_APIC_LVT_TIMER LvtTimer;\r
+\r
+  LvtTimer.Uint32 = ReadLocalApicReg (XAPIC_LVT_TIMER_OFFSET);\r
+  return (BOOLEAN)(LvtTimer.Bits.Mask == 0);\r
+}\r
+\r
+/**\r
+  Send EOI to the local APIC.\r
+**/\r
+VOID\r
+EFIAPI\r
+SendApicEoi (\r
+  VOID\r
+  )\r
+{\r
+  WriteLocalApicReg (XAPIC_EOI_OFFSET, 0);\r
+}\r
+\r
diff --git a/UefiCpuPkg/Library/BaseXApicX2ApicLib/BaseXApicX2ApicLib.inf b/UefiCpuPkg/Library/BaseXApicX2ApicLib/BaseXApicX2ApicLib.inf
new file mode 100644 (file)
index 0000000..df2769c
--- /dev/null
@@ -0,0 +1,47 @@
+## @file\r
+#  Component description file for CPU Local APIC Library.\r
+#\r
+#  This library instance supports x2APIC capable processors\r
+#  which have xAPIC and x2APIC modes.\r
+#\r
+#  Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>\r
+#  This program and the accompanying materials\r
+#  are licensed and made available under the terms and conditions of the BSD License\r
+#  which accompanies this distribution.  The full text of the license may be found at\r
+#  http://opensource.org/licenses/bsd-license.php\r
+#  \r
+#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+#  \r
+##\r
+\r
+[Defines]\r
+  INF_VERSION                    = 0x00010005\r
+  BASE_NAME                      = BaseXApicX2ApicLib\r
+  FILE_GUID                      = 967B6E05-F10D-4c10-8BF7-365291CA143F\r
+  MODULE_TYPE                    = BASE\r
+  VERSION_STRING                 = 1.0\r
+  LIBRARY_CLASS                  = LocalApicLib \r
+\r
+#\r
+# The following information is for reference only and not required by the build tools.\r
+#\r
+#  VALID_ARCHITECTURES           = IA32 X64\r
+#\r
+\r
+[Sources]\r
+  BaseXApicX2ApicLib.c\r
+\r
+[Packages]\r
+  MdePkg/MdePkg.dec\r
+  UefiCpuPkg/UefiCpuPkg.dec\r
+\r
+[LibraryClasses]\r
+  BaseLib\r
+  DebugLib\r
+  TimerLib\r
+  IoLib\r
+\r
+[Pcd]\r
+  gUefiCpuPkgTokenSpaceGuid.PcdCpuLocalApicBaseAddress\r
+\r
index 8547c54e131c16fd904a64bd361c4c72e136bfd2..98fba369207073479278b88bf6ea74f4a671ba8c 100644 (file)
   ##                 to be UEFI specification compliant.
   ##
   UefiCpuLib|Include/Library/UefiCpuLib.h
   ##                 to be UEFI specification compliant.
   ##
   UefiCpuLib|Include/Library/UefiCpuLib.h
+
+[Guids]
+  gUefiCpuPkgTokenSpaceGuid      = { 0xac05bf33, 0x995a, 0x4ed4, { 0xaa, 0xb8, 0xef, 0x7a, 0xe8, 0xf, 0x5c, 0xb0 }}
+
+[PcdsFixedAtBuild, PcdsPatchableInModule]
+  gUefiCpuPkgTokenSpaceGuid.PcdCpuLocalApicBaseAddress|0xfee00000|UINT32|0x00000001
+
index a9e45bc9aeccb8c9d246124f2ea5f5d7041ac3c8..c414ae8b295c0211988815ddc5c0358aa7fd12e1 100644 (file)
@@ -73,4 +73,7 @@
   UefiCpuPkg/CpuDxe/CpuDxe.inf\r
   UefiCpuPkg/CpuIo2Smm/CpuIo2Smm.inf\r
   UefiCpuPkg/Library/BaseUefiCpuLib/BaseUefiCpuLib.inf\r
   UefiCpuPkg/CpuDxe/CpuDxe.inf\r
   UefiCpuPkg/CpuIo2Smm/CpuIo2Smm.inf\r
   UefiCpuPkg/Library/BaseUefiCpuLib/BaseUefiCpuLib.inf\r
-  UefiCpuPkg/Library/MtrrLib/MtrrLib.inf
\ No newline at end of file
+  UefiCpuPkg/Library/MtrrLib/MtrrLib.inf\r
+  UefiCpuPkg/Library/BaseXApicX2ApicLib/BaseXApicX2ApicLib.inf\r
+  UefiCpuPkg/Library/BaseXApicLib/BaseXApicLib.inf\r
+\r