]> git.proxmox.com Git - mirror_edk2.git/blobdiff - UefiCpuPkg/CpuDxe/CpuDxe.c
UefiCpuPkg: Move AsmRelocateApLoopStart from Mpfuncs.nasm to AmdSev.nasm
[mirror_edk2.git] / UefiCpuPkg / CpuDxe / CpuDxe.c
index daf97bd4a6cf6b762b103d6db7d35205e204c89a..a6a91507f6066fbce11911530b083abe9904a658 100644 (file)
@@ -1,88 +1,86 @@
 /** @file\r
-  CPU DXE Module.\r
+  CPU DXE Module to produce CPU ARCH Protocol.\r
 \r
-  Copyright (c) 2008 - 2013, 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
+  Copyright (c) 2008 - 2022, Intel Corporation. All rights reserved.<BR>\r
+  SPDX-License-Identifier: BSD-2-Clause-Patent\r
 \r
 **/\r
 \r
 #include "CpuDxe.h"\r
 #include "CpuMp.h"\r
+#include "CpuPageTable.h"\r
+\r
+#define CPU_INTERRUPT_NUM  256\r
 \r
 //\r
 // Global Variables\r
 //\r
-BOOLEAN                   InterruptState = FALSE;\r
-EFI_HANDLE                mCpuHandle = NULL;\r
-BOOLEAN                   mIsFlushingGCD;\r
-UINT64                    mValidMtrrAddressMask = MTRR_LIB_CACHE_VALID_ADDRESS;\r
-UINT64                    mValidMtrrBitsMask    = MTRR_LIB_MSR_VALID_MASK;\r
-\r
-FIXED_MTRR    mFixedMtrrTable[] = {\r
+BOOLEAN     InterruptState = FALSE;\r
+EFI_HANDLE  mCpuHandle     = NULL;\r
+BOOLEAN     mIsFlushingGCD;\r
+BOOLEAN     mIsAllocatingPageTable = FALSE;\r
+UINT64      mValidMtrrAddressMask;\r
+UINT64      mValidMtrrBitsMask;\r
+UINT64      mTimerPeriod = 0;\r
+\r
+FIXED_MTRR  mFixedMtrrTable[] = {\r
   {\r
-    MTRR_LIB_IA32_MTRR_FIX64K_00000,\r
+    MSR_IA32_MTRR_FIX64K_00000,\r
     0,\r
     0x10000\r
   },\r
   {\r
-    MTRR_LIB_IA32_MTRR_FIX16K_80000,\r
+    MSR_IA32_MTRR_FIX16K_80000,\r
     0x80000,\r
     0x4000\r
   },\r
   {\r
-    MTRR_LIB_IA32_MTRR_FIX16K_A0000,\r
+    MSR_IA32_MTRR_FIX16K_A0000,\r
     0xA0000,\r
     0x4000\r
   },\r
   {\r
-    MTRR_LIB_IA32_MTRR_FIX4K_C0000,\r
+    MSR_IA32_MTRR_FIX4K_C0000,\r
     0xC0000,\r
     0x1000\r
   },\r
   {\r
-    MTRR_LIB_IA32_MTRR_FIX4K_C8000,\r
+    MSR_IA32_MTRR_FIX4K_C8000,\r
     0xC8000,\r
     0x1000\r
   },\r
   {\r
-    MTRR_LIB_IA32_MTRR_FIX4K_D0000,\r
+    MSR_IA32_MTRR_FIX4K_D0000,\r
     0xD0000,\r
     0x1000\r
   },\r
   {\r
-    MTRR_LIB_IA32_MTRR_FIX4K_D8000,\r
+    MSR_IA32_MTRR_FIX4K_D8000,\r
     0xD8000,\r
     0x1000\r
   },\r
   {\r
-    MTRR_LIB_IA32_MTRR_FIX4K_E0000,\r
+    MSR_IA32_MTRR_FIX4K_E0000,\r
     0xE0000,\r
     0x1000\r
   },\r
   {\r
-    MTRR_LIB_IA32_MTRR_FIX4K_E8000,\r
+    MSR_IA32_MTRR_FIX4K_E8000,\r
     0xE8000,\r
     0x1000\r
   },\r
   {\r
-    MTRR_LIB_IA32_MTRR_FIX4K_F0000,\r
+    MSR_IA32_MTRR_FIX4K_F0000,\r
     0xF0000,\r
     0x1000\r
   },\r
   {\r
-    MTRR_LIB_IA32_MTRR_FIX4K_F8000,\r
+    MSR_IA32_MTRR_FIX4K_F8000,\r
     0xF8000,\r
     0x1000\r
   },\r
 };\r
 \r
-\r
 EFI_CPU_ARCH_PROTOCOL  gCpu = {\r
   CpuFlushCpuDataCache,\r
   CpuEnableInterrupt,\r
@@ -118,10 +116,10 @@ EFI_CPU_ARCH_PROTOCOL  gCpu = {
 EFI_STATUS\r
 EFIAPI\r
 CpuFlushCpuDataCache (\r
-  IN EFI_CPU_ARCH_PROTOCOL     *This,\r
-  IN EFI_PHYSICAL_ADDRESS      Start,\r
-  IN UINT64                    Length,\r
-  IN EFI_CPU_FLUSH_TYPE        FlushType\r
+  IN EFI_CPU_ARCH_PROTOCOL  *This,\r
+  IN EFI_PHYSICAL_ADDRESS   Start,\r
+  IN UINT64                 Length,\r
+  IN EFI_CPU_FLUSH_TYPE     FlushType\r
   )\r
 {\r
   if (FlushType == EfiCpuFlushTypeWriteBackInvalidate) {\r
@@ -135,7 +133,6 @@ CpuFlushCpuDataCache (
   }\r
 }\r
 \r
-\r
 /**\r
   Enables CPU interrupts.\r
 \r
@@ -148,7 +145,7 @@ CpuFlushCpuDataCache (
 EFI_STATUS\r
 EFIAPI\r
 CpuEnableInterrupt (\r
-  IN EFI_CPU_ARCH_PROTOCOL          *This\r
+  IN EFI_CPU_ARCH_PROTOCOL  *This\r
   )\r
 {\r
   EnableInterrupts ();\r
@@ -157,7 +154,6 @@ CpuEnableInterrupt (
   return EFI_SUCCESS;\r
 }\r
 \r
-\r
 /**\r
   Disables CPU interrupts.\r
 \r
@@ -170,7 +166,7 @@ CpuEnableInterrupt (
 EFI_STATUS\r
 EFIAPI\r
 CpuDisableInterrupt (\r
-  IN EFI_CPU_ARCH_PROTOCOL     *This\r
+  IN EFI_CPU_ARCH_PROTOCOL  *This\r
   )\r
 {\r
   DisableInterrupts ();\r
@@ -179,7 +175,6 @@ CpuDisableInterrupt (
   return EFI_SUCCESS;\r
 }\r
 \r
-\r
 /**\r
   Return the state of interrupts.\r
 \r
@@ -193,8 +188,8 @@ CpuDisableInterrupt (
 EFI_STATUS\r
 EFIAPI\r
 CpuGetInterruptState (\r
-  IN  EFI_CPU_ARCH_PROTOCOL     *This,\r
-  OUT BOOLEAN                   *State\r
+  IN  EFI_CPU_ARCH_PROTOCOL  *This,\r
+  OUT BOOLEAN                *State\r
   )\r
 {\r
   if (State == NULL) {\r
@@ -205,7 +200,6 @@ CpuGetInterruptState (
   return EFI_SUCCESS;\r
 }\r
 \r
-\r
 /**\r
   Generates an INIT to the CPU.\r
 \r
@@ -221,14 +215,13 @@ CpuGetInterruptState (
 EFI_STATUS\r
 EFIAPI\r
 CpuInit (\r
-  IN EFI_CPU_ARCH_PROTOCOL      *This,\r
-  IN EFI_CPU_INIT_TYPE          InitType\r
+  IN EFI_CPU_ARCH_PROTOCOL  *This,\r
+  IN EFI_CPU_INIT_TYPE      InitType\r
   )\r
 {\r
   return EFI_UNSUPPORTED;\r
 }\r
 \r
-\r
 /**\r
   Registers a function to be called from the CPU interrupt handler.\r
 \r
@@ -252,15 +245,14 @@ CpuInit (
 EFI_STATUS\r
 EFIAPI\r
 CpuRegisterInterruptHandler (\r
-  IN EFI_CPU_ARCH_PROTOCOL         *This,\r
-  IN EFI_EXCEPTION_TYPE            InterruptType,\r
-  IN EFI_CPU_INTERRUPT_HANDLER     InterruptHandler\r
+  IN EFI_CPU_ARCH_PROTOCOL      *This,\r
+  IN EFI_EXCEPTION_TYPE         InterruptType,\r
+  IN EFI_CPU_INTERRUPT_HANDLER  InterruptHandler\r
   )\r
 {\r
   return RegisterCpuInterruptHandler (InterruptType, InterruptHandler);\r
 }\r
 \r
-\r
 /**\r
   Returns a timer value from one of the CPU's internal timers. There is no\r
   inherent time interval between ticks but is a function of the CPU frequency.\r
@@ -287,12 +279,15 @@ CpuRegisterInterruptHandler (
 EFI_STATUS\r
 EFIAPI\r
 CpuGetTimerValue (\r
-  IN  EFI_CPU_ARCH_PROTOCOL     *This,\r
-  IN  UINT32                    TimerIndex,\r
-  OUT UINT64                    *TimerValue,\r
-  OUT UINT64                    *TimerPeriod OPTIONAL\r
+  IN  EFI_CPU_ARCH_PROTOCOL  *This,\r
+  IN  UINT32                 TimerIndex,\r
+  OUT UINT64                 *TimerValue,\r
+  OUT UINT64                 *TimerPeriod OPTIONAL\r
   )\r
 {\r
+  UINT64  BeginValue;\r
+  UINT64  EndValue;\r
+\r
   if (TimerValue == NULL) {\r
     return EFI_INVALID_PARAMETER;\r
   }\r
@@ -304,15 +299,47 @@ CpuGetTimerValue (
   *TimerValue = AsmReadTsc ();\r
 \r
   if (TimerPeriod != NULL) {\r
+    if (mTimerPeriod == 0) {\r
+      //\r
+      // Read time stamp counter before and after delay of 100 microseconds\r
+      //\r
+      BeginValue = AsmReadTsc ();\r
+      MicroSecondDelay (100);\r
+      EndValue = AsmReadTsc ();\r
       //\r
-      // BugBug: Hard coded. Don't know how to do this generically\r
+      // Calculate the actual frequency\r
       //\r
-      *TimerPeriod = 1000000000;\r
+      mTimerPeriod = DivU64x64Remainder (\r
+                       MultU64x32 (\r
+                         1000 * 1000 * 1000,\r
+                         100\r
+                         ),\r
+                       EndValue - BeginValue,\r
+                       NULL\r
+                       );\r
+    }\r
+\r
+    *TimerPeriod = mTimerPeriod;\r
   }\r
 \r
   return EFI_SUCCESS;\r
 }\r
 \r
+/**\r
+  A minimal wrapper function that allows MtrrSetAllMtrrs() to be passed to\r
+  EFI_MP_SERVICES_PROTOCOL.StartupAllAPs() as Procedure.\r
+\r
+  @param[in] Buffer  Pointer to an MTRR_SETTINGS object, to be passed to\r
+                     MtrrSetAllMtrrs().\r
+**/\r
+VOID\r
+EFIAPI\r
+SetMtrrsFromBuffer (\r
+  IN VOID  *Buffer\r
+  )\r
+{\r
+  MtrrSetAllMtrrs (Buffer);\r
+}\r
 \r
 /**\r
   Implementation of SetMemoryAttributes() service of CPU Architecture Protocol.\r
@@ -342,10 +369,10 @@ CpuGetTimerValue (
 EFI_STATUS\r
 EFIAPI\r
 CpuSetMemoryAttributes (\r
-  IN EFI_CPU_ARCH_PROTOCOL     *This,\r
-  IN EFI_PHYSICAL_ADDRESS      BaseAddress,\r
-  IN UINT64                    Length,\r
-  IN UINT64                    Attributes\r
+  IN EFI_CPU_ARCH_PROTOCOL  *This,\r
+  IN EFI_PHYSICAL_ADDRESS   BaseAddress,\r
+  IN UINT64                 Length,\r
+  IN UINT64                 Attributes\r
   )\r
 {\r
   RETURN_STATUS             Status;\r
@@ -353,85 +380,118 @@ CpuSetMemoryAttributes (
   EFI_STATUS                MpStatus;\r
   EFI_MP_SERVICES_PROTOCOL  *MpService;\r
   MTRR_SETTINGS             MtrrSettings;\r
-\r
-  if (!IsMtrrSupported ()) {\r
-    return EFI_UNSUPPORTED;\r
-  }\r
+  UINT64                    CacheAttributes;\r
+  UINT64                    MemoryAttributes;\r
+  MTRR_MEMORY_CACHE_TYPE    CurrentCacheType;\r
 \r
   //\r
   // If this function is called because GCD SetMemorySpaceAttributes () is called\r
-  // by RefreshGcdMemoryAttributes (), then we are just synchronzing GCD memory\r
+  // by RefreshGcdMemoryAttributes (), then we are just synchronizing GCD memory\r
   // map with MTRR values. So there is no need to modify MTRRs, just return immediately\r
   // to avoid unnecessary computing.\r
   //\r
   if (mIsFlushingGCD) {\r
-    DEBUG((EFI_D_INFO, "  Flushing GCD\n"));\r
+    DEBUG ((DEBUG_VERBOSE, "  Flushing GCD\n"));\r
     return EFI_SUCCESS;\r
   }\r
 \r
-  switch (Attributes) {\r
-  case EFI_MEMORY_UC:\r
-    CacheType = CacheUncacheable;\r
-    break;\r
+  //\r
+  // During memory attributes updating, new pages may be allocated to setup\r
+  // smaller granularity of page table. Page allocation action might then cause\r
+  // another calling of CpuSetMemoryAttributes() recursively, due to memory\r
+  // protection policy configured (such as PcdDxeNxMemoryProtectionPolicy).\r
+  // Since this driver will always protect memory used as page table by itself,\r
+  // there's no need to apply protection policy requested from memory service.\r
+  // So it's safe to just return EFI_SUCCESS if this time of calling is caused\r
+  // by page table memory allocation.\r
+  //\r
+  if (mIsAllocatingPageTable) {\r
+    DEBUG ((DEBUG_VERBOSE, "  Allocating page table memory\n"));\r
+    return EFI_SUCCESS;\r
+  }\r
 \r
-  case EFI_MEMORY_WC:\r
-    CacheType = CacheWriteCombining;\r
-    break;\r
+  CacheAttributes  = Attributes & EFI_CACHE_ATTRIBUTE_MASK;\r
+  MemoryAttributes = Attributes & EFI_MEMORY_ATTRIBUTE_MASK;\r
 \r
-  case EFI_MEMORY_WT:\r
-    CacheType = CacheWriteThrough;\r
-    break;\r
+  if (Attributes != (CacheAttributes | MemoryAttributes)) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
 \r
-  case EFI_MEMORY_WP:\r
-    CacheType = CacheWriteProtected;\r
-    break;\r
+  if (CacheAttributes != 0) {\r
+    if (!IsMtrrSupported ()) {\r
+      return EFI_UNSUPPORTED;\r
+    }\r
 \r
-  case EFI_MEMORY_WB:\r
-    CacheType = CacheWriteBack;\r
-    break;\r
+    switch (CacheAttributes) {\r
+      case EFI_MEMORY_UC:\r
+        CacheType = CacheUncacheable;\r
+        break;\r
 \r
-  case EFI_MEMORY_UCE:\r
-  case EFI_MEMORY_RP:\r
-  case EFI_MEMORY_XP:\r
-  case EFI_MEMORY_RUNTIME:\r
-    return EFI_UNSUPPORTED;\r
+      case EFI_MEMORY_WC:\r
+        CacheType = CacheWriteCombining;\r
+        break;\r
 \r
-  default:\r
-    return EFI_INVALID_PARAMETER;\r
-  }\r
-  //\r
-  // call MTRR libary function\r
-  //\r
-  Status = MtrrSetMemoryAttribute (\r
-             BaseAddress,\r
-             Length,\r
-             CacheType\r
-             );\r
+      case EFI_MEMORY_WT:\r
+        CacheType = CacheWriteThrough;\r
+        break;\r
 \r
-  if (!RETURN_ERROR (Status)) {\r
-    MpStatus = gBS->LocateProtocol (\r
-                      &gEfiMpServiceProtocolGuid,\r
-                      NULL,\r
-                      (VOID **)&MpService\r
-                      );\r
-    //\r
-    // Synchronize the update with all APs\r
-    //\r
-    if (!EFI_ERROR (MpStatus)) {\r
-      MtrrGetAllMtrrs (&MtrrSettings);\r
-      MpStatus = MpService->StartupAllAPs (\r
-                              MpService,          // This\r
-                              SetMtrrsFromBuffer, // Procedure\r
-                              TRUE,               // SingleThread\r
-                              NULL,               // WaitEvent\r
-                              0,                  // TimeoutInMicrosecsond\r
-                              &MtrrSettings,      // ProcedureArgument\r
-                              NULL                // FailedCpuList\r
-                              );\r
-      ASSERT (MpStatus == EFI_SUCCESS || MpStatus == EFI_NOT_STARTED);\r
+      case EFI_MEMORY_WP:\r
+        CacheType = CacheWriteProtected;\r
+        break;\r
+\r
+      case EFI_MEMORY_WB:\r
+        CacheType = CacheWriteBack;\r
+        break;\r
+\r
+      default:\r
+        return EFI_INVALID_PARAMETER;\r
+    }\r
+\r
+    CurrentCacheType = MtrrGetMemoryAttribute (BaseAddress);\r
+    if (CurrentCacheType != CacheType) {\r
+      //\r
+      // call MTRR library function\r
+      //\r
+      Status = MtrrSetMemoryAttribute (\r
+                 BaseAddress,\r
+                 Length,\r
+                 CacheType\r
+                 );\r
+\r
+      if (!RETURN_ERROR (Status)) {\r
+        MpStatus = gBS->LocateProtocol (\r
+                          &gEfiMpServiceProtocolGuid,\r
+                          NULL,\r
+                          (VOID **)&MpService\r
+                          );\r
+        //\r
+        // Synchronize the update with all APs\r
+        //\r
+        if (!EFI_ERROR (MpStatus)) {\r
+          MtrrGetAllMtrrs (&MtrrSettings);\r
+          MpStatus = MpService->StartupAllAPs (\r
+                                  MpService,          // This\r
+                                  SetMtrrsFromBuffer, // Procedure\r
+                                  FALSE,              // SingleThread\r
+                                  NULL,               // WaitEvent\r
+                                  0,                  // TimeoutInMicrosecsond\r
+                                  &MtrrSettings,      // ProcedureArgument\r
+                                  NULL                // FailedCpuList\r
+                                  );\r
+          ASSERT (MpStatus == EFI_SUCCESS || MpStatus == EFI_NOT_STARTED);\r
+        }\r
+      }\r
+\r
+      if (EFI_ERROR (Status)) {\r
+        return Status;\r
+      }\r
     }\r
   }\r
-  return (EFI_STATUS) Status;\r
+\r
+  //\r
+  // Set memory attribute by page table\r
+  //\r
+  return AssignMemoryPageAttributes (NULL, BaseAddress, Length, MemoryAttributes, NULL);\r
 }\r
 \r
 /**\r
@@ -445,22 +505,21 @@ InitializeMtrrMask (
   VOID\r
   )\r
 {\r
-  UINT32                              RegEax;\r
-  UINT8                               PhysicalAddressBits;\r
+  UINT32  RegEax;\r
+  UINT8   PhysicalAddressBits;\r
 \r
   AsmCpuid (0x80000000, &RegEax, NULL, NULL, NULL);\r
 \r
   if (RegEax >= 0x80000008) {\r
     AsmCpuid (0x80000008, &RegEax, NULL, NULL, NULL);\r
 \r
-    PhysicalAddressBits = (UINT8) RegEax;\r
-\r
-    mValidMtrrBitsMask    = LShiftU64 (1, PhysicalAddressBits) - 1;\r
-    mValidMtrrAddressMask = mValidMtrrBitsMask & 0xfffffffffffff000ULL;\r
+    PhysicalAddressBits = (UINT8)RegEax;\r
   } else {\r
-    mValidMtrrBitsMask    = MTRR_LIB_MSR_VALID_MASK;\r
-    mValidMtrrAddressMask = MTRR_LIB_CACHE_VALID_ADDRESS;\r
+    PhysicalAddressBits = 36;\r
   }\r
+\r
+  mValidMtrrBitsMask    = LShiftU64 (1, PhysicalAddressBits) - 1;\r
+  mValidMtrrAddressMask = mValidMtrrBitsMask & 0xfffffffffffff000ULL;\r
 }\r
 \r
 /**\r
@@ -475,22 +534,22 @@ InitializeMtrrMask (
 **/\r
 UINT64\r
 GetMemorySpaceAttributeFromMtrrType (\r
-  IN UINT8                MtrrAttributes\r
+  IN UINT8  MtrrAttributes\r
   )\r
 {\r
   switch (MtrrAttributes) {\r
-  case MTRR_CACHE_UNCACHEABLE:\r
-    return EFI_MEMORY_UC;\r
-  case MTRR_CACHE_WRITE_COMBINING:\r
-    return EFI_MEMORY_WC;\r
-  case MTRR_CACHE_WRITE_THROUGH:\r
-    return EFI_MEMORY_WT;\r
-  case MTRR_CACHE_WRITE_PROTECTED:\r
-    return EFI_MEMORY_WP;\r
-  case MTRR_CACHE_WRITE_BACK:\r
-    return EFI_MEMORY_WB;\r
-  default:\r
-    return 0;\r
+    case MTRR_CACHE_UNCACHEABLE:\r
+      return EFI_MEMORY_UC;\r
+    case MTRR_CACHE_WRITE_COMBINING:\r
+      return EFI_MEMORY_WC;\r
+    case MTRR_CACHE_WRITE_THROUGH:\r
+      return EFI_MEMORY_WT;\r
+    case MTRR_CACHE_WRITE_PROTECTED:\r
+      return EFI_MEMORY_WP;\r
+    case MTRR_CACHE_WRITE_BACK:\r
+      return EFI_MEMORY_WB;\r
+    default:\r
+      return 0;\r
   }\r
 }\r
 \r
@@ -514,29 +573,33 @@ GetMemorySpaceAttributeFromMtrrType (
 **/\r
 EFI_STATUS\r
 SearchGcdMemorySpaces (\r
-  IN EFI_GCD_MEMORY_SPACE_DESCRIPTOR     *MemorySpaceMap,\r
-  IN UINTN                               NumberOfDescriptors,\r
-  IN EFI_PHYSICAL_ADDRESS                BaseAddress,\r
-  IN UINT64                              Length,\r
-  OUT UINTN                              *StartIndex,\r
-  OUT UINTN                              *EndIndex\r
+  IN EFI_GCD_MEMORY_SPACE_DESCRIPTOR  *MemorySpaceMap,\r
+  IN UINTN                            NumberOfDescriptors,\r
+  IN EFI_PHYSICAL_ADDRESS             BaseAddress,\r
+  IN UINT64                           Length,\r
+  OUT UINTN                           *StartIndex,\r
+  OUT UINTN                           *EndIndex\r
   )\r
 {\r
-  UINTN           Index;\r
+  UINTN  Index;\r
 \r
   *StartIndex = 0;\r
   *EndIndex   = 0;\r
   for (Index = 0; Index < NumberOfDescriptors; Index++) {\r
-    if (BaseAddress >= MemorySpaceMap[Index].BaseAddress &&\r
-        BaseAddress < MemorySpaceMap[Index].BaseAddress + MemorySpaceMap[Index].Length) {\r
+    if ((BaseAddress >= MemorySpaceMap[Index].BaseAddress) &&\r
+        (BaseAddress < MemorySpaceMap[Index].BaseAddress + MemorySpaceMap[Index].Length))\r
+    {\r
       *StartIndex = Index;\r
     }\r
-    if (BaseAddress + Length - 1 >= MemorySpaceMap[Index].BaseAddress &&\r
-        BaseAddress + Length - 1 < MemorySpaceMap[Index].BaseAddress + MemorySpaceMap[Index].Length) {\r
+\r
+    if ((BaseAddress + Length - 1 >= MemorySpaceMap[Index].BaseAddress) &&\r
+        (BaseAddress + Length - 1 < MemorySpaceMap[Index].BaseAddress + MemorySpaceMap[Index].Length))\r
+    {\r
       *EndIndex = Index;\r
       return EFI_SUCCESS;\r
     }\r
   }\r
+\r
   return EFI_NOT_FOUND;\r
 }\r
 \r
@@ -558,11 +621,11 @@ SearchGcdMemorySpaces (
 **/\r
 EFI_STATUS\r
 SetGcdMemorySpaceAttributes (\r
-  IN EFI_GCD_MEMORY_SPACE_DESCRIPTOR     *MemorySpaceMap,\r
-  IN UINTN                               NumberOfDescriptors,\r
-  IN EFI_PHYSICAL_ADDRESS                BaseAddress,\r
-  IN UINT64                              Length,\r
-  IN UINT64                              Attributes\r
+  IN EFI_GCD_MEMORY_SPACE_DESCRIPTOR  *MemorySpaceMap,\r
+  IN UINTN                            NumberOfDescriptors,\r
+  IN EFI_PHYSICAL_ADDRESS             BaseAddress,\r
+  IN UINT64                           Length,\r
+  IN UINT64                           Attributes\r
   )\r
 {\r
   EFI_STATUS            Status;\r
@@ -594,6 +657,7 @@ SetGcdMemorySpaceAttributes (
     if (MemorySpaceMap[Index].GcdMemoryType == EfiGcdMemoryTypeNonExistent) {\r
       continue;\r
     }\r
+\r
     //\r
     // Calculate the start and end address of the overlapping range\r
     //\r
@@ -602,25 +666,26 @@ SetGcdMemorySpaceAttributes (
     } else {\r
       RegionStart = MemorySpaceMap[Index].BaseAddress;\r
     }\r
+\r
     if (BaseAddress + Length - 1 < MemorySpaceMap[Index].BaseAddress + MemorySpaceMap[Index].Length) {\r
       RegionLength = BaseAddress + Length - RegionStart;\r
     } else {\r
       RegionLength = MemorySpaceMap[Index].BaseAddress + MemorySpaceMap[Index].Length - RegionStart;\r
     }\r
+\r
     //\r
     // Set memory attributes according to MTRR attribute and the original attribute of descriptor\r
     //\r
     gDS->SetMemorySpaceAttributes (\r
            RegionStart,\r
            RegionLength,\r
-           (MemorySpaceMap[Index].Attributes & ~EFI_MEMORY_CACHETYPE_MASK) | (MemorySpaceMap[Index].Capabilities & Attributes)\r
+           (MemorySpaceMap[Index].Attributes & ~EFI_CACHE_ATTRIBUTE_MASK) | (MemorySpaceMap[Index].Capabilities & Attributes)\r
            );\r
   }\r
 \r
   return EFI_SUCCESS;\r
 }\r
 \r
-\r
 /**\r
   Refreshes the GCD Memory Space attributes according to MTRRs.\r
 \r
@@ -628,35 +693,30 @@ SetGcdMemorySpaceAttributes (
 \r
 **/\r
 VOID\r
-RefreshGcdMemoryAttributes (\r
+RefreshMemoryAttributesFromMtrr (\r
   VOID\r
   )\r
 {\r
-  EFI_STATUS                          Status;\r
-  UINTN                               Index;\r
-  UINTN                               SubIndex;\r
-  UINT64                              RegValue;\r
-  EFI_PHYSICAL_ADDRESS                BaseAddress;\r
-  UINT64                              Length;\r
-  UINT64                              Attributes;\r
-  UINT64                              CurrentAttributes;\r
-  UINT8                               MtrrType;\r
-  UINTN                               NumberOfDescriptors;\r
-  EFI_GCD_MEMORY_SPACE_DESCRIPTOR     *MemorySpaceMap;\r
-  UINT64                              DefaultAttributes;\r
-  VARIABLE_MTRR                       VariableMtrr[MTRR_NUMBER_OF_VARIABLE_MTRR];\r
-  MTRR_FIXED_SETTINGS                 MtrrFixedSettings;\r
-  UINT32                              FirmwareVariableMtrrCount;\r
-  UINT8                               DefaultMemoryType;\r
-\r
-  if (!IsMtrrSupported ()) {\r
-    return;\r
-  }\r
+  EFI_STATUS                       Status;\r
+  UINTN                            Index;\r
+  UINTN                            SubIndex;\r
+  UINT64                           RegValue;\r
+  EFI_PHYSICAL_ADDRESS             BaseAddress;\r
+  UINT64                           Length;\r
+  UINT64                           Attributes;\r
+  UINT64                           CurrentAttributes;\r
+  UINT8                            MtrrType;\r
+  UINTN                            NumberOfDescriptors;\r
+  EFI_GCD_MEMORY_SPACE_DESCRIPTOR  *MemorySpaceMap;\r
+  UINT64                           DefaultAttributes;\r
+  VARIABLE_MTRR                    VariableMtrr[MTRR_NUMBER_OF_VARIABLE_MTRR];\r
+  MTRR_FIXED_SETTINGS              MtrrFixedSettings;\r
+  UINT32                           FirmwareVariableMtrrCount;\r
+  UINT8                            DefaultMemoryType;\r
 \r
   FirmwareVariableMtrrCount = GetFirmwareVariableMtrrCount ();\r
   ASSERT (FirmwareVariableMtrrCount <= MTRR_NUMBER_OF_VARIABLE_MTRR);\r
 \r
-  mIsFlushingGCD = TRUE;\r
   MemorySpaceMap = NULL;\r
 \r
   //\r
@@ -682,7 +742,7 @@ RefreshGcdMemoryAttributes (
                   );\r
   ASSERT_EFI_ERROR (Status);\r
 \r
-  DefaultMemoryType = (UINT8) MtrrGetDefaultMemoryType ();\r
+  DefaultMemoryType = (UINT8)MtrrGetDefaultMemoryType ();\r
   DefaultAttributes = GetMemorySpaceAttributeFromMtrrType (DefaultMemoryType);\r
 \r
   //\r
@@ -692,10 +752,11 @@ RefreshGcdMemoryAttributes (
     if (MemorySpaceMap[Index].GcdMemoryType == EfiGcdMemoryTypeNonExistent) {\r
       continue;\r
     }\r
+\r
     gDS->SetMemorySpaceAttributes (\r
            MemorySpaceMap[Index].BaseAddress,\r
            MemorySpaceMap[Index].Length,\r
-           (MemorySpaceMap[Index].Attributes & ~EFI_MEMORY_CACHETYPE_MASK) |\r
+           (MemorySpaceMap[Index].Attributes & ~EFI_CACHE_ATTRIBUTE_MASK) |\r
            (MemorySpaceMap[Index].Capabilities & DefaultAttributes)\r
            );\r
   }\r
@@ -705,7 +766,8 @@ RefreshGcdMemoryAttributes (
   //\r
   for (Index = 0; Index < FirmwareVariableMtrrCount; Index++) {\r
     if (VariableMtrr[Index].Valid &&\r
-        VariableMtrr[Index].Type == MTRR_CACHE_WRITE_BACK) {\r
+        (VariableMtrr[Index].Type == MTRR_CACHE_WRITE_BACK))\r
+    {\r
       SetGcdMemorySpaceAttributes (\r
         MemorySpaceMap,\r
         NumberOfDescriptors,\r
@@ -721,9 +783,10 @@ RefreshGcdMemoryAttributes (
   //\r
   for (Index = 0; Index < FirmwareVariableMtrrCount; Index++) {\r
     if (VariableMtrr[Index].Valid &&\r
-        VariableMtrr[Index].Type != MTRR_CACHE_WRITE_BACK &&\r
-        VariableMtrr[Index].Type != MTRR_CACHE_UNCACHEABLE) {\r
-      Attributes = GetMemorySpaceAttributeFromMtrrType ((UINT8) VariableMtrr[Index].Type);\r
+        (VariableMtrr[Index].Type != MTRR_CACHE_WRITE_BACK) &&\r
+        (VariableMtrr[Index].Type != MTRR_CACHE_UNCACHEABLE))\r
+    {\r
+      Attributes = GetMemorySpaceAttributeFromMtrrType ((UINT8)VariableMtrr[Index].Type);\r
       SetGcdMemorySpaceAttributes (\r
         MemorySpaceMap,\r
         NumberOfDescriptors,\r
@@ -739,7 +802,8 @@ RefreshGcdMemoryAttributes (
   //\r
   for (Index = 0; Index < FirmwareVariableMtrrCount; Index++) {\r
     if (VariableMtrr[Index].Valid &&\r
-        VariableMtrr[Index].Type == MTRR_CACHE_UNCACHEABLE) {\r
+        (VariableMtrr[Index].Type == MTRR_CACHE_UNCACHEABLE))\r
+    {\r
       SetGcdMemorySpaceAttributes (\r
         MemorySpaceMap,\r
         NumberOfDescriptors,\r
@@ -763,7 +827,7 @@ RefreshGcdMemoryAttributes (
     // Check for continuous fixed MTRR sections\r
     //\r
     for (SubIndex = 0; SubIndex < 8; SubIndex++) {\r
-      MtrrType = (UINT8) RShiftU64 (RegValue, SubIndex * 8);\r
+      MtrrType          = (UINT8)RShiftU64 (RegValue, SubIndex * 8);\r
       CurrentAttributes = GetMemorySpaceAttributeFromMtrrType (MtrrType);\r
       if (Length == 0) {\r
         //\r
@@ -772,7 +836,7 @@ RefreshGcdMemoryAttributes (
         Attributes = CurrentAttributes;\r
       } else {\r
         //\r
-        // If fixed MTRR attribute changed, then set memory attribute for previous atrribute\r
+        // If fixed MTRR attribute changed, then set memory attribute for previous attribute\r
         //\r
         if (CurrentAttributes != Attributes) {\r
           SetGcdMemorySpaceAttributes (\r
@@ -783,13 +847,15 @@ RefreshGcdMemoryAttributes (
             Attributes\r
             );\r
           BaseAddress = mFixedMtrrTable[Index].BaseAddress + mFixedMtrrTable[Index].Length * SubIndex;\r
-          Length = 0;\r
-          Attributes = CurrentAttributes;\r
+          Length      = 0;\r
+          Attributes  = CurrentAttributes;\r
         }\r
       }\r
+\r
       Length += mFixedMtrrTable[Index].Length;\r
     }\r
   }\r
+\r
   //\r
   // Handle the last fixed MTRR region\r
   //\r
@@ -807,6 +873,46 @@ RefreshGcdMemoryAttributes (
   if (MemorySpaceMap != NULL) {\r
     FreePool (MemorySpaceMap);\r
   }\r
+}\r
+\r
+/**\r
+ Check if paging is enabled or not.\r
+**/\r
+BOOLEAN\r
+IsPagingAndPageAddressExtensionsEnabled (\r
+  VOID\r
+  )\r
+{\r
+  IA32_CR0  Cr0;\r
+  IA32_CR4  Cr4;\r
+\r
+  Cr0.UintN = AsmReadCr0 ();\r
+  Cr4.UintN = AsmReadCr4 ();\r
+\r
+  return ((Cr0.Bits.PG != 0) && (Cr4.Bits.PAE != 0));\r
+}\r
+\r
+/**\r
+  Refreshes the GCD Memory Space attributes according to MTRRs and Paging.\r
+\r
+  This function refreshes the GCD Memory Space attributes according to MTRRs\r
+  and page tables.\r
+\r
+**/\r
+VOID\r
+RefreshGcdMemoryAttributes (\r
+  VOID\r
+  )\r
+{\r
+  mIsFlushingGCD = TRUE;\r
+\r
+  if (IsMtrrSupported ()) {\r
+    RefreshMemoryAttributesFromMtrr ();\r
+  }\r
+\r
+  if (IsPagingAndPageAddressExtensionsEnabled ()) {\r
+    RefreshGcdMemoryAttributesFromPaging ();\r
+  }\r
 \r
   mIsFlushingGCD = FALSE;\r
 }\r
@@ -820,20 +926,41 @@ InitInterruptDescriptorTable (
   VOID\r
   )\r
 {\r
-  EFI_STATUS                     Status;\r
-  EFI_VECTOR_HANDOFF_INFO        *VectorInfoList;\r
-  EFI_VECTOR_HANDOFF_INFO        *VectorInfo;\r
+  EFI_STATUS                Status;\r
+  EFI_VECTOR_HANDOFF_INFO   *VectorInfoList;\r
+  EFI_VECTOR_HANDOFF_INFO   *VectorInfo;\r
+  IA32_IDT_GATE_DESCRIPTOR  *IdtTable;\r
+  IA32_DESCRIPTOR           IdtDescriptor;\r
+  UINTN                     IdtEntryCount;\r
 \r
   VectorInfo = NULL;\r
-  Status = EfiGetSystemConfigurationTable (&gEfiVectorHandoffTableGuid, (VOID **) &VectorInfoList);\r
-  if (Status == EFI_SUCCESS && VectorInfoList != NULL) {\r
+  Status     = EfiGetSystemConfigurationTable (&gEfiVectorHandoffTableGuid, (VOID **)&VectorInfoList);\r
+  if ((Status == EFI_SUCCESS) && (VectorInfoList != NULL)) {\r
     VectorInfo = VectorInfoList;\r
   }\r
-  Status = InitializeCpuInterruptHandlers (VectorInfo);\r
+\r
+  AsmReadIdtr (&IdtDescriptor);\r
+  IdtEntryCount = (IdtDescriptor.Limit + 1) / sizeof (IA32_IDT_GATE_DESCRIPTOR);\r
+  if (IdtEntryCount < CPU_INTERRUPT_NUM) {\r
+    //\r
+    // Increase Interrupt Descriptor Table and Copy the old IDT table in\r
+    //\r
+    IdtTable = AllocateZeroPool (sizeof (IA32_IDT_GATE_DESCRIPTOR) * CPU_INTERRUPT_NUM);\r
+    ASSERT (IdtTable != NULL);\r
+    CopyMem (IdtTable, (VOID *)IdtDescriptor.Base, sizeof (IA32_IDT_GATE_DESCRIPTOR) * IdtEntryCount);\r
+\r
+    //\r
+    // Load Interrupt Descriptor Table\r
+    //\r
+    IdtDescriptor.Base  = (UINTN)IdtTable;\r
+    IdtDescriptor.Limit = (UINT16)(sizeof (IA32_IDT_GATE_DESCRIPTOR) * CPU_INTERRUPT_NUM - 1);\r
+    AsmWriteIdtr (&IdtDescriptor);\r
+  }\r
+\r
+  Status = InitializeCpuExceptionHandlers (VectorInfo);\r
   ASSERT_EFI_ERROR (Status);\r
 }\r
 \r
-\r
 /**\r
   Callback function for idle events.\r
 \r
@@ -845,13 +972,236 @@ InitInterruptDescriptorTable (
 VOID\r
 EFIAPI\r
 IdleLoopEventCallback (\r
-  IN EFI_EVENT                Event,\r
-  IN VOID                     *Context\r
+  IN EFI_EVENT  Event,\r
+  IN VOID       *Context\r
   )\r
 {\r
   CpuSleep ();\r
 }\r
 \r
+/**\r
+  Ensure the compatibility of a memory space descriptor with the MMIO aperture.\r
+\r
+  The memory space descriptor can come from the GCD memory space map, or it can\r
+  represent a gap between two neighboring memory space descriptors. In the\r
+  latter case, the GcdMemoryType field is expected to be\r
+  EfiGcdMemoryTypeNonExistent.\r
+\r
+  If the memory space descriptor already has type\r
+  EfiGcdMemoryTypeMemoryMappedIo, and its capabilities are a superset of the\r
+  required capabilities, then no action is taken -- it is by definition\r
+  compatible with the aperture.\r
+\r
+  Otherwise, the intersection of the memory space descriptor is calculated with\r
+  the aperture. If the intersection is the empty set (no overlap), no action is\r
+  taken; the memory space descriptor is compatible with the aperture.\r
+\r
+  Otherwise, the type of the descriptor is investigated again. If the type is\r
+  EfiGcdMemoryTypeNonExistent (representing a gap, or a genuine descriptor with\r
+  such a type), then an attempt is made to add the intersection as MMIO space\r
+  to the GCD memory space map, with the specified capabilities. This ensures\r
+  continuity for the aperture, and the descriptor is deemed compatible with the\r
+  aperture.\r
+\r
+  Otherwise, the memory space descriptor is incompatible with the MMIO\r
+  aperture.\r
+\r
+  @param[in] Base         Base address of the aperture.\r
+  @param[in] Length       Length of the aperture.\r
+  @param[in] Capabilities Capabilities required by the aperture.\r
+  @param[in] Descriptor   The descriptor to ensure compatibility with the\r
+                          aperture for.\r
+\r
+  @retval EFI_SUCCESS            The descriptor is compatible. The GCD memory\r
+                                 space map may have been updated, for\r
+                                 continuity within the aperture.\r
+  @retval EFI_INVALID_PARAMETER  The descriptor is incompatible.\r
+  @return                        Error codes from gDS->AddMemorySpace().\r
+**/\r
+EFI_STATUS\r
+IntersectMemoryDescriptor (\r
+  IN  UINT64                                 Base,\r
+  IN  UINT64                                 Length,\r
+  IN  UINT64                                 Capabilities,\r
+  IN  CONST EFI_GCD_MEMORY_SPACE_DESCRIPTOR  *Descriptor\r
+  )\r
+{\r
+  UINT64      IntersectionBase;\r
+  UINT64      IntersectionEnd;\r
+  EFI_STATUS  Status;\r
+\r
+  if ((Descriptor->GcdMemoryType == EfiGcdMemoryTypeMemoryMappedIo) &&\r
+      ((Descriptor->Capabilities & Capabilities) == Capabilities))\r
+  {\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  IntersectionBase = MAX (Base, Descriptor->BaseAddress);\r
+  IntersectionEnd  = MIN (\r
+                       Base + Length,\r
+                       Descriptor->BaseAddress + Descriptor->Length\r
+                       );\r
+  if (IntersectionBase >= IntersectionEnd) {\r
+    //\r
+    // The descriptor and the aperture don't overlap.\r
+    //\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  if (Descriptor->GcdMemoryType == EfiGcdMemoryTypeNonExistent) {\r
+    Status = gDS->AddMemorySpace (\r
+                    EfiGcdMemoryTypeMemoryMappedIo,\r
+                    IntersectionBase,\r
+                    IntersectionEnd - IntersectionBase,\r
+                    Capabilities\r
+                    );\r
+\r
+    DEBUG ((\r
+      EFI_ERROR (Status) ? DEBUG_ERROR : DEBUG_VERBOSE,\r
+      "%a: %a: add [%Lx, %Lx): %r\n",\r
+      gEfiCallerBaseName,\r
+      __FUNCTION__,\r
+      IntersectionBase,\r
+      IntersectionEnd,\r
+      Status\r
+      ));\r
+    return Status;\r
+  }\r
+\r
+  DEBUG ((\r
+    DEBUG_ERROR,\r
+    "%a: %a: desc [%Lx, %Lx) type %u cap %Lx conflicts "\r
+    "with aperture [%Lx, %Lx) cap %Lx\n",\r
+    gEfiCallerBaseName,\r
+    __FUNCTION__,\r
+    Descriptor->BaseAddress,\r
+    Descriptor->BaseAddress + Descriptor->Length,\r
+    (UINT32)Descriptor->GcdMemoryType,\r
+    Descriptor->Capabilities,\r
+    Base,\r
+    Base + Length,\r
+    Capabilities\r
+    ));\r
+  return EFI_INVALID_PARAMETER;\r
+}\r
+\r
+/**\r
+  Add MMIO space to GCD.\r
+  The routine checks the GCD database and only adds those which are\r
+  not added in the specified range to GCD.\r
+\r
+  @param Base         Base address of the MMIO space.\r
+  @param Length       Length of the MMIO space.\r
+  @param Capabilities Capabilities of the MMIO space.\r
+\r
+  @retval EFI_SUCCESS The MMIO space was added successfully.\r
+**/\r
+EFI_STATUS\r
+AddMemoryMappedIoSpace (\r
+  IN  UINT64  Base,\r
+  IN  UINT64  Length,\r
+  IN  UINT64  Capabilities\r
+  )\r
+{\r
+  EFI_STATUS                       Status;\r
+  UINTN                            Index;\r
+  UINTN                            NumberOfDescriptors;\r
+  EFI_GCD_MEMORY_SPACE_DESCRIPTOR  *MemorySpaceMap;\r
+\r
+  Status = gDS->GetMemorySpaceMap (&NumberOfDescriptors, &MemorySpaceMap);\r
+  if (EFI_ERROR (Status)) {\r
+    DEBUG ((\r
+      DEBUG_ERROR,\r
+      "%a: %a: GetMemorySpaceMap(): %r\n",\r
+      gEfiCallerBaseName,\r
+      __FUNCTION__,\r
+      Status\r
+      ));\r
+    return Status;\r
+  }\r
+\r
+  for (Index = 0; Index < NumberOfDescriptors; Index++) {\r
+    Status = IntersectMemoryDescriptor (\r
+               Base,\r
+               Length,\r
+               Capabilities,\r
+               &MemorySpaceMap[Index]\r
+               );\r
+    if (EFI_ERROR (Status)) {\r
+      goto FreeMemorySpaceMap;\r
+    }\r
+  }\r
+\r
+  DEBUG_CODE_BEGIN ();\r
+  //\r
+  // Make sure there are adjacent descriptors covering [Base, Base + Length).\r
+  // It is possible that they have not been merged; merging can be prevented\r
+  // by allocation and different capabilities.\r
+  //\r
+  UINT64                           CheckBase;\r
+  EFI_STATUS                       CheckStatus;\r
+  EFI_GCD_MEMORY_SPACE_DESCRIPTOR  Descriptor;\r
+\r
+  for (CheckBase = Base;\r
+       CheckBase < Base + Length;\r
+       CheckBase = Descriptor.BaseAddress + Descriptor.Length)\r
+  {\r
+    CheckStatus = gDS->GetMemorySpaceDescriptor (CheckBase, &Descriptor);\r
+    ASSERT_EFI_ERROR (CheckStatus);\r
+    ASSERT (Descriptor.GcdMemoryType == EfiGcdMemoryTypeMemoryMappedIo);\r
+    ASSERT ((Descriptor.Capabilities & Capabilities) == Capabilities);\r
+  }\r
+\r
+  DEBUG_CODE_END ();\r
+\r
+FreeMemorySpaceMap:\r
+  FreePool (MemorySpaceMap);\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Add and allocate CPU local APIC memory mapped space.\r
+\r
+  @param[in]ImageHandle     Image handle this driver.\r
+\r
+**/\r
+VOID\r
+AddLocalApicMemorySpace (\r
+  IN EFI_HANDLE  ImageHandle\r
+  )\r
+{\r
+  EFI_STATUS            Status;\r
+  EFI_PHYSICAL_ADDRESS  BaseAddress;\r
+\r
+  BaseAddress = (EFI_PHYSICAL_ADDRESS)GetLocalApicBaseAddress ();\r
+  Status      = AddMemoryMappedIoSpace (BaseAddress, SIZE_4KB, EFI_MEMORY_UC);\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+  //\r
+  // Try to allocate APIC memory mapped space, does not check return\r
+  // status because it may be allocated by other driver, or DXE Core if\r
+  // this range is built into Memory Allocation HOB.\r
+  //\r
+  Status = gDS->AllocateMemorySpace (\r
+                  EfiGcdAllocateAddress,\r
+                  EfiGcdMemoryTypeMemoryMappedIo,\r
+                  0,\r
+                  SIZE_4KB,\r
+                  &BaseAddress,\r
+                  ImageHandle,\r
+                  NULL\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    DEBUG ((\r
+      DEBUG_INFO,\r
+      "%a: %a: AllocateMemorySpace() Status - %r\n",\r
+      gEfiCallerBaseName,\r
+      __FUNCTION__,\r
+      Status\r
+      ));\r
+  }\r
+}\r
 \r
 /**\r
   Initialize the state information for the CPU Architectural Protocol.\r
@@ -867,13 +1217,15 @@ IdleLoopEventCallback (
 EFI_STATUS\r
 EFIAPI\r
 InitializeCpu (\r
-  IN EFI_HANDLE                            ImageHandle,\r
-  IN EFI_SYSTEM_TABLE                      *SystemTable\r
+  IN EFI_HANDLE        ImageHandle,\r
+  IN EFI_SYSTEM_TABLE  *SystemTable\r
   )\r
 {\r
   EFI_STATUS  Status;\r
   EFI_EVENT   IdleLoopEvent;\r
 \r
+  InitializePageTableLib ();\r
+\r
   InitializeFloatingPointUnits ();\r
 \r
   //\r
@@ -891,17 +1243,13 @@ InitializeCpu (
   //\r
   InitInterruptDescriptorTable ();\r
 \r
-  //\r
-  // Enable the local APIC for Virtual Wire Mode.\r
-  //\r
-  ProgramVirtualWireMode ();\r
-\r
   //\r
   // Install CPU Architectural Protocol\r
   //\r
   Status = gBS->InstallMultipleProtocolInterfaces (\r
                   &mCpuHandle,\r
-                  &gEfiCpuArchProtocolGuid, &gCpu,\r
+                  &gEfiCpuArchProtocolGuid,\r
+                  &gCpu,\r
                   NULL\r
                   );\r
   ASSERT_EFI_ERROR (Status);\r
@@ -911,6 +1259,11 @@ InitializeCpu (
   //\r
   RefreshGcdMemoryAttributes ();\r
 \r
+  //\r
+  // Add and allocate local APIC memory mapped space\r
+  //\r
+  AddLocalApicMemorySpace (ImageHandle);\r
+\r
   //\r
   // Setup a callback for idle events\r
   //\r
@@ -928,4 +1281,3 @@ InitializeCpu (
 \r
   return Status;\r
 }\r
-\r