diff options
author | jljusten <jljusten@6f19259b-4bc3-4df7-8a09-765794883524> | 2009-05-27 21:09:47 +0000 |
---|---|---|
committer | jljusten <jljusten@6f19259b-4bc3-4df7-8a09-765794883524> | 2009-05-27 21:09:47 +0000 |
commit | a47463f28382bffcedacde0d96965977261d114a (patch) | |
tree | b526ec8f21e4a8a958957ccedb5eb1e0a56c45f7 | |
parent | e50466da24377199d405f9ee6ac44b293f4548ae (diff) | |
download | edk2-a47463f28382bffcedacde0d96965977261d114a.tar.gz edk2-a47463f28382bffcedacde0d96965977261d114a.tar.bz2 edk2-a47463f28382bffcedacde0d96965977261d114a.zip |
Add CPU DXE driver for IA32 & X64 processor architectures.
git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@8395 6f19259b-4bc3-4df7-8a09-765794883524
-rw-r--r-- | UefiCpuPkg/CpuDxe/CpuDxe.c | 1108 | ||||
-rw-r--r-- | UefiCpuPkg/CpuDxe/CpuDxe.h | 140 | ||||
-rw-r--r-- | UefiCpuPkg/CpuDxe/CpuDxe.inf | 67 | ||||
-rwxr-xr-x | UefiCpuPkg/CpuDxe/CpuGdt.c | 200 | ||||
-rwxr-xr-x | UefiCpuPkg/CpuDxe/Ia32/CpuAsm.S | 395 | ||||
-rwxr-xr-x | UefiCpuPkg/CpuDxe/Ia32/CpuAsm.asm | 384 | ||||
-rwxr-xr-x | UefiCpuPkg/CpuDxe/Ia32/IvtAsm.S | 66 | ||||
-rwxr-xr-x | UefiCpuPkg/CpuDxe/Ia32/IvtAsm.asm | 51 | ||||
-rwxr-xr-x | UefiCpuPkg/CpuDxe/X64/CpuAsm.S | 363 | ||||
-rwxr-xr-x | UefiCpuPkg/CpuDxe/X64/CpuAsm.asm | 345 |
10 files changed, 3119 insertions, 0 deletions
diff --git a/UefiCpuPkg/CpuDxe/CpuDxe.c b/UefiCpuPkg/CpuDxe/CpuDxe.c new file mode 100644 index 0000000000..25131febf2 --- /dev/null +++ b/UefiCpuPkg/CpuDxe/CpuDxe.c @@ -0,0 +1,1108 @@ +/** @file
+ CPU DXE Module.
+
+ Copyright (c) 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.
+
+**/
+
+#include "CpuDxe.h"
+
+//
+// Global Variables
+//
+IA32_IDT_GATE_DESCRIPTOR gIdtTable[INTERRUPT_VECTOR_NUMBER] = { 0 };
+
+EFI_CPU_INTERRUPT_HANDLER ExternalVectorTable[0x100];
+BOOLEAN InterruptState = FALSE;
+EFI_HANDLE mCpuHandle = NULL;
+BOOLEAN mIsFlushingGCD;
+UINT8 mDefaultMemoryType = MTRR_CACHE_WRITE_BACK;
+UINT64 mValidMtrrAddressMask = MTRR_LIB_CACHE_VALID_ADDRESS;
+UINT64 mValidMtrrBitsMask = MTRR_LIB_MSR_VALID_MASK;
+
+FIXED_MTRR mFixedMtrrTable[] = {
+ {
+ MTRR_LIB_IA32_MTRR_FIX64K_00000,
+ 0,
+ 0x10000
+ },
+ {
+ MTRR_LIB_IA32_MTRR_FIX16K_80000,
+ 0x80000,
+ 0x4000
+ },
+ {
+ MTRR_LIB_IA32_MTRR_FIX16K_A0000,
+ 0xA0000,
+ 0x4000
+ },
+ {
+ MTRR_LIB_IA32_MTRR_FIX4K_C0000,
+ 0xC0000,
+ 0x1000
+ },
+ {
+ MTRR_LIB_IA32_MTRR_FIX4K_C8000,
+ 0xC8000,
+ 0x1000
+ },
+ {
+ MTRR_LIB_IA32_MTRR_FIX4K_D0000,
+ 0xD0000,
+ 0x1000
+ },
+ {
+ MTRR_LIB_IA32_MTRR_FIX4K_D8000,
+ 0xD8000,
+ 0x1000
+ },
+ {
+ MTRR_LIB_IA32_MTRR_FIX4K_E0000,
+ 0xE0000,
+ 0x1000
+ },
+ {
+ MTRR_LIB_IA32_MTRR_FIX4K_E8000,
+ 0xE8000,
+ 0x1000
+ },
+ {
+ MTRR_LIB_IA32_MTRR_FIX4K_F0000,
+ 0xF0000,
+ 0x1000
+ },
+ {
+ MTRR_LIB_IA32_MTRR_FIX4K_F8000,
+ 0xF8000,
+ 0x1000
+ },
+};
+
+
+EFI_CPU_ARCH_PROTOCOL gCpu = {
+ CpuFlushCpuDataCache,
+ CpuEnableInterrupt,
+ CpuDisableInterrupt,
+ CpuGetInterruptState,
+ CpuInit,
+ CpuRegisterInterruptHandler,
+ CpuGetTimerValue,
+ CpuSetMemoryAttributes,
+ 1, // NumberOfTimers
+ 4 // DmaBufferAlignment
+};
+
+//
+// Error code flag indicating whether or not an error code will be
+// pushed on the stack if an exception occurs.
+//
+// 1 means an error code will be pushed, otherwise 0
+//
+// bit 0 - exception 0
+// bit 1 - exception 1
+// etc.
+//
+UINT32 mErrorCodeFlag = 0x00027d00;
+
+//
+// CPU Arch Protocol Functions
+//
+
+
+/**
+ Common exception handler.
+
+ @param InterruptType Exception type
+ @param SystemContext EFI_SYSTEM_CONTEXT
+
+**/
+VOID
+EFIAPI
+CommonExceptionHandler (
+ IN EFI_EXCEPTION_TYPE InterruptType,
+ IN EFI_SYSTEM_CONTEXT SystemContext
+ )
+{
+#if defined (MDE_CPU_IA32)
+ DEBUG ((
+ EFI_D_ERROR,
+ "!!!! IA32 Exception Type - %08x !!!!\n",
+ InterruptType
+ ));
+ if (mErrorCodeFlag & (1 << InterruptType)) {
+ DEBUG ((
+ EFI_D_ERROR,
+ "ExceptionData - %08x\n",
+ SystemContext.SystemContextIa32->ExceptionData
+ ));
+ }
+ DEBUG ((
+ EFI_D_ERROR,
+ "CS - %04x, EIP - %08x, EFL - %08x, SS - %04x\n",
+ SystemContext.SystemContextIa32->Cs,
+ SystemContext.SystemContextIa32->Eip,
+ SystemContext.SystemContextIa32->Eflags,
+ SystemContext.SystemContextIa32->Ss
+ ));
+ DEBUG ((
+ EFI_D_ERROR,
+ "DS - %04x, ES - %04x, FS - %04x, GS - %04x\n",
+ SystemContext.SystemContextIa32->Ds,
+ SystemContext.SystemContextIa32->Es,
+ SystemContext.SystemContextIa32->Fs,
+ SystemContext.SystemContextIa32->Gs
+ ));
+ DEBUG ((
+ EFI_D_ERROR,
+ "EAX - %08x, EBX - %08x, ECX - %08x, EDX - %08x\n",
+ SystemContext.SystemContextIa32->Eax,
+ SystemContext.SystemContextIa32->Ebx,
+ SystemContext.SystemContextIa32->Ecx,
+ SystemContext.SystemContextIa32->Edx
+ ));
+ DEBUG ((
+ EFI_D_ERROR,
+ "ESP - %08x, EBP - %08x, ESI - %08x, EDI - %08x\n",
+ SystemContext.SystemContextIa32->Esp,
+ SystemContext.SystemContextIa32->Ebp,
+ SystemContext.SystemContextIa32->Esi,
+ SystemContext.SystemContextIa32->Edi
+ ));
+ DEBUG ((
+ EFI_D_ERROR,
+ "GDT - %08x LIM - %04x, IDT - %08x LIM - %04x\n",
+ SystemContext.SystemContextIa32->Gdtr[0],
+ SystemContext.SystemContextIa32->Gdtr[1],
+ SystemContext.SystemContextIa32->Idtr[0],
+ SystemContext.SystemContextIa32->Idtr[1]
+ ));
+ DEBUG ((
+ EFI_D_ERROR,
+ "LDT - %08x, TR - %08x\n",
+ SystemContext.SystemContextIa32->Ldtr,
+ SystemContext.SystemContextIa32->Tr
+ ));
+ DEBUG ((
+ EFI_D_ERROR,
+ "CR0 - %08x, CR2 - %08x, CR3 - %08x, CR4 - %08x\n",
+ SystemContext.SystemContextIa32->Cr0,
+ SystemContext.SystemContextIa32->Cr2,
+ SystemContext.SystemContextIa32->Cr3,
+ SystemContext.SystemContextIa32->Cr4
+ ));
+ DEBUG ((
+ EFI_D_ERROR,
+ "DR0 - %08x, DR1 - %08x, DR2 - %08x, DR3 - %08x\n",
+ SystemContext.SystemContextIa32->Dr0,
+ SystemContext.SystemContextIa32->Dr1,
+ SystemContext.SystemContextIa32->Dr2,
+ SystemContext.SystemContextIa32->Dr3
+ ));
+ DEBUG ((
+ EFI_D_ERROR,
+ "DR6 - %08x, DR7 - %08x\n",
+ SystemContext.SystemContextIa32->Dr6,
+ SystemContext.SystemContextIa32->Dr7
+ ));
+#elif defined (MDE_CPU_X64)
+ DEBUG ((
+ EFI_D_ERROR,
+ "!!!! X64 Exception Type - %016lx !!!!\n",
+ (UINT64)InterruptType
+ ));
+ if (mErrorCodeFlag & (1 << InterruptType)) {
+ DEBUG ((
+ EFI_D_ERROR,
+ "ExceptionData - %016lx\n",
+ SystemContext.SystemContextX64->ExceptionData
+ ));
+ }
+ DEBUG ((
+ EFI_D_ERROR,
+ "RIP - %016lx, RFL - %016lx\n",
+ SystemContext.SystemContextX64->Rip,
+ SystemContext.SystemContextX64->Rflags
+ ));
+ DEBUG ((
+ EFI_D_ERROR,
+ "RAX - %016lx, RCX - %016lx, RDX - %016lx\n",
+ SystemContext.SystemContextX64->Rax,
+ SystemContext.SystemContextX64->Rcx,
+ SystemContext.SystemContextX64->Rdx
+ ));
+ DEBUG ((
+ EFI_D_ERROR,
+ "RBX - %016lx, RSP - %016lx, RBP - %016lx\n",
+ SystemContext.SystemContextX64->Rbx,
+ SystemContext.SystemContextX64->Rsp,
+ SystemContext.SystemContextX64->Rbp
+ ));
+ DEBUG ((
+ EFI_D_ERROR,
+ "RSI - %016lx, RDI - %016lx\n",
+ SystemContext.SystemContextX64->Rsi,
+ SystemContext.SystemContextX64->Rdi
+ ));
+ DEBUG ((
+ EFI_D_ERROR,
+ "R8 - %016lx, R9 - %016lx, R10 - %016lx\n",
+ SystemContext.SystemContextX64->R8,
+ SystemContext.SystemContextX64->R9,
+ SystemContext.SystemContextX64->R10
+ ));
+ DEBUG ((
+ EFI_D_ERROR,
+ "R11 - %016lx, R12 - %016lx, R13 - %016lx\n",
+ SystemContext.SystemContextX64->R11,
+ SystemContext.SystemContextX64->R12,
+ SystemContext.SystemContextX64->R13
+ ));
+ DEBUG ((
+ EFI_D_ERROR,
+ "R14 - %016lx, R15 - %016lx\n",
+ SystemContext.SystemContextX64->R14,
+ SystemContext.SystemContextX64->R15
+ ));
+ DEBUG ((
+ EFI_D_ERROR,
+ "CS - %04lx, DS - %04lx, ES - %04lx, FS - %04lx, GS - %04lx, SS - %04lx\n",
+ SystemContext.SystemContextX64->Cs,
+ SystemContext.SystemContextX64->Ds,
+ SystemContext.SystemContextX64->Es,
+ SystemContext.SystemContextX64->Fs,
+ SystemContext.SystemContextX64->Gs,
+ SystemContext.SystemContextX64->Ss
+ ));
+ DEBUG ((
+ EFI_D_ERROR,
+ "GDT - %016lx; %04lx, IDT - %016lx; %04lx\n",
+ SystemContext.SystemContextX64->Gdtr[0],
+ SystemContext.SystemContextX64->Gdtr[1],
+ SystemContext.SystemContextX64->Idtr[0],
+ SystemContext.SystemContextX64->Idtr[1]
+ ));
+ DEBUG ((
+ EFI_D_ERROR,
+ "LDT - %016lx, TR - %016lx\n",
+ SystemContext.SystemContextX64->Ldtr,
+ SystemContext.SystemContextX64->Tr
+ ));
+ DEBUG ((
+ EFI_D_ERROR,
+ "CR0 - %016lx, CR2 - %016lx, CR3 - %016lx\n",
+ SystemContext.SystemContextX64->Cr0,
+ SystemContext.SystemContextX64->Cr2,
+ SystemContext.SystemContextX64->Cr3
+ ));
+ DEBUG ((
+ EFI_D_ERROR,
+ "CR4 - %016lx, CR8 - %016lx\n",
+ SystemContext.SystemContextX64->Cr4,
+ SystemContext.SystemContextX64->Cr8
+ ));
+ DEBUG ((
+ EFI_D_ERROR,
+ "DR0 - %016lx, DR1 - %016lx, DR2 - %016lx\n",
+ SystemContext.SystemContextX64->Dr0,
+ SystemContext.SystemContextX64->Dr1,
+ SystemContext.SystemContextX64->Dr2
+ ));
+ DEBUG ((
+ EFI_D_ERROR,
+ "DR3 - %016lx, DR6 - %016lx, DR7 - %016lx\n",
+ SystemContext.SystemContextX64->Dr3,
+ SystemContext.SystemContextX64->Dr6,
+ SystemContext.SystemContextX64->Dr7
+ ));
+#else
+#error CPU type not supported for exception information dump!
+#endif
+
+ //
+ // Hang the system with CpuSleep so the processor will enter a lower power
+ // state.
+ //
+ while (TRUE) {
+ CpuSleep ();
+ };
+}
+
+
+/**
+ Flush CPU data cache. If the instruction cache is fully coherent
+ with all DMA operations then function can just return EFI_SUCCESS.
+
+ @param This Protocol instance structure
+ @param Start Physical address to start flushing from.
+ @param Length Number of bytes to flush. Round up to chipset
+ granularity.
+ @param FlushType Specifies the type of flush operation to perform.
+
+ @retval EFI_SUCCESS If cache was flushed
+ @retval EFI_UNSUPPORTED If flush type is not supported.
+ @retval EFI_DEVICE_ERROR If requested range could not be flushed.
+
+**/
+EFI_STATUS
+EFIAPI
+CpuFlushCpuDataCache (
+ IN EFI_CPU_ARCH_PROTOCOL *This,
+ IN EFI_PHYSICAL_ADDRESS Start,
+ IN UINT64 Length,
+ IN EFI_CPU_FLUSH_TYPE FlushType
+ )
+{
+ if (FlushType == EfiCpuFlushTypeWriteBackInvalidate) {
+ AsmWbinvd ();
+ return EFI_SUCCESS;
+ } else if (FlushType == EfiCpuFlushTypeInvalidate) {
+ AsmInvd ();
+ return EFI_SUCCESS;
+ } else {
+ return EFI_UNSUPPORTED;
+ }
+}
+
+
+/**
+ Enables CPU interrupts.
+
+ @param This Protocol instance structure
+
+ @retval EFI_SUCCESS If interrupts were enabled in the CPU
+ @retval EFI_DEVICE_ERROR If interrupts could not be enabled on the CPU.
+
+**/
+EFI_STATUS
+EFIAPI
+CpuEnableInterrupt (
+ IN EFI_CPU_ARCH_PROTOCOL *This
+ )
+{
+ EnableInterrupts ();
+
+ InterruptState = TRUE;
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Disables CPU interrupts.
+
+ @param This Protocol instance structure
+
+ @retval EFI_SUCCESS If interrupts were disabled in the CPU.
+ @retval EFI_DEVICE_ERROR If interrupts could not be disabled on the CPU.
+
+**/
+EFI_STATUS
+EFIAPI
+CpuDisableInterrupt (
+ IN EFI_CPU_ARCH_PROTOCOL *This
+ )
+{
+ DisableInterrupts ();
+
+ InterruptState = FALSE;
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Return the state of interrupts.
+
+ @param This Protocol instance structure
+ @param State Pointer to the CPU's current interrupt state
+
+ @retval EFI_SUCCESS If interrupts were disabled in the CPU.
+ @retval EFI_INVALID_PARAMETER State is NULL.
+
+**/
+EFI_STATUS
+EFIAPI
+CpuGetInterruptState (
+ IN EFI_CPU_ARCH_PROTOCOL *This,
+ OUT BOOLEAN *State
+ )
+{
+ if (State == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ *State = InterruptState;
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Generates an INIT to the CPU.
+
+ @param This Protocol instance structure
+ @param InitType Type of CPU INIT to perform
+
+ @retval EFI_SUCCESS If CPU INIT occurred. This value should never be
+ seen.
+ @retval EFI_DEVICE_ERROR If CPU INIT failed.
+ @retval EFI_UNSUPPORTED Requested type of CPU INIT not supported.
+
+**/
+EFI_STATUS
+EFIAPI
+CpuInit (
+ IN EFI_CPU_ARCH_PROTOCOL *This,
+ IN EFI_CPU_INIT_TYPE InitType
+ )
+{
+ return EFI_UNSUPPORTED;
+}
+
+
+/**
+ Registers a function to be called from the CPU interrupt handler.
+
+ @param This Protocol instance structure
+ @param InterruptType Defines which interrupt to hook. IA-32
+ valid range is 0x00 through 0xFF
+ @param InterruptHandler A pointer to a function of type
+ EFI_CPU_INTERRUPT_HANDLER that is called
+ when a processor interrupt occurs. A null
+ pointer is an error condition.
+
+ @retval EFI_SUCCESS If handler installed or uninstalled.
+ @retval EFI_ALREADY_STARTED InterruptHandler is not NULL, and a handler
+ for InterruptType was previously installed.
+ @retval EFI_INVALID_PARAMETER InterruptHandler is NULL, and a handler for
+ InterruptType was not previously installed.
+ @retval EFI_UNSUPPORTED The interrupt specified by InterruptType
+ is not supported.
+
+**/
+EFI_STATUS
+EFIAPI
+CpuRegisterInterruptHandler (
+ IN EFI_CPU_ARCH_PROTOCOL *This,
+ IN EFI_EXCEPTION_TYPE InterruptType,
+ IN EFI_CPU_INTERRUPT_HANDLER InterruptHandler
+ )
+{
+ if (InterruptType < 0 || InterruptType > 0xff) {
+ return EFI_UNSUPPORTED;
+ }
+
+ if (InterruptHandler == NULL && ExternalVectorTable[InterruptType] == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (InterruptHandler != NULL && ExternalVectorTable[InterruptType] != NULL) {
+ return EFI_ALREADY_STARTED;
+ }
+
+ ExternalVectorTable[InterruptType] = InterruptHandler;
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Returns a timer value from one of the CPU's internal timers. There is no
+ inherent time interval between ticks but is a function of the CPU frequency.
+
+ @param This - Protocol instance structure.
+ @param TimerIndex - Specifies which CPU timer is requested.
+ @param TimerValue - Pointer to the returned timer value.
+ @param TimerPeriod - A pointer to the amount of time that passes
+ in femtoseconds (10-15) for each increment
+ of TimerValue. If TimerValue does not
+ increment at a predictable rate, then 0 is
+ returned. The amount of time that has
+ passed between two calls to GetTimerValue()
+ can be calculated with the formula
+ (TimerValue2 - TimerValue1) * TimerPeriod.
+ This parameter is optional and may be NULL.
+
+ @retval EFI_SUCCESS - If the CPU timer count was returned.
+ @retval EFI_UNSUPPORTED - If the CPU does not have any readable timers.
+ @retval EFI_DEVICE_ERROR - If an error occurred while reading the timer.
+ @retval EFI_INVALID_PARAMETER - TimerIndex is not valid or TimerValue is NULL.
+
+**/
+EFI_STATUS
+EFIAPI
+CpuGetTimerValue (
+ IN EFI_CPU_ARCH_PROTOCOL *This,
+ IN UINT32 TimerIndex,
+ OUT UINT64 *TimerValue,
+ OUT UINT64 *TimerPeriod OPTIONAL
+ )
+{
+ if (TimerValue == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (TimerIndex != 0) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ *TimerValue = AsmReadTsc ();
+
+ if (TimerPeriod != NULL) {
+ //
+ // BugBug: Hard coded. Don't know how to do this generically
+ //
+ *TimerPeriod = 1000000000;
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Set memory cacheability attributes for given range of memeory.
+
+ @param This Protocol instance structure
+ @param BaseAddress Specifies the start address of the
+ memory range
+ @param Length Specifies the length of the memory range
+ @param Attributes The memory cacheability for the memory range
+
+ @retval EFI_SUCCESS If the cacheability of that memory range is
+ set successfully
+ @retval EFI_UNSUPPORTED If the desired operation cannot be done
+ @retval EFI_INVALID_PARAMETER The input parameter is not correct,
+ such as Length = 0
+
+**/
+EFI_STATUS
+EFIAPI
+CpuSetMemoryAttributes (
+ IN EFI_CPU_ARCH_PROTOCOL *This,
+ IN EFI_PHYSICAL_ADDRESS BaseAddress,
+ IN UINT64 Length,
+ IN UINT64 Attributes
+ )
+{
+ RETURN_STATUS Status;
+ MTRR_MEMORY_CACHE_TYPE CacheType;
+
+ DEBUG((EFI_D_ERROR, "CpuAp: SetMemorySpaceAttributes(BA=%08x, Len=%08x, Attr=%08x)\n", BaseAddress, Length, Attributes));
+
+ //
+ // If this function is called because GCD SetMemorySpaceAttributes () is called
+ // by RefreshGcdMemoryAttributes (), then we are just synchronzing GCD memory
+ // map with MTRR values. So there is no need to modify MTRRs, just return immediately
+ // to avoid unnecessary computing.
+ //
+ if (mIsFlushingGCD) {
+ DEBUG((EFI_D_ERROR, " Flushing GCD\n"));
+ return EFI_SUCCESS;
+ }
+
+ switch (Attributes) {
+ case EFI_MEMORY_UC:
+ CacheType = CacheUncacheable;
+ break;
+
+ case EFI_MEMORY_WC:
+ CacheType = CacheWriteCombining;
+ break;
+
+ case EFI_MEMORY_WT:
+ CacheType = CacheWriteThrough;
+ break;
+
+ case EFI_MEMORY_WP:
+ CacheType = CacheWriteProtected;
+ break;
+
+ case EFI_MEMORY_WB:
+ CacheType = CacheWriteBack;
+ break;
+
+ default:
+ return EFI_UNSUPPORTED;
+ }
+ //
+ // call MTRR libary function
+ //
+ DEBUG((EFI_D_ERROR, " MtrrSetMemoryAttribute()\n"));
+ Status = MtrrSetMemoryAttribute(
+ BaseAddress,
+ Length,
+ CacheType
+ );
+
+ MtrrDebugPrintAllMtrrs ();
+
+ return (EFI_STATUS) Status;
+}
+
+/**
+ Initializes the valid bits mask and valid address mask for MTRRs.
+
+ This function initializes the valid bits mask and valid address mask for MTRRs.
+
+**/
+VOID
+InitializeMtrrMask (
+ VOID
+ )
+{
+ UINT32 RegEax;
+ UINT8 PhysicalAddressBits;
+
+ AsmCpuid (0x80000000, &RegEax, NULL, NULL, NULL);
+
+ if (RegEax >= 0x80000008) {
+ AsmCpuid (0x80000008, &RegEax, NULL, NULL, NULL);
+
+ PhysicalAddressBits = (UINT8) RegEax;
+
+ mValidMtrrBitsMask = LShiftU64 (1, PhysicalAddressBits) - 1;
+ mValidMtrrAddressMask = mValidMtrrBitsMask & 0xfffffffffffff000ULL;
+ } else {
+ mValidMtrrBitsMask = MTRR_LIB_MSR_VALID_MASK;
+ mValidMtrrAddressMask = MTRR_LIB_CACHE_VALID_ADDRESS;
+ }
+}
+
+/**
+ Gets GCD Mem Space type from MTRR Type
+
+ This function gets GCD Mem Space type from MTRR Type
+
+ @param MtrrAttribute MTRR memory type
+
+ @return GCD Mem Space type
+
+**/
+UINT64
+GetMemorySpaceAttributeFromMtrrType (
+ IN UINT8 MtrrAttributes
+ )
+{
+ switch (MtrrAttributes) {
+ case MTRR_CACHE_UNCACHEABLE:
+ return EFI_MEMORY_UC;
+ case MTRR_CACHE_WRITE_COMBINING:
+ return EFI_MEMORY_WC;
+ case MTRR_CACHE_WRITE_THROUGH:
+ return EFI_MEMORY_WT;
+ case MTRR_CACHE_WRITE_PROTECTED:
+ return EFI_MEMORY_WP;
+ case MTRR_CACHE_WRITE_BACK:
+ return EFI_MEMORY_WB;
+ default:
+ return 0;
+ }
+}
+
+/**
+ Searches memory descriptors covered by given memory range.
+
+ This function searches into the Gcd Memory Space for descriptors
+ (from StartIndex to EndIndex) that contains the memory range
+ specified by BaseAddress and Length.
+
+ @param MemorySpaceMap Gcd Memory Space Map as array.
+ @param NumberOfDescriptors Number of descriptors in map.
+ @param BaseAddress BaseAddress for the requested range.
+ @param Length Length for the requested range.
+ @param StartIndex Start index into the Gcd Memory Space Map.
+ @param EndIndex End index into the Gcd Memory Space Map.
+
+ @retval EFI_SUCCESS Search successfully.
+ @retval EFI_NOT_FOUND The requested descriptors does not exist.
+
+**/
+EFI_STATUS
+SearchGcdMemorySpaces (
+ IN EFI_GCD_MEMORY_SPACE_DESCRIPTOR *MemorySpaceMap,
+ IN UINTN NumberOfDescriptors,
+ IN EFI_PHYSICAL_ADDRESS BaseAddress,
+ IN UINT64 Length,
+ OUT UINTN *StartIndex,
+ OUT UINTN *EndIndex
+ )
+{
+ UINTN Index;
+
+ *StartIndex = 0;
+ *EndIndex = 0;
+ for (Index = 0; Index < NumberOfDescriptors; Index++) {
+ if (BaseAddress >= MemorySpaceMap[Index].BaseAddress &&
+ BaseAddress < MemorySpaceMap[Index].BaseAddress + MemorySpaceMap[Index].Length) {
+ *StartIndex = Index;
+ }
+ if (BaseAddress + Length - 1 >= MemorySpaceMap[Index].BaseAddress &&
+ BaseAddress + Length - 1 < MemorySpaceMap[Index].BaseAddress + MemorySpaceMap[Index].Length) {
+ *EndIndex = Index;
+ return EFI_SUCCESS;
+ }
+ }
+ return EFI_NOT_FOUND;
+}
+
+/**
+ Sets the attributes for a specified range in Gcd Memory Space Map.
+
+ This function sets the attributes for a specified range in
+ Gcd Memory Space Map.
+
+ @param MemorySpaceMap Gcd Memory Space Map as array
+ @param NumberOfDescriptors Number of descriptors in map
+ @param BaseAddress BaseAddress for the range
+ @param Length Length for the range
+ @param Attributes Attributes to set
+
+ @retval EFI_SUCCESS Memory attributes set successfully
+ @retval EFI_NOT_FOUND The specified range does not exist in Gcd Memory Space
+
+**/
+EFI_STATUS
+SetGcdMemorySpaceAttributes (
+ IN EFI_GCD_MEMORY_SPACE_DESCRIPTOR *MemorySpaceMap,
+ IN UINTN NumberOfDescriptors,
+ IN EFI_PHYSICAL_ADDRESS BaseAddress,
+ IN UINT64 Length,
+ IN UINT64 Attributes
+ )
+{
+ EFI_STATUS Status;
+ UINTN Index;
+ UINTN StartIndex;
+ UINTN EndIndex;
+ EFI_PHYSICAL_ADDRESS RegionStart;
+ UINT64 RegionLength;
+
+ //
+ // Get all memory descriptors covered by the memory range
+ //
+ Status = SearchGcdMemorySpaces (
+ MemorySpaceMap,
+ NumberOfDescriptors,
+ BaseAddress,
+ Length,
+ &StartIndex,
+ &EndIndex
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Go through all related descriptors and set attributes accordingly
+ //
+ for (Index = StartIndex; Index <= EndIndex; Index++) {
+ if (MemorySpaceMap[Index].GcdMemoryType == EfiGcdMemoryTypeNonExistent) {
+ continue;
+ }
+ //
+ // Calculate the start and end address of the overlapping range
+ //
+ if (BaseAddress >= MemorySpaceMap[Index].BaseAddress) {
+ RegionStart = BaseAddress;
+ } else {
+ RegionStart = MemorySpaceMap[Index].BaseAddress;
+ }
+ if (BaseAddress + Length - 1 < MemorySpaceMap[Index].BaseAddress + MemorySpaceMap[Index].Length) {
+ RegionLength = BaseAddress + Length - RegionStart;
+ } else {
+ RegionLength = MemorySpaceMap[Index].BaseAddress + MemorySpaceMap[Index].Length - RegionStart;
+ }
+ //
+ // Set memory attributes according to MTRR attribute and the original attribute of descriptor
+ //
+ gDS->SetMemorySpaceAttributes (
+ RegionStart,
+ RegionLength,
+ (MemorySpaceMap[Index].Attributes & ~EFI_MEMORY_CACHETYPE_MASK) | (MemorySpaceMap[Index].Capabilities & Attributes)
+ );
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Refreshes the GCD Memory Space attributes according to MTRRs.
+
+ This function refreshes the GCD Memory Space attributes according to MTRRs.
+
+**/
+VOID
+RefreshGcdMemoryAttributes (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ UINTN Index;
+ UINTN SubIndex;
+ UINT64 RegValue;
+ EFI_PHYSICAL_ADDRESS BaseAddress;
+ UINT64 Length;
+ UINT64 Attributes;
+ UINT64 CurrentAttributes;
+ UINT8 MtrrType;
+ UINTN NumberOfDescriptors;
+ EFI_GCD_MEMORY_SPACE_DESCRIPTOR *MemorySpaceMap;
+ UINT64 DefaultAttributes;
+ VARIABLE_MTRR VariableMtrr[MTRR_NUMBER_OF_VARIABLE_MTRR];
+ MTRR_FIXED_SETTINGS MtrrFixedSettings;
+
+// mIsFlushingGCD = TRUE;
+ mIsFlushingGCD = FALSE;
+ MemorySpaceMap = NULL;
+
+ //
+ // Initialize the valid bits mask and valid address mask for MTRRs
+ //
+ InitializeMtrrMask ();
+
+ //
+ // Get the memory attribute of variable MTRRs
+ //
+ MtrrGetMemoryAttributeInVariableMtrr (
+ mValidMtrrBitsMask,
+ mValidMtrrAddressMask,
+ VariableMtrr
+ );
+
+ //
+ // Get the memory space map from GCD
+ //
+ Status = gDS->GetMemorySpaceMap (
+ &NumberOfDescriptors,
+ &MemorySpaceMap
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ DefaultAttributes = GetMemorySpaceAttributeFromMtrrType (mDefaultMemoryType);
+
+ //
+ // Set default attributes to all spaces.
+ //
+ for (Index = 0; Index < NumberOfDescriptors; Index++) {
+ if (MemorySpaceMap[Index].GcdMemoryType == EfiGcdMemoryTypeNonExistent) {
+ continue;
+ }
+ gDS->SetMemorySpaceAttributes (
+ MemorySpaceMap[Index].BaseAddress,
+ MemorySpaceMap[Index].Length,
+ (MemorySpaceMap[Index].Attributes & ~EFI_MEMORY_CACHETYPE_MASK) |
+ (MemorySpaceMap[Index].Capabilities & DefaultAttributes)
+ );
+ }
+
+ //
+ // Go for variable MTRRs with WB attribute
+ //
+ for (Index = 0; Index < FIRMWARE_VARIABLE_MTRR_NUMBER; Index++) {
+ if (VariableMtrr[Index].Valid &&
+ VariableMtrr[Index].Type == MTRR_CACHE_WRITE_BACK) {
+ SetGcdMemorySpaceAttributes (
+ MemorySpaceMap,
+ NumberOfDescriptors,
+ VariableMtrr[Index].BaseAddress,
+ VariableMtrr[Index].Length,
+ EFI_MEMORY_WB
+ );
+ }
+ }
+ //
+ // Go for variable MTRRs with Non-WB attribute
+ //
+ for (Index = 0; Index < FIRMWARE_VARIABLE_MTRR_NUMBER; Index++) {
+ if (VariableMtrr[Index].Valid &&
+ VariableMtrr[Index].Type != MTRR_CACHE_WRITE_BACK) {
+ Attributes = GetMemorySpaceAttributeFromMtrrType ((UINT8) VariableMtrr[Index].Type);
+ SetGcdMemorySpaceAttributes (
+ MemorySpaceMap,
+ NumberOfDescriptors,
+ VariableMtrr[Index].BaseAddress,
+ VariableMtrr[Index].Length,
+ Attributes
+ );
+ }
+ }
+
+ //
+ // Go for fixed MTRRs
+ //
+ Attributes = 0;
+ BaseAddress = 0;
+ Length = 0;
+ MtrrGetFixedMtrr (&MtrrFixedSettings);
+ for (Index = 0; Index < MTRR_NUMBER_OF_FIXED_MTRR; Index++) {
+ RegValue = MtrrFixedSettings.Mtrr[Index];
+ //
+ // Check for continuous fixed MTRR sections
+ //
+ for (SubIndex = 0; SubIndex < 8; SubIndex++) {
+ MtrrType = (UINT8) RShiftU64 (RegValue, SubIndex * 8);
+ CurrentAttributes = GetMemorySpaceAttributeFromMtrrType (MtrrType);
+ if (Length == 0) {
+ //
+ // A new MTRR attribute begins
+ //
+ Attributes = CurrentAttributes;
+ } else {
+ //
+ // If fixed MTRR attribute changed, then set memory attribute for previous atrribute
+ //
+ if (CurrentAttributes != Attributes) {
+ SetGcdMemorySpaceAttributes (
+ MemorySpaceMap,
+ NumberOfDescriptors,
+ BaseAddress,
+ Length,
+ Attributes
+ );
+ BaseAddress = mFixedMtrrTable[Index].BaseAddress + mFixedMtrrTable[Index].Length * SubIndex;
+ Length = 0;
+ Attributes = CurrentAttributes;
+ }
+ }
+ Length += mFixedMtrrTable[Index].Length;
+ }
+ }
+ //
+ // Handle the last fixed MTRR region
+ //
+ SetGcdMemorySpaceAttributes (
+ MemorySpaceMap,
+ NumberOfDescriptors,
+ BaseAddress,
+ Length,
+ Attributes
+ );
+
+ //
+ // Free memory space map allocated by GCD service GetMemorySpaceMap ()
+ //
+ if (MemorySpaceMap != NULL) {
+ FreePool (MemorySpaceMap);
+ }
+
+ mIsFlushingGCD = FALSE;
+}
+
+
+/**
+ Initialize Interrupt Descriptor Table for interrupt handling.
+
+**/
+STATIC
+VOID
+InitInterruptDescriptorTable (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ VOID *IdtPtrAlignmentBuffer;
+ IA32_DESCRIPTOR *IdtPtr;
+ UINTN Index;
+ UINTN CurrentHandler;
+
+ SetMem (ExternalVectorTable, sizeof(ExternalVectorTable), 0);
+
+ //
+ // Intialize IDT
+ //
+ CurrentHandler = (UINTN)AsmIdtVector00;
+ for (Index = 0; Index < INTERRUPT_VECTOR_NUMBER; Index ++, CurrentHandler += 0x08) {
+ gIdtTable[Index].Bits.OffsetLow = (UINT16)CurrentHandler;
+ gIdtTable[Index].Bits.Selector = AsmReadCs();
+ gIdtTable[Index].Bits.Reserved_0 = 0;
+ gIdtTable[Index].Bits.GateType = IA32_IDT_GATE_TYPE_INTERRUPT_32;
+ gIdtTable[Index].Bits.OffsetHigh = (UINT16)(CurrentHandler >> 16);
+#if defined (MDE_CPU_X64)
+ gIdtTable[Index].Bits.OffsetUpper = (UINT32)(CurrentHandler >> 32);
+ gIdtTable[Index].Bits.Reserved_1 = 0;
+#endif
+ }
+
+ //
+ // Load IDT Pointer
+ //
+ IdtPtrAlignmentBuffer = AllocatePool (sizeof (*IdtPtr) + 16);
+ IdtPtr = ALIGN_POINTER (IdtPtrAlignmentBuffer, 16);
+ IdtPtr->Base = (UINT32)(((UINTN)(VOID*) gIdtTable) & (BASE_4GB-1));
+ IdtPtr->Limit = sizeof (gIdtTable) - 1;
+ AsmWriteIdtr (IdtPtr);
+ FreePool (IdtPtrAlignmentBuffer);
+
+ //
+ // Initialize Exception Handlers
+ //
+ for (Index = 0; Index < 32; Index++) {
+ Status = CpuRegisterInterruptHandler (&gCpu, Index, CommonExceptionHandler);
+ ASSERT_EFI_ERROR (Status);
+ }
+
+ //
+ // Set the pointer to the array of C based exception handling routines.
+ //
+ InitializeExternalVectorTablePtr (ExternalVectorTable);
+
+}
+
+
+/**
+ Initialize the state information for the CPU Architectural Protocol.
+
+ @param ImageHandle Image handle this driver.
+ @param SystemTable Pointer to the System Table.
+
+ @retval EFI_SUCCESS Thread can be successfully created
+ @retval EFI_OUT_OF_RESOURCES Cannot allocate protocol data structure
+ @retval EFI_DEVICE_ERROR Cannot create the thread
+
+**/
+EFI_STATUS
+EFIAPI
+InitializeCpu (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+
+ //
+ // Make sure interrupts are disabled
+ //
+ DisableInterrupts ();
+
+ //
+ // Init GDT for DXE
+ //
+ InitGlobalDescriptorTable ();
+
+ //
+ // Setup IDT pointer, IDT and interrupt entry points
+ //
+ InitInterruptDescriptorTable ();
+
+ //
+ // Install CPU Architectural Protocol
+ //
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &mCpuHandle,
+ &gEfiCpuArchProtocolGuid, &gCpu,
+ NULL
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Refresh GCD memory space map according to MTRR value.
+ //
+ RefreshGcdMemoryAttributes ();
+
+ return Status;
+}
+
diff --git a/UefiCpuPkg/CpuDxe/CpuDxe.h b/UefiCpuPkg/CpuDxe/CpuDxe.h new file mode 100644 index 0000000000..fbf3a9830f --- /dev/null +++ b/UefiCpuPkg/CpuDxe/CpuDxe.h @@ -0,0 +1,140 @@ +/** @file
+ CPU DXE Module.
+
+ Copyright (c) 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.
+
+**/
+
+#ifndef _CPU_DXE_H
+#define _CPU_DXE_H
+
+#include <PiDxe.h>
+
+#include <Protocol/Cpu.h>
+
+#include <Library/UefiDriverEntryPoint.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/DxeServicesTableLib.h>
+#include <Library/BaseLib.h>
+#include <Library/CpuLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/DebugLib.h>
+#include <Library/MtrrLib.h>
+
+//
+//
+//
+#define INTERRUPT_VECTOR_NUMBER 256
+
+#define EFI_MEMORY_CACHETYPE_MASK (EFI_MEMORY_UC | \
+ EFI_MEMORY_WC | \
+ EFI_MEMORY_WT | \
+ EFI_MEMORY_WB | \
+ EFI_MEMORY_UCE \
+ )
+
+
+//
+// Function declarations
+//
+EFI_STATUS
+EFIAPI
+CpuFlushCpuDataCache (
+ IN EFI_CPU_ARCH_PROTOCOL *This,
+ IN EFI_PHYSICAL_ADDRESS Start,
+ IN UINT64 Length,
+ IN EFI_CPU_FLUSH_TYPE FlushType
+ );
+
+EFI_STATUS
+EFIAPI
+CpuEnableInterrupt (
+ IN EFI_CPU_ARCH_PROTOCOL *This
+ );
+
+EFI_STATUS
+EFIAPI
+CpuDisableInterrupt (
+ IN EFI_CPU_ARCH_PROTOCOL *This
+ );
+
+EFI_STATUS
+EFIAPI
+CpuGetInterruptState (
+ IN EFI_CPU_ARCH_PROTOCOL *This,
+ OUT BOOLEAN *State
+ );
+
+EFI_STATUS
+EFIAPI
+CpuInit (
+ IN EFI_CPU_ARCH_PROTOCOL *This,
+ IN EFI_CPU_INIT_TYPE InitType
+ );
+
+EFI_STATUS
+EFIAPI
+CpuRegisterInterruptHandler (
+ IN EFI_CPU_ARCH_PROTOCOL *This,
+ IN EFI_EXCEPTION_TYPE InterruptType,
+ IN EFI_CPU_INTERRUPT_HANDLER InterruptHandler
+ );
+
+EFI_STATUS
+EFIAPI
+CpuGetTimerValue (
+ IN EFI_CPU_ARCH_PROTOCOL *This,
+ IN UINT32 TimerIndex,
+ OUT UINT64 *TimerValue,
+ OUT UINT64 *TimerPeriod OPTIONAL
+ );
+
+EFI_STATUS
+EFIAPI
+CpuSetMemoryAttributes (
+ IN EFI_CPU_ARCH_PROTOCOL *This,
+ IN EFI_PHYSICAL_ADDRESS BaseAddress,
+ IN UINT64 Length,
+ IN UINT64 Attributes
+ );
+
+VOID
+EFIAPI
+AsmIdtVector00 (
+ VOID
+ );
+
+VOID
+EFIAPI
+InitializeExternalVectorTablePtr (
+ EFI_CPU_INTERRUPT_HANDLER *VectorTable
+ );
+
+VOID
+InitGlobalDescriptorTable (
+ VOID
+ );
+
+VOID
+EFIAPI
+SetCodeSelector (
+ UINT16 Selector
+ );
+
+VOID
+EFIAPI
+SetDataSelectors (
+ UINT16 Selector
+ );
+
+
+#endif
+
diff --git a/UefiCpuPkg/CpuDxe/CpuDxe.inf b/UefiCpuPkg/CpuDxe/CpuDxe.inf new file mode 100644 index 0000000000..ff832450dd --- /dev/null +++ b/UefiCpuPkg/CpuDxe/CpuDxe.inf @@ -0,0 +1,67 @@ +#/** @file
+#
+# Component description file for simple CPU driver
+#
+# Copyright (c) 2008 - 2009, Intel Corporation. <BR>
+# 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.
+#
+#**/
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = CpuDxe
+ FILE_GUID = 62D171CB-78CD-4480-8678-C6A2A797A8DE
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ EDK_RELEASE_VERSION = 0x00020000
+ EFI_SPECIFICATION_VERSION = 0x0002000A
+
+ ENTRY_POINT = InitializeCpu
+
+[Packages]
+ OvmfPkg/OvmfPkg.dec
+ MdePkg/MdePkg.dec
+ UefiCpuPkg/UefiCpuPkg.dec
+
+[LibraryClasses]
+ BaseLib
+ BaseMemoryLib
+ CpuLib
+ DebugLib
+ DxeServicesTableLib
+ MemoryAllocationLib
+ MtrrLib
+ UefiBootServicesTableLib
+ UefiDriverEntryPoint
+
+[Sources]
+ CpuDxe.c
+ CpuDxe.h
+ CpuGdt.c
+
+ Ia32/IvtAsm.asm | MSFT
+ Ia32/IvtAsm.asm | INTEL
+ Ia32/IvtAsm.S | GCC
+
+[Sources.IA32]
+ Ia32/CpuAsm.asm | MSFT
+ Ia32/CpuAsm.asm | INTEL
+ Ia32/CpuAsm.S | GCC
+
+[Sources.X64]
+ X64/CpuAsm.asm | MSFT
+ X64/CpuAsm.asm | INTEL
+ X64/CpuAsm.S | GCC
+
+[Protocols]
+ gEfiCpuArchProtocolGuid
+
+[Depex]
+ TRUE
+
diff --git a/UefiCpuPkg/CpuDxe/CpuGdt.c b/UefiCpuPkg/CpuDxe/CpuGdt.c new file mode 100755 index 0000000000..b6d8ffb75d --- /dev/null +++ b/UefiCpuPkg/CpuDxe/CpuGdt.c @@ -0,0 +1,200 @@ +/** @file
+ C based implemention of IA32 interrupt handling only
+ requiring a minimal assembly interrupt entry point.
+
+ 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.
+
+**/
+
+#include "CpuDxe.h"
+
+
+//
+// Local structure definitions
+//
+
+#pragma pack (1)
+
+//
+// Global Descriptor Entry structures
+//
+
+typedef
+struct _GDT_ENTRY {
+ UINT16 limit15_0;
+ UINT16 base15_0;
+ UINT8 base23_16;
+ UINT8 type;
+ UINT8 limit19_16_and_flags;
+ UINT8 base31_24;
+} GDT_ENTRY;
+
+typedef
+struct _GDT_ENTRIES {
+ GDT_ENTRY Null;
+ GDT_ENTRY Linear;
+ GDT_ENTRY LinearCode;
+ GDT_ENTRY SysData;
+ GDT_ENTRY SysCode;
+ GDT_ENTRY LinearCode64;
+ GDT_ENTRY Spare4;
+ GDT_ENTRY Spare5;
+} GDT_ENTRIES;
+
+#define NULL_SEL OFFSET_OF (GDT_ENTRIES, Null)
+#define LINEAR_SEL OFFSET_OF (GDT_ENTRIES, Linear)
+#define LINEAR_CODE_SEL OFFSET_OF (GDT_ENTRIES, LinearCode)
+#define SYS_DATA_SEL OFFSET_OF (GDT_ENTRIES, SysData)
+#define SYS_CODE_SEL OFFSET_OF (GDT_ENTRIES, SysCode)
+#define LINEAR_CODE64_SEL OFFSET_OF (GDT_ENTRIES, LinearCode64)
+#define SPARE4_SEL OFFSET_OF (GDT_ENTRIES, Spare4)
+#define SPARE5_SEL OFFSET_OF (GDT_ENTRIES, Spare5)
+
+#if defined (MDE_CPU_IA32)
+#define CPU_CODE_SEL LINEAR_CODE_SEL
+#define CPU_DATA_SEL LINEAR_SEL
+#elif defined (MDE_CPU_X64)
+#define CPU_CODE_SEL LINEAR_CODE64_SEL
+#define CPU_DATA_SEL LINEAR_SEL
+#else
+#error CPU type not supported for CPU GDT initialization!
+#endif
+
+//
+// Global descriptor table (GDT) Template
+//
+STATIC GDT_ENTRIES GdtTemplate = {
+ //
+ // NULL_SEL
+ //
+ {
+ 0x0, // limit 15:0
+ 0x0, // base 15:0
+ 0x0, // base 23:16
+ 0x0, // type
+ 0x0, // limit 19:16, flags
+ 0x0, // base 31:24
+ },
+ //
+ // LINEAR_SEL
+ //
+ {
+ 0x0FFFF, // limit 0xFFFFF
+ 0x0, // base 0
+ 0x0,
+ 0x092, // present, ring 0, data, expand-up, writable
+ 0x0CF, // page-granular, 32-bit
+ 0x0,
+ },
+ //
+ // LINEAR_CODE_SEL
+ //
+ {
+ 0x0FFFF, // limit 0xFFFFF
+ 0x0, // base 0
+ 0x0,
+ 0x09A, // present, ring 0, data, expand-up, writable
+ 0x0CF, // page-granular, 32-bit
+ 0x0,
+ },
+ //
+ // SYS_DATA_SEL
+ //
+ {
+ 0x0FFFF, // limit 0xFFFFF
+ 0x0, // base 0
+ 0x0,
+ 0x092, // present, ring 0, data, expand-up, writable
+ 0x0CF, // page-granular, 32-bit
+ 0x0,
+ },
+ //
+ // SYS_CODE_SEL
+ //
+ {
+ 0x0FFFF, // limit 0xFFFFF
+ 0x0, // base 0
+ 0x0,
+ 0x09A, // present, ring 0, data, expand-up, writable
+ 0x0CF, // page-granular, 32-bit
+ 0x0,
+ },
+ //
+ // LINEAR_CODE64_SEL
+ //
+ {
+ 0x0FFFF, // limit 0xFFFFF
+ 0x0, // base 0
+ 0x0,
+ 0x09B, // present, ring 0, code, expand-up, writable
+ 0x0AF, // LimitHigh (CS.L=1, CS.D=0)
+ 0x0, // base (high)
+ },
+ //
+ // SPARE4_SEL
+ //
+ {
+ 0x0, // limit 0
+ 0x0, // base 0
+ 0x0,
+ 0x0, // present, ring 0, data, expand-up, writable
+ 0x0, // page-granular, 32-bit
+ 0x0,
+ },
+ //
+ // SPARE5_SEL
+ //
+ {
+ 0x0, // limit 0
+ 0x0, // base 0
+ 0x0,
+ 0x0, // present, ring 0, data, expand-up, writable
+ 0x0, // page-granular, 32-bit
+ 0x0,
+ },
+};
+
+/**
+ Initialize Global Descriptor Table
+
+**/
+VOID
+InitGlobalDescriptorTable (
+ )
+{
+ GDT_ENTRIES *gdt;
+ IA32_DESCRIPTOR gdtPtr;
+
+ //
+ // Allocate Runtime Data for the GDT
+ //
+ gdt = AllocateRuntimePool (sizeof (GdtTemplate) + 8);
+ ASSERT (gdt != NULL);
+ gdt = ALIGN_POINTER (gdt, 8);
+
+ //
+ // Initialize all GDT entries
+ //
+ CopyMem (gdt, &GdtTemplate, sizeof (GdtTemplate));
+
+ //
+ // Write GDT register
+ //
+ gdtPtr.Base = (UINT32)(UINTN)(VOID*) gdt;
+ gdtPtr.Limit = sizeof (GdtTemplate) - 1;
+ AsmWriteGdtr (&gdtPtr);
+
+ //
+ // Update selector (segment) registers base on new GDT
+ //
+ SetCodeSelector ((UINT16)CPU_CODE_SEL);
+ SetDataSelectors ((UINT16)CPU_DATA_SEL);
+}
+
diff --git a/UefiCpuPkg/CpuDxe/Ia32/CpuAsm.S b/UefiCpuPkg/CpuDxe/Ia32/CpuAsm.S new file mode 100755 index 0000000000..69fe215637 --- /dev/null +++ b/UefiCpuPkg/CpuDxe/Ia32/CpuAsm.S @@ -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 index 0000000000..dfcbc0deff --- /dev/null +++ b/UefiCpuPkg/CpuDxe/Ia32/CpuAsm.asm @@ -0,0 +1,384 @@ + 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.asm
+;*
+;* Abstract:
+;*
+;------------------------------------------------------------------------------
+
+ .686
+ .model flat,C
+ .code
+
+EXTRN mErrorCodeFlag:DWORD ; Error code flags for exceptions
+
+;
+; point to the external interrupt vector table
+;
+ExternalVectorTablePtr DWORD 0
+
+InitializeExternalVectorTablePtr PROC PUBLIC
+ mov eax, [esp+4]
+ mov ExternalVectorTablePtr, eax
+ ret
+InitializeExternalVectorTablePtr ENDP
+
+;------------------------------------------------------------------------------
+; VOID
+; SetCodeSelector (
+; UINT16 Selector
+; );
+;------------------------------------------------------------------------------
+SetCodeSelector PROC PUBLIC
+ 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
+SetCodeSelector ENDP
+
+;------------------------------------------------------------------------------
+; VOID
+; SetDataSelectors (
+; UINT16 Selector
+; );
+;------------------------------------------------------------------------------
+SetDataSelectors PROC PUBLIC
+ mov ecx, [esp+4]
+ mov ss, cx
+ mov ds, cx
+ mov es, cx
+ mov fs, cx
+ mov gs, cx
+ ret
+SetDataSelectors ENDP
+
+;---------------------------------------;
+; CommonInterruptEntry ;
+;---------------------------------------;
+; The follow algorithm is used for the common interrupt routine.
+
+CommonInterruptEntry PROC PUBLIC
+ 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, 0FFFFh
+ cmp ecx, 32 ; Intel reserved vector for exceptions?
+ jae NoErrorCode
+ bt 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
+ ;
+@@:
+ jmp @B
+
+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, 0fffffff0h
+ 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, 0FFFFh
+ mov [esp+4], eax
+
+ sub esp, 8
+ sgdt [esp]
+ mov eax, [esp + 2]
+ xchg eax, [esp]
+ and eax, 0FFFFh
+ 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, 208h
+ 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
+ db 0fh, 0aeh, 07h ;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
+ db 0fh, 0aeh, 0eh ; 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
+
+CommonInterruptEntry ENDP
+
+END
diff --git a/UefiCpuPkg/CpuDxe/Ia32/IvtAsm.S b/UefiCpuPkg/CpuDxe/Ia32/IvtAsm.S new file mode 100755 index 0000000000..2a6341a989 --- /dev/null +++ b/UefiCpuPkg/CpuDxe/Ia32/IvtAsm.S @@ -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 index 0000000000..e5dfaace8c --- /dev/null +++ b/UefiCpuPkg/CpuDxe/Ia32/IvtAsm.asm @@ -0,0 +1,51 @@ + TITLE IvtAsm.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.
+;*
+;* IvtAsm.asm
+;*
+;* Abstract:
+;*
+;------------------------------------------------------------------------------
+
+#include <Base.h>
+
+#ifdef MDE_CPU_IA32
+ .686
+ .model flat,C
+#endif
+ .code
+
+;------------------------------------------------------------------------------
+; Generic IDT Vector Handlers for the Host. They are all the same so they
+; will compress really well.
+;
+; By knowing the return address for Vector 00 you can can calculate the
+; vector number by looking at the call CommonInterruptEntry return address.
+; (return address - (AsmIdtVector00 + 5))/8 == IDT index
+;
+;------------------------------------------------------------------------------
+
+EXTRN CommonInterruptEntry:PROC
+
+ALIGN 8
+
+PUBLIC AsmIdtVector00
+
+AsmIdtVector00 LABEL BYTE
+REPEAT 256
+ call CommonInterruptEntry
+ dw ($ - AsmIdtVector00 - 5) / 8 ; vector number
+ nop
+ENDM
+
+END
+
diff --git a/UefiCpuPkg/CpuDxe/X64/CpuAsm.S b/UefiCpuPkg/CpuDxe/X64/CpuAsm.S new file mode 100755 index 0000000000..9d4c26190e --- /dev/null +++ b/UefiCpuPkg/CpuDxe/X64/CpuAsm.S @@ -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 index 0000000000..05d9bca119 --- /dev/null +++ b/UefiCpuPkg/CpuDxe/X64/CpuAsm.asm @@ -0,0 +1,345 @@ + 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.asm
+;*
+;* Abstract:
+;*
+;------------------------------------------------------------------------------
+
+ .code
+
+EXTRN mErrorCodeFlag:DWORD ; Error code flags for exceptions
+
+;
+; point to the external interrupt vector table
+;
+ExternalVectorTablePtr QWORD 0
+
+InitializeExternalVectorTablePtr PROC PUBLIC
+ mov ExternalVectorTablePtr, rcx
+ ret
+InitializeExternalVectorTablePtr ENDP
+
+;------------------------------------------------------------------------------
+; VOID
+; SetCodeSelector (
+; UINT16 Selector
+; );
+;------------------------------------------------------------------------------
+SetCodeSelector PROC PUBLIC
+ sub rsp, 0x10
+ lea rax, setCodeSelectorLongJump
+ mov [rsp], rax
+ mov [rsp+4], cx
+ jmp fword ptr [rsp]
+setCodeSelectorLongJump:
+ add rsp, 0x10
+ ret
+SetCodeSelector ENDP
+
+;------------------------------------------------------------------------------
+; VOID
+; SetDataSelectors (
+; UINT16 Selector
+; );
+;------------------------------------------------------------------------------
+SetDataSelectors PROC PUBLIC
+ mov ss, cx
+ mov ds, cx
+ mov es, cx
+ mov fs, cx
+ mov gs, cx
+ ret
+SetDataSelectors ENDP
+
+;---------------------------------------;
+; CommonInterruptEntry ;
+;---------------------------------------;
+; The follow algorithm is used for the common interrupt routine.
+
+CommonInterruptEntry PROC PUBLIC
+ 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
+ bt mErrorCodeFlag, ecx
+ jc @F
+
+NoErrorCode:
+
+ ;
+ ; Push a dummy error code on the stack
+ ; to maintain coherent stack map
+ ;
+ push [rsp]
+ mov qword ptr [rsp + 8], 0
+@@:
+ 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, 208h
+ 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
+ db 0fh, 0aeh, 07h ;fxsave [rdi]
+
+;; UINT32 ExceptionData;
+ push qword ptr [rbp + 16]
+
+;; call into exception handler
+ mov rcx, [rbp + 8]
+ mov rax, ExternalVectorTablePtr ; get the interrupt vectors base
+ 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
+ db 0fh, 0aeh, 0Eh ; 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
+
+CommonInterruptEntry ENDP
+
+END
+
|