]> 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 17513e758fc93f159f3c1fefe15d85296aa5ba1a..a6a91507f6066fbce11911530b083abe9904a658 100644 (file)
@@ -1,92 +1,86 @@
 /** @file\r
-  CPU DXE Module.\r
+  CPU DXE Module to produce CPU ARCH Protocol.\r
 \r
-  Copyright (c) 2008 - 2012, 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
-IA32_IDT_GATE_DESCRIPTOR  gIdtTable[INTERRUPT_VECTOR_NUMBER] = { 0 };\r
-\r
-EFI_CPU_INTERRUPT_HANDLER ExternalVectorTable[0x100];\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
-IA32_IDT_GATE_DESCRIPTOR  *mOrigIdtEntry        = NULL;\r
-UINT16                    mOrigIdtEntryCount    = 0;\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
@@ -100,259 +94,10 @@ EFI_CPU_ARCH_PROTOCOL  gCpu = {
   4                           // DmaBufferAlignment\r
 };\r
 \r
-//\r
-// Error code flag indicating whether or not an error code will be\r
-// pushed on the stack if an exception occurs.\r
-//\r
-// 1 means an error code will be pushed, otherwise 0\r
-//\r
-// bit 0 - exception 0\r
-// bit 1 - exception 1\r
-// etc.\r
-//\r
-UINT32 mErrorCodeFlag = 0x00027d00;\r
-\r
-//\r
-// Local function prototypes\r
-//\r
-\r
-/**\r
-  Set Interrupt Descriptor Table Handler Address.\r
-\r
-  @param Index        The Index of the interrupt descriptor table handle.\r
-  @param Handler      Handler address.\r
-\r
-**/\r
-VOID\r
-SetInterruptDescriptorTableHandlerAddress (\r
-  IN UINTN Index,\r
-  IN VOID  *Handler  OPTIONAL\r
-  );\r
-\r
 //\r
 // CPU Arch Protocol Functions\r
 //\r
 \r
-\r
-/**\r
-  Common exception handler.\r
-\r
-  @param  InterruptType  Exception type\r
-  @param  SystemContext  EFI_SYSTEM_CONTEXT\r
-\r
-**/\r
-VOID\r
-EFIAPI\r
-CommonExceptionHandler (\r
-  IN EFI_EXCEPTION_TYPE   InterruptType,\r
-  IN EFI_SYSTEM_CONTEXT   SystemContext\r
-  )\r
-{\r
-#if defined (MDE_CPU_IA32)\r
-  DEBUG ((\r
-    EFI_D_ERROR,\r
-    "!!!! IA32 Exception Type - %08x !!!!\n",\r
-    InterruptType\r
-    ));\r
-  if ((mErrorCodeFlag & (1 << InterruptType)) != 0) {\r
-    DEBUG ((\r
-      EFI_D_ERROR,\r
-      "ExceptionData - %08x\n",\r
-      SystemContext.SystemContextIa32->ExceptionData\r
-      ));\r
-  }\r
-  DEBUG ((\r
-    EFI_D_ERROR,\r
-    "CS  - %04x,     EIP - %08x, EFL - %08x, SS  - %04x\n",\r
-    SystemContext.SystemContextIa32->Cs,\r
-    SystemContext.SystemContextIa32->Eip,\r
-    SystemContext.SystemContextIa32->Eflags,\r
-    SystemContext.SystemContextIa32->Ss\r
-    ));\r
-  DEBUG ((\r
-    EFI_D_ERROR,\r
-    "DS  - %04x,     ES  - %04x,     FS  - %04x,     GS  - %04x\n",\r
-    SystemContext.SystemContextIa32->Ds,\r
-    SystemContext.SystemContextIa32->Es,\r
-    SystemContext.SystemContextIa32->Fs,\r
-    SystemContext.SystemContextIa32->Gs\r
-    ));\r
-  DEBUG ((\r
-    EFI_D_ERROR,\r
-    "EAX - %08x, EBX - %08x, ECX - %08x, EDX - %08x\n",\r
-    SystemContext.SystemContextIa32->Eax,\r
-    SystemContext.SystemContextIa32->Ebx,\r
-    SystemContext.SystemContextIa32->Ecx,\r
-    SystemContext.SystemContextIa32->Edx\r
-    ));\r
-  DEBUG ((\r
-    EFI_D_ERROR,\r
-    "ESP - %08x, EBP - %08x, ESI - %08x, EDI - %08x\n",\r
-    SystemContext.SystemContextIa32->Esp,\r
-    SystemContext.SystemContextIa32->Ebp,\r
-    SystemContext.SystemContextIa32->Esi,\r
-    SystemContext.SystemContextIa32->Edi\r
-    ));\r
-  DEBUG ((\r
-    EFI_D_ERROR,\r
-    "GDT - %08x  LIM - %04x,     IDT - %08x  LIM - %04x\n",\r
-    SystemContext.SystemContextIa32->Gdtr[0],\r
-    SystemContext.SystemContextIa32->Gdtr[1],\r
-    SystemContext.SystemContextIa32->Idtr[0],\r
-    SystemContext.SystemContextIa32->Idtr[1]\r
-    ));\r
-  DEBUG ((\r
-    EFI_D_ERROR,\r
-    "LDT - %08x, TR  - %08x\n",\r
-    SystemContext.SystemContextIa32->Ldtr,\r
-    SystemContext.SystemContextIa32->Tr\r
-    ));\r
-  DEBUG ((\r
-    EFI_D_ERROR,\r
-    "CR0 - %08x, CR2 - %08x, CR3 - %08x, CR4 - %08x\n",\r
-    SystemContext.SystemContextIa32->Cr0,\r
-    SystemContext.SystemContextIa32->Cr2,\r
-    SystemContext.SystemContextIa32->Cr3,\r
-    SystemContext.SystemContextIa32->Cr4\r
-    ));\r
-  DEBUG ((\r
-    EFI_D_ERROR,\r
-    "DR0 - %08x, DR1 - %08x, DR2 - %08x, DR3 - %08x\n",\r
-    SystemContext.SystemContextIa32->Dr0,\r
-    SystemContext.SystemContextIa32->Dr1,\r
-    SystemContext.SystemContextIa32->Dr2,\r
-    SystemContext.SystemContextIa32->Dr3\r
-    ));\r
-  DEBUG ((\r
-    EFI_D_ERROR,\r
-    "DR6 - %08x, DR7 - %08x\n",\r
-    SystemContext.SystemContextIa32->Dr6,\r
-    SystemContext.SystemContextIa32->Dr7\r
-    ));\r
-#elif defined (MDE_CPU_X64)\r
-  DEBUG ((\r
-    EFI_D_ERROR,\r
-    "!!!! X64 Exception Type - %016lx !!!!\n",\r
-    (UINT64)InterruptType\r
-    ));\r
-  if ((mErrorCodeFlag & (1 << InterruptType)) != 0) {\r
-    DEBUG ((\r
-      EFI_D_ERROR,\r
-      "ExceptionData - %016lx\n",\r
-      SystemContext.SystemContextX64->ExceptionData\r
-      ));\r
-  }\r
-  DEBUG ((\r
-    EFI_D_ERROR,\r
-    "RIP - %016lx, RFL - %016lx\n",\r
-    SystemContext.SystemContextX64->Rip,\r
-    SystemContext.SystemContextX64->Rflags\r
-    ));\r
-  DEBUG ((\r
-    EFI_D_ERROR,\r
-    "RAX - %016lx, RCX - %016lx, RDX - %016lx\n",\r
-    SystemContext.SystemContextX64->Rax,\r
-    SystemContext.SystemContextX64->Rcx,\r
-    SystemContext.SystemContextX64->Rdx\r
-    ));\r
-  DEBUG ((\r
-    EFI_D_ERROR,\r
-    "RBX - %016lx, RSP - %016lx, RBP - %016lx\n",\r
-    SystemContext.SystemContextX64->Rbx,\r
-    SystemContext.SystemContextX64->Rsp,\r
-    SystemContext.SystemContextX64->Rbp\r
-    ));\r
-  DEBUG ((\r
-    EFI_D_ERROR,\r
-    "RSI - %016lx, RDI - %016lx\n",\r
-    SystemContext.SystemContextX64->Rsi,\r
-    SystemContext.SystemContextX64->Rdi\r
-    ));\r
-  DEBUG ((\r
-    EFI_D_ERROR,\r
-    "R8  - %016lx, R9  - %016lx, R10 - %016lx\n",\r
-    SystemContext.SystemContextX64->R8,\r
-    SystemContext.SystemContextX64->R9,\r
-    SystemContext.SystemContextX64->R10\r
-    ));\r
-  DEBUG ((\r
-    EFI_D_ERROR,\r
-    "R11 - %016lx, R12 - %016lx, R13 - %016lx\n",\r
-    SystemContext.SystemContextX64->R11,\r
-    SystemContext.SystemContextX64->R12,\r
-    SystemContext.SystemContextX64->R13\r
-    ));\r
-  DEBUG ((\r
-    EFI_D_ERROR,\r
-    "R14 - %016lx, R15 - %016lx\n",\r
-    SystemContext.SystemContextX64->R14,\r
-    SystemContext.SystemContextX64->R15\r
-    ));\r
-  DEBUG ((\r
-    EFI_D_ERROR,\r
-    "CS  - %04lx, DS  - %04lx, ES  - %04lx, FS  - %04lx, GS  - %04lx, SS  - %04lx\n",\r
-    SystemContext.SystemContextX64->Cs,\r
-    SystemContext.SystemContextX64->Ds,\r
-    SystemContext.SystemContextX64->Es,\r
-    SystemContext.SystemContextX64->Fs,\r
-    SystemContext.SystemContextX64->Gs,\r
-    SystemContext.SystemContextX64->Ss\r
-    ));\r
-  DEBUG ((\r
-    EFI_D_ERROR,\r
-    "GDT - %016lx; %04lx,                   IDT - %016lx; %04lx\n",\r
-    SystemContext.SystemContextX64->Gdtr[0],\r
-    SystemContext.SystemContextX64->Gdtr[1],\r
-    SystemContext.SystemContextX64->Idtr[0],\r
-    SystemContext.SystemContextX64->Idtr[1]\r
-    ));\r
-  DEBUG ((\r
-    EFI_D_ERROR,\r
-    "LDT - %016lx, TR  - %016lx\n",\r
-    SystemContext.SystemContextX64->Ldtr,\r
-    SystemContext.SystemContextX64->Tr\r
-    ));\r
-  DEBUG ((\r
-    EFI_D_ERROR,\r
-    "CR0 - %016lx, CR2 - %016lx, CR3 - %016lx\n",\r
-    SystemContext.SystemContextX64->Cr0,\r
-    SystemContext.SystemContextX64->Cr2,\r
-    SystemContext.SystemContextX64->Cr3\r
-    ));\r
-  DEBUG ((\r
-    EFI_D_ERROR,\r
-    "CR4 - %016lx, CR8 - %016lx\n",\r
-    SystemContext.SystemContextX64->Cr4,\r
-    SystemContext.SystemContextX64->Cr8\r
-    ));\r
-  DEBUG ((\r
-    EFI_D_ERROR,\r
-    "DR0 - %016lx, DR1 - %016lx, DR2 - %016lx\n",\r
-    SystemContext.SystemContextX64->Dr0,\r
-    SystemContext.SystemContextX64->Dr1,\r
-    SystemContext.SystemContextX64->Dr2\r
-    ));\r
-  DEBUG ((\r
-    EFI_D_ERROR,\r
-    "DR3 - %016lx, DR6 - %016lx, DR7 - %016lx\n",\r
-    SystemContext.SystemContextX64->Dr3,\r
-    SystemContext.SystemContextX64->Dr6,\r
-    SystemContext.SystemContextX64->Dr7\r
-    ));\r
-#else\r
-#error CPU type not supported for exception information dump!\r
-#endif\r
-\r
-  //\r
-  // Hang the system with CpuSleep so the processor will enter a lower power\r
-  // state.\r
-  //\r
-  while (TRUE) {\r
-    CpuSleep ();\r
-  };\r
-}\r
-\r
-\r
 /**\r
   Flush CPU data cache. If the instruction cache is fully coherent\r
   with all DMA operations then function can just return EFI_SUCCESS.\r
@@ -371,10 +116,10 @@ CommonExceptionHandler (
 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
@@ -388,7 +133,6 @@ CpuFlushCpuDataCache (
   }\r
 }\r
 \r
-\r
 /**\r
   Enables CPU interrupts.\r
 \r
@@ -401,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
@@ -410,7 +154,6 @@ CpuEnableInterrupt (
   return EFI_SUCCESS;\r
 }\r
 \r
-\r
 /**\r
   Disables CPU interrupts.\r
 \r
@@ -423,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
@@ -432,7 +175,6 @@ CpuDisableInterrupt (
   return EFI_SUCCESS;\r
 }\r
 \r
-\r
 /**\r
   Return the state of interrupts.\r
 \r
@@ -446,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
@@ -458,7 +200,6 @@ CpuGetInterruptState (
   return EFI_SUCCESS;\r
 }\r
 \r
-\r
 /**\r
   Generates an INIT to the CPU.\r
 \r
@@ -474,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
@@ -505,37 +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
-  if (InterruptType < 0 || InterruptType > 0xff) {\r
-    return EFI_UNSUPPORTED;\r
-  }\r
-\r
-  if (InterruptHandler == NULL && ExternalVectorTable[InterruptType] == NULL) {\r
-    return EFI_INVALID_PARAMETER;\r
-  }\r
-\r
-  if (InterruptHandler != NULL && ExternalVectorTable[InterruptType] != NULL) {\r
-    return EFI_ALREADY_STARTED;\r
-  }\r
-\r
-  if (InterruptHandler != NULL) {\r
-    SetInterruptDescriptorTableHandlerAddress ((UINTN)InterruptType, NULL);\r
-  } else {\r
-    //\r
-    // Restore the original IDT handler address if InterruptHandler is NULL.\r
-    //\r
-    RestoreInterruptDescriptorTableHandlerAddress ((UINTN)InterruptType);\r
-  }\r
-\r
-  ExternalVectorTable[InterruptType] = InterruptHandler;\r
-  return EFI_SUCCESS;\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
@@ -562,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
@@ -579,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
@@ -617,70 +369,129 @@ 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
   MTRR_MEMORY_CACHE_TYPE    CacheType;\r
-\r
-  if (!IsMtrrSupported ()) {\r
-    return EFI_UNSUPPORTED;\r
-  }\r
+  EFI_STATUS                MpStatus;\r
+  EFI_MP_SERVICES_PROTOCOL  *MpService;\r
+  MTRR_SETTINGS             MtrrSettings;\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_ERROR, "  Flushing GCD\n"));\r
-      return EFI_SUCCESS;\r
+    DEBUG ((DEBUG_VERBOSE, "  Flushing GCD\n"));\r
+    return EFI_SUCCESS;\r
+  }\r
+\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
+  CacheAttributes  = Attributes & EFI_CACHE_ATTRIBUTE_MASK;\r
+  MemoryAttributes = Attributes & EFI_MEMORY_ATTRIBUTE_MASK;\r
+\r
+  if (Attributes != (CacheAttributes | MemoryAttributes)) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  if (CacheAttributes != 0) {\r
+    if (!IsMtrrSupported ()) {\r
+      return EFI_UNSUPPORTED;\r
     }\r
 \r
-  switch (Attributes) {\r
-  case EFI_MEMORY_UC:\r
-    CacheType = CacheUncacheable;\r
-    break;\r
+    switch (CacheAttributes) {\r
+      case EFI_MEMORY_UC:\r
+        CacheType = CacheUncacheable;\r
+        break;\r
 \r
-  case EFI_MEMORY_WC:\r
-    CacheType = CacheWriteCombining;\r
-    break;\r
+      case EFI_MEMORY_WC:\r
+        CacheType = CacheWriteCombining;\r
+        break;\r
 \r
-  case EFI_MEMORY_WT:\r
-    CacheType = CacheWriteThrough;\r
-    break;\r
+      case EFI_MEMORY_WT:\r
+        CacheType = CacheWriteThrough;\r
+        break;\r
 \r
-  case EFI_MEMORY_WP:\r
-    CacheType = CacheWriteProtected;\r
-    break;\r
+      case EFI_MEMORY_WP:\r
+        CacheType = CacheWriteProtected;\r
+        break;\r
 \r
-  case EFI_MEMORY_WB:\r
-    CacheType = CacheWriteBack;\r
-    break;\r
+      case EFI_MEMORY_WB:\r
+        CacheType = CacheWriteBack;\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
+      default:\r
+        return EFI_INVALID_PARAMETER;\r
+    }\r
 \r
-  default:\r
-    return EFI_INVALID_PARAMETER;\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
+\r
   //\r
-  // call MTRR libary function\r
+  // Set memory attribute by page table\r
   //\r
-  Status = MtrrSetMemoryAttribute (\r
-             BaseAddress,\r
-             Length,\r
-             CacheType\r
-             );\r
-\r
-  return (EFI_STATUS) Status;\r
+  return AssignMemoryPageAttributes (NULL, BaseAddress, Length, MemoryAttributes, NULL);\r
 }\r
 \r
 /**\r
@@ -694,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
@@ -724,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
@@ -763,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
@@ -807,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
@@ -843,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
@@ -851,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
@@ -877,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
@@ -931,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
@@ -941,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
@@ -954,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
@@ -970,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
@@ -988,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
@@ -1012,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
@@ -1021,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
@@ -1032,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
@@ -1056,59 +873,48 @@ RefreshGcdMemoryAttributes (
   if (MemorySpaceMap != NULL) {\r
     FreePool (MemorySpaceMap);\r
   }\r
-\r
-  mIsFlushingGCD = FALSE;\r
 }\r
 \r
 /**\r
-  Set Interrupt Descriptor Table Handler Address.\r
-\r
-  @param Index        The Index of the interrupt descriptor table handle.\r
-  @param Handler      Handler address.\r
-\r
+ Check if paging is enabled or not.\r
 **/\r
-VOID\r
-SetInterruptDescriptorTableHandlerAddress (\r
-  IN UINTN Index,\r
-  IN VOID  *Handler  OPTIONAL\r
+BOOLEAN\r
+IsPagingAndPageAddressExtensionsEnabled (\r
+  VOID\r
   )\r
 {\r
-  UINTN                     UintnHandler;\r
+  IA32_CR0  Cr0;\r
+  IA32_CR4  Cr4;\r
 \r
-  if (Handler != NULL) {\r
-    UintnHandler = (UINTN) Handler;\r
-  } else {\r
-    UintnHandler = ((UINTN) AsmIdtVector00) + (8 * Index);\r
-  }\r
+  Cr0.UintN = AsmReadCr0 ();\r
+  Cr4.UintN = AsmReadCr4 ();\r
 \r
-  gIdtTable[Index].Bits.OffsetLow   = (UINT16)UintnHandler;\r
-  gIdtTable[Index].Bits.Reserved_0  = 0;\r
-  gIdtTable[Index].Bits.GateType    = IA32_IDT_GATE_TYPE_INTERRUPT_32;\r
-  gIdtTable[Index].Bits.OffsetHigh  = (UINT16)(UintnHandler >> 16);\r
-#if defined (MDE_CPU_X64)\r
-  gIdtTable[Index].Bits.OffsetUpper = (UINT32)(UintnHandler >> 32);\r
-  gIdtTable[Index].Bits.Reserved_1  = 0;\r
-#endif\r
+  return ((Cr0.Bits.PG != 0) && (Cr4.Bits.PAE != 0));\r
 }\r
 \r
 /**\r
-  Restore original Interrupt Descriptor Table Handler Address.\r
+  Refreshes the GCD Memory Space attributes according to MTRRs and Paging.\r
 \r
-  @param Index        The Index of the interrupt descriptor table handle.\r
+  This function refreshes the GCD Memory Space attributes according to MTRRs\r
+  and page tables.\r
 \r
 **/\r
 VOID\r
-RestoreInterruptDescriptorTableHandlerAddress (\r
-  IN UINTN       Index\r
+RefreshGcdMemoryAttributes (\r
+  VOID\r
   )\r
 {\r
-  if (Index < mOrigIdtEntryCount) {\r
-    gIdtTable[Index].Bits.OffsetLow   = mOrigIdtEntry[Index].Bits.OffsetLow;\r
-    gIdtTable[Index].Bits.OffsetHigh  = mOrigIdtEntry[Index].Bits.OffsetHigh;\r
-#if defined (MDE_CPU_X64)\r
-    gIdtTable[Index].Bits.OffsetUpper = mOrigIdtEntry[Index].Bits.OffsetUpper;\r
-#endif\r
+  mIsFlushingGCD = TRUE;\r
+\r
+  if (IsMtrrSupported ()) {\r
+    RefreshMemoryAttributesFromMtrr ();\r
   }\r
+\r
+  if (IsPagingAndPageAddressExtensionsEnabled ()) {\r
+    RefreshGcdMemoryAttributesFromPaging ();\r
+  }\r
+\r
+  mIsFlushingGCD = FALSE;\r
 }\r
 \r
 /**\r
@@ -1121,110 +927,281 @@ InitInterruptDescriptorTable (
   )\r
 {\r
   EFI_STATUS                Status;\r
-  IA32_DESCRIPTOR           OldIdtPtr;\r
-  IA32_IDT_GATE_DESCRIPTOR  *OldIdt;\r
-  UINTN                     OldIdtSize;\r
-  VOID                      *IdtPtrAlignmentBuffer;\r
-  IA32_DESCRIPTOR           *IdtPtr;\r
-  UINTN                     Index;\r
-  UINT16                    CurrentCs;\r
-  VOID                      *IntHandler;\r
-\r
-  SetMem (ExternalVectorTable, sizeof(ExternalVectorTable), 0);\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
+    VectorInfo = VectorInfoList;\r
+  }\r
 \r
-  //\r
-  // Get original IDT address and size.\r
-  //\r
-  AsmReadIdtr ((IA32_DESCRIPTOR *) &OldIdtPtr);\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
-  if ((OldIdtPtr.Base != 0) && ((OldIdtPtr.Limit & 7) == 7)) {\r
-    OldIdt = (IA32_IDT_GATE_DESCRIPTOR*) OldIdtPtr.Base;\r
-    OldIdtSize = (OldIdtPtr.Limit + 1) / sizeof (IA32_IDT_GATE_DESCRIPTOR);\r
     //\r
-    // Save original IDT entry and IDT entry count.\r
+    // Load Interrupt Descriptor Table\r
     //\r
-    mOrigIdtEntry = AllocateCopyPool (OldIdtPtr.Limit + 1, (VOID *) OldIdtPtr.Base);\r
-    ASSERT (mOrigIdtEntry != NULL);\r
-    mOrigIdtEntryCount = (UINT16) OldIdtSize;\r
-  } else {\r
-    OldIdt = NULL;\r
-    OldIdtSize = 0;\r
+    IdtDescriptor.Base  = (UINTN)IdtTable;\r
+    IdtDescriptor.Limit = (UINT16)(sizeof (IA32_IDT_GATE_DESCRIPTOR) * CPU_INTERRUPT_NUM - 1);\r
+    AsmWriteIdtr (&IdtDescriptor);\r
   }\r
 \r
-  //\r
-  // Intialize IDT\r
-  //\r
-  CurrentCs = AsmReadCs();\r
-  for (Index = 0; Index < INTERRUPT_VECTOR_NUMBER; Index ++) {\r
+  Status = InitializeCpuExceptionHandlers (VectorInfo);\r
+  ASSERT_EFI_ERROR (Status);\r
+}\r
+\r
+/**\r
+  Callback function for idle events.\r
+\r
+  @param  Event                 Event whose notification function is being invoked.\r
+  @param  Context               The pointer to the notification function's context,\r
+                                which is implementation-dependent.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+IdleLoopEventCallback (\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
-    // If the old IDT had a handler for this interrupt, then\r
-    // preserve it.\r
+    // The descriptor and the aperture don't overlap.\r
     //\r
-    if (Index < OldIdtSize) {\r
-      IntHandler =\r
-        (VOID*) (\r
-          OldIdt[Index].Bits.OffsetLow +\r
-          (OldIdt[Index].Bits.OffsetHigh << 16)\r
-#if defined (MDE_CPU_X64)\r
-            + (((UINTN) OldIdt[Index].Bits.OffsetUpper) << 32)\r
-#endif\r
-          );\r
-    } else {\r
-      IntHandler = NULL;\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
-    gIdtTable[Index].Bits.Selector    = CurrentCs;\r
-    gIdtTable[Index].Bits.Reserved_0  = 0;\r
-    gIdtTable[Index].Bits.GateType    = IA32_IDT_GATE_TYPE_INTERRUPT_32;\r
-    SetInterruptDescriptorTableHandlerAddress (Index, IntHandler);\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
-  //\r
-  // Load IDT Pointer\r
-  //\r
-  IdtPtrAlignmentBuffer = AllocatePool (sizeof (*IdtPtr) + 16);\r
-  IdtPtr = ALIGN_POINTER (IdtPtrAlignmentBuffer, 16);\r
-  IdtPtr->Base = (UINT32)(((UINTN)(VOID*) gIdtTable) & (BASE_4GB-1));\r
-  IdtPtr->Limit = (UINT16) (sizeof (gIdtTable) - 1);\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
-  AsmWriteIdtr (IdtPtr);\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
-  FreePool (IdtPtrAlignmentBuffer);\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
-  //\r
-  // Initialize Exception Handlers\r
-  //\r
-  for (Index = OldIdtSize; Index < 32; Index++) {\r
-    Status = CpuRegisterInterruptHandler (&gCpu, Index, CommonExceptionHandler);\r
-    ASSERT_EFI_ERROR (Status);\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
-  // Set the pointer to the array of C based exception handling routines.\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
-  InitializeExternalVectorTablePtr (ExternalVectorTable);\r
+  UINT64                           CheckBase;\r
+  EFI_STATUS                       CheckStatus;\r
+  EFI_GCD_MEMORY_SPACE_DESCRIPTOR  Descriptor;\r
 \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
-  Callback function for idle events.\r
+  Add and allocate CPU local APIC memory mapped space.\r
 \r
-  @param  Event                 Event whose notification function is being invoked.\r
-  @param  Context               The pointer to the notification function's context,\r
-                                which is implementation-dependent.\r
+  @param[in]ImageHandle     Image handle this driver.\r
 \r
 **/\r
 VOID\r
-EFIAPI\r
-IdleLoopEventCallback (\r
-  IN EFI_EVENT                Event,\r
-  IN VOID                     *Context\r
+AddLocalApicMemorySpace (\r
+  IN EFI_HANDLE  ImageHandle\r
   )\r
 {\r
-  CpuSleep ();\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
@@ -1240,13 +1217,17 @@ 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
   // Make sure interrupts are disabled\r
   //\r
@@ -1262,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
@@ -1282,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
@@ -1295,6 +1277,7 @@ InitializeCpu (
                   );\r
   ASSERT_EFI_ERROR (Status);\r
 \r
+  InitializeMpSupport ();\r
+\r
   return Status;\r
 }\r
-\r