--- /dev/null
+/** @file\r
+ CPU Exception Hanlder Library common functions.\r
+\r
+ Copyright (c) 2012, Intel Corporation. All rights reserved.<BR>\r
+ This program and the accompanying materials\r
+ are licensed and made available under the terms and conditions of the BSD License\r
+ which accompanies this distribution. The full text of the license may be found at\r
+ http://opensource.org/licenses/bsd-license.php\r
+\r
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include "CpuExceptionCommon.h"\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
+UINT32 mErrorCodeFlag = 0x00027d00;\r
+\r
+//\r
+// Define the maximum message length \r
+//\r
+#define MAX_DEBUG_MESSAGE_LENGTH 0x100\r
+\r
+/**\r
+ Prints a message to the serial port.\r
+\r
+ @param Format Format string for the message to print.\r
+ @param ... Variable argument list whose contents are accessed \r
+ based on the format string specified by Format.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+InternalPrintMessage (\r
+ IN CONST CHAR8 *Format,\r
+ ...\r
+ )\r
+{\r
+ CHAR8 Buffer[MAX_DEBUG_MESSAGE_LENGTH];\r
+ VA_LIST Marker;\r
+\r
+ //\r
+ // Convert the message to an ASCII String\r
+ //\r
+ VA_START (Marker, Format);\r
+ AsciiVSPrint (Buffer, sizeof (Buffer), Format, Marker);\r
+ VA_END (Marker);\r
+\r
+ //\r
+ // Send the print string to a Serial Port \r
+ //\r
+ SerialPortWrite ((UINT8 *)Buffer, AsciiStrLen (Buffer));\r
+}\r
+\r
+/**\r
+ Find and display image base address and return image base and its entry point.\r
+ \r
+ @return EFI_SUCCESS Image base address.\r
+ @return 0 Image header cannot be found.\r
+**/\r
+UINTN \r
+FindModuleImageBase (\r
+ IN UINTN CurrentEip,\r
+ OUT UINTN *EntryPoint\r
+ )\r
+{\r
+ UINTN Pe32Data;\r
+ EFI_IMAGE_DOS_HEADER *DosHdr;\r
+ EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr;\r
+ VOID *PdbPointer;\r
+\r
+ //\r
+ // Find Image Base\r
+ //\r
+ Pe32Data = CurrentEip & ~(mImageAlignSize - 1);\r
+ while (Pe32Data != 0) {\r
+ DosHdr = (EFI_IMAGE_DOS_HEADER *) Pe32Data;\r
+ if (DosHdr->e_magic == EFI_IMAGE_DOS_SIGNATURE) {\r
+ //\r
+ // DOS image header is present, so read the PE header after the DOS image header.\r
+ //\r
+ Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)(Pe32Data + (UINTN) ((DosHdr->e_lfanew) & 0x0ffff));\r
+ if (Hdr.Pe32->Signature == EFI_IMAGE_NT_SIGNATURE) {\r
+ //\r
+ // It's PE image.\r
+ //\r
+ InternalPrintMessage ("!!!! Find PE image ");\r
+ *EntryPoint = (UINTN)Pe32Data + (UINTN)(Hdr.Pe32->OptionalHeader.AddressOfEntryPoint & 0x0ffffffff);\r
+ break;\r
+ }\r
+ } else {\r
+ //\r
+ // DOS image header is not present, TE header is at the image base.\r
+ //\r
+ Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)Pe32Data;\r
+ if ((Hdr.Te->Signature == EFI_TE_IMAGE_HEADER_SIGNATURE) &&\r
+ ((Hdr.Te->Machine == IMAGE_FILE_MACHINE_I386) || Hdr.Te->Machine == IMAGE_FILE_MACHINE_X64)) {\r
+ //\r
+ // It's TE image, it TE header and Machine type match\r
+ //\r
+ InternalPrintMessage ("!!!! Find TE image ");\r
+ *EntryPoint = (UINTN)Pe32Data + (UINTN)(Hdr.Te->AddressOfEntryPoint & 0x0ffffffff) + sizeof(EFI_TE_IMAGE_HEADER) - Hdr.Te->StrippedSize;\r
+ break;\r
+ }\r
+ }\r
+\r
+ //\r
+ // Not found the image base, check the previous aligned address\r
+ // \r
+ Pe32Data -= mImageAlignSize;\r
+ }\r
+\r
+ if (Pe32Data != 0) {\r
+ PdbPointer = PeCoffLoaderGetPdbPointer ((VOID *) Pe32Data);\r
+ if (PdbPointer != NULL) {\r
+ InternalPrintMessage ("%a", PdbPointer);\r
+ } else {\r
+ InternalPrintMessage ("(No PDB) " );\r
+ }\r
+ } else {\r
+ InternalPrintMessage ("!!!! Can't find image information. !!!!\n");\r
+ }\r
+\r
+ return Pe32Data;\r
+}\r
+\r
--- /dev/null
+/** @file\r
+ Common header file for CPU Exception Handler Library.\r
+\r
+ Copyright (c) 2012, Intel Corporation. All rights reserved.<BR>\r
+ This program and the accompanying materials\r
+ are licensed and made available under the terms and conditions of the BSD License\r
+ which accompanies this distribution. The full text of the license may be found at\r
+ http://opensource.org/licenses/bsd-license.php\r
+\r
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#ifndef _CPU_EXCEPTION_COMMON_H_\r
+#define _CPU_EXCEPTION_COMMON_H_\r
+\r
+#include <Library/BaseLib.h>\r
+#include <Library/SerialPortLib.h>\r
+#include <Library/PrintLib.h>\r
+#include <Library/LocalApicLib.h>\r
+#include <Library/PeCoffGetEntryPointLib.h>\r
+\r
+#define CPU_EXCEPTION_NUM 32\r
+//\r
+// Record exception handler information\r
+//\r
+typedef struct {\r
+ UINTN ExceptionStart;\r
+ UINTN ExceptionStubHeaderSize;\r
+} EXCEPTION_HANDLER_TEMPLATE_MAP;\r
+\r
+extern UINT32 mErrorCodeFlag;\r
+extern CONST UINTN mImageAlignSize;\r
+\r
+/**\r
+ Return address map of exception handler template so that C code can generate\r
+ exception tables.\r
+\r
+ @param AddressMap Pointer to a buffer where the address map is returned.\r
+**/\r
+VOID\r
+EFIAPI\r
+GetTemplateAddressMap (\r
+ OUT EXCEPTION_HANDLER_TEMPLATE_MAP *AddressMap\r
+ );\r
+\r
+/**\r
+ Internal function to setup CPU exception handlers.\r
+\r
+**/\r
+VOID\r
+InternalSetupCpuExceptionHandlers (\r
+ VOID\r
+ );\r
+\r
+/**\r
+ Prints a message to the serial port.\r
+\r
+ @param Format Format string for the message to print.\r
+ @param ... Variable argument list whose contents are accessed \r
+ based on the format string specified by Format.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+InternalPrintMessage (\r
+ IN CONST CHAR8 *Format,\r
+ ...\r
+ );\r
+\r
+/**\r
+ Find and display image base address and return image base and its entry point.\r
+ \r
+ @return EFI_SUCCESS Image base address.\r
+ @return 0 Image header cannot be found.\r
+**/\r
+UINTN \r
+FindModuleImageBase (\r
+ IN UINTN CurrentEip,\r
+ OUT UINTN *EntryPoint\r
+ );\r
+\r
+/**\r
+ Display CPU information.\r
+\r
+ @param InterruptType Exception type.\r
+ @param SystemContext Pointer to EFI_SYSTEM_CONTEXT.\r
+**/\r
+VOID\r
+DumpCpuContent (\r
+ IN UINTN InterruptType,\r
+ IN EFI_SYSTEM_CONTEXT SystemContext\r
+ );\r
+\r
+#endif\r
--- /dev/null
+/** @file\r
+ CPU Exception Library provides DXE/SMM CPU exception handler.\r
+\r
+Copyright (c) 2012, Intel Corporation. All rights reserved.<BR>\r
+This program and the accompanying materials are licensed and made available under\r
+the terms and conditions of the BSD License that accompanies this distribution.\r
+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 <PiDxe.h>\r
+\r
+#include "CpuExceptionCommon.h"\r
+#include <Library/SynchronizationLib.h>\r
+\r
+//\r
+// Spinlock for CPU information display\r
+//\r
+SPIN_LOCK mDisplayMessageSpinLock;\r
+\r
+//\r
+// Image align size for DXE/SMM\r
+//\r
+CONST UINTN mImageAlignSize = SIZE_4KB;\r
+\r
+/**\r
+ Common exception handler.\r
+\r
+ @param ExceptionType Exception type.\r
+ @param SystemContext Pointer to EFI_SYSTEM_CONTEXT.\r
+**/\r
+VOID\r
+EFIAPI\r
+CommonExceptionHandler (\r
+ IN EFI_EXCEPTION_TYPE ExceptionType, \r
+ IN EFI_SYSTEM_CONTEXT SystemContext\r
+ )\r
+{\r
+ //\r
+ // Get Spinlock to display CPU information\r
+ //\r
+ while (!AcquireSpinLockOrFail (&mDisplayMessageSpinLock)) {\r
+ CpuPause ();\r
+ }\r
+\r
+ //\r
+ // Display ExceptionType, CPU information and Image information\r
+ //\r
+ DumpCpuContent (ExceptionType, SystemContext);\r
+\r
+ //\r
+ // Release Spinlock\r
+ //\r
+ ReleaseSpinLock (&mDisplayMessageSpinLock);\r
+\r
+ //\r
+ // Enter a dead loop.\r
+ //\r
+ CpuDeadLoop ();\r
+}\r
+\r
+/**\r
+ Setup CPU exception handlers.\r
+\r
+ This API will setups the CPU exception handler to display CPU contents and run into\r
+ CpuDeadLoop(). \r
+ @Note: Before invoking this API, caller must allocate memory for IDT table and load \r
+ IDTR by AsmWriteIdtr().\r
+ \r
+**/\r
+VOID\r
+EFIAPI\r
+SetupCpuExceptionHandlers (\r
+ IN VOID\r
+ )\r
+{\r
+ InitializeSpinLock (&mDisplayMessageSpinLock);\r
+ InternalSetupCpuExceptionHandlers ();\r
+}\r
+\r
--- /dev/null
+## @file\r
+# Component description file for DXE/SMM CPU Exception Handler Library instance.\r
+#\r
+# This library instance supports DXE SMM module only.\r
+#\r
+# Copyright (c) 2012, Intel Corporation. All rights reserved.<BR>\r
+# This program and the accompanying materials\r
+# are licensed and made available under the terms and conditions of the BSD License\r
+# which accompanies this distribution. The full text of the license may be found at\r
+# http://opensource.org/licenses/bsd-license.php\r
+# \r
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+# \r
+##\r
+\r
+[Defines]\r
+ INF_VERSION = 0x00010005\r
+ BASE_NAME = DxeSmmCpuExceptionHandlerLib\r
+ FILE_GUID = EC629480-BD36-4e8e-8AB2-D28BF0D45864\r
+ MODULE_TYPE = DXE_DRIVER\r
+ VERSION_STRING = 1.0\r
+ LIBRARY_CLASS = CpuExceptionHandlerLib|DXE_CORE DXE_DRIVER DXE_SMM_DRIVER UEFI_APPLICATION\r
+\r
+#\r
+# The following information is for reference only and not required by the build tools.\r
+#\r
+# VALID_ARCHITECTURES = IA32 X64\r
+#\r
+\r
+[Sources.Ia32]\r
+ Ia32/ExceptionHandlerAsm.asm |MSFT\r
+ Ia32/ExceptionHandlerAsm.S |GCC\r
+ Ia32/ArchExceptionHandler.c\r
+\r
+[Sources.X64]\r
+ X64/ExceptionHandlerAsm.asm |MSFT\r
+ X64/ExceptionHandlerAsm.S |GCC\r
+ X64/ArchExceptionHandler.c\r
+\r
+[Sources.common]\r
+ CpuExceptionCommon.h\r
+ CpuExceptionCommon.c\r
+ DxeSmmCpuException.c\r
+\r
+[Packages]\r
+ MdePkg/MdePkg.dec\r
+ MdeModulePkg/MdeModulePkg.dec\r
+ UefiCpuPkg/UefiCpuPkg.dec\r
+\r
+[LibraryClasses]\r
+ BaseLib\r
+ SerialPortLib\r
+ PrintLib\r
+ SynchronizationLib\r
+ LocalApicLib\r
+ PeCoffGetEntryPointLib \r
--- /dev/null
+/** @file\r
+ IA32 CPU Exception Hanlder functons.\r
+\r
+ Copyright (c) 2012, Intel Corporation. All rights reserved.<BR>\r
+ This program and the accompanying materials\r
+ are licensed and made available under the terms and conditions of the BSD License\r
+ which accompanies this distribution. The full text of the license may be found at\r
+ http://opensource.org/licenses/bsd-license.php\r
+\r
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include "CpuExceptionCommon.h"\r
+\r
+/**\r
+ Internal function to setup CPU exception handlers.\r
+\r
+**/\r
+VOID\r
+InternalSetupCpuExceptionHandlers (\r
+ VOID\r
+ )\r
+{\r
+ IA32_DESCRIPTOR IdtDescriptor;\r
+ UINTN IdtSize;\r
+ EXCEPTION_HANDLER_TEMPLATE_MAP TemplateMap;\r
+ UINT16 CodeSegment;\r
+ IA32_IDT_GATE_DESCRIPTOR *IdtEntry;\r
+ UINTN Index;\r
+ UINTN InterruptHandler;;\r
+\r
+ //\r
+ // Read IDT descriptor and calculate IDT size\r
+ //\r
+ AsmReadIdtr (&IdtDescriptor);\r
+ IdtSize = (IdtDescriptor.Limit + 1) / sizeof (IA32_IDT_GATE_DESCRIPTOR);\r
+ if (IdtSize > CPU_EXCEPTION_NUM) {\r
+ //\r
+ // CPU exeption library only setup CPU_EXCEPTION_NUM exception handler at most\r
+ //\r
+ IdtSize = CPU_EXCEPTION_NUM;\r
+ }\r
+\r
+ //\r
+ // Use current CS as the segment selector of interrupt gate in IDT\r
+ //\r
+ CodeSegment = AsmReadCs ();\r
+ IdtEntry = (IA32_IDT_GATE_DESCRIPTOR *) IdtDescriptor.Base;\r
+\r
+ GetTemplateAddressMap (&TemplateMap);\r
+\r
+ for (Index = 0; Index < IdtSize; Index ++) {\r
+ InterruptHandler = TemplateMap.ExceptionStart + Index * TemplateMap.ExceptionStubHeaderSize;\r
+ IdtEntry[Index].Bits.OffsetLow = (UINT16)(UINTN)InterruptHandler;\r
+ IdtEntry[Index].Bits.OffsetHigh = (UINT16)((UINTN)InterruptHandler >> 16);\r
+ IdtEntry[Index].Bits.Selector = CodeSegment;\r
+ IdtEntry[Index].Bits.GateType = IA32_IDT_GATE_TYPE_INTERRUPT_32;\r
+ }\r
+}\r
+\r
+/**\r
+ Dump CPU content information.\r
+\r
+ @param ExceptionType Exception type.\r
+ @param SystemContext Pointer to EFI_SYSTEM_CONTEXT.\r
+**/\r
+VOID\r
+DumpCpuContent (\r
+ IN UINTN ExceptionType,\r
+ IN EFI_SYSTEM_CONTEXT SystemContext\r
+ )\r
+{\r
+ UINTN ImageBase;\r
+ UINTN EntryPoint;\r
+\r
+ InternalPrintMessage (\r
+ "!!!! IA32 Exception Type - %08x CPU Apic ID - %08x !!!!\n",\r
+ ExceptionType,\r
+ GetApicId ()\r
+ );\r
+ InternalPrintMessage (\r
+ "EIP - %08x, CS - %08x, EFLAGS - %08x\n",\r
+ SystemContext.SystemContextIa32->Eip,\r
+ SystemContext.SystemContextIa32->Cs,\r
+ SystemContext.SystemContextIa32->Eflags\r
+ );\r
+ if ((mErrorCodeFlag & (1 << ExceptionType)) != 0) {\r
+ InternalPrintMessage (\r
+ "ExceptionData - %08x\n",\r
+ SystemContext.SystemContextIa32->ExceptionData\r
+ );\r
+ }\r
+ InternalPrintMessage (\r
+ "EAX - %08x, ECX - %08x, EDX - %08x, EBX - %08x\n",\r
+ SystemContext.SystemContextIa32->Eax,\r
+ SystemContext.SystemContextIa32->Ecx,\r
+ SystemContext.SystemContextIa32->Edx,\r
+ SystemContext.SystemContextIa32->Ebx\r
+ );\r
+ InternalPrintMessage (\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
+ InternalPrintMessage (\r
+ "DS - %08x, ES - %08x, FS - %08x, GS - %08x, SS - %08x\n",\r
+ SystemContext.SystemContextIa32->Ds,\r
+ SystemContext.SystemContextIa32->Es,\r
+ SystemContext.SystemContextIa32->Fs,\r
+ SystemContext.SystemContextIa32->Gs,\r
+ SystemContext.SystemContextIa32->Ss\r
+ );\r
+ InternalPrintMessage (\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
+ InternalPrintMessage (\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
+ InternalPrintMessage (\r
+ "DR6 - %08x, DR7 - %08x\n",\r
+ SystemContext.SystemContextIa32->Dr6,\r
+ SystemContext.SystemContextIa32->Dr7\r
+ );\r
+ InternalPrintMessage (\r
+ "GDTR - %08x %08x, IDTR - %08x %08x\n",\r
+ SystemContext.SystemContextIa32->Gdtr[0],\r
+ SystemContext.SystemContextIa32->Gdtr[1],\r
+ SystemContext.SystemContextIa32->Idtr[0],\r
+ SystemContext.SystemContextIa32->Idtr[1]\r
+ );\r
+ InternalPrintMessage (\r
+ "LDTR - %08x, TR - %08x\n",\r
+ SystemContext.SystemContextIa32->Ldtr,\r
+ SystemContext.SystemContextIa32->Tr\r
+ );\r
+ InternalPrintMessage (\r
+ "FXSAVE_STATE - %08x\n",\r
+ &SystemContext.SystemContextIa32->FxSaveState\r
+ );\r
+\r
+ //\r
+ // Find module image base and module entry point by RIP\r
+ //\r
+ ImageBase = FindModuleImageBase (SystemContext.SystemContextIa32->Eip, &EntryPoint);\r
+ if (ImageBase != 0) {\r
+ InternalPrintMessage (\r
+ " (ImageBase=%08x, EntryPoint=%08x) !!!!\n",\r
+ ImageBase,\r
+ EntryPoint\r
+ );\r
+ }\r
+}\r
--- /dev/null
+#------------------------------------------------------------------------------\r
+#*\r
+#* Copyright (c) 2012, Intel Corporation. All rights reserved.<BR>\r
+#* This program and the accompanying materials\r
+#* are licensed and made available under the terms and conditions of the BSD License\r
+#* which accompanies this distribution. The full text of the license may be found at\r
+#* http://opensource.org/licenses/bsd-license.php\r
+#*\r
+#* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+#* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+#*\r
+#* ExceptionHandlerAsm.S\r
+#*\r
+#* Abstract:\r
+#*\r
+#* IA32 CPU Exception Handler\r
+#\r
+#------------------------------------------------------------------------------\r
+\r
+\r
+\r
+\r
+\r
+#.MMX\r
+#.XMM\r
+\r
+ASM_GLOBAL ASM_PFX(CommonExceptionHandler)\r
+ASM_GLOBAL ASM_PFX(CommonInterruptEntry)\r
+\r
+#EXTRN ASM_PFX(mErrorCodeFlag):DWORD # Error code flags for exceptions\r
+\r
+.text\r
+\r
+#\r
+# exception handler stub table\r
+#\r
+Exception0Handle:\r
+ pushl $0\r
+ jmp ASM_PFX(CommonInterruptEntry)\r
+Exception1Handle:\r
+ pushl $1\r
+ jmp ASM_PFX(CommonInterruptEntry)\r
+Exception2Handle:\r
+ pushl $2\r
+ jmp ASM_PFX(CommonInterruptEntry)\r
+Exception3Handle:\r
+ pushl $3\r
+ jmp ASM_PFX(CommonInterruptEntry)\r
+Exception4Handle:\r
+ pushl $4\r
+ jmp ASM_PFX(CommonInterruptEntry)\r
+Exception5Handle:\r
+ pushl $5\r
+ jmp ASM_PFX(CommonInterruptEntry)\r
+Exception6Handle:\r
+ pushl $6\r
+ jmp ASM_PFX(CommonInterruptEntry)\r
+Exception7Handle:\r
+ pushl $7\r
+ jmp ASM_PFX(CommonInterruptEntry)\r
+Exception8Handle:\r
+ pushl $8\r
+ jmp ASM_PFX(CommonInterruptEntry)\r
+Exception9Handle:\r
+ pushl $9\r
+ jmp ASM_PFX(CommonInterruptEntry)\r
+Exception10Handle:\r
+ pushl $10\r
+ jmp ASM_PFX(CommonInterruptEntry)\r
+Exception11Handle:\r
+ pushl $11\r
+ jmp ASM_PFX(CommonInterruptEntry)\r
+Exception12Handle:\r
+ pushl $12\r
+ jmp ASM_PFX(CommonInterruptEntry)\r
+Exception13Handle:\r
+ pushl $13\r
+ jmp ASM_PFX(CommonInterruptEntry)\r
+Exception14Handle:\r
+ pushl $14\r
+ jmp ASM_PFX(CommonInterruptEntry)\r
+Exception15Handle:\r
+ pushl $15\r
+ jmp ASM_PFX(CommonInterruptEntry)\r
+Exception16Handle:\r
+ pushl $16\r
+ jmp ASM_PFX(CommonInterruptEntry)\r
+Exception17Handle:\r
+ pushl $17\r
+ jmp ASM_PFX(CommonInterruptEntry)\r
+Exception18Handle:\r
+ pushl $18\r
+ jmp ASM_PFX(CommonInterruptEntry)\r
+Exception19Handle:\r
+ pushl $19\r
+ jmp ASM_PFX(CommonInterruptEntry)\r
+Exception20Handle:\r
+ pushl $20\r
+ jmp ASM_PFX(CommonInterruptEntry)\r
+Exception21Handle:\r
+ pushl $21\r
+ jmp ASM_PFX(CommonInterruptEntry)\r
+Exception22Handle:\r
+ pushl $22\r
+ jmp ASM_PFX(CommonInterruptEntry)\r
+Exception23Handle:\r
+ pushl $23\r
+ jmp ASM_PFX(CommonInterruptEntry)\r
+Exception24Handle:\r
+ pushl $24\r
+ jmp ASM_PFX(CommonInterruptEntry)\r
+Exception25Handle:\r
+ pushl $25\r
+ jmp ASM_PFX(CommonInterruptEntry)\r
+Exception26Handle:\r
+ pushl $26\r
+ jmp ASM_PFX(CommonInterruptEntry)\r
+Exception27Handle:\r
+ pushl $27\r
+ jmp ASM_PFX(CommonInterruptEntry)\r
+Exception28Handle:\r
+ pushl $28\r
+ jmp ASM_PFX(CommonInterruptEntry)\r
+Exception29Handle:\r
+ pushl $29\r
+ jmp ASM_PFX(CommonInterruptEntry)\r
+Exception30Handle:\r
+ pushl $30\r
+ jmp ASM_PFX(CommonInterruptEntry)\r
+Exception31Handle:\r
+ pushl $31\r
+ jmp ASM_PFX(CommonInterruptEntry)\r
+\r
+#---------------------------------------;\r
+# CommonInterruptEntry ;\r
+#---------------------------------------;\r
+# The follow algorithm is used for the common interrupt routine.\r
+\r
+ASM_GLOBAL ASM_PFX(CommonInterruptEntry)\r
+ASM_PFX(CommonInterruptEntry):\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
+ xchgl (%esp), %ecx\r
+ andl $0x0FFFF, %ecx\r
+ cmpl $32, %ecx # Intel reserved vector for exceptions?\r
+ jae NoErrorCode\r
+ bt %ecx, ASM_PFX(mErrorCodeFlag)\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
+ pushl %ecx\r
+\r
+ #\r
+ # Put 0 (dummy) error code on stack, and restore ECX\r
+ #\r
+ xorl %ecx, %ecx # ECX = 0\r
+ xchgl 4(%esp), %ecx\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
+ xchgl (%esp), %ecx \r
+\r
+ #\r
+ # Fall through to join main routine code\r
+ # at ErrorCodeAndVectorOnStack\r
+ #\r
+CommonInterruptEntry_al_0000:\r
+ jmp CommonInterruptEntry_al_0000\r
+\r
+ErrorCodeAndVectorOnStack:\r
+ pushl %ebp\r
+ movl %esp, %ebp\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
+ andl $0x0fffffff0, %esp \r
+ subl $12, %esp\r
+\r
+#; UINT32 Edi, Esi, Ebp, Esp, Ebx, Edx, Ecx, Eax;\r
+ pushl %eax\r
+ pushl %ecx\r
+ pushl %edx\r
+ pushl %ebx\r
+ leal 24(%ebp), %ecx\r
+ pushl %ecx # ESP\r
+ pushl (%ebp) # EBP\r
+ pushl %esi\r
+ pushl %edi\r
+\r
+#; UINT32 Gs, Fs, Es, Ds, Cs, Ss;\r
+ movl %ss, %eax\r
+ pushl %eax\r
+ movzwl 16(%ebp), %eax \r
+ pushl %eax\r
+ movl %ds, %eax\r
+ pushl %eax\r
+ movl %es, %eax\r
+ pushl %eax\r
+ movl %fs, %eax\r
+ pushl %eax\r
+ movl %gs, %eax\r
+ pushl %eax\r
+\r
+#; UINT32 Eip;\r
+ movl 12(%ebp), %eax\r
+ pushl %eax\r
+\r
+#; UINT32 Gdtr[2], Idtr[2];\r
+ subl $8, %esp\r
+ sidt (%esp)\r
+ movl 2(%esp), %eax\r
+ xchgl (%esp), %eax\r
+ andl $0x0FFFF, %eax \r
+ movl %eax, 4(%esp)\r
+\r
+ subl $8, %esp\r
+ sgdt (%esp)\r
+ movl 2(%esp), %eax\r
+ xchgl (%esp), %eax\r
+ andl $0x0FFFF, %eax \r
+ movl %eax, 4(%esp)\r
+\r
+#; UINT32 Ldtr, Tr;\r
+ xorl %eax, %eax\r
+ str %ax\r
+ pushl %eax\r
+ sldt %ax\r
+ pushl %eax\r
+\r
+#; UINT32 EFlags;\r
+ movl 20(%ebp), %eax\r
+ pushl %eax\r
+\r
+#; UINT32 Cr0, Cr1, Cr2, Cr3, Cr4;\r
+ movl %cr4, %eax\r
+ orl $0x208, %eax\r
+ movl %eax, %cr4\r
+ pushl %eax\r
+ movl %cr3, %eax\r
+ pushl %eax\r
+ movl %cr2, %eax\r
+ pushl %eax\r
+ xorl %eax, %eax\r
+ pushl %eax\r
+ movl %cr0, %eax\r
+ pushl %eax\r
+\r
+#; UINT32 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;\r
+ movl %dr7, %eax\r
+ pushl %eax\r
+ movl %dr6, %eax\r
+ pushl %eax\r
+ movl %dr3, %eax\r
+ pushl %eax\r
+ movl %dr2, %eax\r
+ pushl %eax\r
+ movl %dr1, %eax\r
+ pushl %eax\r
+ movl %dr0, %eax\r
+ pushl %eax\r
+\r
+#; FX_SAVE_STATE_IA32 FxSaveState;\r
+ subl $512, %esp\r
+ movl %esp, %edi\r
+ .byte 0x0f, 0x0ae, 0x07 #fxsave [edi]\r
+\r
+#; UEFI calling convention for IA32 requires that Direction flag in EFLAGs is clear\r
+ cld\r
+\r
+#; UINT32 ExceptionData;\r
+ pushl 8(%ebp)\r
+\r
+#; Prepare parameter and call\r
+ movl %esp, %edx\r
+ pushl %edx\r
+ movl 4(%ebp), %edx\r
+ pushl %edx\r
+\r
+ #\r
+ # Call External Exception Handler\r
+ #\r
+ call ASM_PFX(CommonExceptionHandler)\r
+ addl $8, %esp\r
+\r
+ cli\r
+#; UINT32 ExceptionData;\r
+ addl $4, %esp\r
+\r
+#; FX_SAVE_STATE_IA32 FxSaveState;\r
+ movl %esp, %esi\r
+ .byte 0x0f, 0x0ae, 0x0e # fxrstor [esi]\r
+ addl $512, %esp\r
+\r
+#; UINT32 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;\r
+#; Skip restoration of DRx registers to support in-circuit emualators\r
+#; or debuggers set breakpoint in interrupt/exception context\r
+ addl $24, %esp\r
+\r
+#; UINT32 Cr0, Cr1, Cr2, Cr3, Cr4;\r
+ popl %eax\r
+ movl %eax, %cr0\r
+ addl $4, %esp # not for Cr1\r
+ popl %eax\r
+ movl %eax, %cr2\r
+ popl %eax\r
+ movl %eax, %cr3\r
+ popl %eax\r
+ movl %eax, %cr4\r
+\r
+#; UINT32 EFlags;\r
+ popl 20(%ebp)\r
+\r
+#; UINT32 Ldtr, Tr;\r
+#; UINT32 Gdtr[2], Idtr[2];\r
+#; Best not let anyone mess with these particular registers...\r
+ addl $24, %esp\r
+\r
+#; UINT32 Eip;\r
+ popl 12(%ebp)\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
+ popl %gs\r
+ popl %fs\r
+ popl %es\r
+ popl %ds\r
+ popl 16(%ebp)\r
+ popl %ss\r
+\r
+#; UINT32 Edi, Esi, Ebp, Esp, Ebx, Edx, Ecx, Eax;\r
+ popl %edi\r
+ popl %esi\r
+ addl $4, %esp # not for ebp\r
+ addl $4, %esp # not for esp\r
+ popl %ebx\r
+ popl %edx\r
+ popl %ecx\r
+ popl %eax\r
+\r
+ movl %ebp, %esp\r
+ popl %ebp\r
+ addl $8, %esp\r
+ iretl\r
+\r
+\r
+#---------------------------------------;\r
+# _GetTemplateAddressMap ;\r
+#----------------------------------------------------------------------------;\r
+# \r
+# Protocol prototype\r
+# GetTemplateAddressMap (\r
+# EXCEPTION_HANDLER_TEMPLATE_MAP *AddressMap\r
+# );\r
+# \r
+# Routine Description:\r
+# \r
+# Return address map of interrupt handler template so that C code can generate\r
+# interrupt table.\r
+# \r
+# Arguments:\r
+# \r
+# \r
+# Returns: \r
+# \r
+# Nothing\r
+#\r
+# \r
+# Input: [ebp][0] = Original ebp\r
+# [ebp][4] = Return address\r
+# \r
+# Output: Nothing\r
+# \r
+# Destroys: Nothing\r
+#-----------------------------------------------------------------------------;\r
+#-------------------------------------------------------------------------------------\r
+# AsmGetAddressMap (&AddressMap);\r
+#-------------------------------------------------------------------------------------\r
+ASM_GLOBAL ASM_PFX(GetTemplateAddressMap)\r
+ASM_PFX(GetTemplateAddressMap):\r
+\r
+ pushl %ebp\r
+ movl %esp,%ebp\r
+ pushal\r
+\r
+ movl 0x8(%ebp), %ebx\r
+ movl $Exception0Handle, (%ebx)\r
+ movl $(Exception1Handle - Exception0Handle), 0x4(%ebx)\r
+\r
+ popal\r
+ popl %ebp\r
+ ret\r
+\r
--- /dev/null
+;------------------------------------------------------------------------------ ;\r
+; Copyright (c) 2012, Intel Corporation. All rights reserved.<BR>\r
+; This program and the accompanying materials\r
+; are licensed and made available under the terms and conditions of the BSD License\r
+; which accompanies this distribution. The full text of the license may be found at\r
+; http://opensource.org/licenses/bsd-license.php.\r
+;\r
+; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+;\r
+; Module Name:\r
+;\r
+; ExceptionHandlerAsm.Asm\r
+;\r
+; Abstract:\r
+;\r
+; IA32 CPU Exception Handler\r
+;\r
+; Notes:\r
+;\r
+;------------------------------------------------------------------------------\r
+\r
+ .686\r
+ .model flat,C\r
+\r
+;\r
+; CommonExceptionHandler()\r
+;\r
+CommonExceptionHandler PROTO C\r
+\r
+.data\r
+\r
+CommonEntryAddr DD CommonInterruptEntry\r
+\r
+EXTRN mErrorCodeFlag:DWORD ; Error code flags for exceptions\r
+\r
+.code\r
+\r
+;\r
+; exception handler stub table\r
+;\r
+Exception0Handle:\r
+ push 0\r
+ jmp dword ptr [CommonEntryAddr]\r
+Exception1Handle:\r
+ push 1\r
+ jmp dword ptr [CommonEntryAddr]\r
+Exception2Handle:\r
+ push 2\r
+ jmp dword ptr [CommonEntryAddr]\r
+Exception3Handle:\r
+ push 3\r
+ jmp dword ptr [CommonEntryAddr]\r
+Exception4Handle:\r
+ push 4\r
+ jmp dword ptr [CommonEntryAddr]\r
+Exception5Handle:\r
+ push 5\r
+ jmp dword ptr [CommonEntryAddr]\r
+Exception6Handle:\r
+ push 6\r
+ jmp dword ptr [CommonEntryAddr]\r
+Exception7Handle:\r
+ push 7\r
+ jmp dword ptr [CommonEntryAddr]\r
+Exception8Handle:\r
+ push 8\r
+ jmp dword ptr [CommonEntryAddr]\r
+Exception9Handle:\r
+ push 9\r
+ jmp dword ptr [CommonEntryAddr]\r
+Exception10Handle:\r
+ push 10\r
+ jmp dword ptr [CommonEntryAddr]\r
+Exception11Handle:\r
+ push 11\r
+ jmp dword ptr [CommonEntryAddr]\r
+Exception12Handle:\r
+ push 12\r
+ jmp dword ptr [CommonEntryAddr]\r
+Exception13Handle:\r
+ push 13\r
+ jmp dword ptr [CommonEntryAddr]\r
+Exception14Handle:\r
+ push 14\r
+ jmp dword ptr [CommonEntryAddr]\r
+Exception15Handle:\r
+ push 15\r
+ jmp dword ptr [CommonEntryAddr]\r
+Exception16Handle:\r
+ push 16\r
+ jmp dword ptr [CommonEntryAddr]\r
+Exception17Handle:\r
+ push 17\r
+ jmp dword ptr [CommonEntryAddr]\r
+Exception18Handle:\r
+ push 18\r
+ jmp dword ptr [CommonEntryAddr]\r
+Exception19Handle:\r
+ push 19\r
+ jmp dword ptr [CommonEntryAddr]\r
+Exception20Handle:\r
+ push 20\r
+ jmp dword ptr [CommonEntryAddr]\r
+Exception21Handle:\r
+ push 21\r
+ jmp dword ptr [CommonEntryAddr]\r
+Exception22Handle:\r
+ push 22\r
+ jmp dword ptr [CommonEntryAddr]\r
+Exception23Handle:\r
+ push 23\r
+ jmp dword ptr [CommonEntryAddr]\r
+Exception24Handle:\r
+ push 24\r
+ jmp dword ptr [CommonEntryAddr]\r
+Exception25Handle:\r
+ push 25\r
+ jmp dword ptr [CommonEntryAddr]\r
+Exception26Handle:\r
+ push 26\r
+ jmp dword ptr [CommonEntryAddr]\r
+Exception27Handle:\r
+ push 27\r
+ jmp dword ptr [CommonEntryAddr]\r
+Exception28Handle:\r
+ push 28\r
+ jmp dword ptr [CommonEntryAddr]\r
+Exception29Handle:\r
+ push 29\r
+ jmp dword ptr [CommonEntryAddr]\r
+Exception30Handle:\r
+ push 30\r
+ jmp dword ptr [CommonEntryAddr]\r
+Exception31Handle:\r
+ push 31\r
+ jmp dword ptr [CommonEntryAddr]\r
+\r
+;----------------------------------------------------------------------------;\r
+; CommonInterruptEntry ;\r
+;----------------------------------------------------------------------------;\r
+; The follow algorithm is used for the common interrupt routine.\r
+; Entry from each interrupt with a push eax and eax=interrupt number\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
+ 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
+ mov eax, dr6\r
+ push eax\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
+;; UEFI calling convention for IA32 requires that Direction flag in EFLAGs is clear\r
+ cld\r
+\r
+;; UINT32 ExceptionData;\r
+ push dword ptr [ebp + 2 * 4]\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
+ mov eax, CommonExceptionHandler\r
+ call eax\r
+ add esp, 8\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
+;; Skip restoration of DRx registers to support in-circuit emualators\r
+;; or debuggers set breakpoint in interrupt/exception context\r
+ add esp, 4 * 6\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
+;---------------------------------------;\r
+; _GetTemplateAddressMap ;\r
+;----------------------------------------------------------------------------;\r
+; \r
+; Protocol prototype\r
+; GetTemplateAddressMap (\r
+; EXCEPTION_HANDLER_TEMPLATE_MAP *AddressMap\r
+; );\r
+; \r
+; Routine Description:\r
+; \r
+; Return address map of interrupt handler template so that C code can generate\r
+; interrupt table.\r
+; \r
+; Arguments:\r
+; \r
+; \r
+; Returns: \r
+; \r
+; Nothing\r
+;\r
+; \r
+; Input: [ebp][0] = Original ebp\r
+; [ebp][4] = Return address\r
+; \r
+; Output: Nothing\r
+; \r
+; Destroys: Nothing\r
+;-----------------------------------------------------------------------------;\r
+GetTemplateAddressMap proc near public\r
+ push ebp ; C prolog\r
+ mov ebp, esp\r
+ pushad\r
+\r
+ mov ebx, dword ptr [ebp+08h]\r
+ mov dword ptr [ebx], Exception0Handle\r
+ mov dword ptr [ebx+4h], Exception1Handle - Exception0Handle\r
+ \r
+ popad\r
+ pop ebp\r
+ ret\r
+GetTemplateAddressMap ENDP\r
+\r
+END\r
--- /dev/null
+/** @file\r
+ CPU Exception Library provides SEC/PEIM CPU exception handler.\r
+\r
+Copyright (c) 2012, Intel Corporation. All rights reserved.<BR>\r
+This program and the accompanying materials are licensed and made available under\r
+the terms and conditions of the BSD License that accompanies this distribution.\r
+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 <PiPei.h>\r
+#include "CpuExceptionCommon.h"\r
+\r
+//\r
+// Image Aglinment size for SEC/PEI phase\r
+//\r
+CONST UINTN mImageAlignSize = 4;\r
+\r
+/**\r
+ Common exception handler.\r
+\r
+ @param ExceptionType Exception type.\r
+ @param SystemContext Pointer to EFI_SYSTEM_CONTEXT.\r
+**/\r
+VOID\r
+EFIAPI\r
+CommonExceptionHandler (\r
+ IN EFI_EXCEPTION_TYPE ExceptionType, \r
+ IN EFI_SYSTEM_CONTEXT SystemContext\r
+ )\r
+{\r
+ //\r
+ // Display ExceptionType, CPU information and Image information\r
+ // \r
+ DumpCpuContent (ExceptionType, SystemContext);\r
+ \r
+ //\r
+ // Enter a dead loop.\r
+ //\r
+ CpuDeadLoop ();\r
+}\r
+\r
+/**\r
+ Setup CPU exception handlers.\r
+\r
+ This API will setups the CPU exception handler to display CPU contents and run into\r
+ CpuDeadLoop(). \r
+ @Note: Before invoking this API, caller must allocate memory for IDT table and load \r
+ IDTR by AsmWriteIdtr().\r
+ \r
+**/\r
+VOID\r
+EFIAPI\r
+SetupCpuExceptionHandlers (\r
+ IN VOID\r
+ )\r
+{\r
+ InternalSetupCpuExceptionHandlers ();\r
+}\r
--- /dev/null
+## @file\r
+# Component description file for SEC/PEI CPU Exception Handler Library instance\r
+#\r
+# This library instance supports SEC/PEI module only.\r
+#\r
+# Copyright (c) 2012, Intel Corporation. All rights reserved.<BR>\r
+# This program and the accompanying materials\r
+# are licensed and made available under the terms and conditions of the BSD License\r
+# which accompanies this distribution. The full text of the license may be found at\r
+# http://opensource.org/licenses/bsd-license.php\r
+# \r
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+# \r
+##\r
+\r
+[Defines]\r
+ INF_VERSION = 0x00010005\r
+ BASE_NAME = SecPeiCpuExceptionHandlerLib\r
+ FILE_GUID = CA4BBC99-DFC6-4234-B553-8B6586B7B113\r
+ MODULE_TYPE = PEIM\r
+ VERSION_STRING = 1.0\r
+ LIBRARY_CLASS = CpuExceptionHandlerLib|SEC PEIM_CORE PEIM\r
+\r
+#\r
+# The following information is for reference only and not required by the build tools.\r
+#\r
+# VALID_ARCHITECTURES = IA32 X64\r
+#\r
+\r
+[Sources.Ia32]\r
+ Ia32/ExceptionHandlerAsm.asm |MSFT\r
+ Ia32/ExceptionHandlerAsm.S |GCC\r
+ Ia32/ArchExceptionHandler.c\r
+\r
+[Sources.X64]\r
+ X64/ExceptionHandlerAsm.asm |MSFT\r
+ X64/ExceptionHandlerAsm.S |GCC\r
+ X64/ArchExceptionHandler.c\r
+\r
+[Sources.common]\r
+ CpuExceptionCommon.h\r
+ CpuExceptionCommon.c\r
+ SecPeiCpuException.c\r
+\r
+[Packages]\r
+ MdePkg/MdePkg.dec\r
+ MdeModulePkg/MdeModulePkg.dec\r
+ UefiCpuPkg/UefiCpuPkg.dec\r
+\r
+[LibraryClasses]\r
+ BaseLib\r
+ SerialPortLib\r
+ PrintLib\r
+ LocalApicLib\r
+ PeCoffGetEntryPointLib\r
--- /dev/null
+/** @file\r
+ x64 CPU Exception Hanlder.\r
+\r
+ Copyright (c) 2012, Intel Corporation. All rights reserved.<BR>\r
+ This program and the accompanying materials\r
+ are licensed and made available under the terms and conditions of the BSD License\r
+ which accompanies this distribution. The full text of the license may be found at\r
+ http://opensource.org/licenses/bsd-license.php\r
+\r
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include "CpuExceptionCommon.h"\r
+\r
+/**\r
+ Internal function to setup CPU exception handlers.\r
+\r
+**/\r
+VOID\r
+InternalSetupCpuExceptionHandlers (\r
+ VOID\r
+ )\r
+{\r
+ IA32_DESCRIPTOR IdtDescriptor;\r
+ UINTN IdtSize;\r
+ EXCEPTION_HANDLER_TEMPLATE_MAP TemplateMap;\r
+ UINT16 CodeSegment;\r
+ IA32_IDT_GATE_DESCRIPTOR *IdtEntry;\r
+ UINTN Index;\r
+ UINTN InterruptHandler;\r
+\r
+ //\r
+ // Read IDT descriptor and calculate IDT size\r
+ //\r
+ AsmReadIdtr (&IdtDescriptor);\r
+ IdtSize = (IdtDescriptor.Limit + 1) / sizeof (IA32_IDT_GATE_DESCRIPTOR);\r
+ if (IdtSize > CPU_EXCEPTION_NUM) {\r
+ //\r
+ // CPU exeption library only setup CPU_EXCEPTION_NUM exception handler at most\r
+ //\r
+ IdtSize = CPU_EXCEPTION_NUM;\r
+ }\r
+\r
+ //\r
+ // Use current CS as the segment selector of interrupt gate in IDT\r
+ //\r
+ CodeSegment = AsmReadCs ();\r
+ IdtEntry = (IA32_IDT_GATE_DESCRIPTOR *) IdtDescriptor.Base;\r
+\r
+ GetTemplateAddressMap (&TemplateMap);\r
+\r
+ for (Index = 0; Index < IdtSize; Index ++) {\r
+ InterruptHandler = TemplateMap.ExceptionStart + Index * TemplateMap.ExceptionStubHeaderSize;\r
+ IdtEntry[Index].Bits.OffsetLow = (UINT16)(UINTN)InterruptHandler;\r
+ IdtEntry[Index].Bits.OffsetHigh = (UINT16)((UINTN)InterruptHandler >> 16);\r
+ IdtEntry[Index].Bits.OffsetUpper = (UINT32)((UINTN)InterruptHandler >> 32);\r
+ IdtEntry[Index].Bits.Selector = CodeSegment;\r
+ IdtEntry[Index].Bits.GateType = IA32_IDT_GATE_TYPE_INTERRUPT_32;\r
+ }\r
+}\r
+\r
+/**\r
+ Common exception handler.\r
+\r
+ @param ExceptionType Exception type.\r
+ @param SystemContext Pointer to EFI_SYSTEM_CONTEXT.\r
+**/\r
+VOID\r
+DumpCpuContent (\r
+ IN UINTN ExceptionType,\r
+ IN EFI_SYSTEM_CONTEXT SystemContext\r
+ )\r
+{\r
+ UINTN ImageBase;\r
+ UINTN EntryPoint;\r
+\r
+ InternalPrintMessage (\r
+ "!!!! X64 Exception Type - %016lx CPU Apic ID - %08x !!!!\n",\r
+ ExceptionType,\r
+ GetApicId ()\r
+ );\r
+ InternalPrintMessage (\r
+ "RIP - %016lx, CS - %016lx, RFLAGS - %016lx\n",\r
+ SystemContext.SystemContextX64->Rip,\r
+ SystemContext.SystemContextX64->Cs,\r
+ SystemContext.SystemContextX64->Rflags\r
+ );\r
+ if (mErrorCodeFlag & (1 << ExceptionType)) {\r
+ InternalPrintMessage (\r
+ "ExceptionData - %016lx\n",\r
+ SystemContext.SystemContextX64->ExceptionData\r
+ );\r
+ }\r
+ InternalPrintMessage (\r
+ "RAX - %016lx, RCX - %016lx, RDX - %016lx\n",\r
+ SystemContext.SystemContextX64->Rax,\r
+ SystemContext.SystemContextX64->Rcx,\r
+ SystemContext.SystemContextX64->Rdx\r
+ );\r
+ InternalPrintMessage (\r
+ "RBX - %016lx, RSP - %016lx, RBP - %016lx\n",\r
+ SystemContext.SystemContextX64->Rbx,\r
+ SystemContext.SystemContextX64->Rsp,\r
+ SystemContext.SystemContextX64->Rbp\r
+ );\r
+ InternalPrintMessage (\r
+ "RSI - %016lx, RDI - %016lx\n",\r
+ SystemContext.SystemContextX64->Rsi,\r
+ SystemContext.SystemContextX64->Rdi\r
+ );\r
+ InternalPrintMessage (\r
+ "R8 - %016lx, R9 - %016lx, R10 - %016lx\n",\r
+ SystemContext.SystemContextX64->R8,\r
+ SystemContext.SystemContextX64->R9,\r
+ SystemContext.SystemContextX64->R10\r
+ );\r
+ InternalPrintMessage (\r
+ "R11 - %016lx, R12 - %016lx, R13 - %016lx\n",\r
+ SystemContext.SystemContextX64->R11,\r
+ SystemContext.SystemContextX64->R12,\r
+ SystemContext.SystemContextX64->R13\r
+ );\r
+ InternalPrintMessage (\r
+ "R14 - %016lx, R15 - %016lx\n",\r
+ SystemContext.SystemContextX64->R14,\r
+ SystemContext.SystemContextX64->R15\r
+ );\r
+ InternalPrintMessage (\r
+ "DS - %016lx, ES - %016lx, FS - %016lx\n",\r
+ SystemContext.SystemContextX64->Ds,\r
+ SystemContext.SystemContextX64->Es,\r
+ SystemContext.SystemContextX64->Fs\r
+ );\r
+ InternalPrintMessage (\r
+ "GS - %016lx, SS - %016lx\n",\r
+ SystemContext.SystemContextX64->Gs,\r
+ SystemContext.SystemContextX64->Ss\r
+ );\r
+ InternalPrintMessage (\r
+ "CR0 - %016lx, CR2 - %016lx, CR3 - %016lx\n",\r
+ SystemContext.SystemContextX64->Cr0,\r
+ SystemContext.SystemContextX64->Cr2,\r
+ SystemContext.SystemContextX64->Cr3\r
+ );\r
+ InternalPrintMessage (\r
+ "CR4 - %016lx, CR8 - %016lx\n",\r
+ SystemContext.SystemContextX64->Cr4,\r
+ SystemContext.SystemContextX64->Cr8\r
+ );\r
+ InternalPrintMessage (\r
+ "DR0 - %016lx, DR1 - %016lx, DR2 - %016lx\n",\r
+ SystemContext.SystemContextX64->Dr0,\r
+ SystemContext.SystemContextX64->Dr1,\r
+ SystemContext.SystemContextX64->Dr2\r
+ );\r
+ InternalPrintMessage (\r
+ "DR3 - %016lx, DR6 - %016lx, DR7 - %016lx\n",\r
+ SystemContext.SystemContextX64->Dr3,\r
+ SystemContext.SystemContextX64->Dr6,\r
+ SystemContext.SystemContextX64->Dr7\r
+ );\r
+ InternalPrintMessage (\r
+ "GDTR - %016lx %016lx, LDTR - %016lx\n",\r
+ SystemContext.SystemContextX64->Gdtr[0],\r
+ SystemContext.SystemContextX64->Gdtr[1],\r
+ SystemContext.SystemContextX64->Ldtr\r
+ );\r
+ InternalPrintMessage (\r
+ "IDTR - %016lx %016lx, TR - %016lx\n",\r
+ SystemContext.SystemContextX64->Idtr[0],\r
+ SystemContext.SystemContextX64->Idtr[1],\r
+ SystemContext.SystemContextX64->Tr\r
+ );\r
+ InternalPrintMessage (\r
+ "FXSAVE_STATE - %016lx\n",\r
+ &SystemContext.SystemContextX64->FxSaveState\r
+ );\r
+\r
+ //\r
+ // Find module image base and module entry point by RIP\r
+ //\r
+ ImageBase = FindModuleImageBase (SystemContext.SystemContextX64->Rip, &EntryPoint);\r
+ if (ImageBase != 0) {\r
+ InternalPrintMessage (\r
+ " (ImageBase=%016lx, EntryPoint=%016lx) !!!!\n",\r
+ ImageBase,\r
+ EntryPoint\r
+ );\r
+ }\r
+}\r
--- /dev/null
+#------------------------------------------------------------------------------ ;\r
+# Copyright (c) 2012, Intel Corporation. All rights reserved.<BR>\r
+# This program and the accompanying materials\r
+# are licensed and made available under the terms and conditions of the BSD License\r
+# which accompanies this distribution. The full text of the license may be found at\r
+# http://opensource.org/licenses/bsd-license.php.\r
+#\r
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+#\r
+# Module Name:\r
+#\r
+# ExceptionHandlerAsm.S\r
+#\r
+# Abstract:\r
+#\r
+# x64 CPU Exception Handler\r
+#\r
+# Notes:\r
+#\r
+#------------------------------------------------------------------------------\r
+\r
+\r
+#EXTRN ASM_PFX(mErrorCodeFlag):DWORD # Error code flags for exceptions\r
+\r
+ASM_GLOBAL ASM_PFX(CommonExceptionHandler)\r
+ASM_GLOBAL ASM_PFX(CommonInterruptEntry)\r
+\r
+\r
+.text\r
+\r
+#\r
+# point to the external interrupt vector table\r
+#\r
+Exception0Handle:\r
+ pushq $0\r
+ jmp ASM_PFX(CommonInterruptEntry)\r
+Exception1Handle:\r
+ pushq $1\r
+ jmp ASM_PFX(CommonInterruptEntry)\r
+Exception2Handle:\r
+ pushq $2\r
+ jmp ASM_PFX(CommonInterruptEntry)\r
+Exception3Handle:\r
+ pushq $3\r
+ jmp ASM_PFX(CommonInterruptEntry)\r
+Exception4Handle:\r
+ pushq $4\r
+ jmp ASM_PFX(CommonInterruptEntry)\r
+Exception5Handle:\r
+ pushq $5\r
+ jmp ASM_PFX(CommonInterruptEntry)\r
+Exception6Handle:\r
+ pushq $6\r
+ jmp ASM_PFX(CommonInterruptEntry)\r
+Exception7Handle:\r
+ pushq $7\r
+ jmp ASM_PFX(CommonInterruptEntry)\r
+Exception8Handle:\r
+ pushq $8\r
+ jmp ASM_PFX(CommonInterruptEntry)\r
+Exception9Handle:\r
+ pushq $9\r
+ jmp ASM_PFX(CommonInterruptEntry)\r
+Exception10Handle:\r
+ pushq $10\r
+ jmp ASM_PFX(CommonInterruptEntry)\r
+Exception11Handle:\r
+ pushq $11\r
+ jmp ASM_PFX(CommonInterruptEntry)\r
+Exception12Handle:\r
+ pushq $12\r
+ jmp ASM_PFX(CommonInterruptEntry)\r
+Exception13Handle:\r
+ pushq $13\r
+ jmp ASM_PFX(CommonInterruptEntry)\r
+Exception14Handle:\r
+ pushq $14\r
+ jmp ASM_PFX(CommonInterruptEntry)\r
+Exception15Handle:\r
+ pushq $15\r
+ jmp ASM_PFX(CommonInterruptEntry)\r
+Exception16Handle:\r
+ pushq $16\r
+ jmp ASM_PFX(CommonInterruptEntry)\r
+Exception17Handle:\r
+ pushq $17\r
+ jmp ASM_PFX(CommonInterruptEntry)\r
+Exception18Handle:\r
+ pushq $18\r
+ jmp ASM_PFX(CommonInterruptEntry)\r
+Exception19Handle:\r
+ pushq $19\r
+ jmp ASM_PFX(CommonInterruptEntry)\r
+Exception20Handle:\r
+ pushq $20\r
+ jmp ASM_PFX(CommonInterruptEntry)\r
+Exception21Handle:\r
+ pushq $21\r
+ jmp ASM_PFX(CommonInterruptEntry)\r
+Exception22Handle:\r
+ pushq $22\r
+ jmp ASM_PFX(CommonInterruptEntry)\r
+Exception23Handle:\r
+ pushq $23\r
+ jmp ASM_PFX(CommonInterruptEntry)\r
+Exception24Handle:\r
+ pushq $24\r
+ jmp ASM_PFX(CommonInterruptEntry)\r
+Exception25Handle:\r
+ pushq $25\r
+ jmp ASM_PFX(CommonInterruptEntry)\r
+Exception26Handle:\r
+ pushq $26\r
+ jmp ASM_PFX(CommonInterruptEntry)\r
+Exception27Handle:\r
+ pushq $27\r
+ jmp ASM_PFX(CommonInterruptEntry)\r
+Exception28Handle:\r
+ pushq $28\r
+ jmp ASM_PFX(CommonInterruptEntry)\r
+Exception29Handle:\r
+ pushq $29\r
+ jmp ASM_PFX(CommonInterruptEntry)\r
+Exception30Handle:\r
+ pushq $30\r
+ jmp ASM_PFX(CommonInterruptEntry)\r
+Exception31Handle:\r
+ pushq $31\r
+ jmp ASM_PFX(CommonInterruptEntry)\r
+\r
+\r
+#---------------------------------------;\r
+# CommonInterruptEntry ;\r
+#---------------------------------------;\r
+# The follow algorithm is used for the common interrupt routine.\r
+\r
+ASM_GLOBAL ASM_PFX(CommonInterruptEntry)\r
+ASM_PFX(CommonInterruptEntry):\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
+ xchgq (%rsp), %rcx # get the return address of call, actually, it is the address of vector number.\r
+ cmp $32, %ecx # Intel reserved vector for exceptions?\r
+ jae NoErrorCode\r
+ pushq %rax\r
+ leaq ASM_PFX(mErrorCodeFlag)(%rip), %rax\r
+ bt %ecx, (%rax) \r
+ popq %rax\r
+ jc CommonInterruptEntry_al_0000\r
+\r
+NoErrorCode:\r
+\r
+ #\r
+ # Push a dummy error code on the stack\r
+ # to maintain coherent stack map\r
+ #\r
+ pushq (%rsp)\r
+ movq $0, 8(%rsp)\r
+CommonInterruptEntry_al_0000:\r
+ pushq %rbp\r
+ movq %rsp, %rbp\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
+ pushq %r15\r
+ pushq %r14\r
+ pushq %r13\r
+ pushq %r12\r
+ pushq %r11\r
+ pushq %r10\r
+ pushq %r9\r
+ pushq %r8\r
+ pushq %rax\r
+ pushq 8(%rbp) # RCX\r
+ pushq %rdx\r
+ pushq %rbx\r
+ pushq 48(%rbp) # RSP\r
+ pushq (%rbp) # RBP\r
+ pushq %rsi\r
+ pushq %rdi\r
+\r
+#; UINT64 Gs, Fs, Es, Ds, Cs, Ss; insure high 16 bits of each is zero\r
+ movzwq 56(%rbp), %rax\r
+ pushq %rax # for ss\r
+ movzwq 32(%rbp), %rax\r
+ pushq %rax # for cs\r
+ movl %ds, %eax\r
+ pushq %rax\r
+ movl %es, %eax\r
+ pushq %rax\r
+ movl %fs, %eax\r
+ pushq %rax\r
+ movl %gs, %eax\r
+ pushq %rax\r
+\r
+ movq %rcx, 8(%rbp) # save vector number\r
+\r
+#; UINT64 Rip;\r
+ pushq 24(%rbp)\r
+\r
+#; UINT64 Gdtr[2], Idtr[2];\r
+ xorq %rax, %rax\r
+ pushq %rax\r
+ pushq %rax\r
+ sidt (%rsp)\r
+ xchgq 2(%rsp), %rax\r
+ xchgq (%rsp), %rax\r
+ xchgq 8(%rsp), %rax\r
+\r
+ xorq %rax, %rax\r
+ pushq %rax\r
+ pushq %rax\r
+ sgdt (%rsp)\r
+ xchgq 2(%rsp), %rax\r
+ xchgq (%rsp), %rax\r
+ xchgq 8(%rsp), %rax\r
+\r
+#; UINT64 Ldtr, Tr;\r
+ xorq %rax, %rax\r
+ str %ax\r
+ pushq %rax\r
+ sldt %ax\r
+ pushq %rax\r
+\r
+#; UINT64 RFlags;\r
+ pushq 40(%rbp)\r
+\r
+#; UINT64 Cr0, Cr1, Cr2, Cr3, Cr4, Cr8;\r
+ movq %cr8, %rax\r
+ pushq %rax\r
+ movq %cr4, %rax\r
+ orq $0x208, %rax \r
+ movq %rax, %cr4 \r
+ pushq %rax\r
+ mov %cr3, %rax \r
+ pushq %rax\r
+ mov %cr2, %rax \r
+ pushq %rax\r
+ xorq %rax, %rax\r
+ pushq %rax\r
+ mov %cr0, %rax \r
+ pushq %rax\r
+\r
+#; UINT64 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;\r
+ movq %dr7, %rax\r
+ pushq %rax\r
+ movq %dr6, %rax\r
+ pushq %rax\r
+ movq %dr3, %rax\r
+ pushq %rax\r
+ movq %dr2, %rax\r
+ pushq %rax\r
+ movq %dr1, %rax\r
+ pushq %rax\r
+ movq %dr0, %rax\r
+ pushq %rax\r
+\r
+#; FX_SAVE_STATE_X64 FxSaveState;\r
+ subq $512, %rsp\r
+ movq %rsp, %rdi\r
+ .byte 0x0f, 0x0ae, 0x07 #fxsave [rdi]\r
+\r
+#; UEFI calling convention for x64 requires that Direction flag in EFLAGs is clear\r
+ cld\r
+\r
+#; UINT32 ExceptionData;\r
+ pushq 16(%rbp)\r
+\r
+#; Prepare parameter and call\r
+ mov 8(%rbp), %rcx\r
+ mov %rsp, %rdx\r
+ #\r
+ # Per X64 calling convention, allocate maximum parameter stack space\r
+ # and make sure RSP is 16-byte aligned\r
+ #\r
+ subq $40, %rsp \r
+ call ASM_PFX(CommonExceptionHandler)\r
+ addq $40, %rsp\r
+\r
+ cli\r
+#; UINT64 ExceptionData;\r
+ addq $8, %rsp\r
+\r
+#; FX_SAVE_STATE_X64 FxSaveState;\r
+\r
+ movq %rsp, %rsi\r
+ .byte 0x0f, 0x0ae, 0x0E # fxrstor [rsi]\r
+ addq $512, %rsp\r
+\r
+#; UINT64 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;\r
+#; Skip restoration of DRx registers to support in-circuit emualators\r
+#; or debuggers set breakpoint in interrupt/exception context\r
+ addq $48, %rsp\r
+\r
+#; UINT64 Cr0, Cr1, Cr2, Cr3, Cr4, Cr8;\r
+ popq %rax\r
+ movq %rax, %cr0\r
+ addq $8, %rsp # not for Cr1\r
+ popq %rax\r
+ movq %rax, %cr2\r
+ popq %rax\r
+ movq %rax, %cr3\r
+ popq %rax\r
+ movq %rax, %cr4\r
+ popq %rax\r
+ movq %rax, %cr8\r
+\r
+#; UINT64 RFlags;\r
+ popq 40(%rbp)\r
+\r
+#; UINT64 Ldtr, Tr;\r
+#; UINT64 Gdtr[2], Idtr[2];\r
+#; Best not let anyone mess with these particular registers...\r
+ addq $48, %rsp\r
+\r
+#; UINT64 Rip;\r
+ popq 24(%rbp)\r
+\r
+#; UINT64 Gs, Fs, Es, Ds, Cs, Ss;\r
+ popq %rax\r
+ # mov %rax, %gs ; not for gs\r
+ popq %rax\r
+ # mov %rax, %fs ; not for fs\r
+ # (X64 will not use fs and gs, so we do not restore it)\r
+ popq %rax\r
+ movl %eax, %es\r
+ popq %rax\r
+ movl %eax, %ds\r
+ popq 32(%rbp) # for cs\r
+ popq 56(%rbp) # for ss\r
+\r
+#; UINT64 Rdi, Rsi, Rbp, Rsp, Rbx, Rdx, Rcx, Rax;\r
+#; UINT64 R8, R9, R10, R11, R12, R13, R14, R15;\r
+ popq %rdi\r
+ popq %rsi\r
+ addq $8, %rsp # not for rbp\r
+ popq 48(%rbp) # for rsp\r
+ popq %rbx\r
+ popq %rdx\r
+ popq %rcx\r
+ popq %rax\r
+ popq %r8\r
+ popq %r9\r
+ popq %r10\r
+ popq %r11\r
+ popq %r12\r
+ popq %r13\r
+ popq %r14\r
+ popq %r15\r
+\r
+ movq %rbp, %rsp\r
+ popq %rbp\r
+ addq $16, %rsp\r
+ iretq\r
+\r
+\r
+#-------------------------------------------------------------------------------------\r
+# AsmGetAddressMap (&AddressMap);\r
+#-------------------------------------------------------------------------------------\r
+# comments here for definition of address map\r
+ASM_GLOBAL ASM_PFX(GetTemplateAddressMap)\r
+ASM_PFX(GetTemplateAddressMap):\r
+\r
+ movabsq $Exception0Handle, %rax\r
+ movq %rax, (%rcx)\r
+ movq $(Exception1Handle - Exception0Handle), 0x08(%rcx)\r
+\r
+ ret\r
+\r
+#END\r
+\r
+\r
--- /dev/null
+;------------------------------------------------------------------------------ ;\r
+; Copyright (c) 2012, Intel Corporation. All rights reserved.<BR>\r
+; This program and the accompanying materials\r
+; are licensed and made available under the terms and conditions of the BSD License\r
+; which accompanies this distribution. The full text of the license may be found at\r
+; http://opensource.org/licenses/bsd-license.php.\r
+;\r
+; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+;\r
+; Module Name:\r
+;\r
+; ExceptionHandlerAsm.Asm\r
+;\r
+; Abstract:\r
+;\r
+; x64 CPU Exception Handler\r
+;\r
+; Notes:\r
+;\r
+;------------------------------------------------------------------------------\r
+\r
+;\r
+; CommonExceptionHandler()\r
+;\r
+CommonExceptionHandler PROTO C\r
+\r
+EXTRN mErrorCodeFlag:DWORD ; Error code flags for exceptions\r
+\r
+data SEGMENT\r
+\r
+CommonEntryAddr dq CommonInterruptEntry;\r
+\r
+.code\r
+\r
+Exception0Handle:\r
+ push 0\r
+ jmp qword ptr [CommonEntryAddr]\r
+Exception1Handle:\r
+ push 1\r
+ jmp qword ptr [CommonEntryAddr]\r
+Exception2Handle:\r
+ push 2\r
+ jmp qword ptr [CommonEntryAddr]\r
+Exception3Handle:\r
+ push 3\r
+ jmp qword ptr [CommonEntryAddr]\r
+Exception4Handle:\r
+ push 4\r
+ jmp qword ptr [CommonEntryAddr]\r
+Exception5Handle:\r
+ push 5\r
+ jmp qword ptr [CommonEntryAddr]\r
+Exception6Handle:\r
+ push 6\r
+ jmp qword ptr [CommonEntryAddr]\r
+Exception7Handle:\r
+ push 7\r
+ jmp qword ptr [CommonEntryAddr]\r
+Exception8Handle:\r
+ push 8\r
+ jmp qword ptr [CommonEntryAddr]\r
+Exception9Handle:\r
+ push 9\r
+ jmp qword ptr [CommonEntryAddr]\r
+Exception10Handle:\r
+ push 10\r
+ jmp qword ptr [CommonEntryAddr]\r
+Exception11Handle:\r
+ push 11\r
+ jmp qword ptr [CommonEntryAddr]\r
+Exception12Handle:\r
+ push 12\r
+ jmp qword ptr [CommonEntryAddr]\r
+Exception13Handle:\r
+ push 13\r
+ jmp qword ptr [CommonEntryAddr]\r
+Exception14Handle:\r
+ push 14\r
+ jmp qword ptr [CommonEntryAddr]\r
+Exception15Handle:\r
+ push 15\r
+ jmp qword ptr [CommonEntryAddr]\r
+Exception16Handle:\r
+ push 16\r
+ jmp qword ptr [CommonEntryAddr]\r
+Exception17Handle:\r
+ push 17\r
+ jmp qword ptr [CommonEntryAddr]\r
+Exception18Handle:\r
+ push 18\r
+ jmp qword ptr [CommonEntryAddr]\r
+Exception19Handle:\r
+ push 19\r
+ jmp qword ptr [CommonEntryAddr]\r
+Exception20Handle:\r
+ push 20\r
+ jmp qword ptr [CommonEntryAddr]\r
+Exception21Handle:\r
+ push 21\r
+ jmp qword ptr [CommonEntryAddr]\r
+Exception22Handle:\r
+ push 22\r
+ jmp qword ptr [CommonEntryAddr]\r
+Exception23Handle:\r
+ push 23\r
+ jmp qword ptr [CommonEntryAddr]\r
+Exception24Handle:\r
+ push 24\r
+ jmp qword ptr [CommonEntryAddr]\r
+Exception25Handle:\r
+ push 25\r
+ jmp qword ptr [CommonEntryAddr]\r
+Exception26Handle:\r
+ push 26\r
+ jmp qword ptr [CommonEntryAddr]\r
+Exception27Handle:\r
+ push 27\r
+ jmp qword ptr [CommonEntryAddr]\r
+Exception28Handle:\r
+ push 28\r
+ jmp qword ptr [CommonEntryAddr]\r
+Exception29Handle:\r
+ push 29\r
+ jmp qword ptr [CommonEntryAddr]\r
+Exception30Handle:\r
+ push 30\r
+ jmp qword ptr [CommonEntryAddr]\r
+Exception31Handle:\r
+ push 31\r
+ jmp qword ptr [CommonEntryAddr]\r
+\r
+;CommonInterruptEntrypoint:\r
+;---------------------------------------;\r
+; _CommonEntry ;\r
+;----------------------------------------------------------------------------;\r
+; The follow algorithm is used for the common interrupt routine.\r
+; Entry from each interrupt with a push eax and eax=interrupt number\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
+ 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
+ mov rax, dr6\r
+ push rax\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
+;; UEFI calling convention for x64 requires that Direction flag in EFLAGs is clear\r
+ cld\r
+\r
+;; UINT32 ExceptionData;\r
+ push qword ptr [rbp + 16]\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
+ mov rax, CommonExceptionHandler\r
+ call rax\r
+ add rsp, 4 * 8 + 8\r
+\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
+;; Skip restoration of DRx registers to support in-circuit emualators\r
+;; or debuggers set breakpoint in interrupt/exception context\r
+ add rsp, 8 * 6\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
+;-------------------------------------------------------------------------------------\r
+; GetTemplateAddressMap (&AddressMap);\r
+;-------------------------------------------------------------------------------------\r
+; comments here for definition of address map\r
+GetTemplateAddressMap PROC\r
+ mov rax, offset Exception0Handle\r
+ mov qword ptr [rcx], rax\r
+ mov qword ptr [rcx+8h], Exception1Handle - Exception0Handle\r
+ ret\r
+GetTemplateAddressMap ENDP\r
+\r
+END\r
## @file\r
# UefiCpuPkg Package\r
#\r
-# Copyright (c) 2007 - 2011, Intel Corporation. All rights reserved.<BR>\r
+# Copyright (c) 2007 - 2012, Intel Corporation. All rights reserved.<BR>\r
#\r
# This program and the accompanying materials\r
# are licensed and made available under the terms and conditions of the BSD License\r
UefiCpuPkg/Library/MtrrLib/MtrrLib.inf\r
UefiCpuPkg/Library/BaseXApicX2ApicLib/BaseXApicX2ApicLib.inf\r
UefiCpuPkg/Library/BaseXApicLib/BaseXApicLib.inf\r
+ UefiCpuPkg/Library/CpuExceptionHandlerLib/SecPeiCpuExceptionHandlerLib.inf\r
+ UefiCpuPkg/Library/CpuExceptionHandlerLib/DxeSmmCpuExceptionHandlerLib.inf\r
UefiCpuPkg/Universal/Acpi/S3Resume2Pei/S3Resume2Pei.inf\r
\r