]> git.proxmox.com Git - mirror_edk2.git/commitdiff
Add CPU DXE driver for IA32 & X64 processor architectures.
authorjljusten <jljusten@6f19259b-4bc3-4df7-8a09-765794883524>
Wed, 27 May 2009 21:09:47 +0000 (21:09 +0000)
committerjljusten <jljusten@6f19259b-4bc3-4df7-8a09-765794883524>
Wed, 27 May 2009 21:09:47 +0000 (21:09 +0000)
git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@8395 6f19259b-4bc3-4df7-8a09-765794883524

UefiCpuPkg/CpuDxe/CpuDxe.c [new file with mode: 0644]
UefiCpuPkg/CpuDxe/CpuDxe.h [new file with mode: 0644]
UefiCpuPkg/CpuDxe/CpuDxe.inf [new file with mode: 0644]
UefiCpuPkg/CpuDxe/CpuGdt.c [new file with mode: 0755]
UefiCpuPkg/CpuDxe/Ia32/CpuAsm.S [new file with mode: 0755]
UefiCpuPkg/CpuDxe/Ia32/CpuAsm.asm [new file with mode: 0755]
UefiCpuPkg/CpuDxe/Ia32/IvtAsm.S [new file with mode: 0755]
UefiCpuPkg/CpuDxe/Ia32/IvtAsm.asm [new file with mode: 0755]
UefiCpuPkg/CpuDxe/X64/CpuAsm.S [new file with mode: 0755]
UefiCpuPkg/CpuDxe/X64/CpuAsm.asm [new file with mode: 0755]

diff --git a/UefiCpuPkg/CpuDxe/CpuDxe.c b/UefiCpuPkg/CpuDxe/CpuDxe.c
new file mode 100644 (file)
index 0000000..25131fe
--- /dev/null
@@ -0,0 +1,1108 @@
+/** @file\r
+  CPU DXE Module.\r
+\r
+  Copyright (c) 2008 - 2009, Intel Corporation\r
+  All rights reserved. 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 "CpuDxe.h"\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
+UINT8                     mDefaultMemoryType    = MTRR_CACHE_WRITE_BACK;\r
+UINT64                    mValidMtrrAddressMask = MTRR_LIB_CACHE_VALID_ADDRESS;\r
+UINT64                    mValidMtrrBitsMask    = MTRR_LIB_MSR_VALID_MASK;\r
+\r
+FIXED_MTRR    mFixedMtrrTable[] = {\r
+  {\r
+    MTRR_LIB_IA32_MTRR_FIX64K_00000,\r
+    0,\r
+    0x10000\r
+  },\r
+  {\r
+    MTRR_LIB_IA32_MTRR_FIX16K_80000,\r
+    0x80000,\r
+    0x4000\r
+  },\r
+  {\r
+    MTRR_LIB_IA32_MTRR_FIX16K_A0000,\r
+    0xA0000,\r
+    0x4000\r
+  },\r
+  {\r
+    MTRR_LIB_IA32_MTRR_FIX4K_C0000,\r
+    0xC0000,\r
+    0x1000\r
+  },\r
+  {\r
+    MTRR_LIB_IA32_MTRR_FIX4K_C8000,\r
+    0xC8000,\r
+    0x1000\r
+  },\r
+  {\r
+    MTRR_LIB_IA32_MTRR_FIX4K_D0000,\r
+    0xD0000,\r
+    0x1000\r
+  },\r
+  {\r
+    MTRR_LIB_IA32_MTRR_FIX4K_D8000,\r
+    0xD8000,\r
+    0x1000\r
+  },\r
+  {\r
+    MTRR_LIB_IA32_MTRR_FIX4K_E0000,\r
+    0xE0000,\r
+    0x1000\r
+  },\r
+  {\r
+    MTRR_LIB_IA32_MTRR_FIX4K_E8000,\r
+    0xE8000,\r
+    0x1000\r
+  },\r
+  {\r
+    MTRR_LIB_IA32_MTRR_FIX4K_F0000,\r
+    0xF0000,\r
+    0x1000\r
+  },\r
+  {\r
+    MTRR_LIB_IA32_MTRR_FIX4K_F8000,\r
+    0xF8000,\r
+    0x1000\r
+  },\r
+};\r
+\r
+\r
+EFI_CPU_ARCH_PROTOCOL  gCpu = {\r
+  CpuFlushCpuDataCache,\r
+  CpuEnableInterrupt,\r
+  CpuDisableInterrupt,\r
+  CpuGetInterruptState,\r
+  CpuInit,\r
+  CpuRegisterInterruptHandler,\r
+  CpuGetTimerValue,\r
+  CpuSetMemoryAttributes,\r
+  1,                          // NumberOfTimers\r
+  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
+// 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)) {\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)) {\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
+\r
+  @param  This              Protocol instance structure\r
+  @param  Start             Physical address to start flushing from.\r
+  @param  Length            Number of bytes to flush. Round up to chipset\r
+                            granularity.\r
+  @param  FlushType         Specifies the type of flush operation to perform.\r
+\r
+  @retval EFI_SUCCESS       If cache was flushed\r
+  @retval EFI_UNSUPPORTED   If flush type is not supported.\r
+  @retval EFI_DEVICE_ERROR  If requested range could not be flushed.\r
+\r
+**/\r
+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
+  )\r
+{\r
+  if (FlushType == EfiCpuFlushTypeWriteBackInvalidate) {\r
+    AsmWbinvd ();\r
+    return EFI_SUCCESS;\r
+  } else if (FlushType == EfiCpuFlushTypeInvalidate) {\r
+    AsmInvd ();\r
+    return EFI_SUCCESS;\r
+  } else {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+}\r
+\r
+\r
+/**\r
+  Enables CPU interrupts.\r
+\r
+  @param  This              Protocol instance structure\r
+\r
+  @retval EFI_SUCCESS       If interrupts were enabled in the CPU\r
+  @retval EFI_DEVICE_ERROR  If interrupts could not be enabled on the CPU.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+CpuEnableInterrupt (\r
+  IN EFI_CPU_ARCH_PROTOCOL          *This\r
+  )\r
+{\r
+  EnableInterrupts ();\r
+\r
+  InterruptState = TRUE;\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+  Disables CPU interrupts.\r
+\r
+  @param  This              Protocol instance structure\r
+\r
+  @retval EFI_SUCCESS       If interrupts were disabled in the CPU.\r
+  @retval EFI_DEVICE_ERROR  If interrupts could not be disabled on the CPU.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+CpuDisableInterrupt (\r
+  IN EFI_CPU_ARCH_PROTOCOL     *This\r
+  )\r
+{\r
+  DisableInterrupts ();\r
+\r
+  InterruptState = FALSE;\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+  Return the state of interrupts.\r
+\r
+  @param  This                   Protocol instance structure\r
+  @param  State                  Pointer to the CPU's current interrupt state\r
+\r
+  @retval EFI_SUCCESS            If interrupts were disabled in the CPU.\r
+  @retval EFI_INVALID_PARAMETER  State is NULL.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+CpuGetInterruptState (\r
+  IN  EFI_CPU_ARCH_PROTOCOL     *This,\r
+  OUT BOOLEAN                   *State\r
+  )\r
+{\r
+  if (State == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  *State = InterruptState;\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+  Generates an INIT to the CPU.\r
+\r
+  @param  This              Protocol instance structure\r
+  @param  InitType          Type of CPU INIT to perform\r
+\r
+  @retval EFI_SUCCESS       If CPU INIT occurred. This value should never be\r
+                            seen.\r
+  @retval EFI_DEVICE_ERROR  If CPU INIT failed.\r
+  @retval EFI_UNSUPPORTED   Requested type of CPU INIT not supported.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+CpuInit (\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
+  @param  This                   Protocol instance structure\r
+  @param  InterruptType          Defines which interrupt to hook. IA-32\r
+                                 valid range is 0x00 through 0xFF\r
+  @param  InterruptHandler       A pointer to a function of type\r
+                                 EFI_CPU_INTERRUPT_HANDLER that is called\r
+                                 when a processor interrupt occurs.  A null\r
+                                 pointer is an error condition.\r
+\r
+  @retval EFI_SUCCESS            If handler installed or uninstalled.\r
+  @retval EFI_ALREADY_STARTED    InterruptHandler is not NULL, and a handler\r
+                                 for InterruptType was previously installed.\r
+  @retval EFI_INVALID_PARAMETER  InterruptHandler is NULL, and a handler for\r
+                                 InterruptType was not previously installed.\r
+  @retval EFI_UNSUPPORTED        The interrupt specified by InterruptType\r
+                                 is not supported.\r
+\r
+**/\r
+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
+  )\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
+  ExternalVectorTable[InterruptType] = InterruptHandler;\r
+  return EFI_SUCCESS;\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
+\r
+  @param  This                - Protocol instance structure.\r
+  @param  TimerIndex          - Specifies which CPU timer is requested.\r
+  @param  TimerValue          - Pointer to the returned timer value.\r
+  @param  TimerPeriod         - A pointer to the amount of time that passes\r
+                                in femtoseconds (10-15) for each increment\r
+                                of TimerValue. If TimerValue does not\r
+                                increment at a predictable rate, then 0 is\r
+                                returned.  The amount of time that has\r
+                                passed between two calls to GetTimerValue()\r
+                                can be calculated with the formula\r
+                                (TimerValue2 - TimerValue1) * TimerPeriod.\r
+                                This parameter is optional and may be NULL.\r
+\r
+  @retval EFI_SUCCESS           - If the CPU timer count was returned.\r
+  @retval EFI_UNSUPPORTED       - If the CPU does not have any readable timers.\r
+  @retval EFI_DEVICE_ERROR      - If an error occurred while reading the timer.\r
+  @retval EFI_INVALID_PARAMETER - TimerIndex is not valid or TimerValue is NULL.\r
+\r
+**/\r
+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
+  )\r
+{\r
+  if (TimerValue == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  if (TimerIndex != 0) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  *TimerValue = AsmReadTsc ();\r
+\r
+  if (TimerPeriod != NULL) {\r
+      //\r
+      // BugBug: Hard coded. Don't know how to do this generically\r
+      //\r
+      *TimerPeriod = 1000000000;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+  Set memory cacheability attributes for given range of memeory.\r
+\r
+  @param  This                   Protocol instance structure\r
+  @param  BaseAddress            Specifies the start address of the\r
+                                 memory range\r
+  @param  Length                 Specifies the length of the memory range\r
+  @param  Attributes             The memory cacheability for the memory range\r
+\r
+  @retval EFI_SUCCESS            If the cacheability of that memory range is\r
+                                 set successfully\r
+  @retval EFI_UNSUPPORTED        If the desired operation cannot be done\r
+  @retval EFI_INVALID_PARAMETER  The input parameter is not correct,\r
+                                 such as Length = 0\r
+\r
+**/\r
+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
+  )\r
+{\r
+  RETURN_STATUS             Status;\r
+  MTRR_MEMORY_CACHE_TYPE    CacheType;\r
+\r
+  DEBUG((EFI_D_ERROR, "CpuAp: SetMemorySpaceAttributes(BA=%08x, Len=%08x, Attr=%08x)\n", BaseAddress, Length, Attributes));\r
+\r
+  //\r
+  // If this function is called because GCD SetMemorySpaceAttributes () is called\r
+  // by RefreshGcdMemoryAttributes (), then we are just synchronzing 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
+    }\r
+\r
+  switch (Attributes) {\r
+  case EFI_MEMORY_UC:\r
+    CacheType = CacheUncacheable;\r
+    break;\r
+\r
+  case EFI_MEMORY_WC:\r
+    CacheType = CacheWriteCombining;\r
+    break;\r
+\r
+  case EFI_MEMORY_WT:\r
+    CacheType = CacheWriteThrough;\r
+    break;\r
+\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_UNSUPPORTED;\r
+  }\r
+  //\r
+  // call MTRR libary function\r
+  //\r
+  DEBUG((EFI_D_ERROR, "  MtrrSetMemoryAttribute()\n"));\r
+  Status = MtrrSetMemoryAttribute(\r
+             BaseAddress,\r
+             Length,\r
+             CacheType\r
+             );\r
+\r
+  MtrrDebugPrintAllMtrrs ();\r
+\r
+  return (EFI_STATUS) Status;\r
+}\r
+\r
+/**\r
+  Initializes the valid bits mask and valid address mask for MTRRs.\r
+\r
+  This function initializes the valid bits mask and valid address mask for MTRRs.\r
+\r
+**/\r
+VOID\r
+InitializeMtrrMask (\r
+  VOID\r
+  )\r
+{\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
+  } else {\r
+    mValidMtrrBitsMask    = MTRR_LIB_MSR_VALID_MASK;\r
+    mValidMtrrAddressMask = MTRR_LIB_CACHE_VALID_ADDRESS;\r
+  }\r
+}\r
+\r
+/**\r
+  Gets GCD Mem Space type from MTRR Type\r
+\r
+  This function gets GCD Mem Space type from MTRR Type\r
+\r
+  @param  MtrrAttribute  MTRR memory type\r
+\r
+  @return GCD Mem Space type\r
+\r
+**/\r
+UINT64\r
+GetMemorySpaceAttributeFromMtrrType (\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
+  }\r
+}\r
+\r
+/**\r
+  Searches memory descriptors covered by given memory range.\r
+\r
+  This function searches into the Gcd Memory Space for descriptors\r
+  (from StartIndex to EndIndex) that contains the memory range\r
+  specified by BaseAddress and Length.\r
+\r
+  @param  MemorySpaceMap       Gcd Memory Space Map as array.\r
+  @param  NumberOfDescriptors  Number of descriptors in map.\r
+  @param  BaseAddress          BaseAddress for the requested range.\r
+  @param  Length               Length for the requested range.\r
+  @param  StartIndex           Start index into the Gcd Memory Space Map.\r
+  @param  EndIndex             End index into the Gcd Memory Space Map.\r
+\r
+  @retval EFI_SUCCESS          Search successfully.\r
+  @retval EFI_NOT_FOUND        The requested descriptors does not exist.\r
+\r
+**/\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
+  )\r
+{\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
+      *StartIndex = Index;\r
+    }\r
+    if (BaseAddress + Length - 1 >= MemorySpaceMap[Index].BaseAddress &&\r
+        BaseAddress + Length - 1 < MemorySpaceMap[Index].BaseAddress + MemorySpaceMap[Index].Length) {\r
+      *EndIndex = Index;\r
+      return EFI_SUCCESS;\r
+    }\r
+  }\r
+  return EFI_NOT_FOUND;\r
+}\r
+\r
+/**\r
+  Sets the attributes for a specified range in Gcd Memory Space Map.\r
+\r
+  This function sets the attributes for a specified range in\r
+  Gcd Memory Space Map.\r
+\r
+  @param  MemorySpaceMap       Gcd Memory Space Map as array\r
+  @param  NumberOfDescriptors  Number of descriptors in map\r
+  @param  BaseAddress          BaseAddress for the range\r
+  @param  Length               Length for the range\r
+  @param  Attributes           Attributes to set\r
+\r
+  @retval EFI_SUCCESS          Memory attributes set successfully\r
+  @retval EFI_NOT_FOUND        The specified range does not exist in Gcd Memory Space\r
+\r
+**/\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
+  )\r
+{\r
+  EFI_STATUS            Status;\r
+  UINTN                 Index;\r
+  UINTN                 StartIndex;\r
+  UINTN                 EndIndex;\r
+  EFI_PHYSICAL_ADDRESS  RegionStart;\r
+  UINT64                RegionLength;\r
+\r
+  //\r
+  // Get all memory descriptors covered by the memory range\r
+  //\r
+  Status = SearchGcdMemorySpaces (\r
+             MemorySpaceMap,\r
+             NumberOfDescriptors,\r
+             BaseAddress,\r
+             Length,\r
+             &StartIndex,\r
+             &EndIndex\r
+             );\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  //\r
+  // Go through all related descriptors and set attributes accordingly\r
+  //\r
+  for (Index = StartIndex; Index <= EndIndex; Index++) {\r
+    if (MemorySpaceMap[Index].GcdMemoryType == EfiGcdMemoryTypeNonExistent) {\r
+      continue;\r
+    }\r
+    //\r
+    // Calculate the start and end address of the overlapping range\r
+    //\r
+    if (BaseAddress >= MemorySpaceMap[Index].BaseAddress) {\r
+      RegionStart = BaseAddress;\r
+    } else {\r
+      RegionStart = MemorySpaceMap[Index].BaseAddress;\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
+    // 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
+           );\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+  Refreshes the GCD Memory Space attributes according to MTRRs.\r
+\r
+  This function refreshes the GCD Memory Space attributes according to MTRRs.\r
+\r
+**/\r
+VOID\r
+RefreshGcdMemoryAttributes (\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
+\r
+//  mIsFlushingGCD = TRUE;\r
+  mIsFlushingGCD = FALSE;\r
+  MemorySpaceMap = NULL;\r
+\r
+  //\r
+  // Initialize the valid bits mask and valid address mask for MTRRs\r
+  //\r
+  InitializeMtrrMask ();\r
+\r
+  //\r
+  // Get the memory attribute of variable MTRRs\r
+  //\r
+  MtrrGetMemoryAttributeInVariableMtrr (\r
+    mValidMtrrBitsMask,\r
+    mValidMtrrAddressMask,\r
+    VariableMtrr\r
+    );\r
+\r
+  //\r
+  // Get the memory space map from GCD\r
+  //\r
+  Status = gDS->GetMemorySpaceMap (\r
+                  &NumberOfDescriptors,\r
+                  &MemorySpaceMap\r
+                  );\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+  DefaultAttributes = GetMemorySpaceAttributeFromMtrrType (mDefaultMemoryType);\r
+\r
+  //\r
+  // Set default attributes to all spaces.\r
+  //\r
+  for (Index = 0; Index < NumberOfDescriptors; Index++) {\r
+    if (MemorySpaceMap[Index].GcdMemoryType == EfiGcdMemoryTypeNonExistent) {\r
+      continue;\r
+    }\r
+    gDS->SetMemorySpaceAttributes (\r
+           MemorySpaceMap[Index].BaseAddress,\r
+           MemorySpaceMap[Index].Length,\r
+           (MemorySpaceMap[Index].Attributes & ~EFI_MEMORY_CACHETYPE_MASK) |\r
+           (MemorySpaceMap[Index].Capabilities & DefaultAttributes)\r
+           );\r
+  }\r
+\r
+  //\r
+  // Go for variable MTRRs with WB attribute\r
+  //\r
+  for (Index = 0; Index < FIRMWARE_VARIABLE_MTRR_NUMBER; Index++) {\r
+    if (VariableMtrr[Index].Valid &&\r
+        VariableMtrr[Index].Type == MTRR_CACHE_WRITE_BACK) {\r
+      SetGcdMemorySpaceAttributes (\r
+        MemorySpaceMap,\r
+        NumberOfDescriptors,\r
+        VariableMtrr[Index].BaseAddress,\r
+        VariableMtrr[Index].Length,\r
+        EFI_MEMORY_WB\r
+        );\r
+    }\r
+  }\r
+  //\r
+  // Go for variable MTRRs with Non-WB attribute\r
+  //\r
+  for (Index = 0; Index < FIRMWARE_VARIABLE_MTRR_NUMBER; Index++) {\r
+    if (VariableMtrr[Index].Valid &&\r
+        VariableMtrr[Index].Type != MTRR_CACHE_WRITE_BACK) {\r
+      Attributes = GetMemorySpaceAttributeFromMtrrType ((UINT8) VariableMtrr[Index].Type);\r
+      SetGcdMemorySpaceAttributes (\r
+        MemorySpaceMap,\r
+        NumberOfDescriptors,\r
+        VariableMtrr[Index].BaseAddress,\r
+        VariableMtrr[Index].Length,\r
+        Attributes\r
+        );\r
+    }\r
+  }\r
+\r
+  //\r
+  // Go for fixed MTRRs\r
+  //\r
+  Attributes  = 0;\r
+  BaseAddress = 0;\r
+  Length      = 0;\r
+  MtrrGetFixedMtrr (&MtrrFixedSettings);\r
+  for (Index = 0; Index < MTRR_NUMBER_OF_FIXED_MTRR; Index++) {\r
+    RegValue = MtrrFixedSettings.Mtrr[Index];\r
+    //\r
+    // Check for continuous fixed MTRR sections\r
+    //\r
+    for (SubIndex = 0; SubIndex < 8; SubIndex++) {\r
+      MtrrType = (UINT8) RShiftU64 (RegValue, SubIndex * 8);\r
+      CurrentAttributes = GetMemorySpaceAttributeFromMtrrType (MtrrType);\r
+      if (Length == 0) {\r
+        //\r
+        // A new MTRR attribute begins\r
+        //\r
+        Attributes = CurrentAttributes;\r
+      } else {\r
+        //\r
+        // If fixed MTRR attribute changed, then set memory attribute for previous atrribute\r
+        //\r
+        if (CurrentAttributes != Attributes) {\r
+          SetGcdMemorySpaceAttributes (\r
+            MemorySpaceMap,\r
+            NumberOfDescriptors,\r
+            BaseAddress,\r
+            Length,\r
+            Attributes\r
+            );\r
+          BaseAddress = mFixedMtrrTable[Index].BaseAddress + mFixedMtrrTable[Index].Length * SubIndex;\r
+          Length = 0;\r
+          Attributes = CurrentAttributes;\r
+        }\r
+      }\r
+      Length += mFixedMtrrTable[Index].Length;\r
+    }\r
+  }\r
+  //\r
+  // Handle the last fixed MTRR region\r
+  //\r
+  SetGcdMemorySpaceAttributes (\r
+    MemorySpaceMap,\r
+    NumberOfDescriptors,\r
+    BaseAddress,\r
+    Length,\r
+    Attributes\r
+    );\r
+\r
+  //\r
+  // Free memory space map allocated by GCD service GetMemorySpaceMap ()\r
+  //\r
+  if (MemorySpaceMap != NULL) {\r
+    FreePool (MemorySpaceMap);\r
+  }\r
+\r
+  mIsFlushingGCD = FALSE;\r
+}\r
+\r
+\r
+/**\r
+  Initialize Interrupt Descriptor Table for interrupt handling.\r
+\r
+**/\r
+STATIC\r
+VOID\r
+InitInterruptDescriptorTable (\r
+  VOID\r
+  )\r
+{\r
+  EFI_STATUS      Status;\r
+  VOID            *IdtPtrAlignmentBuffer;\r
+  IA32_DESCRIPTOR *IdtPtr;\r
+  UINTN           Index;\r
+  UINTN           CurrentHandler;\r
+\r
+  SetMem (ExternalVectorTable, sizeof(ExternalVectorTable), 0);\r
+\r
+  //\r
+  // Intialize IDT\r
+  //\r
+  CurrentHandler = (UINTN)AsmIdtVector00;\r
+  for (Index = 0; Index < INTERRUPT_VECTOR_NUMBER; Index ++, CurrentHandler += 0x08) {\r
+    gIdtTable[Index].Bits.OffsetLow   = (UINT16)CurrentHandler;\r
+    gIdtTable[Index].Bits.Selector    = AsmReadCs();\r
+    gIdtTable[Index].Bits.Reserved_0  = 0;\r
+    gIdtTable[Index].Bits.GateType    = IA32_IDT_GATE_TYPE_INTERRUPT_32;\r
+    gIdtTable[Index].Bits.OffsetHigh  = (UINT16)(CurrentHandler >> 16);\r
+#if defined (MDE_CPU_X64)\r
+    gIdtTable[Index].Bits.OffsetUpper = (UINT32)(CurrentHandler >> 32);\r
+    gIdtTable[Index].Bits.Reserved_1  = 0;\r
+#endif\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 = sizeof (gIdtTable) - 1;\r
+  AsmWriteIdtr (IdtPtr);\r
+  FreePool (IdtPtrAlignmentBuffer);\r
+\r
+  //\r
+  // Initialize Exception Handlers\r
+  //\r
+  for (Index = 0; Index < 32; Index++) {\r
+    Status = CpuRegisterInterruptHandler (&gCpu, Index, CommonExceptionHandler);\r
+    ASSERT_EFI_ERROR (Status);\r
+  }\r
+\r
+  //\r
+  // Set the pointer to the array of C based exception handling routines.\r
+  //\r
+  InitializeExternalVectorTablePtr (ExternalVectorTable);\r
+\r
+}\r
+\r
+\r
+/**\r
+  Initialize the state information for the CPU Architectural Protocol.\r
+\r
+  @param ImageHandle     Image handle this driver.\r
+  @param SystemTable     Pointer to the System Table.\r
+\r
+  @retval EFI_SUCCESS           Thread can be successfully created\r
+  @retval EFI_OUT_OF_RESOURCES  Cannot allocate protocol data structure\r
+  @retval EFI_DEVICE_ERROR      Cannot create the thread\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+InitializeCpu (\r
+  IN EFI_HANDLE                            ImageHandle,\r
+  IN EFI_SYSTEM_TABLE                      *SystemTable\r
+  )\r
+{\r
+  EFI_STATUS  Status;\r
+\r
+  //\r
+  // Make sure interrupts are disabled\r
+  //\r
+  DisableInterrupts ();\r
+\r
+  //\r
+  // Init GDT for DXE\r
+  //\r
+  InitGlobalDescriptorTable ();\r
+\r
+  //\r
+  // Setup IDT pointer, IDT and interrupt entry points\r
+  //\r
+  InitInterruptDescriptorTable ();\r
+\r
+  //\r
+  // Install CPU Architectural Protocol\r
+  //\r
+  Status = gBS->InstallMultipleProtocolInterfaces (\r
+                  &mCpuHandle,\r
+                  &gEfiCpuArchProtocolGuid, &gCpu,\r
+                  NULL\r
+                  );\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+  //\r
+  // Refresh GCD memory space map according to MTRR value.\r
+  //\r
+  RefreshGcdMemoryAttributes ();\r
+\r
+  return Status;\r
+}\r
+\r
diff --git a/UefiCpuPkg/CpuDxe/CpuDxe.h b/UefiCpuPkg/CpuDxe/CpuDxe.h
new file mode 100644 (file)
index 0000000..fbf3a98
--- /dev/null
@@ -0,0 +1,140 @@
+/** @file\r
+  CPU DXE Module.\r
+\r
+  Copyright (c) 2008 - 2009, Intel Corporation\r
+  All rights reserved. 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 _CPU_DXE_H\r
+#define _CPU_DXE_H\r
+\r
+#include <PiDxe.h>\r
+\r
+#include <Protocol/Cpu.h>\r
+\r
+#include <Library/UefiDriverEntryPoint.h>\r
+#include <Library/UefiBootServicesTableLib.h>\r
+#include <Library/DxeServicesTableLib.h>\r
+#include <Library/BaseLib.h>\r
+#include <Library/CpuLib.h>\r
+#include <Library/BaseMemoryLib.h>\r
+#include <Library/MemoryAllocationLib.h>\r
+#include <Library/DebugLib.h>\r
+#include <Library/MtrrLib.h>\r
+\r
+//\r
+//\r
+//\r
+#define INTERRUPT_VECTOR_NUMBER   256\r
+\r
+#define EFI_MEMORY_CACHETYPE_MASK     (EFI_MEMORY_UC  | \\r
+                                       EFI_MEMORY_WC  | \\r
+                                       EFI_MEMORY_WT  | \\r
+                                       EFI_MEMORY_WB  | \\r
+                                       EFI_MEMORY_UCE   \\r
+                                       )\r
+\r
+\r
+//\r
+// Function declarations\r
+//\r
+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
+  );\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+CpuEnableInterrupt (\r
+  IN EFI_CPU_ARCH_PROTOCOL     *This\r
+  );\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+CpuDisableInterrupt (\r
+  IN EFI_CPU_ARCH_PROTOCOL     *This\r
+  );\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+CpuGetInterruptState (\r
+  IN  EFI_CPU_ARCH_PROTOCOL     *This,\r
+  OUT BOOLEAN                   *State\r
+  );\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+CpuInit (\r
+  IN EFI_CPU_ARCH_PROTOCOL     *This,\r
+  IN EFI_CPU_INIT_TYPE         InitType\r
+  );\r
+\r
+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
+  );\r
+\r
+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
+  );\r
+\r
+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
+  );\r
+\r
+VOID\r
+EFIAPI\r
+AsmIdtVector00 (\r
+  VOID\r
+  );\r
+\r
+VOID\r
+EFIAPI\r
+InitializeExternalVectorTablePtr (\r
+  EFI_CPU_INTERRUPT_HANDLER  *VectorTable\r
+  );\r
+\r
+VOID\r
+InitGlobalDescriptorTable (\r
+  VOID\r
+  );\r
+\r
+VOID\r
+EFIAPI\r
+SetCodeSelector (\r
+  UINT16 Selector\r
+  );\r
+\r
+VOID\r
+EFIAPI\r
+SetDataSelectors (\r
+  UINT16 Selector\r
+  );\r
+\r
+\r
+#endif\r
+\r
diff --git a/UefiCpuPkg/CpuDxe/CpuDxe.inf b/UefiCpuPkg/CpuDxe/CpuDxe.inf
new file mode 100644 (file)
index 0000000..ff83245
--- /dev/null
@@ -0,0 +1,67 @@
+#/** @file\r
+#\r
+#    Component description file for simple CPU driver\r
+#\r
+#  Copyright (c) 2008 - 2009, Intel Corporation. <BR>\r
+#  All rights reserved. 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                      = CpuDxe\r
+  FILE_GUID                      = 62D171CB-78CD-4480-8678-C6A2A797A8DE\r
+  MODULE_TYPE                    = DXE_DRIVER\r
+  VERSION_STRING                 = 1.0\r
+  EDK_RELEASE_VERSION            = 0x00020000\r
+  EFI_SPECIFICATION_VERSION      = 0x0002000A\r
+\r
+  ENTRY_POINT                    = InitializeCpu\r
+\r
+[Packages]\r
+  OvmfPkg/OvmfPkg.dec\r
+  MdePkg/MdePkg.dec\r
+  UefiCpuPkg/UefiCpuPkg.dec\r
+\r
+[LibraryClasses]\r
+  BaseLib\r
+  BaseMemoryLib\r
+  CpuLib\r
+  DebugLib\r
+  DxeServicesTableLib\r
+  MemoryAllocationLib\r
+  MtrrLib\r
+  UefiBootServicesTableLib\r
+  UefiDriverEntryPoint\r
+\r
+[Sources]\r
+  CpuDxe.c\r
+  CpuDxe.h\r
+  CpuGdt.c\r
+\r
+  Ia32/IvtAsm.asm | MSFT\r
+  Ia32/IvtAsm.asm | INTEL\r
+  Ia32/IvtAsm.S   | GCC\r
+\r
+[Sources.IA32]\r
+  Ia32/CpuAsm.asm | MSFT\r
+  Ia32/CpuAsm.asm | INTEL\r
+  Ia32/CpuAsm.S   | GCC\r
+\r
+[Sources.X64]\r
+  X64/CpuAsm.asm | MSFT\r
+  X64/CpuAsm.asm | INTEL\r
+  X64/CpuAsm.S   | GCC\r
+\r
+[Protocols]\r
+  gEfiCpuArchProtocolGuid\r
+\r
+[Depex]\r
+  TRUE\r
+\r
diff --git a/UefiCpuPkg/CpuDxe/CpuGdt.c b/UefiCpuPkg/CpuDxe/CpuGdt.c
new file mode 100755 (executable)
index 0000000..b6d8ffb
--- /dev/null
@@ -0,0 +1,200 @@
+/** @file\r
+  C based implemention of IA32 interrupt handling only\r
+  requiring a minimal assembly interrupt entry point.\r
+\r
+  Copyright (c) 2006 - 2009, Intel Corporation\r
+  All rights reserved. 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 "CpuDxe.h"\r
+\r
+\r
+//\r
+// Local structure definitions\r
+//\r
+\r
+#pragma pack (1)\r
+\r
+//\r
+// Global Descriptor Entry structures\r
+//\r
+\r
+typedef\r
+struct _GDT_ENTRY {\r
+  UINT16 limit15_0;\r
+  UINT16 base15_0;\r
+  UINT8  base23_16;\r
+  UINT8  type;\r
+  UINT8  limit19_16_and_flags;\r
+  UINT8  base31_24;\r
+} GDT_ENTRY;\r
+\r
+typedef\r
+struct _GDT_ENTRIES {\r
+  GDT_ENTRY Null;\r
+  GDT_ENTRY Linear;\r
+  GDT_ENTRY LinearCode;\r
+  GDT_ENTRY SysData;\r
+  GDT_ENTRY SysCode;\r
+  GDT_ENTRY LinearCode64;\r
+  GDT_ENTRY Spare4;\r
+  GDT_ENTRY Spare5;\r
+} GDT_ENTRIES;\r
+\r
+#define NULL_SEL          OFFSET_OF (GDT_ENTRIES, Null)\r
+#define LINEAR_SEL        OFFSET_OF (GDT_ENTRIES, Linear)\r
+#define LINEAR_CODE_SEL   OFFSET_OF (GDT_ENTRIES, LinearCode)\r
+#define SYS_DATA_SEL      OFFSET_OF (GDT_ENTRIES, SysData)\r
+#define SYS_CODE_SEL      OFFSET_OF (GDT_ENTRIES, SysCode)\r
+#define LINEAR_CODE64_SEL OFFSET_OF (GDT_ENTRIES, LinearCode64)\r
+#define SPARE4_SEL        OFFSET_OF (GDT_ENTRIES, Spare4)\r
+#define SPARE5_SEL        OFFSET_OF (GDT_ENTRIES, Spare5)\r
+\r
+#if defined (MDE_CPU_IA32)\r
+#define CPU_CODE_SEL LINEAR_CODE_SEL\r
+#define CPU_DATA_SEL LINEAR_SEL\r
+#elif defined (MDE_CPU_X64)\r
+#define CPU_CODE_SEL LINEAR_CODE64_SEL\r
+#define CPU_DATA_SEL LINEAR_SEL\r
+#else\r
+#error CPU type not supported for CPU GDT initialization!\r
+#endif\r
+\r
+//\r
+// Global descriptor table (GDT) Template\r
+//\r
+STATIC GDT_ENTRIES GdtTemplate = {\r
+  //\r
+  // NULL_SEL\r
+  //\r
+  {\r
+    0x0,            // limit 15:0\r
+    0x0,            // base 15:0\r
+    0x0,            // base 23:16\r
+    0x0,            // type\r
+    0x0,            // limit 19:16, flags\r
+    0x0,            // base 31:24\r
+  },\r
+  //\r
+  // LINEAR_SEL\r
+  //\r
+  {\r
+    0x0FFFF,        // limit 0xFFFFF\r
+    0x0,            // base 0\r
+    0x0,\r
+    0x092,          // present, ring 0, data, expand-up, writable\r
+    0x0CF,          // page-granular, 32-bit\r
+    0x0,\r
+  },\r
+  //\r
+  // LINEAR_CODE_SEL\r
+  //\r
+  {\r
+    0x0FFFF,        // limit 0xFFFFF\r
+    0x0,            // base 0\r
+    0x0,\r
+    0x09A,          // present, ring 0, data, expand-up, writable\r
+    0x0CF,          // page-granular, 32-bit\r
+    0x0,\r
+  },\r
+  //\r
+  // SYS_DATA_SEL\r
+  //\r
+  {\r
+    0x0FFFF,        // limit 0xFFFFF\r
+    0x0,            // base 0\r
+    0x0,\r
+    0x092,          // present, ring 0, data, expand-up, writable\r
+    0x0CF,          // page-granular, 32-bit\r
+    0x0,\r
+  },\r
+  //\r
+  // SYS_CODE_SEL\r
+  //\r
+  {\r
+    0x0FFFF,        // limit 0xFFFFF\r
+    0x0,            // base 0\r
+    0x0,\r
+    0x09A,          // present, ring 0, data, expand-up, writable\r
+    0x0CF,          // page-granular, 32-bit\r
+    0x0,\r
+  },\r
+  //\r
+  // LINEAR_CODE64_SEL\r
+  //\r
+  {\r
+    0x0FFFF,        // limit 0xFFFFF\r
+    0x0,            // base 0\r
+    0x0,\r
+    0x09B,          // present, ring 0, code, expand-up, writable\r
+    0x0AF,          // LimitHigh (CS.L=1, CS.D=0)\r
+    0x0,            // base (high)\r
+  },\r
+  //\r
+  // SPARE4_SEL\r
+  //\r
+  {\r
+    0x0,            // limit 0\r
+    0x0,            // base 0\r
+    0x0,\r
+    0x0,            // present, ring 0, data, expand-up, writable\r
+    0x0,            // page-granular, 32-bit\r
+    0x0,\r
+  },\r
+  //\r
+  // SPARE5_SEL\r
+  //\r
+  {\r
+    0x0,            // limit 0\r
+    0x0,            // base 0\r
+    0x0,\r
+    0x0,            // present, ring 0, data, expand-up, writable\r
+    0x0,            // page-granular, 32-bit\r
+    0x0,\r
+  },\r
+};\r
+\r
+/**\r
+  Initialize Global Descriptor Table\r
+\r
+**/\r
+VOID\r
+InitGlobalDescriptorTable (\r
+  )\r
+{\r
+  GDT_ENTRIES *gdt;\r
+  IA32_DESCRIPTOR gdtPtr;\r
+\r
+  //\r
+  // Allocate Runtime Data for the GDT\r
+  //\r
+  gdt = AllocateRuntimePool (sizeof (GdtTemplate) + 8);\r
+  ASSERT (gdt != NULL);\r
+  gdt = ALIGN_POINTER (gdt, 8);\r
+\r
+  //\r
+  // Initialize all GDT entries\r
+  //\r
+  CopyMem (gdt, &GdtTemplate, sizeof (GdtTemplate));\r
+\r
+  //\r
+  // Write GDT register\r
+  //\r
+  gdtPtr.Base = (UINT32)(UINTN)(VOID*) gdt;\r
+  gdtPtr.Limit = sizeof (GdtTemplate) - 1;\r
+  AsmWriteGdtr (&gdtPtr);\r
+\r
+  //\r
+  // Update selector (segment) registers base on new GDT\r
+  //\r
+  SetCodeSelector ((UINT16)CPU_CODE_SEL);\r
+  SetDataSelectors ((UINT16)CPU_DATA_SEL);\r
+}\r
+\r
diff --git a/UefiCpuPkg/CpuDxe/Ia32/CpuAsm.S b/UefiCpuPkg/CpuDxe/Ia32/CpuAsm.S
new file mode 100755 (executable)
index 0000000..69fe215
--- /dev/null
@@ -0,0 +1,395 @@
+#
+# ConvertAsm.py: Automatically generated from CpuAsm.asm
+#
+#      TITLE   CpuAsm.asm:
+
+#------------------------------------------------------------------------------
+#*
+#*   Copyright 2006 - 2009, Intel Corporation
+#*   All rights reserved. This program and the accompanying materials
+#*   are licensed and made available under the terms and conditions of the BSD License
+#*   which accompanies this distribution.  The full text of the license may be found at
+#*   http://opensource.org/licenses/bsd-license.php
+#*
+#*   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+#*   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#*
+#*    CpuAsm.S
+#*
+#*   Abstract:
+#*
+#------------------------------------------------------------------------------
+
+
+#.MMX
+#.XMM
+
+#EXTRN ASM_PFX(mErrorCodeFlag):DWORD # Error code flags for exceptions
+
+
+#
+# point to the external interrupt vector table
+#
+ExternalVectorTablePtr:
+    .byte      0, 0, 0, 0
+
+.intel_syntax
+ASM_GLOBAL ASM_PFX(InitializeExternalVectorTablePtr)
+ASM_PFX(InitializeExternalVectorTablePtr):
+    mov     eax, [esp+4]
+    mov     ExternalVectorTablePtr, eax
+    ret
+
+#------------------------------------------------------------------------------
+# VOID
+# SetCodeSelector (
+#   UINT16 Selector
+#   );
+#------------------------------------------------------------------------------
+.intel_syntax
+ASM_GLOBAL ASM_PFX(SetCodeSelector)
+ASM_PFX(SetCodeSelector):
+    mov     %ecx, [%esp+4]
+    sub     %esp, 0x10
+    lea     %eax, setCodeSelectorLongJump
+    mov     [%esp], %eax
+    mov     [%esp+4], %cx
+    jmp     fword ptr [%esp]
+setCodeSelectorLongJump:
+    add     %esp, 0x10
+    ret
+
+#------------------------------------------------------------------------------
+# VOID
+# SetDataSelectors (
+#   UINT16 Selector
+#   );
+#------------------------------------------------------------------------------
+.intel_syntax
+ASM_GLOBAL ASM_PFX(SetDataSelectors)
+ASM_PFX(SetDataSelectors):
+    mov     %ecx, [%esp+4]
+    mov     %ss, %cx
+    mov     %ds, %cx
+    mov     %es, %cx
+    mov     %fs, %cx
+    mov     %gs, %cx
+    ret
+
+#---------------------------------------;
+# CommonInterruptEntry                  ;
+#---------------------------------------;
+# The follow algorithm is used for the common interrupt routine.
+
+.intel_syntax
+ASM_GLOBAL ASM_PFX(CommonInterruptEntry)
+ASM_PFX(CommonInterruptEntry):
+    cli
+    #
+    # All interrupt handlers are invoked through interrupt gates, so
+    # IF flag automatically cleared at the entry point
+    #
+
+    #
+    # Calculate vector number
+    #
+    # Get the return address of call, actually, it is the
+    # address of vector number.
+    #
+    xchg    ecx, [esp]
+    mov     cx, [ecx]
+    and     ecx, 0x0FFFF
+    cmp     ecx, 32         # Intel reserved vector for exceptions?
+    jae     NoErrorCode
+    bt      ASM_PFX(mErrorCodeFlag), ecx
+    jc      HasErrorCode
+
+NoErrorCode:
+
+    #
+    # Stack:
+    # +---------------------+
+    # +    EFlags           +
+    # +---------------------+
+    # +    CS               +
+    # +---------------------+
+    # +    EIP              +
+    # +---------------------+
+    # +    ECX              +
+    # +---------------------+ <-- ESP
+    #
+    # Registers:
+    #   ECX - Vector Number
+    #
+
+    #
+    # Put Vector Number on stack
+    #
+    push    ecx
+
+    #
+    # Put 0 (dummy) error code on stack, and restore ECX
+    #
+    xor     ecx, ecx  # ECX = 0
+    xchg    ecx, [esp+4]
+
+    jmp     ErrorCodeAndVectorOnStack
+
+HasErrorCode:
+
+    #
+    # Stack:
+    # +---------------------+
+    # +    EFlags           +
+    # +---------------------+
+    # +    CS               +
+    # +---------------------+
+    # +    EIP              +
+    # +---------------------+
+    # +    Error Code       +
+    # +---------------------+
+    # +    ECX              +
+    # +---------------------+ <-- ESP
+    #
+    # Registers:
+    #   ECX - Vector Number
+    #
+
+    #
+    # Put Vector Number on stack and restore ECX
+    #
+    xchg    ecx, [esp]
+
+    #
+    # Fall through to join main routine code
+    # at ErrorCodeAndVectorOnStack
+    #
+CommonInterruptEntry_al_0000:
+    jmp CommonInterruptEntry_al_0000
+
+ErrorCodeAndVectorOnStack:
+    push    ebp
+    mov     ebp, esp
+
+    #
+    # Stack:
+    # +---------------------+
+    # +    EFlags           +
+    # +---------------------+
+    # +    CS               +
+    # +---------------------+
+    # +    EIP              +
+    # +---------------------+
+    # +    Error Code       +
+    # +---------------------+
+    # +    Vector Number    +
+    # +---------------------+
+    # +    EBP              +
+    # +---------------------+ <-- EBP
+    #
+
+    #
+    # Align stack to make sure that EFI_FX_SAVE_STATE_IA32 of EFI_SYSTEM_CONTEXT_IA32
+    # is 16-byte aligned
+    #
+    and     esp, 0x0fffffff0
+    sub     esp, 12
+
+#; UINT32  Edi, Esi, Ebp, Esp, Ebx, Edx, Ecx, Eax;
+    push    eax
+    push    ecx
+    push    edx
+    push    ebx
+    lea     ecx, [ebp + 6 * 4]
+    push    ecx                          # ESP
+    push    dword ptr [ebp]              # EBP
+    push    esi
+    push    edi
+
+#; UINT32  Gs, Fs, Es, Ds, Cs, Ss;
+    mov     eax, ss
+    push    eax
+    movzx   eax, word ptr [ebp + 4 * 4]
+    push    eax
+    mov     eax, ds
+    push    eax
+    mov     eax, es
+    push    eax
+    mov     eax, fs
+    push    eax
+    mov     eax, gs
+    push    eax
+
+#; UINT32  Eip;
+    mov     eax, [ebp + 3 * 4]
+    push    eax
+
+#; UINT32  Gdtr[2], Idtr[2];
+    sub     esp, 8
+    sidt    [esp]
+    mov     eax, [esp + 2]
+    xchg    eax, [esp]
+    and     eax, 0x0FFFF
+    mov     [esp+4], eax
+
+    sub     esp, 8
+    sgdt    [esp]
+    mov     eax, [esp + 2]
+    xchg    eax, [esp]
+    and     eax, 0x0FFFF
+    mov     [esp+4], eax
+
+#; UINT32  Ldtr, Tr;
+    xor     eax, eax
+    str     ax
+    push    eax
+    sldt    ax
+    push    eax
+
+#; UINT32  EFlags;
+    mov     eax, [ebp + 5 * 4]
+    push    eax
+
+#; UINT32  Cr0, Cr1, Cr2, Cr3, Cr4;
+    mov     eax, cr4
+    or      eax, 0x208
+    mov     cr4, eax
+    push    eax
+    mov     eax, cr3
+    push    eax
+    mov     eax, cr2
+    push    eax
+    xor     eax, eax
+    push    eax
+    mov     eax, cr0
+    push    eax
+
+#; UINT32  Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;
+    mov     eax, dr7
+    push    eax
+#; clear Dr7 while executing debugger itself
+    xor     eax, eax
+    mov     dr7, eax
+
+    mov     eax, dr6
+    push    eax
+#; insure all status bits in dr6 are clear...
+    xor     eax, eax
+    mov     dr6, eax
+
+    mov     eax, dr3
+    push    eax
+    mov     eax, dr2
+    push    eax
+    mov     eax, dr1
+    push    eax
+    mov     eax, dr0
+    push    eax
+
+#; FX_SAVE_STATE_IA32 FxSaveState;
+    sub     esp, 512
+    mov     edi, esp
+    .byte      0x0f, 0x0ae, 0x07 #fxsave [edi]
+
+#; UINT32  ExceptionData;
+    push    dword ptr [ebp + 2 * 4]
+
+#; call into exception handler
+    mov     eax, ExternalVectorTablePtr  # get the interrupt vectors base
+    or      eax, eax                        # NULL?
+    jz      nullExternalExceptionHandler
+
+    mov     ecx, [ebp + 4]
+    mov     eax, [eax + ecx * 4]
+    or      eax, eax                        # NULL?
+    jz      nullExternalExceptionHandler
+
+#; Prepare parameter and call
+    mov     edx, esp
+    push    edx
+    mov     edx, dword ptr [ebp + 1 * 4]
+    push    edx
+
+    #
+    # Call External Exception Handler
+    #
+    call    eax
+    add     esp, 8
+
+nullExternalExceptionHandler:
+
+    cli
+#; UINT32  ExceptionData;
+    add     esp, 4
+
+#; FX_SAVE_STATE_IA32 FxSaveState;
+    mov     esi, esp
+    .byte      0x0f, 0x0ae, 0x0e # fxrstor [esi]
+    add     esp, 512
+
+#; UINT32  Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;
+    pop     eax
+    mov     dr0, eax
+    pop     eax
+    mov     dr1, eax
+    pop     eax
+    mov     dr2, eax
+    pop     eax
+    mov     dr3, eax
+#; skip restore of dr6.  We cleared dr6 during the context save.
+    add     esp, 4
+    pop     eax
+    mov     dr7, eax
+
+#; UINT32  Cr0, Cr1, Cr2, Cr3, Cr4;
+    pop     eax
+    mov     cr0, eax
+    add     esp, 4    # not for Cr1
+    pop     eax
+    mov     cr2, eax
+    pop     eax
+    mov     cr3, eax
+    pop     eax
+    mov     cr4, eax
+
+#; UINT32  EFlags;
+    pop     dword ptr [ebp + 5 * 4]
+
+#; UINT32  Ldtr, Tr;
+#; UINT32  Gdtr[2], Idtr[2];
+#; Best not let anyone mess with these particular registers...
+    add     esp, 24
+
+#; UINT32  Eip;
+    pop     dword ptr [ebp + 3 * 4]
+
+#; UINT32  Gs, Fs, Es, Ds, Cs, Ss;
+#; NOTE - modified segment registers could hang the debugger...  We
+#;        could attempt to insulate ourselves against this possibility,
+#;        but that poses risks as well.
+#;
+    pop     gs
+    pop     fs
+    pop     es
+    pop     ds
+    pop     dword ptr [ebp + 4 * 4]
+    pop     ss
+
+#; UINT32  Edi, Esi, Ebp, Esp, Ebx, Edx, Ecx, Eax;
+    pop     edi
+    pop     esi
+    add     esp, 4   # not for ebp
+    add     esp, 4   # not for esp
+    pop     ebx
+    pop     edx
+    pop     ecx
+    pop     eax
+
+    mov     esp, ebp
+    pop     ebp
+    add     esp, 8
+    iretd
+
+
+#END
+
diff --git a/UefiCpuPkg/CpuDxe/Ia32/CpuAsm.asm b/UefiCpuPkg/CpuDxe/Ia32/CpuAsm.asm
new file mode 100755 (executable)
index 0000000..dfcbc0d
--- /dev/null
@@ -0,0 +1,384 @@
+      TITLE   CpuAsm.asm:\r
+;------------------------------------------------------------------------------\r
+;*\r
+;*   Copyright 2006 - 2009, Intel Corporation\r
+;*   All rights reserved. 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
+;*    CpuAsm.asm\r
+;*\r
+;*   Abstract:\r
+;*\r
+;------------------------------------------------------------------------------\r
+\r
+    .686\r
+    .model  flat,C\r
+    .code\r
+\r
+EXTRN mErrorCodeFlag:DWORD ; Error code flags for exceptions\r
+\r
+;\r
+; point to the external interrupt vector table\r
+;\r
+ExternalVectorTablePtr DWORD 0\r
+\r
+InitializeExternalVectorTablePtr PROC PUBLIC\r
+    mov     eax, [esp+4]\r
+    mov     ExternalVectorTablePtr, eax\r
+    ret\r
+InitializeExternalVectorTablePtr ENDP\r
+\r
+;------------------------------------------------------------------------------\r
+; VOID\r
+; SetCodeSelector (\r
+;   UINT16 Selector\r
+;   );\r
+;------------------------------------------------------------------------------\r
+SetCodeSelector PROC PUBLIC\r
+    mov     ecx, [esp+4]\r
+    sub     esp, 0x10\r
+    lea     eax, setCodeSelectorLongJump\r
+    mov     [esp], eax\r
+    mov     [esp+4], cx\r
+    jmp     fword ptr [esp]\r
+setCodeSelectorLongJump:\r
+    add     esp, 0x10\r
+    ret\r
+SetCodeSelector ENDP\r
+\r
+;------------------------------------------------------------------------------\r
+; VOID\r
+; SetDataSelectors (\r
+;   UINT16 Selector\r
+;   );\r
+;------------------------------------------------------------------------------\r
+SetDataSelectors PROC PUBLIC\r
+    mov     ecx, [esp+4]\r
+    mov     ss, cx\r
+    mov     ds, cx\r
+    mov     es, cx\r
+    mov     fs, cx\r
+    mov     gs, cx\r
+    ret\r
+SetDataSelectors ENDP\r
+\r
+;---------------------------------------;\r
+; CommonInterruptEntry                  ;\r
+;---------------------------------------;\r
+; The follow algorithm is used for the common interrupt routine.\r
+\r
+CommonInterruptEntry PROC PUBLIC\r
+    cli\r
+    ;\r
+    ; All interrupt handlers are invoked through interrupt gates, so\r
+    ; IF flag automatically cleared at the entry point\r
+    ;\r
+\r
+    ;\r
+    ; Calculate vector number\r
+    ;\r
+    ; Get the return address of call, actually, it is the\r
+    ; address of vector number.\r
+    ;\r
+    xchg    ecx, [esp]\r
+    mov     cx, [ecx]\r
+    and     ecx, 0FFFFh\r
+    cmp     ecx, 32         ; Intel reserved vector for exceptions?\r
+    jae     NoErrorCode\r
+    bt      mErrorCodeFlag, ecx\r
+    jc      HasErrorCode\r
+\r
+NoErrorCode:\r
+\r
+    ;\r
+    ; Stack:\r
+    ; +---------------------+\r
+    ; +    EFlags           +\r
+    ; +---------------------+\r
+    ; +    CS               +\r
+    ; +---------------------+\r
+    ; +    EIP              +\r
+    ; +---------------------+\r
+    ; +    ECX              +\r
+    ; +---------------------+ <-- ESP\r
+    ;\r
+    ; Registers:\r
+    ;   ECX - Vector Number\r
+    ;\r
+\r
+    ;\r
+    ; Put Vector Number on stack\r
+    ;\r
+    push    ecx\r
+\r
+    ;\r
+    ; Put 0 (dummy) error code on stack, and restore ECX\r
+    ;\r
+    xor     ecx, ecx  ; ECX = 0\r
+    xchg    ecx, [esp+4]\r
+\r
+    jmp     ErrorCodeAndVectorOnStack\r
+\r
+HasErrorCode:\r
+\r
+    ;\r
+    ; Stack:\r
+    ; +---------------------+\r
+    ; +    EFlags           +\r
+    ; +---------------------+\r
+    ; +    CS               +\r
+    ; +---------------------+\r
+    ; +    EIP              +\r
+    ; +---------------------+\r
+    ; +    Error Code       +\r
+    ; +---------------------+\r
+    ; +    ECX              +\r
+    ; +---------------------+ <-- ESP\r
+    ;\r
+    ; Registers:\r
+    ;   ECX - Vector Number\r
+    ;\r
+\r
+    ;\r
+    ; Put Vector Number on stack and restore ECX\r
+    ;\r
+    xchg    ecx, [esp]\r
+\r
+    ;\r
+    ; Fall through to join main routine code\r
+    ; at ErrorCodeAndVectorOnStack\r
+    ;\r
+@@:\r
+    jmp @B\r
+\r
+ErrorCodeAndVectorOnStack:\r
+    push    ebp\r
+    mov     ebp, esp\r
+\r
+    ;\r
+    ; Stack:\r
+    ; +---------------------+\r
+    ; +    EFlags           +\r
+    ; +---------------------+\r
+    ; +    CS               +\r
+    ; +---------------------+\r
+    ; +    EIP              +\r
+    ; +---------------------+\r
+    ; +    Error Code       +\r
+    ; +---------------------+\r
+    ; +    Vector Number    +\r
+    ; +---------------------+\r
+    ; +    EBP              +\r
+    ; +---------------------+ <-- EBP\r
+    ;\r
+\r
+    ;\r
+    ; Align stack to make sure that EFI_FX_SAVE_STATE_IA32 of EFI_SYSTEM_CONTEXT_IA32\r
+    ; is 16-byte aligned\r
+    ;\r
+    and     esp, 0fffffff0h\r
+    sub     esp, 12\r
+\r
+;; UINT32  Edi, Esi, Ebp, Esp, Ebx, Edx, Ecx, Eax;\r
+    push    eax\r
+    push    ecx\r
+    push    edx\r
+    push    ebx\r
+    lea     ecx, [ebp + 6 * 4]\r
+    push    ecx                          ; ESP\r
+    push    dword ptr [ebp]              ; EBP\r
+    push    esi\r
+    push    edi\r
+\r
+;; UINT32  Gs, Fs, Es, Ds, Cs, Ss;\r
+    mov     eax, ss\r
+    push    eax\r
+    movzx   eax, word ptr [ebp + 4 * 4]\r
+    push    eax\r
+    mov     eax, ds\r
+    push    eax\r
+    mov     eax, es\r
+    push    eax\r
+    mov     eax, fs\r
+    push    eax\r
+    mov     eax, gs\r
+    push    eax\r
+\r
+;; UINT32  Eip;\r
+    mov     eax, [ebp + 3 * 4]\r
+    push    eax\r
+\r
+;; UINT32  Gdtr[2], Idtr[2];\r
+    sub     esp, 8\r
+    sidt    [esp]\r
+    mov     eax, [esp + 2]\r
+    xchg    eax, [esp]\r
+    and     eax, 0FFFFh\r
+    mov     [esp+4], eax\r
+\r
+    sub     esp, 8\r
+    sgdt    [esp]\r
+    mov     eax, [esp + 2]\r
+    xchg    eax, [esp]\r
+    and     eax, 0FFFFh\r
+    mov     [esp+4], eax\r
+\r
+;; UINT32  Ldtr, Tr;\r
+    xor     eax, eax\r
+    str     ax\r
+    push    eax\r
+    sldt    ax\r
+    push    eax\r
+\r
+;; UINT32  EFlags;\r
+    mov     eax, [ebp + 5 * 4]\r
+    push    eax\r
+\r
+;; UINT32  Cr0, Cr1, Cr2, Cr3, Cr4;\r
+    mov     eax, cr4\r
+    or      eax, 208h\r
+    mov     cr4, eax\r
+    push    eax\r
+    mov     eax, cr3\r
+    push    eax\r
+    mov     eax, cr2\r
+    push    eax\r
+    xor     eax, eax\r
+    push    eax\r
+    mov     eax, cr0\r
+    push    eax\r
+\r
+;; UINT32  Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;\r
+    mov     eax, dr7\r
+    push    eax\r
+;; clear Dr7 while executing debugger itself\r
+    xor     eax, eax\r
+    mov     dr7, eax\r
+\r
+    mov     eax, dr6\r
+    push    eax\r
+;; insure all status bits in dr6 are clear...\r
+    xor     eax, eax\r
+    mov     dr6, eax\r
+\r
+    mov     eax, dr3\r
+    push    eax\r
+    mov     eax, dr2\r
+    push    eax\r
+    mov     eax, dr1\r
+    push    eax\r
+    mov     eax, dr0\r
+    push    eax\r
+\r
+;; FX_SAVE_STATE_IA32 FxSaveState;\r
+    sub     esp, 512\r
+    mov     edi, esp\r
+    db      0fh, 0aeh, 07h ;fxsave [edi]\r
+\r
+;; UINT32  ExceptionData;\r
+    push    dword ptr [ebp + 2 * 4]\r
+\r
+;; call into exception handler\r
+    mov     eax, ExternalVectorTablePtr  ; get the interrupt vectors base\r
+    or      eax, eax                        ; NULL?\r
+    jz      nullExternalExceptionHandler\r
+\r
+    mov     ecx, [ebp + 4]\r
+    mov     eax, [eax + ecx * 4]\r
+    or      eax, eax                        ; NULL?\r
+    jz      nullExternalExceptionHandler\r
+\r
+;; Prepare parameter and call\r
+    mov     edx, esp\r
+    push    edx\r
+    mov     edx, dword ptr [ebp + 1 * 4]\r
+    push    edx\r
+\r
+    ;\r
+    ; Call External Exception Handler\r
+    ;\r
+    call    eax\r
+    add     esp, 8\r
+\r
+nullExternalExceptionHandler:\r
+\r
+    cli\r
+;; UINT32  ExceptionData;\r
+    add     esp, 4\r
+\r
+;; FX_SAVE_STATE_IA32 FxSaveState;\r
+    mov     esi, esp\r
+    db      0fh, 0aeh, 0eh ; fxrstor [esi]\r
+    add     esp, 512\r
+\r
+;; UINT32  Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;\r
+    pop     eax\r
+    mov     dr0, eax\r
+    pop     eax\r
+    mov     dr1, eax\r
+    pop     eax\r
+    mov     dr2, eax\r
+    pop     eax\r
+    mov     dr3, eax\r
+;; skip restore of dr6.  We cleared dr6 during the context save.\r
+    add     esp, 4\r
+    pop     eax\r
+    mov     dr7, eax\r
+\r
+;; UINT32  Cr0, Cr1, Cr2, Cr3, Cr4;\r
+    pop     eax\r
+    mov     cr0, eax\r
+    add     esp, 4    ; not for Cr1\r
+    pop     eax\r
+    mov     cr2, eax\r
+    pop     eax\r
+    mov     cr3, eax\r
+    pop     eax\r
+    mov     cr4, eax\r
+\r
+;; UINT32  EFlags;\r
+    pop     dword ptr [ebp + 5 * 4]\r
+\r
+;; UINT32  Ldtr, Tr;\r
+;; UINT32  Gdtr[2], Idtr[2];\r
+;; Best not let anyone mess with these particular registers...\r
+    add     esp, 24\r
+\r
+;; UINT32  Eip;\r
+    pop     dword ptr [ebp + 3 * 4]\r
+\r
+;; UINT32  Gs, Fs, Es, Ds, Cs, Ss;\r
+;; NOTE - modified segment registers could hang the debugger...  We\r
+;;        could attempt to insulate ourselves against this possibility,\r
+;;        but that poses risks as well.\r
+;;\r
+    pop     gs\r
+    pop     fs\r
+    pop     es\r
+    pop     ds\r
+    pop     dword ptr [ebp + 4 * 4]\r
+    pop     ss\r
+\r
+;; UINT32  Edi, Esi, Ebp, Esp, Ebx, Edx, Ecx, Eax;\r
+    pop     edi\r
+    pop     esi\r
+    add     esp, 4   ; not for ebp\r
+    add     esp, 4   ; not for esp\r
+    pop     ebx\r
+    pop     edx\r
+    pop     ecx\r
+    pop     eax\r
+\r
+    mov     esp, ebp\r
+    pop     ebp\r
+    add     esp, 8\r
+    iretd\r
+\r
+CommonInterruptEntry ENDP\r
+\r
+END\r
diff --git a/UefiCpuPkg/CpuDxe/Ia32/IvtAsm.S b/UefiCpuPkg/CpuDxe/Ia32/IvtAsm.S
new file mode 100755 (executable)
index 0000000..2a6341a
--- /dev/null
@@ -0,0 +1,66 @@
+#------------------------------------------------------------------------------
+#
+# Copyright (c) 2006 - 2009, Intel Corporation
+# All rights reserved. This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution.  The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+# Module Name:
+#
+#   IvtAsm.S
+#
+# Abstract:
+#
+#   Interrupt Vector Table
+#
+#------------------------------------------------------------------------------
+
+#
+# Interrupt Vector Table
+#
+
+.macro SingleIdtVectorMacro vectorNum
+    .intel_syntax
+    call    ASM_PFX(CommonInterruptEntry)
+    .short  \vectorNum
+    nop
+.endm
+
+.macro EightIdtVectors firstVectorNum
+    SingleIdtVectorMacro \firstVectorNum
+    SingleIdtVectorMacro "(\firstVectorNum+1)"
+    SingleIdtVectorMacro "(\firstVectorNum+2)"
+    SingleIdtVectorMacro "(\firstVectorNum+3)"
+    SingleIdtVectorMacro "(\firstVectorNum+4)"
+    SingleIdtVectorMacro "(\firstVectorNum+5)"
+    SingleIdtVectorMacro "(\firstVectorNum+6)"
+    SingleIdtVectorMacro "(\firstVectorNum+7)"
+.endm
+
+.macro SixtyFourIdtVectors firstVectorNum
+    EightIdtVectors \firstVectorNum
+    EightIdtVectors "(\firstVectorNum+0x08)"
+    EightIdtVectors "(\firstVectorNum+0x10)"
+    EightIdtVectors "(\firstVectorNum+0x18)"
+    EightIdtVectors "(\firstVectorNum+0x20)"
+    EightIdtVectors "(\firstVectorNum+0x28)"
+    EightIdtVectors "(\firstVectorNum+0x30)"
+    EightIdtVectors "(\firstVectorNum+0x38)"
+.endm
+
+ASM_GLOBAL ASM_PFX(AsmIdtVector00)
+.align  8
+ASM_PFX(AsmIdtVector00):
+    SixtyFourIdtVectors 0x00
+    SixtyFourIdtVectors 0x40
+    SixtyFourIdtVectors 0x80
+    SixtyFourIdtVectors 0xC0
+ASM_GLOBAL ASM_PFX(AsmCommonIdtEnd)
+ASM_PFX(AsmCommonIdtEnd):
+    .byte 0
+
+
diff --git a/UefiCpuPkg/CpuDxe/Ia32/IvtAsm.asm b/UefiCpuPkg/CpuDxe/Ia32/IvtAsm.asm
new file mode 100755 (executable)
index 0000000..e5dfaac
--- /dev/null
@@ -0,0 +1,51 @@
+      TITLE   IvtAsm.asm:\r
+;------------------------------------------------------------------------------\r
+;*\r
+;*   Copyright 2008 - 2009, Intel Corporation\r
+;*   All rights reserved. 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
+;*    IvtAsm.asm\r
+;*\r
+;*   Abstract:\r
+;*\r
+;------------------------------------------------------------------------------\r
+\r
+#include <Base.h>\r
+\r
+#ifdef MDE_CPU_IA32\r
+    .686\r
+    .model  flat,C\r
+#endif\r
+    .code\r
+\r
+;------------------------------------------------------------------------------\r
+;  Generic IDT Vector Handlers for the Host. They are all the same so they\r
+;  will compress really well.\r
+;\r
+;  By knowing the return address for Vector 00 you can can calculate the\r
+;  vector number by looking at the call CommonInterruptEntry return address.\r
+;  (return address - (AsmIdtVector00 + 5))/8 == IDT index\r
+;\r
+;------------------------------------------------------------------------------\r
+\r
+EXTRN CommonInterruptEntry:PROC\r
+\r
+ALIGN   8\r
+\r
+PUBLIC AsmIdtVector00\r
+\r
+AsmIdtVector00 LABEL BYTE\r
+REPEAT  256\r
+    call    CommonInterruptEntry\r
+    dw      ($ - AsmIdtVector00 - 5) / 8 ; vector number\r
+    nop\r
+ENDM\r
+\r
+END\r
+\r
diff --git a/UefiCpuPkg/CpuDxe/X64/CpuAsm.S b/UefiCpuPkg/CpuDxe/X64/CpuAsm.S
new file mode 100755 (executable)
index 0000000..9d4c261
--- /dev/null
@@ -0,0 +1,363 @@
+#      TITLE   CpuAsm.asm: 
+
+#------------------------------------------------------------------------------
+#*
+#*   Copyright 2008 - 2009, Intel Corporation
+#*   All rights reserved. This program and the accompanying materials
+#*   are licensed and made available under the terms and conditions of the BSD License
+#*   which accompanies this distribution.  The full text of the license may be found at
+#*   http://opensource.org/licenses/bsd-license.php
+#*
+#*   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+#*   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#*
+#*    CpuAsm.S
+#*
+#*   Abstract:
+#*
+#------------------------------------------------------------------------------
+
+
+#text  SEGMENT
+
+
+#EXTRN ASM_PFX(mErrorCodeFlag):DWORD # Error code flags for exceptions
+
+
+#
+# point to the external interrupt vector table
+#
+ExternalVectorTablePtr:
+    .byte      0, 0, 0, 0, 0, 0, 0, 0
+
+.intel_syntax
+ASM_GLOBAL ASM_PFX(InitializeExternalVectorTablePtr)
+ASM_PFX(InitializeExternalVectorTablePtr):
+    lea     %rax, [%rip+ExternalVectorTablePtr] # save vector number
+    mov     [%rax], %rcx
+    ret
+
+
+#------------------------------------------------------------------------------
+# VOID
+# SetCodeSelector (
+#   UINT16 Selector
+#   );
+#------------------------------------------------------------------------------
+.intel_syntax
+ASM_GLOBAL ASM_PFX(SetCodeSelector)
+ASM_PFX(SetCodeSelector):
+    sub     %rsp, 0x10
+    lea     %rax, [%rip+setCodeSelectorLongJump]
+    mov     [%rsp], %rax
+    mov     [%rsp+4], %cx
+    jmp     fword ptr [%rsp]
+setCodeSelectorLongJump:
+    add     %rsp, 0x10
+    ret
+
+#------------------------------------------------------------------------------
+# VOID
+# SetDataSelectors (
+#   UINT16 Selector
+#   );
+#------------------------------------------------------------------------------
+.intel_syntax
+ASM_GLOBAL ASM_PFX(SetDataSelectors)
+ASM_PFX(SetDataSelectors):
+    mov     %ss, %cx
+    mov     %ds, %cx
+    mov     %es, %cx
+    mov     %fs, %cx
+    mov     %gs, %cx
+    ret
+
+#---------------------------------------;
+# CommonInterruptEntry                  ;
+#---------------------------------------;
+# The follow algorithm is used for the common interrupt routine.
+
+.intel_syntax
+ASM_GLOBAL ASM_PFX(CommonInterruptEntry)
+ASM_PFX(CommonInterruptEntry):
+    cli
+    #
+    # All interrupt handlers are invoked through interrupt gates, so
+    # IF flag automatically cleared at the entry point
+    #
+    #
+    # Calculate vector number
+    #
+    xchg    %rcx, [%rsp] # get the return address of call, actually, it is the address of vector number.
+    movzx   %ecx, word ptr [%rcx]
+    cmp     %ecx, 32         # Intel reserved vector for exceptions?
+    jae     NoErrorCode
+    push    %rax
+    lea     %rax, [%rip+ASM_PFX(mErrorCodeFlag)]
+    bt      dword ptr [%rax], %ecx
+    pop     %rax
+    jc      CommonInterruptEntry_al_0000
+
+NoErrorCode:
+
+    #
+    # Push a dummy error code on the stack
+    # to maintain coherent stack map
+    #
+    push    [%rsp]
+    mov     qword ptr [%rsp + 8], 0
+CommonInterruptEntry_al_0000:
+    push    %rbp
+    mov     %rbp, %rsp
+
+    #
+    # Stack:
+    # +---------------------+ <-- 16-byte aligned ensured by processor
+    # +    Old SS           +
+    # +---------------------+
+    # +    Old RSP          +
+    # +---------------------+
+    # +    RFlags           +
+    # +---------------------+
+    # +    CS               +
+    # +---------------------+
+    # +    RIP              +
+    # +---------------------+
+    # +    Error Code       +
+    # +---------------------+
+    # + RCX / Vector Number +
+    # +---------------------+
+    # +    RBP              +
+    # +---------------------+ <-- RBP, 16-byte aligned
+    #
+
+
+    #
+    # Since here the stack pointer is 16-byte aligned, so
+    # EFI_FX_SAVE_STATE_X64 of EFI_SYSTEM_CONTEXT_x64
+    # is 16-byte aligned
+    #
+
+#; UINT64  Rdi, Rsi, Rbp, Rsp, Rbx, Rdx, Rcx, Rax;
+#; UINT64  R8, R9, R10, R11, R12, R13, R14, R15;
+    push    %r15
+    push    %r14
+    push    %r13
+    push    %r12
+    push    %r11
+    push    %r10
+    push    %r9
+    push    %r8
+    push    %rax
+    push    qword ptr [%rbp + 8]   # RCX
+    push    %rdx
+    push    %rbx
+    push    qword ptr [%rbp + 48]  # RSP
+    push    qword ptr [%rbp]       # RBP
+    push    %rsi
+    push    %rdi
+
+#; UINT64  Gs, Fs, Es, Ds, Cs, Ss;  insure high 16 bits of each is zero
+    movzx   %rax, word ptr [%rbp + 56]
+    push    %rax                      # for ss
+    movzx   %rax, word ptr [%rbp + 32]
+    push    %rax                      # for cs
+    mov     %rax, %ds
+    push    %rax
+    mov     %rax, %es
+    push    %rax
+    mov     %rax, %fs
+    push    %rax
+    mov     %rax, %gs
+    push    %rax
+
+    mov     [%rbp + 8], %rcx               # save vector number
+
+#; UINT64  Rip;
+    push    qword ptr [%rbp + 24]
+
+#; UINT64  Gdtr[2], Idtr[2];
+    xor     %rax, %rax
+    push    %rax
+    push    %rax
+    sidt    [%rsp]
+    xchg    %rax, [%rsp + 2]
+    xchg    %rax, [%rsp]
+    xchg    %rax, [%rsp + 8]
+
+    xor     %rax, %rax
+    push    %rax
+    push    %rax
+    sgdt    [%rsp]
+    xchg    %rax, [%rsp + 2]
+    xchg    %rax, [%rsp]
+    xchg    %rax, [%rsp + 8]
+
+#; UINT64  Ldtr, Tr;
+    xor     %rax, %rax
+    str     %ax
+    push    %rax
+    sldt    %ax
+    push    %rax
+
+#; UINT64  RFlags;
+    push    qword ptr [%rbp + 40]
+
+#; UINT64  Cr0, Cr1, Cr2, Cr3, Cr4, Cr8;
+    mov     %rax, %cr8
+    push    %rax
+    mov     %rax, %cr4
+    or      %rax, 0x208
+    mov     %cr4, %rax
+    push    %rax
+    mov     %rax, %cr3
+    push    %rax
+    mov     %rax, %cr2
+    push    %rax
+    xor     %rax, %rax
+    push    %rax
+    mov     %rax, %cr0
+    push    %rax
+
+#; UINT64  Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;
+    mov     %rax, %dr7
+    push    %rax
+#; clear Dr7 while executing debugger itself
+    xor     %rax, %rax
+    mov     %dr7, %rax
+
+    mov     %rax, %dr6
+    push    %rax
+#; insure all status bits in dr6 are clear...
+    xor     %rax, %rax
+    mov     %dr6, %rax
+
+    mov     %rax, %dr3
+    push    %rax
+    mov     %rax, %dr2
+    push    %rax
+    mov     %rax, %dr1
+    push    %rax
+    mov     %rax, %dr0
+    push    %rax
+
+#; FX_SAVE_STATE_X64 FxSaveState;
+    sub     %rsp, 512
+    mov     %rdi, %rsp
+    .byte 0x0f, 0x0ae, 0x07 #fxsave [rdi]
+
+#; UINT32  ExceptionData;
+    push    qword ptr [%rbp + 16]
+
+#; call into exception handler
+    mov     %rcx, [%rbp + 8]
+    lea     %rax, [%rip+ExternalVectorTablePtr]
+    mov     %eax, [%eax]
+    mov     %rax, [%rax + %rcx * 8]
+    or      %rax, %rax                        # NULL?
+
+    je    nonNullValue#
+
+#; Prepare parameter and call
+#  mov     rcx, [rbp + 8]
+    mov     %rdx, %rsp
+    #
+    # Per X64 calling convention, allocate maximum parameter stack space
+    # and make sure RSP is 16-byte aligned
+    #
+    sub     %rsp, 4 * 8 + 8
+    call    %rax
+    add     %rsp, 4 * 8 + 8
+
+nonNullValue:
+    cli
+#; UINT64  ExceptionData;
+    add     %rsp, 8
+
+#; FX_SAVE_STATE_X64 FxSaveState;
+
+    mov     %rsi, %rsp
+    .byte   0x0f, 0x0ae, 0x0E # fxrstor [rsi]
+    add     %rsp, 512
+
+#; UINT64  Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;
+    pop     %rax
+    mov     %dr0, %rax
+    pop     %rax
+    mov     %dr1, %rax
+    pop     %rax
+    mov     %dr2, %rax
+    pop     %rax
+    mov     %dr3, %rax
+#; skip restore of dr6.  We cleared dr6 during the context save.
+    add     %rsp, 8
+    pop     %rax
+    mov     %dr7, %rax
+
+#; UINT64  Cr0, Cr1, Cr2, Cr3, Cr4, Cr8;
+    pop     %rax
+    mov     %cr0, %rax
+    add     %rsp, 8   # not for Cr1
+    pop     %rax
+    mov     %cr2, %rax
+    pop     %rax
+    mov     %cr3, %rax
+    pop     %rax
+    mov     %cr4, %rax
+    pop     %rax
+    mov     %cr8, %rax
+
+#; UINT64  RFlags;
+    pop     qword ptr [%rbp + 40]
+
+#; UINT64  Ldtr, Tr;
+#; UINT64  Gdtr[2], Idtr[2];
+#; Best not let anyone mess with these particular registers...
+    add     %rsp, 48
+
+#; UINT64  Rip;
+    pop     qword ptr [%rbp + 24]
+
+#; UINT64  Gs, Fs, Es, Ds, Cs, Ss;
+    pop     %rax
+    # mov     gs, rax ; not for gs
+    pop     %rax
+    # mov     fs, rax ; not for fs
+    # (X64 will not use fs and gs, so we do not restore it)
+    pop     %rax
+    mov     %es, %rax
+    pop     %rax
+    mov     %ds, %rax
+    pop     qword ptr [%rbp + 32]  # for cs
+    pop     qword ptr [%rbp + 56]  # for ss
+
+#; UINT64  Rdi, Rsi, Rbp, Rsp, Rbx, Rdx, Rcx, Rax;
+#; UINT64  R8, R9, R10, R11, R12, R13, R14, R15;
+    pop     %rdi
+    pop     %rsi
+    add     %rsp, 8               # not for rbp
+    pop     qword ptr [%rbp + 48] # for rsp
+    pop     %rbx
+    pop     %rdx
+    pop     %rcx
+    pop     %rax
+    pop     %r8
+    pop     %r9
+    pop     %r10
+    pop     %r11
+    pop     %r12
+    pop     %r13
+    pop     %r14
+    pop     %r15
+
+    mov     %rsp, %rbp
+    pop     %rbp
+    add     %rsp, 16
+    iretq
+
+
+#text  ENDS
+
+#END
+
+
diff --git a/UefiCpuPkg/CpuDxe/X64/CpuAsm.asm b/UefiCpuPkg/CpuDxe/X64/CpuAsm.asm
new file mode 100755 (executable)
index 0000000..05d9bca
--- /dev/null
@@ -0,0 +1,345 @@
+      TITLE   CpuAsm.asm: \r
+;------------------------------------------------------------------------------\r
+;*\r
+;*   Copyright 2008 - 2009, Intel Corporation                                                         \r
+;*   All rights reserved. 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
+;*    CpuAsm.asm\r
+;*  \r
+;*   Abstract:\r
+;*\r
+;------------------------------------------------------------------------------\r
+\r
+    .code\r
+\r
+EXTRN mErrorCodeFlag:DWORD ; Error code flags for exceptions\r
+\r
+;\r
+; point to the external interrupt vector table\r
+;\r
+ExternalVectorTablePtr QWORD 0\r
+\r
+InitializeExternalVectorTablePtr PROC PUBLIC\r
+    mov  ExternalVectorTablePtr, rcx\r
+    ret\r
+InitializeExternalVectorTablePtr ENDP\r
+\r
+;------------------------------------------------------------------------------\r
+; VOID\r
+; SetCodeSelector (\r
+;   UINT16 Selector\r
+;   );\r
+;------------------------------------------------------------------------------\r
+SetCodeSelector PROC PUBLIC\r
+    sub     rsp, 0x10\r
+    lea     rax, setCodeSelectorLongJump\r
+    mov     [rsp], rax\r
+    mov     [rsp+4], cx\r
+    jmp     fword ptr [rsp]\r
+setCodeSelectorLongJump:\r
+    add     rsp, 0x10\r
+    ret\r
+SetCodeSelector ENDP\r
+\r
+;------------------------------------------------------------------------------\r
+; VOID\r
+; SetDataSelectors (\r
+;   UINT16 Selector\r
+;   );\r
+;------------------------------------------------------------------------------\r
+SetDataSelectors PROC PUBLIC\r
+    mov     ss, cx\r
+    mov     ds, cx\r
+    mov     es, cx\r
+    mov     fs, cx\r
+    mov     gs, cx\r
+    ret\r
+SetDataSelectors ENDP\r
+\r
+;---------------------------------------;\r
+; CommonInterruptEntry                  ;\r
+;---------------------------------------;\r
+; The follow algorithm is used for the common interrupt routine.\r
+\r
+CommonInterruptEntry PROC PUBLIC  \r
+    cli\r
+    ;\r
+    ; All interrupt handlers are invoked through interrupt gates, so\r
+    ; IF flag automatically cleared at the entry point\r
+    ;\r
+    ;\r
+    ; Calculate vector number\r
+    ;\r
+    xchg    rcx, [rsp] ; get the return address of call, actually, it is the address of vector number.\r
+    movzx   ecx, word ptr [rcx]\r
+    cmp     ecx, 32         ; Intel reserved vector for exceptions?\r
+    jae     NoErrorCode\r
+    bt      mErrorCodeFlag, ecx\r
+    jc      @F\r
+\r
+NoErrorCode:\r
+\r
+    ;\r
+    ; Push a dummy error code on the stack\r
+    ; to maintain coherent stack map\r
+    ;\r
+    push    [rsp]\r
+    mov     qword ptr [rsp + 8], 0\r
+@@:       \r
+    push    rbp\r
+    mov     rbp, rsp\r
+\r
+    ;\r
+    ; Stack:\r
+    ; +---------------------+ <-- 16-byte aligned ensured by processor\r
+    ; +    Old SS           +\r
+    ; +---------------------+\r
+    ; +    Old RSP          +\r
+    ; +---------------------+\r
+    ; +    RFlags           +\r
+    ; +---------------------+\r
+    ; +    CS               +\r
+    ; +---------------------+\r
+    ; +    RIP              +\r
+    ; +---------------------+\r
+    ; +    Error Code       +\r
+    ; +---------------------+\r
+    ; + RCX / Vector Number +\r
+    ; +---------------------+\r
+    ; +    RBP              +\r
+    ; +---------------------+ <-- RBP, 16-byte aligned\r
+    ;\r
+\r
+\r
+    ;\r
+    ; Since here the stack pointer is 16-byte aligned, so\r
+    ; EFI_FX_SAVE_STATE_X64 of EFI_SYSTEM_CONTEXT_x64\r
+    ; is 16-byte aligned\r
+    ;\r
+\r
+;; UINT64  Rdi, Rsi, Rbp, Rsp, Rbx, Rdx, Rcx, Rax;\r
+;; UINT64  R8, R9, R10, R11, R12, R13, R14, R15;\r
+    push r15\r
+    push r14\r
+    push r13\r
+    push r12\r
+    push r11\r
+    push r10\r
+    push r9\r
+    push r8\r
+    push rax\r
+    push qword ptr [rbp + 8]   ; RCX\r
+    push rdx\r
+    push rbx\r
+    push qword ptr [rbp + 48]  ; RSP\r
+    push qword ptr [rbp]       ; RBP\r
+    push rsi\r
+    push rdi\r
+\r
+;; UINT64  Gs, Fs, Es, Ds, Cs, Ss;  insure high 16 bits of each is zero\r
+    movzx   rax, word ptr [rbp + 56]\r
+    push    rax                      ; for ss\r
+    movzx   rax, word ptr [rbp + 32]\r
+    push    rax                      ; for cs\r
+    mov     rax, ds\r
+    push    rax\r
+    mov     rax, es\r
+    push    rax\r
+    mov     rax, fs\r
+    push    rax\r
+    mov     rax, gs\r
+    push    rax\r
+\r
+    mov     [rbp + 8], rcx               ; save vector number\r
+\r
+;; UINT64  Rip;\r
+    push    qword ptr [rbp + 24]\r
+\r
+;; UINT64  Gdtr[2], Idtr[2];\r
+    xor     rax, rax\r
+    push    rax\r
+    push    rax\r
+    sidt    [rsp]\r
+    xchg    rax, [rsp + 2]\r
+    xchg    rax, [rsp]\r
+    xchg    rax, [rsp + 8]\r
+\r
+    xor     rax, rax\r
+    push    rax\r
+    push    rax\r
+    sgdt    [rsp]\r
+    xchg    rax, [rsp + 2]\r
+    xchg    rax, [rsp]\r
+    xchg    rax, [rsp + 8]\r
+\r
+;; UINT64  Ldtr, Tr;\r
+    xor     rax, rax\r
+    str     ax\r
+    push    rax\r
+    sldt    ax\r
+    push    rax\r
+\r
+;; UINT64  RFlags;\r
+    push    qword ptr [rbp + 40]\r
+\r
+;; UINT64  Cr0, Cr1, Cr2, Cr3, Cr4, Cr8;\r
+    mov     rax, cr8\r
+    push    rax\r
+    mov     rax, cr4\r
+    or      rax, 208h\r
+    mov     cr4, rax\r
+    push    rax\r
+    mov     rax, cr3\r
+    push    rax\r
+    mov     rax, cr2\r
+    push    rax\r
+    xor     rax, rax\r
+    push    rax\r
+    mov     rax, cr0\r
+    push    rax\r
+\r
+;; UINT64  Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;\r
+    mov     rax, dr7\r
+    push    rax\r
+;; clear Dr7 while executing debugger itself\r
+    xor     rax, rax\r
+    mov     dr7, rax\r
+\r
+    mov     rax, dr6\r
+    push    rax\r
+;; insure all status bits in dr6 are clear...\r
+    xor     rax, rax\r
+    mov     dr6, rax\r
+\r
+    mov     rax, dr3\r
+    push    rax\r
+    mov     rax, dr2\r
+    push    rax\r
+    mov     rax, dr1\r
+    push    rax\r
+    mov     rax, dr0\r
+    push    rax\r
+\r
+;; FX_SAVE_STATE_X64 FxSaveState;\r
+    sub rsp, 512\r
+    mov rdi, rsp\r
+    db 0fh, 0aeh, 07h ;fxsave [rdi]\r
+\r
+;; UINT32  ExceptionData;\r
+    push    qword ptr [rbp + 16]\r
+\r
+;; call into exception handler\r
+    mov     rcx, [rbp + 8]\r
+    mov     rax, ExternalVectorTablePtr  ; get the interrupt vectors base\r
+    mov     rax, [rax + rcx * 8]       \r
+    or      rax, rax                        ; NULL?\r
+\r
+    je    nonNullValue;\r
+\r
+;; Prepare parameter and call\r
+;  mov     rcx, [rbp + 8]\r
+    mov     rdx, rsp\r
+    ;\r
+    ; Per X64 calling convention, allocate maximum parameter stack space\r
+    ; and make sure RSP is 16-byte aligned\r
+    ;\r
+    sub     rsp, 4 * 8 + 8\r
+    call    rax\r
+    add     rsp, 4 * 8 + 8\r
+\r
+nonNullValue:\r
+    cli\r
+;; UINT64  ExceptionData;\r
+    add     rsp, 8\r
+\r
+;; FX_SAVE_STATE_X64 FxSaveState;\r
+\r
+    mov rsi, rsp\r
+    db 0fh, 0aeh, 0Eh ; fxrstor [rsi]\r
+    add rsp, 512\r
+\r
+;; UINT64  Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;\r
+    pop     rax\r
+    mov     dr0, rax\r
+    pop     rax\r
+    mov     dr1, rax\r
+    pop     rax\r
+    mov     dr2, rax\r
+    pop     rax\r
+    mov     dr3, rax\r
+;; skip restore of dr6.  We cleared dr6 during the context save.\r
+    add     rsp, 8\r
+    pop     rax\r
+    mov     dr7, rax\r
+\r
+;; UINT64  Cr0, Cr1, Cr2, Cr3, Cr4, Cr8;\r
+    pop     rax\r
+    mov     cr0, rax\r
+    add     rsp, 8   ; not for Cr1\r
+    pop     rax\r
+    mov     cr2, rax\r
+    pop     rax\r
+    mov     cr3, rax\r
+    pop     rax\r
+    mov     cr4, rax\r
+    pop     rax\r
+    mov     cr8, rax\r
+\r
+;; UINT64  RFlags;\r
+    pop     qword ptr [rbp + 40]\r
+\r
+;; UINT64  Ldtr, Tr;\r
+;; UINT64  Gdtr[2], Idtr[2];\r
+;; Best not let anyone mess with these particular registers...\r
+    add     rsp, 48\r
+\r
+;; UINT64  Rip;\r
+    pop     qword ptr [rbp + 24]\r
+\r
+;; UINT64  Gs, Fs, Es, Ds, Cs, Ss;\r
+    pop     rax\r
+    ; mov     gs, rax ; not for gs\r
+    pop     rax\r
+    ; mov     fs, rax ; not for fs\r
+    ; (X64 will not use fs and gs, so we do not restore it)\r
+    pop     rax\r
+    mov     es, rax\r
+    pop     rax\r
+    mov     ds, rax\r
+    pop     qword ptr [rbp + 32]  ; for cs\r
+    pop     qword ptr [rbp + 56]  ; for ss\r
+\r
+;; UINT64  Rdi, Rsi, Rbp, Rsp, Rbx, Rdx, Rcx, Rax;\r
+;; UINT64  R8, R9, R10, R11, R12, R13, R14, R15;\r
+    pop     rdi\r
+    pop     rsi\r
+    add     rsp, 8               ; not for rbp\r
+    pop     qword ptr [rbp + 48] ; for rsp\r
+    pop     rbx\r
+    pop     rdx\r
+    pop     rcx\r
+    pop     rax\r
+    pop     r8\r
+    pop     r9\r
+    pop     r10\r
+    pop     r11\r
+    pop     r12\r
+    pop     r13\r
+    pop     r14\r
+    pop     r15\r
+\r
+    mov     rsp, rbp\r
+    pop     rbp\r
+    add     rsp, 16\r
+    iretq\r
+\r
+CommonInterruptEntry ENDP\r
+\r
+END\r
+\r