From e41aad152135f27ae1da142454af85a6597719ee Mon Sep 17 00:00:00 2001 From: Jeff Fan Date: Fri, 22 Nov 2013 06:24:41 +0000 Subject: [PATCH] 1. Separated DxeSmmCpuExceptionHandlerLib.inf into 2 instance DxeCpuExceptionHandlerLib.inf and SmmCpuExceptionHandlerLib.inf. 2. Updated CPU Exception Handler Library instance according to the new CPU Exception Handler Library class definitions. 3. Updated CPU Exception Handler Library instance to handle the vector attributes defined in PI 1.2.1. Signed-off-by: Jeff Fan Reviewed-by: Jiewen Yao Reviewed-by: Feng Tian Reviewed-by: Hot Tian git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@14885 6f19259b-4bc3-4df7-8a09-765794883524 --- UefiCpuPkg/CpuDxe/CpuDxe.c | 424 +-------- UefiCpuPkg/CpuDxe/CpuDxe.h | 45 +- UefiCpuPkg/CpuDxe/CpuDxe.inf | 9 +- UefiCpuPkg/CpuDxe/Ia32/CpuAsm.S | 310 +------ UefiCpuPkg/CpuDxe/Ia32/CpuAsm.asm | 307 +------ UefiCpuPkg/CpuDxe/Ia32/IvtAsm.S | 818 ------------------ UefiCpuPkg/CpuDxe/Ia32/IvtAsm.asm | 51 -- UefiCpuPkg/CpuDxe/X64/CpuAsm.S | 287 +----- UefiCpuPkg/CpuDxe/X64/CpuAsm.asm | 279 +----- .../CpuExceptionCommon.c | 39 +- .../CpuExceptionCommon.h | 159 +++- ...rLib.inf => DxeCpuExceptionHandlerLib.inf} | 21 +- .../CpuExceptionHandlerLib/DxeException.c | 170 ++++ .../DxeSmmCpuException.c | 264 +++++- .../Ia32/ArchExceptionHandler.c | 104 ++- .../Ia32/ArchInterruptDefs.h | 44 + .../Ia32/ExceptionHandlerAsm.S | 342 ++++++-- .../Ia32/ExceptionHandlerAsm.asm | 209 ++--- .../SecPeiCpuException.c | 142 ++- .../SecPeiCpuExceptionHandlerLib.inf | 8 +- .../SmmCpuExceptionHandlerLib.inf | 65 ++ .../CpuExceptionHandlerLib/SmmException.c | 101 +++ .../X64/ArchExceptionHandler.c | 115 ++- .../X64/ArchInterruptDefs.h | 46 + .../X64/ExceptionHandlerAsm.S | 333 +++++-- .../X64/ExceptionHandlerAsm.asm | 216 +++-- UefiCpuPkg/UefiCpuPkg.dsc | 8 +- 27 files changed, 1893 insertions(+), 3023 deletions(-) delete mode 100644 UefiCpuPkg/CpuDxe/Ia32/IvtAsm.S delete mode 100644 UefiCpuPkg/CpuDxe/Ia32/IvtAsm.asm rename UefiCpuPkg/Library/CpuExceptionHandlerLib/{DxeSmmCpuExceptionHandlerLib.inf => DxeCpuExceptionHandlerLib.inf} (69%) create mode 100644 UefiCpuPkg/Library/CpuExceptionHandlerLib/DxeException.c create mode 100644 UefiCpuPkg/Library/CpuExceptionHandlerLib/Ia32/ArchInterruptDefs.h create mode 100644 UefiCpuPkg/Library/CpuExceptionHandlerLib/SmmCpuExceptionHandlerLib.inf create mode 100644 UefiCpuPkg/Library/CpuExceptionHandlerLib/SmmException.c create mode 100644 UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ArchInterruptDefs.h diff --git a/UefiCpuPkg/CpuDxe/CpuDxe.c b/UefiCpuPkg/CpuDxe/CpuDxe.c index 2dfde0677d..f165e17c59 100644 --- a/UefiCpuPkg/CpuDxe/CpuDxe.c +++ b/UefiCpuPkg/CpuDxe/CpuDxe.c @@ -1,7 +1,7 @@ /** @file CPU DXE Module. - Copyright (c) 2008 - 2012, Intel Corporation. All rights reserved.
+ Copyright (c) 2008 - 2013, 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 @@ -17,16 +17,11 @@ // // 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; UINT64 mValidMtrrAddressMask = MTRR_LIB_CACHE_VALID_ADDRESS; UINT64 mValidMtrrBitsMask = MTRR_LIB_MSR_VALID_MASK; -IA32_IDT_GATE_DESCRIPTOR *mOrigIdtEntry = NULL; -UINT16 mOrigIdtEntryCount = 0; FIXED_MTRR mFixedMtrrTable[] = { { @@ -100,259 +95,10 @@ EFI_CPU_ARCH_PROTOCOL gCpu = { 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; - -// -// Local function prototypes -// - -/** - Set Interrupt Descriptor Table Handler Address. - - @param Index The Index of the interrupt descriptor table handle. - @param Handler Handler address. - -**/ -VOID -SetInterruptDescriptorTableHandlerAddress ( - IN UINTN Index, - IN VOID *Handler OPTIONAL - ); - // // 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)) != 0) { - 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)) != 0) { - 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. @@ -510,29 +256,7 @@ CpuRegisterInterruptHandler ( 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; - } - - if (InterruptHandler != NULL) { - SetInterruptDescriptorTableHandlerAddress ((UINTN)InterruptType, NULL); - } else { - // - // Restore the original IDT handler address if InterruptHandler is NULL. - // - RestoreInterruptDescriptorTableHandlerAddress ((UINTN)InterruptType); - } - - ExternalVectorTable[InterruptType] = InterruptHandler; - return EFI_SUCCESS; + return RegisterCpuInterruptHandler (InterruptType, InterruptHandler); } @@ -1060,57 +784,6 @@ RefreshGcdMemoryAttributes ( mIsFlushingGCD = FALSE; } -/** - Set Interrupt Descriptor Table Handler Address. - - @param Index The Index of the interrupt descriptor table handle. - @param Handler Handler address. - -**/ -VOID -SetInterruptDescriptorTableHandlerAddress ( - IN UINTN Index, - IN VOID *Handler OPTIONAL - ) -{ - UINTN UintnHandler; - - if (Handler != NULL) { - UintnHandler = (UINTN) Handler; - } else { - UintnHandler = ((UINTN) AsmIdtVector00) + (8 * Index); - } - - gIdtTable[Index].Bits.OffsetLow = (UINT16)UintnHandler; - gIdtTable[Index].Bits.Reserved_0 = 0; - gIdtTable[Index].Bits.GateType = IA32_IDT_GATE_TYPE_INTERRUPT_32; - gIdtTable[Index].Bits.OffsetHigh = (UINT16)(UintnHandler >> 16); -#if defined (MDE_CPU_X64) - gIdtTable[Index].Bits.OffsetUpper = (UINT32)(UintnHandler >> 32); - gIdtTable[Index].Bits.Reserved_1 = 0; -#endif -} - -/** - Restore original Interrupt Descriptor Table Handler Address. - - @param Index The Index of the interrupt descriptor table handle. - -**/ -VOID -RestoreInterruptDescriptorTableHandlerAddress ( - IN UINTN Index - ) -{ - if (Index < mOrigIdtEntryCount) { - gIdtTable[Index].Bits.OffsetLow = mOrigIdtEntry[Index].Bits.OffsetLow; - gIdtTable[Index].Bits.OffsetHigh = mOrigIdtEntry[Index].Bits.OffsetHigh; -#if defined (MDE_CPU_X64) - gIdtTable[Index].Bits.OffsetUpper = mOrigIdtEntry[Index].Bits.OffsetUpper; -#endif - } -} - /** Initialize Interrupt Descriptor Table for interrupt handling. @@ -1120,90 +793,17 @@ InitInterruptDescriptorTable ( VOID ) { - EFI_STATUS Status; - IA32_DESCRIPTOR OldIdtPtr; - IA32_IDT_GATE_DESCRIPTOR *OldIdt; - UINTN OldIdtSize; - VOID *IdtPtrAlignmentBuffer; - IA32_DESCRIPTOR *IdtPtr; - UINTN Index; - UINT16 CurrentCs; - VOID *IntHandler; - - SetMem (ExternalVectorTable, sizeof(ExternalVectorTable), 0); - - // - // Get original IDT address and size. - // - AsmReadIdtr ((IA32_DESCRIPTOR *) &OldIdtPtr); - - if ((OldIdtPtr.Base != 0) && ((OldIdtPtr.Limit & 7) == 7)) { - OldIdt = (IA32_IDT_GATE_DESCRIPTOR*) OldIdtPtr.Base; - OldIdtSize = (OldIdtPtr.Limit + 1) / sizeof (IA32_IDT_GATE_DESCRIPTOR); - // - // Save original IDT entry and IDT entry count. - // - mOrigIdtEntry = AllocateCopyPool (OldIdtPtr.Limit + 1, (VOID *) OldIdtPtr.Base); - ASSERT (mOrigIdtEntry != NULL); - mOrigIdtEntryCount = (UINT16) OldIdtSize; - } else { - OldIdt = NULL; - OldIdtSize = 0; - } - - // - // Intialize IDT - // - CurrentCs = AsmReadCs(); - for (Index = 0; Index < INTERRUPT_VECTOR_NUMBER; Index ++) { - // - // If the old IDT had a handler for this interrupt, then - // preserve it. - // - if (Index < OldIdtSize) { - IntHandler = - (VOID*) ( - OldIdt[Index].Bits.OffsetLow + - (((UINTN) OldIdt[Index].Bits.OffsetHigh) << 16) -#if defined (MDE_CPU_X64) - + (((UINTN) OldIdt[Index].Bits.OffsetUpper) << 32) -#endif - ); - } else { - IntHandler = NULL; - } - - gIdtTable[Index].Bits.Selector = CurrentCs; - gIdtTable[Index].Bits.Reserved_0 = 0; - gIdtTable[Index].Bits.GateType = IA32_IDT_GATE_TYPE_INTERRUPT_32; - SetInterruptDescriptorTableHandlerAddress (Index, IntHandler); - } - - // - // Load IDT Pointer - // - IdtPtrAlignmentBuffer = AllocatePool (sizeof (*IdtPtr) + 16); - IdtPtr = ALIGN_POINTER (IdtPtrAlignmentBuffer, 16); - IdtPtr->Base = (UINT32)(((UINTN)(VOID*) gIdtTable) & (BASE_4GB-1)); - IdtPtr->Limit = (UINT16) (sizeof (gIdtTable) - 1); - - AsmWriteIdtr (IdtPtr); - - FreePool (IdtPtrAlignmentBuffer); - - // - // Initialize Exception Handlers - // - for (Index = OldIdtSize; Index < 32; Index++) { - Status = CpuRegisterInterruptHandler (&gCpu, Index, CommonExceptionHandler); - ASSERT_EFI_ERROR (Status); + EFI_STATUS Status; + EFI_VECTOR_HANDOFF_INFO *VectorInfoList; + EFI_VECTOR_HANDOFF_INFO *VectorInfo; + + VectorInfo = NULL; + Status = EfiGetSystemConfigurationTable (&gEfiVectorHandoffTableGuid, (VOID **) &VectorInfoList); + if (Status == EFI_SUCCESS && VectorInfoList != NULL) { + VectorInfo = VectorInfoList; } - - // - // Set the pointer to the array of C based exception handling routines. - // - InitializeExternalVectorTablePtr (ExternalVectorTable); - + Status = InitializeCpuInterruptHandlers (VectorInfo); + ASSERT_EFI_ERROR (Status); } diff --git a/UefiCpuPkg/CpuDxe/CpuDxe.h b/UefiCpuPkg/CpuDxe/CpuDxe.h index a75ec0593f..2001cfc605 100644 --- a/UefiCpuPkg/CpuDxe/CpuDxe.h +++ b/UefiCpuPkg/CpuDxe/CpuDxe.h @@ -1,7 +1,7 @@ /** @file CPU DXE Module. - Copyright (c) 2008 - 2012, Intel Corporation. All rights reserved.
+ Copyright (c) 2008 - 2013, 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 @@ -30,12 +30,10 @@ #include #include #include +#include +#include #include - -// -// -// -#define INTERRUPT_VECTOR_NUMBER 256 +#include #define EFI_MEMORY_CACHETYPE_MASK (EFI_MEMORY_UC | \ EFI_MEMORY_WC | \ @@ -220,30 +218,6 @@ CpuSetMemoryAttributes ( IN UINT64 Attributes ); -/** - Label of base address of IDT vector 0. - - This is just a label of base address of IDT vector 0. - -**/ -VOID -EFIAPI -AsmIdtVector00 ( - VOID - ); - -/** - Initializes the pointer to the external interrupt vector table. - - @param VectorTable Address of the external interrupt vector table. - -**/ -VOID -EFIAPI -InitializeExternalVectorTablePtr ( - EFI_CPU_INTERRUPT_HANDLER *VectorTable - ); - /** Initialize Global Descriptor Table. @@ -277,16 +251,5 @@ SetDataSelectors ( UINT16 Selector ); -/** - Restore original Interrupt Descriptor Table Handler Address. - - @param Index The Index of the interrupt descriptor table handle. - -**/ -VOID -RestoreInterruptDescriptorTableHandlerAddress ( - IN UINTN Index - ); - #endif diff --git a/UefiCpuPkg/CpuDxe/CpuDxe.inf b/UefiCpuPkg/CpuDxe/CpuDxe.inf index b43506ef58..a8dfed163b 100644 --- a/UefiCpuPkg/CpuDxe/CpuDxe.inf +++ b/UefiCpuPkg/CpuDxe/CpuDxe.inf @@ -2,7 +2,7 @@ # # Component description file for simple CPU driver # -# Copyright (c) 2008 - 2012, Intel Corporation. All rights reserved.
+# Copyright (c) 2008 - 2013, 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 @@ -39,16 +39,14 @@ UefiDriverEntryPoint LocalApicLib UefiCpuLib + UefiLib + CpuExceptionHandlerLib [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 @@ -64,6 +62,7 @@ [Guids] gIdleLoopEventGuid ## CONSUMES ## GUID + gEfiVectorHandoffTableGuid ## CONSUMES ## Configuration Table [Depex] TRUE diff --git a/UefiCpuPkg/CpuDxe/Ia32/CpuAsm.S b/UefiCpuPkg/CpuDxe/Ia32/CpuAsm.S index 3b43b6fd8b..e034bc2e2e 100644 --- a/UefiCpuPkg/CpuDxe/Ia32/CpuAsm.S +++ b/UefiCpuPkg/CpuDxe/Ia32/CpuAsm.S @@ -1,6 +1,6 @@ #------------------------------------------------------------------------------ #* -#* Copyright (c) 2006 - 2012, Intel Corporation. All rights reserved.
+#* Copyright (c) 2006 - 2013, 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 @@ -19,21 +19,6 @@ #.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 - -ASM_GLOBAL ASM_PFX(InitializeExternalVectorTablePtr) -ASM_PFX(InitializeExternalVectorTablePtr): - movl 4(%esp), %eax - movl %eax, ExternalVectorTablePtr - ret - #------------------------------------------------------------------------------ # VOID # SetCodeSelector ( @@ -68,298 +53,5 @@ ASM_PFX(SetDataSelectors): movw %cx, %gs ret -#---------------------------------------; -# CommonInterruptEntry ; -#---------------------------------------; -# The follow algorithm is used for the common interrupt routine. - -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. - # - xchgl (%esp), %ecx - movw (%ecx), %cx - andl $0x0FFFF, %ecx - cmpl $32, %ecx # Intel reserved vector for exceptions? - jae NoErrorCode - bt %ecx, ASM_PFX(mErrorCodeFlag) - jc HasErrorCode - -NoErrorCode: - - # - # Stack: - # +---------------------+ - # + EFlags + - # +---------------------+ - # + CS + - # +---------------------+ - # + EIP + - # +---------------------+ - # + ECX + - # +---------------------+ <-- ESP - # - # Registers: - # ECX - Vector Number - # - - # - # Put Vector Number on stack - # - pushl %ecx - - # - # Put 0 (dummy) error code on stack, and restore ECX - # - xorl %ecx, %ecx # ECX = 0 - xchgl 4(%esp), %ecx - - jmp ErrorCodeAndVectorOnStack - -HasErrorCode: - - # - # Stack: - # +---------------------+ - # + EFlags + - # +---------------------+ - # + CS + - # +---------------------+ - # + EIP + - # +---------------------+ - # + Error Code + - # +---------------------+ - # + ECX + - # +---------------------+ <-- ESP - # - # Registers: - # ECX - Vector Number - # - - # - # Put Vector Number on stack and restore ECX - # - xchgl (%esp), %ecx - -ErrorCodeAndVectorOnStack: - pushl %ebp - movl %esp, %ebp - - # - # 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 - # - andl $0x0fffffff0, %esp - subl $12, %esp - -#; UINT32 Edi, Esi, Ebp, Esp, Ebx, Edx, Ecx, Eax; - pushl %eax - pushl %ecx - pushl %edx - pushl %ebx - leal 24(%ebp), %ecx - pushl %ecx # ESP - pushl (%ebp) # EBP - pushl %esi - pushl %edi - -#; UINT32 Gs, Fs, Es, Ds, Cs, Ss; - movl %ss, %eax - pushl %eax - movzwl 16(%ebp), %eax - pushl %eax - movl %ds, %eax - pushl %eax - movl %es, %eax - pushl %eax - movl %fs, %eax - pushl %eax - movl %gs, %eax - pushl %eax - -#; UINT32 Eip; - movl 12(%ebp), %eax - pushl %eax - -#; UINT32 Gdtr[2], Idtr[2]; - subl $8, %esp - sidt (%esp) - movl 2(%esp), %eax - xchgl (%esp), %eax - andl $0x0FFFF, %eax - movl %eax, 4(%esp) - - subl $8, %esp - sgdt (%esp) - movl 2(%esp), %eax - xchgl (%esp), %eax - andl $0x0FFFF, %eax - movl %eax, 4(%esp) - -#; UINT32 Ldtr, Tr; - xorl %eax, %eax - str %ax - pushl %eax - sldt %ax - pushl %eax - -#; UINT32 EFlags; - movl 20(%ebp), %eax - pushl %eax - -#; UINT32 Cr0, Cr1, Cr2, Cr3, Cr4; - movl %cr4, %eax - orl $0x208, %eax - movl %eax, %cr4 - pushl %eax - movl %cr3, %eax - pushl %eax - movl %cr2, %eax - pushl %eax - xorl %eax, %eax - pushl %eax - movl %cr0, %eax - pushl %eax - -#; UINT32 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7; - movl %dr7, %eax - pushl %eax - movl %dr6, %eax - pushl %eax - movl %dr3, %eax - pushl %eax - movl %dr2, %eax - pushl %eax - movl %dr1, %eax - pushl %eax - movl %dr0, %eax - pushl %eax - -#; FX_SAVE_STATE_IA32 FxSaveState; - subl $512, %esp - movl %esp, %edi - .byte 0x0f, 0x0ae, 0x07 #fxsave [edi] - -#; UEFI calling convention for IA32 requires that Direction flag in EFLAGs is clear - cld - -#; UINT32 ExceptionData; - pushl 8(%ebp) - -#; call into exception handler - movl ExternalVectorTablePtr, %eax # get the interrupt vectors base - orl %eax, %eax # NULL? - jz nullExternalExceptionHandler - - mov 4(%ebp), %ecx - movl (%eax,%ecx,4), %eax - orl %eax, %eax # NULL? - jz nullExternalExceptionHandler - -#; Prepare parameter and call - movl %esp, %edx - pushl %edx - movl 4(%ebp), %edx - pushl %edx - - # - # Call External Exception Handler - # - call *%eax - addl $8, %esp - -nullExternalExceptionHandler: - - cli -#; UINT32 ExceptionData; - addl $4, %esp - -#; FX_SAVE_STATE_IA32 FxSaveState; - movl %esp, %esi - .byte 0x0f, 0x0ae, 0x0e # fxrstor [esi] - addl $512, %esp - -#; UINT32 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7; -#; Skip restoration of DRx registers to support in-circuit emualators -#; or debuggers set breakpoint in interrupt/exception context - addl $24, %esp - -#; UINT32 Cr0, Cr1, Cr2, Cr3, Cr4; - popl %eax - movl %eax, %cr0 - addl $4, %esp # not for Cr1 - popl %eax - movl %eax, %cr2 - popl %eax - movl %eax, %cr3 - popl %eax - movl %eax, %cr4 - -#; UINT32 EFlags; - popl 20(%ebp) - -#; UINT32 Ldtr, Tr; -#; UINT32 Gdtr[2], Idtr[2]; -#; Best not let anyone mess with these particular registers... - addl $24, %esp - -#; UINT32 Eip; - popl 12(%ebp) - -#; 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. -#; - popl %gs - popl %fs - popl %es - popl %ds - popl 16(%ebp) - popl %ss - -#; UINT32 Edi, Esi, Ebp, Esp, Ebx, Edx, Ecx, Eax; - popl %edi - popl %esi - addl $4, %esp # not for ebp - addl $4, %esp # not for esp - popl %ebx - popl %edx - popl %ecx - popl %eax - - movl %ebp, %esp - popl %ebp - addl $8, %esp - iretl - - #END diff --git a/UefiCpuPkg/CpuDxe/Ia32/CpuAsm.asm b/UefiCpuPkg/CpuDxe/Ia32/CpuAsm.asm index 0924dc5bb3..7f8f0d6f3a 100644 --- a/UefiCpuPkg/CpuDxe/Ia32/CpuAsm.asm +++ b/UefiCpuPkg/CpuDxe/Ia32/CpuAsm.asm @@ -1,7 +1,7 @@ TITLE CpuAsm.asm: ;------------------------------------------------------------------------------ ;* -;* Copyright (c) 2006 - 2012, Intel Corporation. All rights reserved.
+;* Copyright (c) 2006 - 2013, 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 @@ -20,19 +20,6 @@ .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 ( @@ -67,297 +54,5 @@ SetDataSelectors PROC PUBLIC 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] - -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 - mov eax, dr6 - push 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] - -;; UEFI calling convention for IA32 requires that Direction flag in EFLAGs is clear - cld - -;; 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; -;; Skip restoration of DRx registers to support in-circuit emualators -;; or debuggers set breakpoint in interrupt/exception context - add esp, 4 * 6 - -;; 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 deleted file mode 100644 index c38461dc9c..0000000000 --- a/UefiCpuPkg/CpuDxe/Ia32/IvtAsm.S +++ /dev/null @@ -1,818 +0,0 @@ -#------------------------------------------------------------------------------ -# -# 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 -# - - -ASM_GLOBAL ASM_PFX(AsmIdtVector00) -.p2align 3 -ASM_PFX(AsmIdtVector00): - call ASM_PFX(CommonInterruptEntry) - .short 0x00 - nop - call ASM_PFX(CommonInterruptEntry) - .short 0x01 - nop - call ASM_PFX(CommonInterruptEntry) - .short 0x02 - nop - call ASM_PFX(CommonInterruptEntry) - .short 0x03 - nop - call ASM_PFX(CommonInterruptEntry) - .short 0x04 - nop - call ASM_PFX(CommonInterruptEntry) - .short 0x05 - nop - call ASM_PFX(CommonInterruptEntry) - .short 0x06 - nop - call ASM_PFX(CommonInterruptEntry) - .short 0x07 - nop - call ASM_PFX(CommonInterruptEntry) - .short 0x08 - nop - call ASM_PFX(CommonInterruptEntry) - .short 0x09 - nop - call ASM_PFX(CommonInterruptEntry) - .short 0x0a - nop - call ASM_PFX(CommonInterruptEntry) - .short 0x0b - nop - call ASM_PFX(CommonInterruptEntry) - .short 0x0c - nop - call ASM_PFX(CommonInterruptEntry) - .short 0x0d - nop - call ASM_PFX(CommonInterruptEntry) - .short 0x0e - nop - call ASM_PFX(CommonInterruptEntry) - .short 0x0f - nop - - call ASM_PFX(CommonInterruptEntry) - .short 0x10 - nop - call ASM_PFX(CommonInterruptEntry) - .short 0x11 - nop - call ASM_PFX(CommonInterruptEntry) - .short 0x12 - nop - call ASM_PFX(CommonInterruptEntry) - .short 0x13 - nop - call ASM_PFX(CommonInterruptEntry) - .short 0x14 - nop - call ASM_PFX(CommonInterruptEntry) - .short 0x15 - nop - call ASM_PFX(CommonInterruptEntry) - .short 0x16 - nop - call ASM_PFX(CommonInterruptEntry) - .short 0x17 - nop - call ASM_PFX(CommonInterruptEntry) - .short 0x18 - nop - call ASM_PFX(CommonInterruptEntry) - .short 0x19 - nop - call ASM_PFX(CommonInterruptEntry) - .short 0x1a - nop - call ASM_PFX(CommonInterruptEntry) - .short 0x1b - nop - call ASM_PFX(CommonInterruptEntry) - .short 0x1c - nop - call ASM_PFX(CommonInterruptEntry) - .short 0x1d - nop - call ASM_PFX(CommonInterruptEntry) - .short 0x1e - nop - call ASM_PFX(CommonInterruptEntry) - .short 0x1f - nop - - call ASM_PFX(CommonInterruptEntry) - .short 0x00 - nop - call ASM_PFX(CommonInterruptEntry) - .short 0x21 - nop - call ASM_PFX(CommonInterruptEntry) - .short 0x22 - nop - call ASM_PFX(CommonInterruptEntry) - .short 0x23 - nop - call ASM_PFX(CommonInterruptEntry) - .short 0x24 - nop - call ASM_PFX(CommonInterruptEntry) - .short 0x25 - nop - call ASM_PFX(CommonInterruptEntry) - .short 0x26 - nop - call ASM_PFX(CommonInterruptEntry) - .short 0x27 - nop - call ASM_PFX(CommonInterruptEntry) - .short 0x28 - nop - call ASM_PFX(CommonInterruptEntry) - .short 0x29 - nop - call ASM_PFX(CommonInterruptEntry) - .short 0x2a - nop - call ASM_PFX(CommonInterruptEntry) - .short 0x2b - nop - call ASM_PFX(CommonInterruptEntry) - .short 0x2c - nop - call ASM_PFX(CommonInterruptEntry) - .short 0x2d - nop - call ASM_PFX(CommonInterruptEntry) - .short 0x2e - nop - call ASM_PFX(CommonInterruptEntry) - .short 0x2f - nop - - call ASM_PFX(CommonInterruptEntry) - .short 0x30 - nop - call ASM_PFX(CommonInterruptEntry) - .short 0x31 - nop - call ASM_PFX(CommonInterruptEntry) - .short 0x32 - nop - call ASM_PFX(CommonInterruptEntry) - .short 0x33 - nop - call ASM_PFX(CommonInterruptEntry) - .short 0x34 - nop - call ASM_PFX(CommonInterruptEntry) - .short 0x35 - nop - call ASM_PFX(CommonInterruptEntry) - .short 0x36 - nop - call ASM_PFX(CommonInterruptEntry) - .short 0x37 - nop - call ASM_PFX(CommonInterruptEntry) - .short 0x38 - nop - call ASM_PFX(CommonInterruptEntry) - .short 0x39 - nop - call ASM_PFX(CommonInterruptEntry) - .short 0x3a - nop - call ASM_PFX(CommonInterruptEntry) - .short 0x3b - nop - call ASM_PFX(CommonInterruptEntry) - .short 0x3c - nop - call ASM_PFX(CommonInterruptEntry) - .short 0x3d - nop - call ASM_PFX(CommonInterruptEntry) - .short 0x3e - nop - call ASM_PFX(CommonInterruptEntry) - .short 0x3f - nop - - call ASM_PFX(CommonInterruptEntry) - .short 0x40 - nop - call ASM_PFX(CommonInterruptEntry) - .short 0x41 - nop - call ASM_PFX(CommonInterruptEntry) - .short 0x42 - nop - call ASM_PFX(CommonInterruptEntry) - .short 0x43 - nop - call ASM_PFX(CommonInterruptEntry) - .short 0x44 - nop - call ASM_PFX(CommonInterruptEntry) - .short 0x45 - nop - call ASM_PFX(CommonInterruptEntry) - .short 0x46 - nop - call ASM_PFX(CommonInterruptEntry) - .short 0x47 - nop - call ASM_PFX(CommonInterruptEntry) - .short 0x48 - nop - call ASM_PFX(CommonInterruptEntry) - .short 0x49 - nop - call ASM_PFX(CommonInterruptEntry) - .short 0x4a - nop - call ASM_PFX(CommonInterruptEntry) - .short 0x4b - nop - call ASM_PFX(CommonInterruptEntry) - .short 0x4c - nop - call ASM_PFX(CommonInterruptEntry) - .short 0x4d - nop - call ASM_PFX(CommonInterruptEntry) - .short 0x4e - nop - call ASM_PFX(CommonInterruptEntry) - .short 0x4f - nop - - call ASM_PFX(CommonInterruptEntry) - .short 0x50 - nop - call ASM_PFX(CommonInterruptEntry) - .short 0x51 - nop - call ASM_PFX(CommonInterruptEntry) - .short 0x52 - nop - call ASM_PFX(CommonInterruptEntry) - .short 0x53 - nop - call ASM_PFX(CommonInterruptEntry) - .short 0x54 - nop - call ASM_PFX(CommonInterruptEntry) - .short 0x55 - nop - call ASM_PFX(CommonInterruptEntry) - .short 0x56 - nop - call ASM_PFX(CommonInterruptEntry) - .short 0x57 - nop - call ASM_PFX(CommonInterruptEntry) - .short 0x58 - nop - call ASM_PFX(CommonInterruptEntry) - .short 0x59 - nop - call ASM_PFX(CommonInterruptEntry) - .short 0x5a - nop - call ASM_PFX(CommonInterruptEntry) - .short 0x5b - nop - call ASM_PFX(CommonInterruptEntry) - .short 0x5c - nop - call ASM_PFX(CommonInterruptEntry) - .short 0x5d - nop - call ASM_PFX(CommonInterruptEntry) - .short 0x5e - nop - call ASM_PFX(CommonInterruptEntry) - .short 0x5f - nop - - call ASM_PFX(CommonInterruptEntry) - .short 0x60 - nop - call ASM_PFX(CommonInterruptEntry) - .short 0x61 - nop - call ASM_PFX(CommonInterruptEntry) - .short 0x62 - nop - call ASM_PFX(CommonInterruptEntry) - .short 0x63 - nop - call ASM_PFX(CommonInterruptEntry) - .short 0x64 - nop - call ASM_PFX(CommonInterruptEntry) - .short 0x65 - nop - call ASM_PFX(CommonInterruptEntry) - .short 0x66 - nop - call ASM_PFX(CommonInterruptEntry) - .short 0x67 - nop - call ASM_PFX(CommonInterruptEntry) - .short 0x68 - nop - call ASM_PFX(CommonInterruptEntry) - .short 0x69 - nop - call ASM_PFX(CommonInterruptEntry) - .short 0x6a - nop - call ASM_PFX(CommonInterruptEntry) - .short 0x6b - nop - call ASM_PFX(CommonInterruptEntry) - .short 0x6c - nop - call ASM_PFX(CommonInterruptEntry) - .short 0x6d - nop - call ASM_PFX(CommonInterruptEntry) - .short 0x6e - nop - call ASM_PFX(CommonInterruptEntry) - .short 0x6f - nop - - call ASM_PFX(CommonInterruptEntry) - .short 0x70 - nop - call ASM_PFX(CommonInterruptEntry) - .short 0x71 - nop - call ASM_PFX(CommonInterruptEntry) - .short 0x72 - nop - call ASM_PFX(CommonInterruptEntry) - .short 0x73 - nop - call ASM_PFX(CommonInterruptEntry) - .short 0x74 - nop - call ASM_PFX(CommonInterruptEntry) - .short 0x75 - nop - call ASM_PFX(CommonInterruptEntry) - .short 0x76 - nop - call ASM_PFX(CommonInterruptEntry) - .short 0x77 - nop - call ASM_PFX(CommonInterruptEntry) - .short 0x78 - nop - call ASM_PFX(CommonInterruptEntry) - .short 0x79 - nop - call ASM_PFX(CommonInterruptEntry) - .short 0x7a - nop - call ASM_PFX(CommonInterruptEntry) - .short 0x7b - nop - call ASM_PFX(CommonInterruptEntry) - .short 0x7c - nop - call ASM_PFX(CommonInterruptEntry) - .short 0x7d - nop - call ASM_PFX(CommonInterruptEntry) - .short 0x7e - nop - call ASM_PFX(CommonInterruptEntry) - .short 0x7f - nop - - call ASM_PFX(CommonInterruptEntry) - .short 0x80 - nop - call ASM_PFX(CommonInterruptEntry) - .short 0x81 - nop - call ASM_PFX(CommonInterruptEntry) - .short 0x82 - nop - call ASM_PFX(CommonInterruptEntry) - .short 0x83 - nop - call ASM_PFX(CommonInterruptEntry) - .short 0x84 - nop - call ASM_PFX(CommonInterruptEntry) - .short 0x85 - nop - call ASM_PFX(CommonInterruptEntry) - .short 0x86 - nop - call ASM_PFX(CommonInterruptEntry) - .short 0x87 - nop - call ASM_PFX(CommonInterruptEntry) - .short 0x88 - nop - call ASM_PFX(CommonInterruptEntry) - .short 0x89 - nop - call ASM_PFX(CommonInterruptEntry) - .short 0x8a - nop - call ASM_PFX(CommonInterruptEntry) - .short 0x8b - nop - call ASM_PFX(CommonInterruptEntry) - .short 0x8c - nop - call ASM_PFX(CommonInterruptEntry) - .short 0x8d - nop - call ASM_PFX(CommonInterruptEntry) - .short 0x8e - nop - call ASM_PFX(CommonInterruptEntry) - .short 0x8f - nop - - call ASM_PFX(CommonInterruptEntry) - .short 0x90 - nop - call ASM_PFX(CommonInterruptEntry) - .short 0x91 - nop - call ASM_PFX(CommonInterruptEntry) - .short 0x92 - nop - call ASM_PFX(CommonInterruptEntry) - .short 0x93 - nop - call ASM_PFX(CommonInterruptEntry) - .short 0x94 - nop - call ASM_PFX(CommonInterruptEntry) - .short 0x95 - nop - call ASM_PFX(CommonInterruptEntry) - .short 0x96 - nop - call ASM_PFX(CommonInterruptEntry) - .short 0x97 - nop - call ASM_PFX(CommonInterruptEntry) - .short 0x98 - nop - call ASM_PFX(CommonInterruptEntry) - .short 0x99 - nop - call ASM_PFX(CommonInterruptEntry) - .short 0x9a - nop - call ASM_PFX(CommonInterruptEntry) - .short 0x9b - nop - call ASM_PFX(CommonInterruptEntry) - .short 0x9c - nop - call ASM_PFX(CommonInterruptEntry) - .short 0x9d - nop - call ASM_PFX(CommonInterruptEntry) - .short 0x9e - nop - call ASM_PFX(CommonInterruptEntry) - .short 0x9f - nop - - call ASM_PFX(CommonInterruptEntry) - .short 0xa0 - nop - call ASM_PFX(CommonInterruptEntry) - .short 0xa1 - nop - call ASM_PFX(CommonInterruptEntry) - .short 0xa2 - nop - call ASM_PFX(CommonInterruptEntry) - .short 0xa3 - nop - call ASM_PFX(CommonInterruptEntry) - .short 0xa4 - nop - call ASM_PFX(CommonInterruptEntry) - .short 0xa5 - nop - call ASM_PFX(CommonInterruptEntry) - .short 0xa6 - nop - call ASM_PFX(CommonInterruptEntry) - .short 0xa7 - nop - call ASM_PFX(CommonInterruptEntry) - .short 0xa8 - nop - call ASM_PFX(CommonInterruptEntry) - .short 0xa9 - nop - call ASM_PFX(CommonInterruptEntry) - .short 0xaa - nop - call ASM_PFX(CommonInterruptEntry) - .short 0xab - nop - call ASM_PFX(CommonInterruptEntry) - .short 0xac - nop - call ASM_PFX(CommonInterruptEntry) - .short 0xad - nop - call ASM_PFX(CommonInterruptEntry) - .short 0xae - nop - call ASM_PFX(CommonInterruptEntry) - .short 0xaf - nop - - call ASM_PFX(CommonInterruptEntry) - .short 0xb0 - nop - call ASM_PFX(CommonInterruptEntry) - .short 0xb1 - nop - call ASM_PFX(CommonInterruptEntry) - .short 0xb2 - nop - call ASM_PFX(CommonInterruptEntry) - .short 0xb3 - nop - call ASM_PFX(CommonInterruptEntry) - .short 0xb4 - nop - call ASM_PFX(CommonInterruptEntry) - .short 0xb5 - nop - call ASM_PFX(CommonInterruptEntry) - .short 0xb6 - nop - call ASM_PFX(CommonInterruptEntry) - .short 0xb7 - nop - call ASM_PFX(CommonInterruptEntry) - .short 0xb8 - nop - call ASM_PFX(CommonInterruptEntry) - .short 0xb9 - nop - call ASM_PFX(CommonInterruptEntry) - .short 0xba - nop - call ASM_PFX(CommonInterruptEntry) - .short 0xbb - nop - call ASM_PFX(CommonInterruptEntry) - .short 0xbc - nop - call ASM_PFX(CommonInterruptEntry) - .short 0xbd - nop - call ASM_PFX(CommonInterruptEntry) - .short 0xbe - nop - call ASM_PFX(CommonInterruptEntry) - .short 0xbf - nop - - call ASM_PFX(CommonInterruptEntry) - .short 0xc0 - nop - call ASM_PFX(CommonInterruptEntry) - .short 0xc1 - nop - call ASM_PFX(CommonInterruptEntry) - .short 0xc2 - nop - call ASM_PFX(CommonInterruptEntry) - .short 0xc3 - nop - call ASM_PFX(CommonInterruptEntry) - .short 0xc4 - nop - call ASM_PFX(CommonInterruptEntry) - .short 0xc5 - nop - call ASM_PFX(CommonInterruptEntry) - .short 0xc6 - nop - call ASM_PFX(CommonInterruptEntry) - .short 0xc7 - nop - call ASM_PFX(CommonInterruptEntry) - .short 0xc8 - nop - call ASM_PFX(CommonInterruptEntry) - .short 0xc9 - nop - call ASM_PFX(CommonInterruptEntry) - .short 0xca - nop - call ASM_PFX(CommonInterruptEntry) - .short 0xcb - nop - call ASM_PFX(CommonInterruptEntry) - .short 0xcc - nop - call ASM_PFX(CommonInterruptEntry) - .short 0xcd - nop - call ASM_PFX(CommonInterruptEntry) - .short 0xce - nop - call ASM_PFX(CommonInterruptEntry) - .short 0xcf - nop - - call ASM_PFX(CommonInterruptEntry) - .short 0xd0 - nop - call ASM_PFX(CommonInterruptEntry) - .short 0xd1 - nop - call ASM_PFX(CommonInterruptEntry) - .short 0xd2 - nop - call ASM_PFX(CommonInterruptEntry) - .short 0xd3 - nop - call ASM_PFX(CommonInterruptEntry) - .short 0xd4 - nop - call ASM_PFX(CommonInterruptEntry) - .short 0xd5 - nop - call ASM_PFX(CommonInterruptEntry) - .short 0xd6 - nop - call ASM_PFX(CommonInterruptEntry) - .short 0xd7 - nop - call ASM_PFX(CommonInterruptEntry) - .short 0xd8 - nop - call ASM_PFX(CommonInterruptEntry) - .short 0xd9 - nop - call ASM_PFX(CommonInterruptEntry) - .short 0xda - nop - call ASM_PFX(CommonInterruptEntry) - .short 0xdb - nop - call ASM_PFX(CommonInterruptEntry) - .short 0xdc - nop - call ASM_PFX(CommonInterruptEntry) - .short 0xdd - nop - call ASM_PFX(CommonInterruptEntry) - .short 0xde - nop - call ASM_PFX(CommonInterruptEntry) - .short 0xdf - nop - - call ASM_PFX(CommonInterruptEntry) - .short 0xe0 - nop - call ASM_PFX(CommonInterruptEntry) - .short 0xe1 - nop - call ASM_PFX(CommonInterruptEntry) - .short 0xe2 - nop - call ASM_PFX(CommonInterruptEntry) - .short 0xe3 - nop - call ASM_PFX(CommonInterruptEntry) - .short 0xe4 - nop - call ASM_PFX(CommonInterruptEntry) - .short 0xe5 - nop - call ASM_PFX(CommonInterruptEntry) - .short 0xe6 - nop - call ASM_PFX(CommonInterruptEntry) - .short 0xe7 - nop - call ASM_PFX(CommonInterruptEntry) - .short 0xe8 - nop - call ASM_PFX(CommonInterruptEntry) - .short 0xe9 - nop - call ASM_PFX(CommonInterruptEntry) - .short 0xea - nop - call ASM_PFX(CommonInterruptEntry) - .short 0xeb - nop - call ASM_PFX(CommonInterruptEntry) - .short 0xec - nop - call ASM_PFX(CommonInterruptEntry) - .short 0xed - nop - call ASM_PFX(CommonInterruptEntry) - .short 0xee - nop - call ASM_PFX(CommonInterruptEntry) - .short 0xef - nop - - call ASM_PFX(CommonInterruptEntry) - .short 0xf0 - nop - call ASM_PFX(CommonInterruptEntry) - .short 0xf1 - nop - call ASM_PFX(CommonInterruptEntry) - .short 0xf2 - nop - call ASM_PFX(CommonInterruptEntry) - .short 0xf3 - nop - call ASM_PFX(CommonInterruptEntry) - .short 0xf4 - nop - call ASM_PFX(CommonInterruptEntry) - .short 0xf5 - nop - call ASM_PFX(CommonInterruptEntry) - .short 0xf6 - nop - call ASM_PFX(CommonInterruptEntry) - .short 0xf7 - nop - call ASM_PFX(CommonInterruptEntry) - .short 0xf8 - nop - call ASM_PFX(CommonInterruptEntry) - .short 0xf9 - nop - call ASM_PFX(CommonInterruptEntry) - .short 0xfa - nop - call ASM_PFX(CommonInterruptEntry) - .short 0xfb - nop - call ASM_PFX(CommonInterruptEntry) - .short 0xfc - nop - call ASM_PFX(CommonInterruptEntry) - .short 0xfd - nop - call ASM_PFX(CommonInterruptEntry) - .short 0xfe - nop - call ASM_PFX(CommonInterruptEntry) - .short 0xff - nop - -ASM_GLOBAL ASM_PFX(AsmCommonIdtEnd) -ASM_PFX(AsmCommonIdtEnd): - .byte 0 - - diff --git a/UefiCpuPkg/CpuDxe/Ia32/IvtAsm.asm b/UefiCpuPkg/CpuDxe/Ia32/IvtAsm.asm deleted file mode 100644 index 02003c9fa5..0000000000 --- a/UefiCpuPkg/CpuDxe/Ia32/IvtAsm.asm +++ /dev/null @@ -1,51 +0,0 @@ - TITLE IvtAsm.asm: -;------------------------------------------------------------------------------ -;* -;* 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. -;* -;* IvtAsm.asm -;* -;* Abstract: -;* -;------------------------------------------------------------------------------ - -#include - -#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 index e038f2e341..e82cadf369 100644 --- a/UefiCpuPkg/CpuDxe/X64/CpuAsm.S +++ b/UefiCpuPkg/CpuDxe/X64/CpuAsm.S @@ -2,7 +2,7 @@ #------------------------------------------------------------------------------ #* -#* Copyright (c) 2008 - 2011, Intel Corporation. All rights reserved.
+#* Copyright (c) 2008 - 2013, 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 @@ -21,22 +21,6 @@ #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 - -ASM_GLOBAL ASM_PFX(InitializeExternalVectorTablePtr) -ASM_PFX(InitializeExternalVectorTablePtr): - lea ExternalVectorTablePtr(%rip), %rax # save vector number - mov %rcx, (%rax) - ret - - #------------------------------------------------------------------------------ # VOID # SetCodeSelector ( @@ -69,275 +53,6 @@ ASM_PFX(SetDataSelectors): movw %cx, %gs ret -#---------------------------------------; -# CommonInterruptEntry ; -#---------------------------------------; -# The follow algorithm is used for the common interrupt routine. - -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 - # - xchgq (%rsp), %rcx # get the return address of call, actually, it is the address of vector number. - movzwl (%rcx), %ecx - cmp $32, %ecx # Intel reserved vector for exceptions? - jae NoErrorCode - pushq %rax - leaq ASM_PFX(mErrorCodeFlag)(%rip), %rax - bt %ecx, (%rax) - popq %rax - jc CommonInterruptEntry_al_0000 - -NoErrorCode: - - # - # Push a dummy error code on the stack - # to maintain coherent stack map - # - pushq (%rsp) - movq $0, 8(%rsp) -CommonInterruptEntry_al_0000: - pushq %rbp - movq %rsp, %rbp - - # - # 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; - pushq %r15 - pushq %r14 - pushq %r13 - pushq %r12 - pushq %r11 - pushq %r10 - pushq %r9 - pushq %r8 - pushq %rax - pushq 8(%rbp) # RCX - pushq %rdx - pushq %rbx - pushq 48(%rbp) # RSP - pushq (%rbp) # RBP - pushq %rsi - pushq %rdi - -#; UINT64 Gs, Fs, Es, Ds, Cs, Ss; insure high 16 bits of each is zero - movzwq 56(%rbp), %rax - pushq %rax # for ss - movzwq 32(%rbp), %rax - pushq %rax # for cs - movl %ds, %eax - pushq %rax - movl %es, %eax - pushq %rax - movl %fs, %eax - pushq %rax - movl %gs, %eax - pushq %rax - - movq %rcx, 8(%rbp) # save vector number - -#; UINT64 Rip; - pushq 24(%rbp) - -#; UINT64 Gdtr[2], Idtr[2]; - xorq %rax, %rax - pushq %rax - pushq %rax - sidt (%rsp) - xchgq 2(%rsp), %rax - xchgq (%rsp), %rax - xchgq 8(%rsp), %rax - - xorq %rax, %rax - pushq %rax - pushq %rax - sgdt (%rsp) - xchgq 2(%rsp), %rax - xchgq (%rsp), %rax - xchgq 8(%rsp), %rax - -#; UINT64 Ldtr, Tr; - xorq %rax, %rax - str %ax - pushq %rax - sldt %ax - pushq %rax - -#; UINT64 RFlags; - pushq 40(%rbp) - -#; UINT64 Cr0, Cr1, Cr2, Cr3, Cr4, Cr8; - movq %cr8, %rax - pushq %rax - movq %cr4, %rax - orq $0x208, %rax - movq %rax, %cr4 - pushq %rax - mov %cr3, %rax - pushq %rax - mov %cr2, %rax - pushq %rax - xorq %rax, %rax - pushq %rax - mov %cr0, %rax - pushq %rax - -#; UINT64 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7; - movq %dr7, %rax - pushq %rax - movq %dr6, %rax - pushq %rax - movq %dr3, %rax - pushq %rax - movq %dr2, %rax - pushq %rax - movq %dr1, %rax - pushq %rax - movq %dr0, %rax - pushq %rax - -#; FX_SAVE_STATE_X64 FxSaveState; - subq $512, %rsp - movq %rsp, %rdi - .byte 0x0f, 0x0ae, 0x07 #fxsave [rdi] - -#; UEFI calling convention for x64 requires that Direction flag in EFLAGs is clear - cld - -#; UINT32 ExceptionData; - pushq 16(%rbp) - -#; call into exception handler - movq 8(%rbp), %rcx - leaq ExternalVectorTablePtr(%rip), %rax - movl (%eax), %eax - movq (%rax,%rcx,8), %rax - orq %rax, %rax # NULL? - - je nonNullValue# - -#; Prepare parameter and call -# mov rcx, [rbp + 8] - mov %rsp, %rdx - # - # Per X64 calling convention, allocate maximum parameter stack space - # and make sure RSP is 16-byte aligned - # - subq $40, %rsp - call *%rax - addq $40, %rsp - -nonNullValue: - cli -#; UINT64 ExceptionData; - addq $8, %rsp - -#; FX_SAVE_STATE_X64 FxSaveState; - - movq %rsp, %rsi - .byte 0x0f, 0x0ae, 0x0E # fxrstor [rsi] - addq $512, %rsp - -#; UINT64 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7; -#; Skip restoration of DRx registers to support in-circuit emualators -#; or debuggers set breakpoint in interrupt/exception context - addq $48, %rsp - -#; UINT64 Cr0, Cr1, Cr2, Cr3, Cr4, Cr8; - popq %rax - movq %rax, %cr0 - addq $8, %rsp # not for Cr1 - popq %rax - movq %rax, %cr2 - popq %rax - movq %rax, %cr3 - popq %rax - movq %rax, %cr4 - popq %rax - movq %rax, %cr8 - -#; UINT64 RFlags; - popq 40(%rbp) - -#; UINT64 Ldtr, Tr; -#; UINT64 Gdtr[2], Idtr[2]; -#; Best not let anyone mess with these particular registers... - addq $48, %rsp - -#; UINT64 Rip; - popq 24(%rbp) - -#; UINT64 Gs, Fs, Es, Ds, Cs, Ss; - popq %rax - # mov %rax, %gs ; not for gs - popq %rax - # mov %rax, %fs ; not for fs - # (X64 will not use fs and gs, so we do not restore it) - popq %rax - movl %eax, %es - popq %rax - movl %eax, %ds - popq 32(%rbp) # for cs - popq 56(%rbp) # for ss - -#; UINT64 Rdi, Rsi, Rbp, Rsp, Rbx, Rdx, Rcx, Rax; -#; UINT64 R8, R9, R10, R11, R12, R13, R14, R15; - popq %rdi - popq %rsi - addq $8, %rsp # not for rbp - popq 48(%rbp) # for rsp - popq %rbx - popq %rdx - popq %rcx - popq %rax - popq %r8 - popq %r9 - popq %r10 - popq %r11 - popq %r12 - popq %r13 - popq %r14 - popq %r15 - - movq %rbp, %rsp - popq %rbp - addq $16, %rsp - iretq - - #text ENDS #END diff --git a/UefiCpuPkg/CpuDxe/X64/CpuAsm.asm b/UefiCpuPkg/CpuDxe/X64/CpuAsm.asm index 68fcd3f404..c71b06a81e 100644 --- a/UefiCpuPkg/CpuDxe/X64/CpuAsm.asm +++ b/UefiCpuPkg/CpuDxe/X64/CpuAsm.asm @@ -1,7 +1,7 @@ TITLE CpuAsm.asm: ;------------------------------------------------------------------------------ ;* -;* Copyright (c) 2008 - 2011, Intel Corporation. All rights reserved.
+;* Copyright (c) 2008 - 2013, 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 @@ -18,18 +18,6 @@ .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 ( @@ -62,270 +50,5 @@ SetDataSelectors PROC PUBLIC 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 - mov rax, dr6 - push 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] - -;; UEFI calling convention for x64 requires that Direction flag in EFLAGs is clear - cld - -;; 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; -;; Skip restoration of DRx registers to support in-circuit emualators -;; or debuggers set breakpoint in interrupt/exception context - add rsp, 8 * 6 - -;; 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 diff --git a/UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.c b/UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.c index b1c6923035..c075d5f168 100644 --- a/UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.c +++ b/UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.c @@ -1,7 +1,7 @@ /** @file CPU Exception Hanlder Library common functions. - Copyright (c) 2012, Intel Corporation. All rights reserved.
+ Copyright (c) 2012 - 2013, 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 @@ -15,12 +15,13 @@ #include "CpuExceptionCommon.h" // -// Error code flag indicating whether or not an error code will be +// 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 // -UINT32 mErrorCodeFlag = 0x00027d00; +CONST UINT32 mErrorCodeFlag = 0x00027d00; +RESERVED_VECTORS_DATA *mReservedVectors = NULL; // // Define the maximum message length @@ -133,3 +134,35 @@ FindModuleImageBase ( return Pe32Data; } +/** + Read and save reserved vector information + + @param[in] VectorInfo Pointer to reserved vector list. + @param[out] ReservedVector Pointer to reserved vector data buffer. + @param[in] VectorCount Vector number to be updated. + + @return EFI_SUCCESS Read and save vector info successfully. + @retval EFI_INVALID_PARAMETER VectorInfo includes the invalid content if VectorInfo is not NULL. + +**/ +EFI_STATUS +ReadAndVerifyVectorInfo ( + IN EFI_VECTOR_HANDOFF_INFO *VectorInfo, + OUT RESERVED_VECTORS_DATA *ReservedVector, + IN UINTN VectorCount + ) +{ + while (VectorInfo->Attribute != EFI_VECTOR_HANDOFF_LAST_ENTRY) { + if (VectorInfo->Attribute > EFI_VECTOR_HANDOFF_HOOK_AFTER) { + // + // If vector attrubute is invalid + // + return EFI_INVALID_PARAMETER; + } + if (VectorInfo->VectorNumber < VectorCount) { + ReservedVector[VectorInfo->VectorNumber].Attribute = VectorInfo->Attribute; + } + VectorInfo ++; + } + return EFI_SUCCESS; +} \ No newline at end of file diff --git a/UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.h b/UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.h index 66847eaae6..6b0ccfe73d 100644 --- a/UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.h +++ b/UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.h @@ -1,7 +1,7 @@ /** @file Common header file for CPU Exception Handler Library. - Copyright (c) 2012, Intel Corporation. All rights reserved.
+ Copyright (c) 2012 - 2013, 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 @@ -15,23 +15,36 @@ #ifndef _CPU_EXCEPTION_COMMON_H_ #define _CPU_EXCEPTION_COMMON_H_ +#include +#include #include #include #include #include #include +#include +#include +#include + +#define CPU_EXCEPTION_NUM 32 +#define CPU_INTERRUPT_NUM 256 +#define HOOKAFTER_STUB_SIZE 16 + +#include "ArchInterruptDefs.h" -#define CPU_EXCEPTION_NUM 32 // // Record exception handler information // typedef struct { UINTN ExceptionStart; UINTN ExceptionStubHeaderSize; + UINTN HookAfterStubHeaderStart; } EXCEPTION_HANDLER_TEMPLATE_MAP; -extern UINT32 mErrorCodeFlag; -extern CONST UINTN mImageAlignSize; +extern CONST UINT32 mErrorCodeFlag; +extern CONST UINTN mImageAlignSize; +extern CONST UINTN mDoFarReturnFlag; +extern RESERVED_VECTORS_DATA *mReservedVectors; /** Return address map of exception handler template so that C code can generate @@ -41,17 +54,33 @@ extern CONST UINTN mImageAlignSize; **/ VOID EFIAPI -GetTemplateAddressMap ( +AsmGetTemplateAddressMap ( OUT EXCEPTION_HANDLER_TEMPLATE_MAP *AddressMap ); /** - Internal function to setup CPU exception handlers. + Return address map of exception handler template so that C code can generate + exception tables. + + @param IdtEntry Pointer to IDT entry to be updated. + @param InterruptHandler IDT handler value. **/ VOID -InternalSetupCpuExceptionHandlers ( - VOID +ArchUpdateIdtEntry ( + IN IA32_IDT_GATE_DESCRIPTOR *IdtEntry, + IN UINTN InterruptHandler + ); + +/** + Read IDT handler value from IDT entry. + + @param IdtEntry Pointer to IDT entry to be read. + +**/ +UINTN +ArchGetIdtHandler ( + IN IA32_IDT_GATE_DESCRIPTOR *IdtEntry ); /** @@ -92,8 +121,120 @@ FindModuleImageBase ( **/ VOID DumpCpuContent ( - IN UINTN InterruptType, + IN EFI_EXCEPTION_TYPE ExceptionType, IN EFI_SYSTEM_CONTEXT SystemContext ); +/** + Internal worker function to initialize exception handler. + + @param[in] VectorInfo Pointer to reserved vector list. + + @retval EFI_SUCCESS CPU Exception Entries have been successfully initialized + with default exception handlers. + @retval EFI_INVALID_PARAMETER VectorInfo includes the invalid content if VectorInfo is not NULL. + @retval EFI_UNSUPPORTED This function is not supported. + +**/ +EFI_STATUS +InitializeCpuExceptionHandlersWorker ( + IN EFI_VECTOR_HANDOFF_INFO *VectorInfo OPTIONAL + ); + +/** + Registers a function to be called from the processor interrupt handler. + + @param[in] InterruptType Defines which interrupt or exception to hook. + @param[in] InterruptHandler A pointer to a function of type EFI_CPU_INTERRUPT_HANDLER that is called + when a processor interrupt occurs. If this parameter is NULL, then the handler + will be uninstalled. + + @retval EFI_SUCCESS The handler for the processor interrupt was successfully 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, + or this function is not supported. +*/ +EFI_STATUS +RegisterCpuInterruptHandlerWorker ( + IN EFI_EXCEPTION_TYPE InterruptType, + IN EFI_CPU_INTERRUPT_HANDLER InterruptHandler + ); + +/** + Internal worker function to update IDT entries accordling to vector attributes. + + @param[in] IdtTable Pointer to IDT table. + @param[in] TemplateMap Pointer to a buffer where the address map is returned. + @param[in] IdtEntryCount IDT entries number to be updated. + +**/ +VOID +UpdateIdtTable ( + IN IA32_IDT_GATE_DESCRIPTOR *IdtTable, + IN EXCEPTION_HANDLER_TEMPLATE_MAP *TemplateMap, + IN UINTN IdtEntryCount + ); + +/** + Save CPU exception context when handling EFI_VECTOR_HANDOFF_HOOK_AFTER case. + + @param[in] ExceptionType Exception type. + @param[in] SystemContext Pointer to EFI_SYSTEM_CONTEXT. + +**/ +VOID +ArchSaveExceptionContext ( + IN UINTN ExceptionType, + IN EFI_SYSTEM_CONTEXT SystemContext + ); + +/** + Restore CPU exception context when handling EFI_VECTOR_HANDOFF_HOOK_AFTER case. + + @param[in] ExceptionType Exception type. + @param[in] SystemContext Pointer to EFI_SYSTEM_CONTEXT. + +**/ +VOID +ArchRestoreExceptionContext ( + IN UINTN ExceptionType, + IN EFI_SYSTEM_CONTEXT SystemContext + ); + +/** + Fix up the vector number in the vector code. + + @param[in] VectorBase Base address of the vector handler. + @param[in] VectorNum Index of vector. + +**/ +VOID +EFIAPI +AsmVectorNumFixup ( + IN VOID *VectorBase, + IN UINT8 VectorNum + ); + +/** + Read and save reserved vector information + + @param[in] VectorInfo Pointer to reserved vector list. + @param[out] ReservedVector Pointer to reserved vector data buffer. + @param[in] VectorCount Vector number to be updated. + + @return EFI_SUCCESS Read and save vector info successfully. + @retval EFI_INVALID_PARAMETER VectorInfo includes the invalid content if VectorInfo is not NULL. + +**/ +EFI_STATUS +ReadAndVerifyVectorInfo ( + IN EFI_VECTOR_HANDOFF_INFO *VectorInfo, + OUT RESERVED_VECTORS_DATA *ReservedVector, + IN UINTN VectorCount + ); + #endif + diff --git a/UefiCpuPkg/Library/CpuExceptionHandlerLib/DxeSmmCpuExceptionHandlerLib.inf b/UefiCpuPkg/Library/CpuExceptionHandlerLib/DxeCpuExceptionHandlerLib.inf similarity index 69% rename from UefiCpuPkg/Library/CpuExceptionHandlerLib/DxeSmmCpuExceptionHandlerLib.inf rename to UefiCpuPkg/Library/CpuExceptionHandlerLib/DxeCpuExceptionHandlerLib.inf index 9f0f2d9beb..454307b6e7 100644 --- a/UefiCpuPkg/Library/CpuExceptionHandlerLib/DxeSmmCpuExceptionHandlerLib.inf +++ b/UefiCpuPkg/Library/CpuExceptionHandlerLib/DxeCpuExceptionHandlerLib.inf @@ -1,9 +1,9 @@ ## @file -# Component description file for DXE/SMM CPU Exception Handler Library instance. +# Component description file for DXE CPU Exception Handler Library instance. # -# This library instance supports DXE SMM module only. +# This library instance supports DXE module only. # -# Copyright (c) 2012, Intel Corporation. All rights reserved.
+# Copyright (c) 2013, 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 @@ -16,11 +16,11 @@ [Defines] INF_VERSION = 0x00010005 - BASE_NAME = DxeSmmCpuExceptionHandlerLib - FILE_GUID = EC629480-BD36-4e8e-8AB2-D28BF0D45864 + BASE_NAME = DxeCpuExceptionHandlerLib + FILE_GUID = B6E9835A-EDCF-4748-98A8-27D3C722E02D MODULE_TYPE = DXE_DRIVER VERSION_STRING = 1.0 - LIBRARY_CLASS = CpuExceptionHandlerLib|DXE_CORE DXE_DRIVER DXE_SMM_DRIVER UEFI_APPLICATION + LIBRARY_CLASS = CpuExceptionHandlerLib|DXE_CORE DXE_DRIVER UEFI_APPLICATION # # The following information is for reference only and not required by the build tools. @@ -32,16 +32,19 @@ Ia32/ExceptionHandlerAsm.asm |MSFT Ia32/ExceptionHandlerAsm.S |GCC Ia32/ArchExceptionHandler.c + Ia32/ArchInterruptDefs.h [Sources.X64] X64/ExceptionHandlerAsm.asm |MSFT X64/ExceptionHandlerAsm.S |GCC X64/ArchExceptionHandler.c + X64/ArchInterruptDefs.h [Sources.common] CpuExceptionCommon.h CpuExceptionCommon.c DxeSmmCpuException.c + DxeException.c [Packages] MdePkg/MdePkg.dec @@ -55,3 +58,9 @@ SynchronizationLib LocalApicLib PeCoffGetEntryPointLib + ReportStatusCodeLib + MemoryAllocationLib + DebugLib + +[Ppis] + gEfiVectorHandoffInfoPpiGuid diff --git a/UefiCpuPkg/Library/CpuExceptionHandlerLib/DxeException.c b/UefiCpuPkg/Library/CpuExceptionHandlerLib/DxeException.c new file mode 100644 index 0000000000..b4b844cde9 --- /dev/null +++ b/UefiCpuPkg/Library/CpuExceptionHandlerLib/DxeException.c @@ -0,0 +1,170 @@ +/** @file + CPU exception handler library implemenation for DXE modules. + + Copyright (c) 2013, 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 +#include "CpuExceptionCommon.h" +#include +#include + +CONST UINTN mDoFarReturnFlag = 0; + +extern SPIN_LOCK mDisplayMessageSpinLock; +extern EFI_CPU_INTERRUPT_HANDLER *mExternalInterruptHandler; + +/** + Initializes all CPU exceptions entries and provides the default exception handlers. + + Caller should try to get an array of interrupt and/or exception vectors that are in use and need to + persist by EFI_VECTOR_HANDOFF_INFO defined in PI 1.3 specification. + If caller cannot get reserved vector list or it does not exists, set VectorInfo to NULL. + If VectorInfo is not NULL, the exception vectors will be initialized per vector attribute accordingly. + + @param[in] VectorInfo Pointer to reserved vector list. + + @retval EFI_SUCCESS CPU Exception Entries have been successfully initialized + with default exception handlers. + @retval EFI_INVALID_PARAMETER VectorInfo includes the invalid content if VectorInfo is not NULL. + @retval EFI_UNSUPPORTED This function is not supported. + +**/ +EFI_STATUS +EFIAPI +InitializeCpuExceptionHandlers ( + IN EFI_VECTOR_HANDOFF_INFO *VectorInfo OPTIONAL + ) +{ + return InitializeCpuExceptionHandlersWorker (VectorInfo); +} + +/** + Initializes all CPU interrupt/exceptions entries and provides the default interrupt/exception handlers. + + Caller should try to get an array of interrupt and/or exception vectors that are in use and need to + persist by EFI_VECTOR_HANDOFF_INFO defined in PI 1.3 specification. + If caller cannot get reserved vector list or it does not exists, set VectorInfo to NULL. + If VectorInfo is not NULL, the exception vectors will be initialized per vector attribute accordingly. + + @param[in] VectorInfo Pointer to reserved vector list. + + @retval EFI_SUCCESS All CPU interrupt/exception entries have been successfully initialized + with default interrupt/exception handlers. + @retval EFI_INVALID_PARAMETER VectorInfo includes the invalid content if VectorInfo is not NULL. + @retval EFI_UNSUPPORTED This function is not supported. + +**/ +EFI_STATUS +EFIAPI +InitializeCpuInterruptHandlers ( + IN EFI_VECTOR_HANDOFF_INFO *VectorInfo OPTIONAL + ) +{ + EFI_STATUS Status; + IA32_IDT_GATE_DESCRIPTOR *IdtTable; + IA32_DESCRIPTOR IdtDescriptor; + UINTN IdtEntryCount; + EXCEPTION_HANDLER_TEMPLATE_MAP TemplateMap; + UINTN Index; + UINTN InterruptEntry; + UINT8 *InterruptEntryCode; + + mReservedVectors = AllocatePool (sizeof (RESERVED_VECTORS_DATA) * CPU_INTERRUPT_NUM); + ASSERT (mReservedVectors != NULL); + SetMem ((VOID *) mReservedVectors, sizeof (RESERVED_VECTORS_DATA) * CPU_INTERRUPT_NUM, 0xff); + if (VectorInfo != NULL) { + Status = ReadAndVerifyVectorInfo (VectorInfo, mReservedVectors, CPU_INTERRUPT_NUM); + if (EFI_ERROR (Status)) { + FreePool (mReservedVectors); + return EFI_INVALID_PARAMETER; + } + } + InitializeSpinLock (&mDisplayMessageSpinLock); + mExternalInterruptHandler = AllocateZeroPool (sizeof (EFI_CPU_INTERRUPT_HANDLER) * CPU_INTERRUPT_NUM); + ASSERT (mExternalInterruptHandler != NULL); + + // + // Read IDT descriptor and calculate IDT size + // + AsmReadIdtr (&IdtDescriptor); + IdtEntryCount = (IdtDescriptor.Limit + 1) / sizeof (IA32_IDT_GATE_DESCRIPTOR); + if (IdtEntryCount > CPU_INTERRUPT_NUM) { + IdtEntryCount = CPU_INTERRUPT_NUM; + } + // + // Create Interrupt Descriptor Table and Copy the old IDT table in + // + IdtTable = AllocateZeroPool (sizeof (IA32_IDT_GATE_DESCRIPTOR) * CPU_INTERRUPT_NUM); + ASSERT (IdtTable != NULL); + CopyMem (IdtTable, (VOID *)IdtDescriptor.Base, sizeof (IA32_IDT_GATE_DESCRIPTOR) * IdtEntryCount); + + AsmGetTemplateAddressMap (&TemplateMap); + ASSERT (TemplateMap.ExceptionStubHeaderSize <= HOOKAFTER_STUB_SIZE); + InterruptEntryCode = AllocatePool (TemplateMap.ExceptionStubHeaderSize * CPU_INTERRUPT_NUM); + ASSERT (InterruptEntryCode != NULL); + + InterruptEntry = (UINTN) InterruptEntryCode; + for (Index = 0; Index < CPU_INTERRUPT_NUM; Index ++) { + CopyMem ( + (VOID *) InterruptEntry, + (VOID *) TemplateMap.ExceptionStart, + TemplateMap.ExceptionStubHeaderSize + ); + AsmVectorNumFixup ((VOID *) InterruptEntry, (UINT8) Index); + InterruptEntry += TemplateMap.ExceptionStubHeaderSize; + } + + TemplateMap.ExceptionStart = (UINTN) InterruptEntryCode; + UpdateIdtTable (IdtTable, &TemplateMap, CPU_INTERRUPT_NUM); + + // + // Load Interrupt Descriptor Table + // + IdtDescriptor.Base = (UINTN) IdtTable; + IdtDescriptor.Limit = (UINT16) (sizeof (IA32_IDT_GATE_DESCRIPTOR) * CPU_INTERRUPT_NUM - 1); + AsmWriteIdtr ((IA32_DESCRIPTOR *) &IdtDescriptor); + + return EFI_SUCCESS; +} + +/** + Registers a function to be called from the processor interrupt handler. + + This function registers and enables the handler specified by InterruptHandler for a processor + interrupt or exception type specified by InterruptType. If InterruptHandler is NULL, then the + handler for the processor interrupt or exception type specified by InterruptType is uninstalled. + The installed handler is called once for each processor interrupt or exception. + NOTE: This function should be invoked after InitializeCpuExceptionHandlers() or + InitializeCpuInterruptHandlers() invoked, otherwise EFI_UNSUPPORTED returned. + + @param[in] InterruptType Defines which interrupt or exception to hook. + @param[in] InterruptHandler A pointer to a function of type EFI_CPU_INTERRUPT_HANDLER that is called + when a processor interrupt occurs. If this parameter is NULL, then the handler + will be uninstalled. + + @retval EFI_SUCCESS The handler for the processor interrupt was successfully 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, + or this function is not supported. +*/ +EFI_STATUS +EFIAPI +RegisterCpuInterruptHandler ( + IN EFI_EXCEPTION_TYPE InterruptType, + IN EFI_CPU_INTERRUPT_HANDLER InterruptHandler + ) +{ + return RegisterCpuInterruptHandlerWorker (InterruptType, InterruptHandler); +} diff --git a/UefiCpuPkg/Library/CpuExceptionHandlerLib/DxeSmmCpuException.c b/UefiCpuPkg/Library/CpuExceptionHandlerLib/DxeSmmCpuException.c index 682def43be..aed5cf8128 100644 --- a/UefiCpuPkg/Library/CpuExceptionHandlerLib/DxeSmmCpuException.c +++ b/UefiCpuPkg/Library/CpuExceptionHandlerLib/DxeSmmCpuException.c @@ -1,7 +1,7 @@ /** @file - CPU Exception Library provides DXE/SMM CPU exception handler. + CPU Exception Library provides DXE/SMM CPU common exception handler. -Copyright (c) 2012, Intel Corporation. All rights reserved.
+Copyright (c) 2012 - 2013, 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 that accompanies this distribution. The full text of the license may be found at @@ -12,10 +12,8 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. **/ -#include - #include "CpuExceptionCommon.h" -#include +#include // // Spinlock for CPU information display @@ -27,6 +25,11 @@ SPIN_LOCK mDisplayMessageSpinLock; // CONST UINTN mImageAlignSize = SIZE_4KB; +RESERVED_VECTORS_DATA mReservedVectorsData[CPU_EXCEPTION_NUM]; +EFI_CPU_INTERRUPT_HANDLER mExternalInterruptHandlerTable[CPU_EXCEPTION_NUM]; +EFI_CPU_INTERRUPT_HANDLER *mExternalInterruptHandler = NULL; +UINTN mEnabledInterruptNum = 0; + /** Common exception handler. @@ -36,49 +39,250 @@ CONST UINTN mImageAlignSize = SIZE_4KB; VOID EFIAPI CommonExceptionHandler ( - IN EFI_EXCEPTION_TYPE ExceptionType, - IN EFI_SYSTEM_CONTEXT SystemContext + IN EFI_EXCEPTION_TYPE ExceptionType, + IN EFI_SYSTEM_CONTEXT SystemContext ) { - // - // Get Spinlock to display CPU information - // - while (!AcquireSpinLockOrFail (&mDisplayMessageSpinLock)) { - CpuPause (); + EXCEPTION_HANDLER_CONTEXT *ExceptionHandlerContext; + + ExceptionHandlerContext = (EXCEPTION_HANDLER_CONTEXT *) (UINTN) (SystemContext.SystemContextIa32); + + switch (mReservedVectors[ExceptionType].Attribute) { + case EFI_VECTOR_HANDOFF_HOOK_BEFORE: + // + // Need to jmp to old IDT handler after this exception handler + // + ExceptionHandlerContext->ExceptionDataFlag = (mErrorCodeFlag & (1 << ExceptionType)) ? TRUE : FALSE; + ExceptionHandlerContext->OldIdtHandler = mReservedVectors[ExceptionType].ExceptonHandler; + break; + case EFI_VECTOR_HANDOFF_HOOK_AFTER: + while (TRUE) { + // + // If if anyone has gotten SPIN_LOCK for owner running hook after + // + if (AcquireSpinLockOrFail (&mReservedVectors[ExceptionType].SpinLock)) { + // + // Need to execute old IDT handler before running this exception handler + // + mReservedVectors[ExceptionType].ApicId = GetApicId (); + ArchSaveExceptionContext (ExceptionType, SystemContext); + ExceptionHandlerContext->ExceptionDataFlag = (mErrorCodeFlag & (1 << ExceptionType)) ? TRUE : FALSE; + ExceptionHandlerContext->OldIdtHandler = mReservedVectors[ExceptionType].ExceptonHandler; + return; + } + // + // If failed to acquire SPIN_LOCK, check if it was locked by processor itself + // + if (mReservedVectors[ExceptionType].ApicId == GetApicId ()) { + // + // Old IDT handler has been executed, then retore CPU exception content to + // run new exception handler. + // + ArchRestoreExceptionContext (ExceptionType, SystemContext); + // + // Rlease spin lock for ApicId + // + ReleaseSpinLock (&mReservedVectors[ExceptionType].SpinLock); + break; + } + CpuPause (); + } + break; + case 0xffffffff: + break; + default: + // + // It should never reach here + // + CpuDeadLoop (); + break; } + + if (mExternalInterruptHandler[ExceptionType] != NULL) { + (mExternalInterruptHandler[ExceptionType]) (ExceptionType, SystemContext); + } else { + // + // Get Spinlock to display CPU information + // + while (!AcquireSpinLockOrFail (&mDisplayMessageSpinLock)) { + CpuPause (); + } + // + // Display ExceptionType, CPU information and Image information + // + DumpCpuContent (ExceptionType, SystemContext); + // + // Release Spinlock of output message + // + ReleaseSpinLock (&mDisplayMessageSpinLock); + // + // Enter a dead loop if needn't to execute old IDT handler further + // + if (mReservedVectors[ExceptionType].Attribute != EFI_VECTOR_HANDOFF_HOOK_BEFORE) { + CpuDeadLoop (); + } + } +} - // - // Display ExceptionType, CPU information and Image information - // - DumpCpuContent (ExceptionType, SystemContext); +/** + Internal worker function to update IDT entries accordling to vector attributes. + + @param[in] IdtTable Pointer to IDT table. + @param[in] TemplateMap Pointer to a buffer where the address map is returned. + @param[in] IdtEntryCount IDT entries number to be updated. + +**/ +VOID +UpdateIdtTable ( + IN IA32_IDT_GATE_DESCRIPTOR *IdtTable, + IN EXCEPTION_HANDLER_TEMPLATE_MAP *TemplateMap, + IN UINTN IdtEntryCount + ) +{ + UINT16 CodeSegment; + UINTN Index; + UINTN InterruptHandler; // - // Release Spinlock + // Use current CS as the segment selector of interrupt gate in IDT // - ReleaseSpinLock (&mDisplayMessageSpinLock); + CodeSegment = AsmReadCs (); + for (Index = 0; Index < IdtEntryCount; Index ++) { + IdtTable[Index].Bits.Selector = CodeSegment; + // + // Check reserved vectors attributes + // + switch (mReservedVectors[Index].Attribute) { + case EFI_VECTOR_HANDOFF_DO_NOT_HOOK: + // + // Keep original IDT entry + // + continue; + case EFI_VECTOR_HANDOFF_HOOK_AFTER: + InitializeSpinLock (&mReservedVectors[Index].SpinLock); + CopyMem ( + (VOID *) mReservedVectors[Index].HookAfterStubHeaderCode, + (VOID *) TemplateMap->HookAfterStubHeaderStart, + TemplateMap->ExceptionStubHeaderSize + ); + AsmVectorNumFixup ((VOID *) mReservedVectors[Index].HookAfterStubHeaderCode, (UINT8) Index); + // + // Go on the following code + // + case EFI_VECTOR_HANDOFF_HOOK_BEFORE: + // + // Save original IDT handler address + // + mReservedVectors[Index].ExceptonHandler = ArchGetIdtHandler (&IdtTable[Index]); + // + // Go on the following code + // + default: + // + // Update new IDT entry + // + InterruptHandler = TemplateMap->ExceptionStart + Index * TemplateMap->ExceptionStubHeaderSize; + ArchUpdateIdtEntry (&IdtTable[Index], InterruptHandler); + break; + } + } + // - // Enter a dead loop. + // Save Interrupt number to global variable used for RegisterCpuInterruptHandler () // - CpuDeadLoop (); + mEnabledInterruptNum = IdtEntryCount; } /** - Setup CPU exception handlers. + Internal worker function to initialize exception handler. - This API will setups the CPU exception handler to display CPU contents and run into - CpuDeadLoop(). - Note: Before invoking this API, caller must allocate memory for IDT table and load - IDTR by AsmWriteIdtr(). + @param[in] VectorInfo Pointer to reserved vector list. + @retval EFI_SUCCESS CPU Exception Entries have been successfully initialized + with default exception handlers. + @retval EFI_INVALID_PARAMETER VectorInfo includes the invalid content if VectorInfo is not NULL. + @retval EFI_UNSUPPORTED This function is not supported. + **/ -VOID -EFIAPI -SetupCpuExceptionHandlers ( - IN VOID +EFI_STATUS +InitializeCpuExceptionHandlersWorker ( + IN EFI_VECTOR_HANDOFF_INFO *VectorInfo OPTIONAL ) { + EFI_STATUS Status; + IA32_DESCRIPTOR IdtDescriptor; + UINTN IdtEntryCount; + EXCEPTION_HANDLER_TEMPLATE_MAP TemplateMap; + IA32_IDT_GATE_DESCRIPTOR *IdtTable; + + mReservedVectors = mReservedVectorsData; + SetMem ((VOID *) mReservedVectors, sizeof (RESERVED_VECTORS_DATA) * CPU_EXCEPTION_NUM, 0xff); + if (VectorInfo != NULL) { + Status = ReadAndVerifyVectorInfo (VectorInfo, mReservedVectors, CPU_EXCEPTION_NUM); + if (EFI_ERROR (Status)) { + return EFI_INVALID_PARAMETER; + } + } InitializeSpinLock (&mDisplayMessageSpinLock); - InternalSetupCpuExceptionHandlers (); + + mExternalInterruptHandler = mExternalInterruptHandlerTable; + // + // Read IDT descriptor and calculate IDT size + // + AsmReadIdtr (&IdtDescriptor); + IdtEntryCount = (IdtDescriptor.Limit + 1) / sizeof (IA32_IDT_GATE_DESCRIPTOR); + if (IdtEntryCount > CPU_EXCEPTION_NUM) { + // + // CPU exeption library only setup CPU_EXCEPTION_NUM exception handler at most + // + IdtEntryCount = CPU_EXCEPTION_NUM; + } + + IdtTable = (IA32_IDT_GATE_DESCRIPTOR *) IdtDescriptor.Base; + AsmGetTemplateAddressMap (&TemplateMap); + ASSERT (TemplateMap.ExceptionStubHeaderSize <= HOOKAFTER_STUB_SIZE); + UpdateIdtTable (IdtTable, &TemplateMap, IdtEntryCount); + mEnabledInterruptNum = IdtEntryCount; + return EFI_SUCCESS; +} + +/** + Registers a function to be called from the processor interrupt handler. + + @param[in] InterruptType Defines which interrupt or exception to hook. + @param[in] InterruptHandler A pointer to a function of type EFI_CPU_INTERRUPT_HANDLER that is called + when a processor interrupt occurs. If this parameter is NULL, then the handler + will be uninstalled. + + @retval EFI_SUCCESS The handler for the processor interrupt was successfully 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, + or this function is not supported. +*/ +EFI_STATUS +RegisterCpuInterruptHandlerWorker ( + IN EFI_EXCEPTION_TYPE InterruptType, + IN EFI_CPU_INTERRUPT_HANDLER InterruptHandler + ) +{ + if (InterruptType < 0 || InterruptType > (EFI_EXCEPTION_TYPE)mEnabledInterruptNum || + mReservedVectors[InterruptType].Attribute == EFI_VECTOR_HANDOFF_DO_NOT_HOOK) { + return EFI_UNSUPPORTED; + } + + if (InterruptHandler == NULL && mExternalInterruptHandler[InterruptType] == NULL) { + return EFI_INVALID_PARAMETER; + } + + if (InterruptHandler != NULL && mExternalInterruptHandler[InterruptType] != NULL) { + return EFI_ALREADY_STARTED; + } + + mExternalInterruptHandler[InterruptType] = InterruptHandler; + return EFI_SUCCESS; } diff --git a/UefiCpuPkg/Library/CpuExceptionHandlerLib/Ia32/ArchExceptionHandler.c b/UefiCpuPkg/Library/CpuExceptionHandlerLib/Ia32/ArchExceptionHandler.c index a69f0d3d2b..ba2cc6f227 100644 --- a/UefiCpuPkg/Library/CpuExceptionHandlerLib/Ia32/ArchExceptionHandler.c +++ b/UefiCpuPkg/Library/CpuExceptionHandlerLib/Ia32/ArchExceptionHandler.c @@ -1,7 +1,7 @@ /** @file IA32 CPU Exception Hanlder functons. - Copyright (c) 2012, Intel Corporation. All rights reserved.
+ Copyright (c) 2012 - 2013, 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 @@ -15,49 +15,87 @@ #include "CpuExceptionCommon.h" /** - Internal function to setup CPU exception handlers. + Return address map of exception handler template so that C code can generate + exception tables. + + @param IdtEntry Pointer to IDT entry to be updated. + @param InterruptHandler IDT handler value. **/ VOID -InternalSetupCpuExceptionHandlers ( - VOID +ArchUpdateIdtEntry ( + IN IA32_IDT_GATE_DESCRIPTOR *IdtEntry, + IN UINTN InterruptHandler + ) +{ + IdtEntry->Bits.OffsetLow = (UINT16)(UINTN)InterruptHandler; + IdtEntry->Bits.OffsetHigh = (UINT16)((UINTN)InterruptHandler >> 16); + IdtEntry->Bits.GateType = IA32_IDT_GATE_TYPE_INTERRUPT_32; +} + +/** + Read IDT handler value from IDT entry. + + @param IdtEntry Pointer to IDT entry to be read. + +**/ +UINTN +ArchGetIdtHandler ( + IN IA32_IDT_GATE_DESCRIPTOR *IdtEntry ) { - IA32_DESCRIPTOR IdtDescriptor; - UINTN IdtSize; - EXCEPTION_HANDLER_TEMPLATE_MAP TemplateMap; - UINT16 CodeSegment; - IA32_IDT_GATE_DESCRIPTOR *IdtEntry; - UINTN Index; - UINTN InterruptHandler;; + return (UINTN)IdtEntry->Bits.OffsetLow + (((UINTN)IdtEntry->Bits.OffsetHigh) << 16); +} + +/** + Save CPU exception context when handling EFI_VECTOR_HANDOFF_HOOK_AFTER case. + @param ExceptionType Exception type. + @param SystemContext Pointer to EFI_SYSTEM_CONTEXT. + +**/ +VOID +ArchSaveExceptionContext ( + IN UINTN ExceptionType, + IN EFI_SYSTEM_CONTEXT SystemContext + ) +{ + IA32_EFLAGS32 Eflags; // - // Read IDT descriptor and calculate IDT size + // Save Exception context in global variable // - AsmReadIdtr (&IdtDescriptor); - IdtSize = (IdtDescriptor.Limit + 1) / sizeof (IA32_IDT_GATE_DESCRIPTOR); - if (IdtSize > CPU_EXCEPTION_NUM) { - // - // CPU exeption library only setup CPU_EXCEPTION_NUM exception handler at most - // - IdtSize = CPU_EXCEPTION_NUM; - } - + mReservedVectors[ExceptionType].OldFlags = SystemContext.SystemContextIa32->Eflags; + mReservedVectors[ExceptionType].OldCs = SystemContext.SystemContextIa32->Cs; + mReservedVectors[ExceptionType].OldIp = SystemContext.SystemContextIa32->Eip; + mReservedVectors[ExceptionType].ExceptionData = SystemContext.SystemContextIa32->ExceptionData; + // + // Clear IF flag to avoid old IDT handler enable interrupt by IRET // - // Use current CS as the segment selector of interrupt gate in IDT + Eflags.UintN = SystemContext.SystemContextIa32->Eflags; + Eflags.Bits.IF = 0; + SystemContext.SystemContextIa32->Eflags = Eflags.UintN; // - CodeSegment = AsmReadCs (); - IdtEntry = (IA32_IDT_GATE_DESCRIPTOR *) IdtDescriptor.Base; + // Modify the EIP in stack, then old IDT handler will return to the stub code + // + SystemContext.SystemContextIa32->Eip = (UINTN) mReservedVectors[ExceptionType].HookAfterStubHeaderCode; +} - GetTemplateAddressMap (&TemplateMap); +/** + Restore CPU exception context when handling EFI_VECTOR_HANDOFF_HOOK_AFTER case. - for (Index = 0; Index < IdtSize; Index ++) { - InterruptHandler = TemplateMap.ExceptionStart + Index * TemplateMap.ExceptionStubHeaderSize; - IdtEntry[Index].Bits.OffsetLow = (UINT16)(UINTN)InterruptHandler; - IdtEntry[Index].Bits.OffsetHigh = (UINT16)((UINTN)InterruptHandler >> 16); - IdtEntry[Index].Bits.Selector = CodeSegment; - IdtEntry[Index].Bits.GateType = IA32_IDT_GATE_TYPE_INTERRUPT_32; - } + @param ExceptionType Exception type. + @param SystemContext Pointer to EFI_SYSTEM_CONTEXT. +**/ +VOID +ArchRestoreExceptionContext ( + IN UINTN ExceptionType, + IN EFI_SYSTEM_CONTEXT SystemContext + ) +{ + SystemContext.SystemContextIa32->Eflags = mReservedVectors[ExceptionType].OldFlags; + SystemContext.SystemContextIa32->Cs = mReservedVectors[ExceptionType].OldCs; + SystemContext.SystemContextIa32->Eip = mReservedVectors[ExceptionType].OldIp; + SystemContext.SystemContextIa32->ExceptionData = mReservedVectors[ExceptionType].ExceptionData; } /** @@ -68,7 +106,7 @@ InternalSetupCpuExceptionHandlers ( **/ VOID DumpCpuContent ( - IN UINTN ExceptionType, + IN EFI_EXCEPTION_TYPE ExceptionType, IN EFI_SYSTEM_CONTEXT SystemContext ) { diff --git a/UefiCpuPkg/Library/CpuExceptionHandlerLib/Ia32/ArchInterruptDefs.h b/UefiCpuPkg/Library/CpuExceptionHandlerLib/Ia32/ArchInterruptDefs.h new file mode 100644 index 0000000000..a8d3556a80 --- /dev/null +++ b/UefiCpuPkg/Library/CpuExceptionHandlerLib/Ia32/ArchInterruptDefs.h @@ -0,0 +1,44 @@ +/** @file + Ia32 arch definition for CPU Exception Handler Library. + + Copyright (c) 2013, 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 _ARCH_CPU_INTERRUPT_DEFS_H_ +#define _ARCH_CPU_INTERRUPT_DEFS_H_ + +typedef struct { + EFI_SYSTEM_CONTEXT_IA32 SystemContext; + BOOLEAN ExceptionDataFlag; + UINTN OldIdtHandler; +} EXCEPTION_HANDLER_CONTEXT; + +// +// Register Structure Definitions +// +typedef struct { + EFI_STATUS_CODE_DATA Header; + EFI_SYSTEM_CONTEXT_IA32 SystemContext; +} CPU_STATUS_CODE_TEMPLATE; + +typedef struct { + SPIN_LOCK SpinLock; + UINT32 ApicId; + UINT32 Attribute; + UINTN ExceptonHandler; + UINTN OldFlags; + UINTN OldCs; + UINTN OldIp; + UINTN ExceptionData; + UINT8 HookAfterStubHeaderCode[HOOKAFTER_STUB_SIZE]; +} RESERVED_VECTORS_DATA; + +#endif diff --git a/UefiCpuPkg/Library/CpuExceptionHandlerLib/Ia32/ExceptionHandlerAsm.S b/UefiCpuPkg/Library/CpuExceptionHandlerLib/Ia32/ExceptionHandlerAsm.S index b9e881ac5e..92c8dcafd4 100644 --- a/UefiCpuPkg/Library/CpuExceptionHandlerLib/Ia32/ExceptionHandlerAsm.S +++ b/UefiCpuPkg/Library/CpuExceptionHandlerLib/Ia32/ExceptionHandlerAsm.S @@ -1,6 +1,6 @@ #------------------------------------------------------------------------------ #* -#* Copyright (c) 2012, Intel Corporation. All rights reserved.
+#* Copyright (c) 2012 - 2013, 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 @@ -18,16 +18,15 @@ #------------------------------------------------------------------------------ - - - #.MMX #.XMM ASM_GLOBAL ASM_PFX(CommonExceptionHandler) ASM_GLOBAL ASM_PFX(CommonInterruptEntry) +ASM_GLOBAL ASM_PFX(HookAfterStubEnd) -#EXTRN ASM_PFX(mErrorCodeFlag):DWORD # Error code flags for exceptions +#EXTRN ASM_PFX(mErrorCodeFlag):DWORD # Error code flags for exceptions +#EXTRN ASM_PFX(mDoFarReturnFlag):DWORD # Do far return flag .text @@ -35,101 +34,250 @@ ASM_GLOBAL ASM_PFX(CommonInterruptEntry) # exception handler stub table # Exception0Handle: - pushl $0 - jmp ASM_PFX(CommonInterruptEntry) + .byte 0x6a # push #VectorNum + .byte 0 + pushl %eax + .byte 0xB8 + .long ASM_PFX(CommonInterruptEntry) + jmp *%eax Exception1Handle: - pushl $1 - jmp ASM_PFX(CommonInterruptEntry) + .byte 0x6a # push #VectorNum + .byte 1 + pushl %eax + .byte 0xB8 + .long ASM_PFX(CommonInterruptEntry) + jmp *%eax Exception2Handle: - pushl $2 - jmp ASM_PFX(CommonInterruptEntry) + .byte 0x6a # push #VectorNum + .byte 2 + pushl %eax + .byte 0xB8 + .long ASM_PFX(CommonInterruptEntry) + jmp *%eax Exception3Handle: - pushl $3 - jmp ASM_PFX(CommonInterruptEntry) + .byte 0x6a # push #VectorNum + .byte 3 + pushl %eax + .byte 0xB8 + .long ASM_PFX(CommonInterruptEntry) + jmp *%eax Exception4Handle: - pushl $4 - jmp ASM_PFX(CommonInterruptEntry) + .byte 0x6a # push #VectorNum + .byte 4 + pushl %eax + .byte 0xB8 + .long ASM_PFX(CommonInterruptEntry) + jmp *%eax Exception5Handle: - pushl $5 - jmp ASM_PFX(CommonInterruptEntry) + .byte 0x6a # push #VectorNum + .byte 5 + pushl %eax + .byte 0xB8 + .long ASM_PFX(CommonInterruptEntry) + jmp *%eax Exception6Handle: - pushl $6 - jmp ASM_PFX(CommonInterruptEntry) + .byte 0x6a # push #VectorNum + .byte 6 + pushl %eax + .byte 0xB8 + .long ASM_PFX(CommonInterruptEntry) + jmp *%eax Exception7Handle: - pushl $7 - jmp ASM_PFX(CommonInterruptEntry) + .byte 0x6a # push #VectorNum + .byte 7 + pushl %eax + .byte 0xB8 + .long ASM_PFX(CommonInterruptEntry) + jmp *%eax Exception8Handle: - pushl $8 - jmp ASM_PFX(CommonInterruptEntry) + .byte 0x6a # push #VectorNum + .byte 8 + pushl %eax + .byte 0xB8 + .long ASM_PFX(CommonInterruptEntry) + jmp *%eax Exception9Handle: - pushl $9 - jmp ASM_PFX(CommonInterruptEntry) + .byte 0x6a # push #VectorNum + .byte 9 + pushl %eax + .byte 0xB8 + .long ASM_PFX(CommonInterruptEntry) + jmp *%eax Exception10Handle: - pushl $10 - jmp ASM_PFX(CommonInterruptEntry) + .byte 0x6a # push #VectorNum + .byte 10 + pushl %eax + .byte 0xB8 + .long ASM_PFX(CommonInterruptEntry) + jmp *%eax Exception11Handle: - pushl $11 - jmp ASM_PFX(CommonInterruptEntry) + .byte 0x6a # push #VectorNum + .byte 11 + pushl %eax + .byte 0xB8 + .long ASM_PFX(CommonInterruptEntry) + jmp *%eax Exception12Handle: - pushl $12 - jmp ASM_PFX(CommonInterruptEntry) + .byte 0x6a # push #VectorNum + .byte 12 + pushl %eax + .byte 0xB8 + .long ASM_PFX(CommonInterruptEntry) + jmp *%eax Exception13Handle: - pushl $13 - jmp ASM_PFX(CommonInterruptEntry) + .byte 0x6a # push #VectorNum + .byte 13 + pushl %eax + .byte 0xB8 + .long ASM_PFX(CommonInterruptEntry) + jmp *%eax Exception14Handle: - pushl $14 - jmp ASM_PFX(CommonInterruptEntry) + .byte 0x6a # push #VectorNum + .byte 14 + pushl %eax + .byte 0xB8 + .long ASM_PFX(CommonInterruptEntry) + jmp *%eax Exception15Handle: - pushl $15 - jmp ASM_PFX(CommonInterruptEntry) + .byte 0x6a # push #VectorNum + .byte 15 + pushl %eax + .byte 0xB8 + .long ASM_PFX(CommonInterruptEntry) + jmp *%eax Exception16Handle: - pushl $16 - jmp ASM_PFX(CommonInterruptEntry) + .byte 0x6a # push #VectorNum + .byte 16 + pushl %eax + .byte 0xB8 + .long ASM_PFX(CommonInterruptEntry) + jmp *%eax Exception17Handle: - pushl $17 - jmp ASM_PFX(CommonInterruptEntry) + .byte 0x6a # push #VectorNum + .byte 17 + pushl %eax + .byte 0xB8 + .long ASM_PFX(CommonInterruptEntry) + jmp *%eax Exception18Handle: - pushl $18 - jmp ASM_PFX(CommonInterruptEntry) + .byte 0x6a # push #VectorNum + .byte 18 + pushl %eax + .byte 0xB8 + .long ASM_PFX(CommonInterruptEntry) + jmp *%eax Exception19Handle: - pushl $19 - jmp ASM_PFX(CommonInterruptEntry) + .byte 0x6a # push #VectorNum + .byte 19 + pushl %eax + .byte 0xB8 + .long ASM_PFX(CommonInterruptEntry) + jmp *%eax Exception20Handle: - pushl $20 - jmp ASM_PFX(CommonInterruptEntry) + .byte 0x6a # push #VectorNum + .byte 20 + pushl %eax + .byte 0xB8 + .long ASM_PFX(CommonInterruptEntry) + jmp *%eax Exception21Handle: - pushl $21 - jmp ASM_PFX(CommonInterruptEntry) + .byte 0x6a # push #VectorNum + .byte 21 + pushl %eax + .byte 0xB8 + .long ASM_PFX(CommonInterruptEntry) + jmp *%eax Exception22Handle: - pushl $22 - jmp ASM_PFX(CommonInterruptEntry) + .byte 0x6a # push #VectorNum + .byte 22 + pushl %eax + .byte 0xB8 + .long ASM_PFX(CommonInterruptEntry) + jmp *%eax Exception23Handle: - pushl $23 - jmp ASM_PFX(CommonInterruptEntry) + .byte 0x6a # push #VectorNum + .byte 23 + pushl %eax + .byte 0xB8 + .long ASM_PFX(CommonInterruptEntry) + jmp *%eax Exception24Handle: - pushl $24 - jmp ASM_PFX(CommonInterruptEntry) + .byte 0x6a # push #VectorNum + .byte 24 + pushl %eax + .byte 0xB8 + .long ASM_PFX(CommonInterruptEntry) + jmp *%eax Exception25Handle: - pushl $25 - jmp ASM_PFX(CommonInterruptEntry) + .byte 0x6a # push #VectorNum + .byte 25 + pushl %eax + .byte 0xB8 + .long ASM_PFX(CommonInterruptEntry) + jmp *%eax Exception26Handle: - pushl $26 - jmp ASM_PFX(CommonInterruptEntry) + .byte 0x6a # push #VectorNum + .byte 26 + pushl %eax + .byte 0xB8 + .long ASM_PFX(CommonInterruptEntry) + jmp *%eax Exception27Handle: - pushl $27 - jmp ASM_PFX(CommonInterruptEntry) + .byte 0x6a # push #VectorNum + .byte 27 + pushl %eax + .byte 0xB8 + .long ASM_PFX(CommonInterruptEntry) + jmp *%eax Exception28Handle: - pushl $28 - jmp ASM_PFX(CommonInterruptEntry) + .byte 0x6a # push #VectorNum + .byte 28 + pushl %eax + .byte 0xB8 + .long ASM_PFX(CommonInterruptEntry) + jmp *%eax Exception29Handle: - pushl $29 - jmp ASM_PFX(CommonInterruptEntry) + .byte 0x6a # push #VectorNum + .byte 29 + pushl %eax + .byte 0xB8 + .long ASM_PFX(CommonInterruptEntry) + jmp *%eax Exception30Handle: - pushl $30 - jmp ASM_PFX(CommonInterruptEntry) + .byte 0x6a # push #VectorNum + .byte 30 + pushl %eax + .byte 0xB8 + .long ASM_PFX(CommonInterruptEntry) + jmp *%eax Exception31Handle: - pushl $31 - jmp ASM_PFX(CommonInterruptEntry) + .byte 0x6a # push #VectorNum + .byte 31 + pushl %eax + .byte 0xB8 + .long ASM_PFX(CommonInterruptEntry) + jmp *%eax + +HookAfterStubBegin: + .byte 0x6a # push +VectorNum: + .byte 0 # 0 will be fixed + pushl %eax + .byte 0xB8 # movl ASM_PFX(HookAfterStubHeaderEnd), %eax + .long ASM_PFX(HookAfterStubHeaderEnd) + jmp *%eax +ASM_GLOBAL ASM_PFX(HookAfterStubHeaderEnd) +HookAfterStubHeaderEnd: + popl %eax + subl $8, %esp # reserve room for filling exception data later + pushl 8(%esp) + xchgl (%esp), %ecx # get vector number + bt %ecx, ASM_PFX(mErrorCodeFlag) + jnc NoErrorData + pushl (%esp) # addition push if exception data needed +NoErrorData: + xchg (%esp), %ecx # restore ecx + pushl %eax #---------------------------------------; # CommonInterruptEntry ; @@ -139,19 +287,17 @@ Exception31Handle: ASM_GLOBAL ASM_PFX(CommonInterruptEntry) ASM_PFX(CommonInterruptEntry): cli + popl %eax # # 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. + # Get vector number from top of stack # xchgl (%esp), %ecx - andl $0x0FFFF, %ecx + andl $0x0FF, %ecx # Vector number should be less than 256 cmpl $32, %ecx # Intel reserved vector for exceptions? jae NoErrorCode bt %ecx, ASM_PFX(mErrorCodeFlag) @@ -241,6 +387,10 @@ ErrorCodeAndVectorOnStack: andl $0x0fffffff0, %esp subl $12, %esp + subl $8, %esp + pushl $0 # check EXCEPTION_HANDLER_CONTEXT.OldIdtHandler + pushl $0 # check EXCEPTION_HANDLER_CONTEXT.ExceptionDataFlag + #; UINT32 Edi, Esi, Ebp, Esp, Ebx, Edx, Ecx, Eax; pushl %eax pushl %ecx @@ -405,18 +555,41 @@ ErrorCodeAndVectorOnStack: popl %ecx popl %eax + popl -8(%ebp) + popl -4(%ebp) movl %ebp, %esp popl %ebp addl $8, %esp + cmpl $0, -16(%esp) # check EXCEPTION_HANDLER_CONTEXT.OldIdtHandler + jz DoReturn + cmpl $1, -20(%esp) # check EXCEPTION_HANDLER_CONTEXT.ExceptionDataFlag + jz ErrorCode + jmp *-16(%esp) +ErrorCode: + subl $4, %esp + jmp *-12(%esp) + +DoReturn: + cmpl $0, ASM_PFX(mDoFarReturnFlag) + jz DoIret + pushl 8(%esp) # save EFLAGS + addl $16, %esp + pushl -8(%esp) # save CS in new location + pushl -8(%esp) # save EIP in new location + pushl -8(%esp) # save EFLAGS in new location + popfl # restore EFLAGS + retf # far return + +DoIret: iretl #---------------------------------------; -# _GetTemplateAddressMap ; -#----------------------------------------------------------------------------; +# _AsmGetTemplateAddressMap ; +#---------------------------------------; # # Protocol prototype -# GetTemplateAddressMap ( +# AsmGetTemplateAddressMap ( # EXCEPTION_HANDLER_TEMPLATE_MAP *AddressMap # ); # @@ -443,8 +616,8 @@ ErrorCodeAndVectorOnStack: #------------------------------------------------------------------------------------- # AsmGetAddressMap (&AddressMap); #------------------------------------------------------------------------------------- -ASM_GLOBAL ASM_PFX(GetTemplateAddressMap) -ASM_PFX(GetTemplateAddressMap): +ASM_GLOBAL ASM_PFX(AsmGetTemplateAddressMap) +ASM_PFX(AsmGetTemplateAddressMap): pushl %ebp movl %esp,%ebp @@ -453,8 +626,17 @@ ASM_PFX(GetTemplateAddressMap): movl 0x8(%ebp), %ebx movl $Exception0Handle, (%ebx) movl $(Exception1Handle - Exception0Handle), 0x4(%ebx) + movl $(HookAfterStubBegin), 0x8(%ebx) popal popl %ebp ret - +#------------------------------------------------------------------------------------- +# AsmVectorNumFixup (*VectorBase, VectorNum); +#------------------------------------------------------------------------------------- +ASM_GLOBAL ASM_PFX(AsmVectorNumFixup) +ASM_PFX(AsmVectorNumFixup): + movl 8(%esp), %eax + movl 4(%esp), %ecx + movb %al, (VectorNum - HookAfterStubBegin)(%ecx) + ret diff --git a/UefiCpuPkg/Library/CpuExceptionHandlerLib/Ia32/ExceptionHandlerAsm.asm b/UefiCpuPkg/Library/CpuExceptionHandlerLib/Ia32/ExceptionHandlerAsm.asm index 869f18dfde..74d4e89047 100644 --- a/UefiCpuPkg/Library/CpuExceptionHandlerLib/Ia32/ExceptionHandlerAsm.asm +++ b/UefiCpuPkg/Library/CpuExceptionHandlerLib/Ia32/ExceptionHandlerAsm.asm @@ -1,5 +1,5 @@ ;------------------------------------------------------------------------------ ; -; Copyright (c) 2012, Intel Corporation. All rights reserved.
+; Copyright (c) 2012 - 2013, 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 @@ -30,133 +30,77 @@ CommonExceptionHandler PROTO C .data -CommonEntryAddr DD CommonInterruptEntry - -EXTRN mErrorCodeFlag:DWORD ; Error code flags for exceptions +EXTRN mErrorCodeFlag:DWORD ; Error code flags for exceptions +EXTRN mDoFarReturnFlag:DWORD ; Do far return flag .code +ALIGN 8 + ; ; exception handler stub table ; -Exception0Handle: - push 0 - jmp dword ptr [CommonEntryAddr] -Exception1Handle: - push 1 - jmp dword ptr [CommonEntryAddr] -Exception2Handle: - push 2 - jmp dword ptr [CommonEntryAddr] -Exception3Handle: - push 3 - jmp dword ptr [CommonEntryAddr] -Exception4Handle: - push 4 - jmp dword ptr [CommonEntryAddr] -Exception5Handle: - push 5 - jmp dword ptr [CommonEntryAddr] -Exception6Handle: - push 6 - jmp dword ptr [CommonEntryAddr] -Exception7Handle: - push 7 - jmp dword ptr [CommonEntryAddr] -Exception8Handle: - push 8 - jmp dword ptr [CommonEntryAddr] -Exception9Handle: - push 9 - jmp dword ptr [CommonEntryAddr] -Exception10Handle: - push 10 - jmp dword ptr [CommonEntryAddr] -Exception11Handle: - push 11 - jmp dword ptr [CommonEntryAddr] -Exception12Handle: - push 12 - jmp dword ptr [CommonEntryAddr] -Exception13Handle: - push 13 - jmp dword ptr [CommonEntryAddr] -Exception14Handle: - push 14 - jmp dword ptr [CommonEntryAddr] -Exception15Handle: - push 15 - jmp dword ptr [CommonEntryAddr] -Exception16Handle: - push 16 - jmp dword ptr [CommonEntryAddr] -Exception17Handle: - push 17 - jmp dword ptr [CommonEntryAddr] -Exception18Handle: - push 18 - jmp dword ptr [CommonEntryAddr] -Exception19Handle: - push 19 - jmp dword ptr [CommonEntryAddr] -Exception20Handle: - push 20 - jmp dword ptr [CommonEntryAddr] -Exception21Handle: - push 21 - jmp dword ptr [CommonEntryAddr] -Exception22Handle: - push 22 - jmp dword ptr [CommonEntryAddr] -Exception23Handle: - push 23 - jmp dword ptr [CommonEntryAddr] -Exception24Handle: - push 24 - jmp dword ptr [CommonEntryAddr] -Exception25Handle: - push 25 - jmp dword ptr [CommonEntryAddr] -Exception26Handle: - push 26 - jmp dword ptr [CommonEntryAddr] -Exception27Handle: - push 27 - jmp dword ptr [CommonEntryAddr] -Exception28Handle: - push 28 - jmp dword ptr [CommonEntryAddr] -Exception29Handle: - push 29 - jmp dword ptr [CommonEntryAddr] -Exception30Handle: - push 30 - jmp dword ptr [CommonEntryAddr] -Exception31Handle: - push 31 - jmp dword ptr [CommonEntryAddr] +AsmIdtVectorBegin: +REPEAT 32 + db 6ah ; push #VectorNum + db ($ - AsmIdtVectorBegin) / ((AsmIdtVectorEnd - AsmIdtVectorBegin) / 32) ; VectorNum + push eax + mov eax, CommonInterruptEntry + jmp eax +ENDM +AsmIdtVectorEnd: + +HookAfterStubBegin: + db 6ah ; push +VectorNum: + db 0 ; 0 will be fixed + push eax + mov eax, HookAfterStubHeaderEnd + jmp eax +HookAfterStubHeaderEnd: + pop eax + sub esp, 8 ; reserve room for filling exception data later + push [esp + 8] + xchg ecx, [esp] ; get vector number + bt mErrorCodeFlag, ecx + jnc @F + push [esp] ; addition push if exception data needed +@@: + xchg ecx, [esp] ; restore ecx + push eax ;----------------------------------------------------------------------------; ; CommonInterruptEntry ; ;----------------------------------------------------------------------------; ; The follow algorithm is used for the common interrupt routine. ; Entry from each interrupt with a push eax and eax=interrupt number - +; Stack: +; +---------------------+ +; + EFlags + +; +---------------------+ +; + CS + +; +---------------------+ +; + EIP + +; +---------------------+ +; + Error Code + +; +---------------------+ +; + Vector Number + +; +---------------------+ +; + EBP + +; +---------------------+ <-- EBP CommonInterruptEntry PROC PUBLIC cli + pop eax ; ; 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. + ; Get vector number from top of stack ; xchg ecx, [esp] - and ecx, 0FFFFh + and ecx, 0FFh ; Vector number should be less than 256 cmp ecx, 32 ; Intel reserved vector for exceptions? jae NoErrorCode bt mErrorCodeFlag, ecx @@ -246,6 +190,10 @@ ErrorCodeAndVectorOnStack: and esp, 0fffffff0h sub esp, 12 + sub esp, 8 + push 0 ; clear EXCEPTION_HANDLER_CONTEXT.OldIdtHandler + push 0 ; clear EXCEPTION_HANDLER_CONTEXT.ExceptionDataFlag + ;; UINT32 Edi, Esi, Ebp, Esp, Ebx, Edx, Ecx, Eax; push eax push ecx @@ -411,19 +359,42 @@ ErrorCodeAndVectorOnStack: pop ecx pop eax + pop dword ptr [ebp - 8] + pop dword ptr [ebp - 4] mov esp, ebp pop ebp add esp, 8 + cmp dword ptr [esp - 16], 0 ; check EXCEPTION_HANDLER_CONTEXT.OldIdtHandler + jz DoReturn + cmp dword ptr [esp - 20], 1 ; check EXCEPTION_HANDLER_CONTEXT.ExceptionDataFlag + jz ErrorCode + jmp dword ptr [esp - 16] +ErrorCode: + sub esp, 4 + jmp dword ptr [esp - 12] + +DoReturn: + cmp mDoFarReturnFlag, 0 ; Check if need to do far return instead of IRET + jz DoIret + push [esp + 8] ; save EFLAGS + add esp, 16 + push [esp - 8] ; save CS in new location + push [esp - 8] ; save EIP in new location + push [esp - 8] ; save EFLAGS in new location + popfd ; restore EFLAGS + retf ; far return + +DoIret: iretd CommonInterruptEntry ENDP ;---------------------------------------; -; _GetTemplateAddressMap ; +; _AsmGetTemplateAddressMap ; ;----------------------------------------------------------------------------; ; ; Protocol prototype -; GetTemplateAddressMap ( +; AsmGetTemplateAddressMap ( ; EXCEPTION_HANDLER_TEMPLATE_MAP *AddressMap ; ); ; @@ -447,18 +418,28 @@ CommonInterruptEntry ENDP ; ; Destroys: Nothing ;-----------------------------------------------------------------------------; -GetTemplateAddressMap proc near public +AsmGetTemplateAddressMap proc near public push ebp ; C prolog mov ebp, esp pushad - mov ebx, dword ptr [ebp+08h] - mov dword ptr [ebx], Exception0Handle - mov dword ptr [ebx+4h], Exception1Handle - Exception0Handle + mov ebx, dword ptr [ebp + 08h] + mov dword ptr [ebx], AsmIdtVectorBegin + mov dword ptr [ebx + 4h], (AsmIdtVectorEnd - AsmIdtVectorBegin) / 32 + mov dword ptr [ebx + 8h], HookAfterStubBegin popad pop ebp ret -GetTemplateAddressMap ENDP - +AsmGetTemplateAddressMap ENDP + +;------------------------------------------------------------------------------------- +; AsmVectorNumFixup (*VectorBase, VectorNum); +;------------------------------------------------------------------------------------- +AsmVectorNumFixup proc near public + mov eax, dword ptr [esp + 8] + mov ecx, [esp + 4] + mov [ecx + (VectorNum - HookAfterStubBegin)], al + ret +AsmVectorNumFixup ENDP END diff --git a/UefiCpuPkg/Library/CpuExceptionHandlerLib/SecPeiCpuException.c b/UefiCpuPkg/Library/CpuExceptionHandlerLib/SecPeiCpuException.c index ebd9fe32b7..f2e7c81257 100644 --- a/UefiCpuPkg/Library/CpuExceptionHandlerLib/SecPeiCpuException.c +++ b/UefiCpuPkg/Library/CpuExceptionHandlerLib/SecPeiCpuException.c @@ -1,7 +1,7 @@ /** @file - CPU Exception Library provides SEC/PEIM CPU exception handler. + CPU exception handler library implemenation for SEC/PEIM modules. -Copyright (c) 2012, Intel Corporation. All rights reserved.
+Copyright (c) 2012 - 2013, 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 that accompanies this distribution. The full text of the license may be found at @@ -18,7 +18,8 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. // // Image Aglinment size for SEC/PEI phase // -CONST UINTN mImageAlignSize = 4; +CONST UINTN mImageAlignSize = 4; +CONST UINTN mDoFarReturnFlag = 0; /** Common exception handler. @@ -45,19 +46,138 @@ CommonExceptionHandler ( } /** - Setup CPU exception handlers. - - This API will setups the CPU exception handler to display CPU contents and run into - CpuDeadLoop(). + Initializes all CPU exceptions entries and provides the default exception handlers. + + Caller should try to get an array of interrupt and/or exception vectors that are in use and need to + persist by EFI_VECTOR_HANDOFF_INFO defined in PI 1.3 specification. + If caller cannot get reserved vector list or it does not exists, set VectorInfo to NULL. + If VectorInfo is not NULL, the exception vectors will be initialized per vector attribute accordingly. Note: Before invoking this API, caller must allocate memory for IDT table and load IDTR by AsmWriteIdtr(). + + @param[in] VectorInfo Pointer to reserved vector list. + @retval EFI_SUCCESS CPU Exception Entries have been successfully initialized + with default exception handlers. + @retval EFI_INVALID_PARAMETER VectorInfo includes the invalid content if VectorInfo is not NULL. + @retval EFI_UNSUPPORTED This function is not supported. + **/ -VOID +EFI_STATUS +EFIAPI +InitializeCpuExceptionHandlers ( + IN EFI_VECTOR_HANDOFF_INFO *VectorInfo OPTIONAL + ) +{ + EFI_STATUS Status; + RESERVED_VECTORS_DATA ReservedVectorData[CPU_EXCEPTION_NUM]; + IA32_DESCRIPTOR IdtDescriptor; + UINTN IdtEntryCount; + UINT16 CodeSegment; + EXCEPTION_HANDLER_TEMPLATE_MAP TemplateMap; + IA32_IDT_GATE_DESCRIPTOR *IdtTable; + UINTN Index; + UINTN InterruptHandler; + + if (VectorInfo != NULL) { + SetMem ((VOID *) ReservedVectorData, sizeof (RESERVED_VECTORS_DATA) * CPU_EXCEPTION_NUM, 0xff); + Status = ReadAndVerifyVectorInfo (VectorInfo, ReservedVectorData, CPU_EXCEPTION_NUM); + if (EFI_ERROR (Status)) { + return EFI_INVALID_PARAMETER; + } + } + // + // Read IDT descriptor and calculate IDT size + // + AsmReadIdtr (&IdtDescriptor); + IdtEntryCount = (IdtDescriptor.Limit + 1) / sizeof (IA32_IDT_GATE_DESCRIPTOR); + if (IdtEntryCount > CPU_EXCEPTION_NUM) { + // + // CPU exeption library only setup CPU_EXCEPTION_NUM exception handler at most + // + IdtEntryCount = CPU_EXCEPTION_NUM; + } + // + // Use current CS as the segment selector of interrupt gate in IDT + // + CodeSegment = AsmReadCs (); + + AsmGetTemplateAddressMap (&TemplateMap); + IdtTable = (IA32_IDT_GATE_DESCRIPTOR *)IdtDescriptor.Base; + for (Index = 0; Index < IdtEntryCount; Index ++) { + IdtTable[Index].Bits.Selector = CodeSegment; + // + // Check reserved vectors attributes if has, only EFI_VECTOR_HANDOFF_DO_NOT_HOOK + // supported in this instance + // + if (VectorInfo != NULL) { + if (ReservedVectorData[Index].Attribute == EFI_VECTOR_HANDOFF_DO_NOT_HOOK) { + continue; + } + } + // + // Update IDT entry + // + InterruptHandler = TemplateMap.ExceptionStart + Index * TemplateMap.ExceptionStubHeaderSize; + ArchUpdateIdtEntry (&IdtTable[Index], InterruptHandler); + } + return EFI_SUCCESS; +} + +/** + Initializes all CPU interrupt/exceptions entries and provides the default interrupt/exception handlers. + + Caller should try to get an array of interrupt and/or exception vectors that are in use and need to + persist by EFI_VECTOR_HANDOFF_INFO defined in PI 1.3 specification. + If caller cannot get reserved vector list or it does not exists, set VectorInfo to NULL. + If VectorInfo is not NULL, the exception vectors will be initialized per vector attribute accordingly. + + @param[in] VectorInfo Pointer to reserved vector list. + + @retval EFI_SUCCESS All CPU interrupt/exception entries have been successfully initialized + with default interrupt/exception handlers. + @retval EFI_INVALID_PARAMETER VectorInfo includes the invalid content if VectorInfo is not NULL. + @retval EFI_UNSUPPORTED This function is not supported. + +**/ +EFI_STATUS EFIAPI -SetupCpuExceptionHandlers ( - IN VOID +InitializeCpuInterruptHandlers ( + IN EFI_VECTOR_HANDOFF_INFO *VectorInfo OPTIONAL ) { - InternalSetupCpuExceptionHandlers (); + return EFI_UNSUPPORTED; } + +/** + Registers a function to be called from the processor interrupt handler. + + This function registers and enables the handler specified by InterruptHandler for a processor + interrupt or exception type specified by InterruptType. If InterruptHandler is NULL, then the + handler for the processor interrupt or exception type specified by InterruptType is uninstalled. + The installed handler is called once for each processor interrupt or exception. + NOTE: This function should be invoked after InitializeCpuExceptionHandlers() or + InitializeCpuInterruptHandlers() invoked, otherwise EFI_UNSUPPORTED returned. + + @param[in] InterruptType Defines which interrupt or exception to hook. + @param[in] InterruptHandler A pointer to a function of type EFI_CPU_INTERRUPT_HANDLER that is called + when a processor interrupt occurs. If this parameter is NULL, then the handler + will be uninstalled. + + @retval EFI_SUCCESS The handler for the processor interrupt was successfully 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, + or this function is not supported. +*/ +EFI_STATUS +EFIAPI +RegisterCpuInterruptHandler ( + IN EFI_EXCEPTION_TYPE InterruptType, + IN EFI_CPU_INTERRUPT_HANDLER InterruptHandler + ) +{ + return EFI_UNSUPPORTED; +} \ No newline at end of file diff --git a/UefiCpuPkg/Library/CpuExceptionHandlerLib/SecPeiCpuExceptionHandlerLib.inf b/UefiCpuPkg/Library/CpuExceptionHandlerLib/SecPeiCpuExceptionHandlerLib.inf index 96ddaafd43..c8553623d2 100644 --- a/UefiCpuPkg/Library/CpuExceptionHandlerLib/SecPeiCpuExceptionHandlerLib.inf +++ b/UefiCpuPkg/Library/CpuExceptionHandlerLib/SecPeiCpuExceptionHandlerLib.inf @@ -3,7 +3,7 @@ # # This library instance supports SEC/PEI module only. # -# Copyright (c) 2012, Intel Corporation. All rights reserved.
+# Copyright (c) 2012 - 2013, 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 @@ -32,11 +32,13 @@ Ia32/ExceptionHandlerAsm.asm |MSFT Ia32/ExceptionHandlerAsm.S |GCC Ia32/ArchExceptionHandler.c + Ia32/ArchInterruptDefs.h [Sources.X64] X64/ExceptionHandlerAsm.asm |MSFT X64/ExceptionHandlerAsm.S |GCC X64/ArchExceptionHandler.c + X64/ArchInterruptDefs.h [Sources.common] CpuExceptionCommon.h @@ -54,3 +56,7 @@ PrintLib LocalApicLib PeCoffGetEntryPointLib + ReportStatusCodeLib + +[Ppis] + gEfiVectorHandoffInfoPpiGuid diff --git a/UefiCpuPkg/Library/CpuExceptionHandlerLib/SmmCpuExceptionHandlerLib.inf b/UefiCpuPkg/Library/CpuExceptionHandlerLib/SmmCpuExceptionHandlerLib.inf new file mode 100644 index 0000000000..bee0c46e2c --- /dev/null +++ b/UefiCpuPkg/Library/CpuExceptionHandlerLib/SmmCpuExceptionHandlerLib.inf @@ -0,0 +1,65 @@ +## @file +# Component description file for SMM CPU Exception Handler Library instance. +# +# This library instance supports SMM module only. +# +# Copyright (c) 2013, 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. +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = SmmCpuExceptionHandlerLib + FILE_GUID = 8D2C439B-3981-42ff-9CE5-1B50ECA502D6 + MODULE_TYPE = DXE_SMM_DRIVER + VERSION_STRING = 1.0 + LIBRARY_CLASS = CpuExceptionHandlerLib|DXE_SMM_DRIVER + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 +# + +[Sources.Ia32] + Ia32/ExceptionHandlerAsm.asm |MSFT + Ia32/ExceptionHandlerAsm.S |GCC + Ia32/ArchExceptionHandler.c + Ia32/ArchInterruptDefs.h + +[Sources.X64] + X64/ExceptionHandlerAsm.asm |MSFT + X64/ExceptionHandlerAsm.S |GCC + X64/ArchExceptionHandler.c + X64/ArchInterruptDefs.h + +[Sources.common] + CpuExceptionCommon.h + CpuExceptionCommon.c + DxeSmmCpuException.c + SmmException.c + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + UefiCpuPkg/UefiCpuPkg.dec + +[LibraryClasses] + BaseLib + SerialPortLib + PrintLib + SynchronizationLib + LocalApicLib + PeCoffGetEntryPointLib + ReportStatusCodeLib + DebugLib + +[Ppis] + gEfiVectorHandoffInfoPpiGuid diff --git a/UefiCpuPkg/Library/CpuExceptionHandlerLib/SmmException.c b/UefiCpuPkg/Library/CpuExceptionHandlerLib/SmmException.c new file mode 100644 index 0000000000..c3f4425e09 --- /dev/null +++ b/UefiCpuPkg/Library/CpuExceptionHandlerLib/SmmException.c @@ -0,0 +1,101 @@ +/** @file + CPU exception handler library implemenation for SMM modules. + + Copyright (c) 2013, 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 +#include "CpuExceptionCommon.h" + +CONST UINTN mDoFarReturnFlag = 1; + +/** + Initializes all CPU exceptions entries and provides the default exception handlers. + + Caller should try to get an array of interrupt and/or exception vectors that are in use and need to + persist by EFI_VECTOR_HANDOFF_INFO defined in PI 1.3 specification. + If caller cannot get reserved vector list or it does not exists, set VectorInfo to NULL. + If VectorInfo is not NULL, the exception vectors will be initialized per vector attribute accordingly. + + @param[in] VectorInfo Pointer to reserved vector list. + + @retval EFI_SUCCESS CPU Exception Entries have been successfully initialized + with default exception handlers. + @retval EFI_INVALID_PARAMETER VectorInfo includes the invalid content if VectorInfo is not NULL. + @retval EFI_UNSUPPORTED This function is not supported. + +**/ +EFI_STATUS +EFIAPI +InitializeCpuExceptionHandlers ( + IN EFI_VECTOR_HANDOFF_INFO *VectorInfo OPTIONAL + ) +{ + return InitializeCpuExceptionHandlersWorker (VectorInfo); +} + +/** + Initializes all CPU interrupt/exceptions entries and provides the default interrupt/exception handlers. + + Caller should try to get an array of interrupt and/or exception vectors that are in use and need to + persist by EFI_VECTOR_HANDOFF_INFO defined in PI 1.3 specification. + If caller cannot get reserved vector list or it does not exists, set VectorInfo to NULL. + If VectorInfo is not NULL, the exception vectors will be initialized per vector attribute accordingly. + + @param[in] VectorInfo Pointer to reserved vector list. + + @retval EFI_SUCCESS All CPU interrupt/exception entries have been successfully initialized + with default interrupt/exception handlers. + @retval EFI_INVALID_PARAMETER VectorInfo includes the invalid content if VectorInfo is not NULL. + @retval EFI_UNSUPPORTED This function is not supported. + +**/ +EFI_STATUS +EFIAPI +InitializeCpuInterruptHandlers ( + IN EFI_VECTOR_HANDOFF_INFO *VectorInfo OPTIONAL + ) +{ + return EFI_UNSUPPORTED; +} + +/** + Registers a function to be called from the processor interrupt handler. + + This function registers and enables the handler specified by InterruptHandler for a processor + interrupt or exception type specified by InterruptType. If InterruptHandler is NULL, then the + handler for the processor interrupt or exception type specified by InterruptType is uninstalled. + The installed handler is called once for each processor interrupt or exception. + NOTE: This function should be invoked after InitializeCpuExceptionHandlers() or + InitializeCpuInterruptHandlers() invoked, otherwise EFI_UNSUPPORTED returned. + + @param[in] InterruptType Defines which interrupt or exception to hook. + @param[in] InterruptHandler A pointer to a function of type EFI_CPU_INTERRUPT_HANDLER that is called + when a processor interrupt occurs. If this parameter is NULL, then the handler + will be uninstalled. + + @retval EFI_SUCCESS The handler for the processor interrupt was successfully 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, + or this function is not supported. +*/ +EFI_STATUS +EFIAPI +RegisterCpuInterruptHandler ( + IN EFI_EXCEPTION_TYPE InterruptType, + IN EFI_CPU_INTERRUPT_HANDLER InterruptHandler + ) +{ + return RegisterCpuInterruptHandlerWorker (InterruptType, InterruptHandler); +} \ No newline at end of file diff --git a/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ArchExceptionHandler.c b/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ArchExceptionHandler.c index 664472a667..1af2999ac0 100644 --- a/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ArchExceptionHandler.c +++ b/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ArchExceptionHandler.c @@ -1,7 +1,7 @@ /** @file x64 CPU Exception Hanlder. - Copyright (c) 2012, Intel Corporation. All rights reserved.
+ Copyright (c) 2012 - 2013, 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 @@ -15,61 +15,102 @@ #include "CpuExceptionCommon.h" /** - Internal function to setup CPU exception handlers. + Return address map of exception handler template so that C code can generate + exception tables. + @param IdtEntry Pointer to IDT entry to be updated. + @param InterruptHandler IDT handler value. **/ VOID -InternalSetupCpuExceptionHandlers ( - VOID +ArchUpdateIdtEntry ( + IN IA32_IDT_GATE_DESCRIPTOR *IdtEntry, + IN UINTN InterruptHandler ) { - IA32_DESCRIPTOR IdtDescriptor; - UINTN IdtSize; - EXCEPTION_HANDLER_TEMPLATE_MAP TemplateMap; - UINT16 CodeSegment; - IA32_IDT_GATE_DESCRIPTOR *IdtEntry; - UINTN Index; - UINTN InterruptHandler; + IdtEntry->Bits.OffsetLow = (UINT16)(UINTN)InterruptHandler; + IdtEntry->Bits.OffsetHigh = (UINT16)((UINTN)InterruptHandler >> 16); + IdtEntry->Bits.OffsetUpper = (UINT32)((UINTN)InterruptHandler >> 32); + IdtEntry->Bits.GateType = IA32_IDT_GATE_TYPE_INTERRUPT_32; +} + +/** + Read IDT handler value from IDT entry. + + @param IdtEntry Pointer to IDT entry to be read. + +**/ +UINTN +ArchGetIdtHandler ( + IN IA32_IDT_GATE_DESCRIPTOR *IdtEntry + ) +{ + return IdtEntry->Bits.OffsetLow + (((UINTN) IdtEntry->Bits.OffsetHigh) << 16) + + (((UINTN) IdtEntry->Bits.OffsetUpper) << 32); +} +/** + Save CPU exception context when handling EFI_VECTOR_HANDOFF_HOOK_AFTER case. + + @param ExceptionType Exception type. + @param SystemContext Pointer to EFI_SYSTEM_CONTEXT. +**/ +VOID +ArchSaveExceptionContext ( + IN UINTN ExceptionType, + IN EFI_SYSTEM_CONTEXT SystemContext + ) +{ + IA32_EFLAGS32 Eflags; // - // Read IDT descriptor and calculate IDT size + // Save Exception context in global variable // - AsmReadIdtr (&IdtDescriptor); - IdtSize = (IdtDescriptor.Limit + 1) / sizeof (IA32_IDT_GATE_DESCRIPTOR); - if (IdtSize > CPU_EXCEPTION_NUM) { - // - // CPU exeption library only setup CPU_EXCEPTION_NUM exception handler at most - // - IdtSize = CPU_EXCEPTION_NUM; - } - + mReservedVectors[ExceptionType].OldSs = SystemContext.SystemContextX64->Ss; + mReservedVectors[ExceptionType].OldSp = SystemContext.SystemContextX64->Rsp; + mReservedVectors[ExceptionType].OldFlags = SystemContext.SystemContextX64->Rflags; + mReservedVectors[ExceptionType].OldCs = SystemContext.SystemContextX64->Cs; + mReservedVectors[ExceptionType].OldIp = SystemContext.SystemContextX64->Rip; + mReservedVectors[ExceptionType].ExceptionData = SystemContext.SystemContextX64->ExceptionData; // - // Use current CS as the segment selector of interrupt gate in IDT + // Clear IF flag to avoid old IDT handler enable interrupt by IRET // - CodeSegment = AsmReadCs (); - IdtEntry = (IA32_IDT_GATE_DESCRIPTOR *) IdtDescriptor.Base; - - GetTemplateAddressMap (&TemplateMap); - - for (Index = 0; Index < IdtSize; Index ++) { - InterruptHandler = TemplateMap.ExceptionStart + Index * TemplateMap.ExceptionStubHeaderSize; - IdtEntry[Index].Bits.OffsetLow = (UINT16)(UINTN)InterruptHandler; - IdtEntry[Index].Bits.OffsetHigh = (UINT16)((UINTN)InterruptHandler >> 16); - IdtEntry[Index].Bits.OffsetUpper = (UINT32)((UINTN)InterruptHandler >> 32); - IdtEntry[Index].Bits.Selector = CodeSegment; - IdtEntry[Index].Bits.GateType = IA32_IDT_GATE_TYPE_INTERRUPT_32; - } + Eflags.UintN = SystemContext.SystemContextX64->Rflags; + Eflags.Bits.IF = 0; + SystemContext.SystemContextX64->Rflags = Eflags.UintN; + // + // Modify the EIP in stack, then old IDT handler will return to the stub code + // + SystemContext.SystemContextX64->Rip = (UINTN) mReservedVectors[ExceptionType].HookAfterStubHeaderCode; } /** - Common exception handler. + Restore CPU exception context when handling EFI_VECTOR_HANDOFF_HOOK_AFTER case. @param ExceptionType Exception type. @param SystemContext Pointer to EFI_SYSTEM_CONTEXT. **/ VOID -DumpCpuContent ( +ArchRestoreExceptionContext ( IN UINTN ExceptionType, + IN EFI_SYSTEM_CONTEXT SystemContext + ) +{ + SystemContext.SystemContextX64->Ss = mReservedVectors[ExceptionType].OldSs; + SystemContext.SystemContextX64->Rsp = mReservedVectors[ExceptionType].OldSp; + SystemContext.SystemContextX64->Rflags = mReservedVectors[ExceptionType].OldFlags; + SystemContext.SystemContextX64->Cs = mReservedVectors[ExceptionType].OldCs; + SystemContext.SystemContextX64->Rip = mReservedVectors[ExceptionType].OldIp; + SystemContext.SystemContextX64->ExceptionData = mReservedVectors[ExceptionType].ExceptionData; +} + +/** + Dump CPU content information. + + @param ExceptionType Exception type. + @param SystemContext Pointer to EFI_SYSTEM_CONTEXT. +**/ +VOID +DumpCpuContent ( + IN EFI_EXCEPTION_TYPE ExceptionType, IN EFI_SYSTEM_CONTEXT SystemContext ) { diff --git a/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ArchInterruptDefs.h b/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ArchInterruptDefs.h new file mode 100644 index 0000000000..906480134a --- /dev/null +++ b/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ArchInterruptDefs.h @@ -0,0 +1,46 @@ +/** @file + X64 arch definition for CPU Exception Handler Library. + + Copyright (c) 2013, 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 _ARCH_CPU_INTERRUPT_DEFS_H_ +#define _ARCH_CPU_INTERRUPT_DEFS_H_ + +typedef struct { + EFI_SYSTEM_CONTEXT_X64 SystemContext; + BOOLEAN ExceptionDataFlag; + UINTN OldIdtHandler; +} EXCEPTION_HANDLER_CONTEXT; + +// +// Register Structure Definitions +// +typedef struct { + EFI_STATUS_CODE_DATA Header; + EFI_SYSTEM_CONTEXT_X64 SystemContext; +} CPU_STATUS_CODE_TEMPLATE; + +typedef struct { + SPIN_LOCK SpinLock; + UINT32 ApicId; + UINT32 Attribute; + UINTN ExceptonHandler; + UINTN OldSs; + UINTN OldSp; + UINTN OldFlags; + UINTN OldCs; + UINTN OldIp; + UINTN ExceptionData; + UINT8 HookAfterStubHeaderCode[HOOKAFTER_STUB_SIZE]; +} RESERVED_VECTORS_DATA; + +#endif diff --git a/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ExceptionHandlerAsm.S b/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ExceptionHandlerAsm.S index cd101475a7..7d5672f892 100644 --- a/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ExceptionHandlerAsm.S +++ b/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ExceptionHandlerAsm.S @@ -1,5 +1,5 @@ #------------------------------------------------------------------------------ ; -# Copyright (c) 2012, Intel Corporation. All rights reserved.
+# Copyright (c) 2012 - 2013, 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 @@ -21,114 +21,264 @@ #------------------------------------------------------------------------------ -#EXTRN ASM_PFX(mErrorCodeFlag):DWORD # Error code flags for exceptions ASM_GLOBAL ASM_PFX(CommonExceptionHandler) ASM_GLOBAL ASM_PFX(CommonInterruptEntry) +ASM_GLOBAL ASM_PFX(HookAfterStubHeaderEnd) - +#EXTRN ASM_PFX(mErrorCodeFlag):DWORD # Error code flags for exceptions +#EXTRN ASM_PFX(mDoFarReturnFlag):QWORD # Do far return flag .text # -# point to the external interrupt vector table +# exception handler stub table # Exception0Handle: - pushq $0 - jmp ASM_PFX(CommonInterruptEntry) + .byte 0x6a # push #VectorNum + .byte 0 + pushq %rax + .byte 0x48, 0xB8 + .quad ASM_PFX(CommonInterruptEntry) + jmp *%rax Exception1Handle: - pushq $1 - jmp ASM_PFX(CommonInterruptEntry) + .byte 0x6a # push #VectorNum + .byte 1 + pushq %rax + .byte 0x48, 0xB8 + .quad ASM_PFX(CommonInterruptEntry) + jmp *%rax Exception2Handle: - pushq $2 - jmp ASM_PFX(CommonInterruptEntry) + .byte 0x6a # push #VectorNum + .byte 2 + pushq %rax + .byte 0x48, 0xB8 + .quad ASM_PFX(CommonInterruptEntry) + jmp *%rax Exception3Handle: - pushq $3 - jmp ASM_PFX(CommonInterruptEntry) + .byte 0x6a # push #VectorNum + .byte 3 + pushq %rax + .byte 0x48, 0xB8 + .quad ASM_PFX(CommonInterruptEntry) + jmp *%rax Exception4Handle: - pushq $4 - jmp ASM_PFX(CommonInterruptEntry) + .byte 0x6a # push #VectorNum + .byte 4 + pushq %rax + .byte 0x48, 0xB8 + .quad ASM_PFX(CommonInterruptEntry) + jmp *%rax Exception5Handle: - pushq $5 - jmp ASM_PFX(CommonInterruptEntry) + .byte 0x6a # push #VectorNum + .byte 5 + pushq %rax + .byte 0x48, 0xB8 + .quad ASM_PFX(CommonInterruptEntry) + jmp *%rax Exception6Handle: - pushq $6 - jmp ASM_PFX(CommonInterruptEntry) + .byte 0x6a # push #VectorNum + .byte 6 + pushq %rax + .byte 0x48, 0xB8 + .quad ASM_PFX(CommonInterruptEntry) + jmp *%rax Exception7Handle: - pushq $7 - jmp ASM_PFX(CommonInterruptEntry) + .byte 0x6a # push #VectorNum + .byte 7 + pushq %rax + .byte 0x48, 0xB8 + .quad ASM_PFX(CommonInterruptEntry) + jmp *%rax Exception8Handle: - pushq $8 - jmp ASM_PFX(CommonInterruptEntry) + .byte 0x6a # push #VectorNum + .byte 8 + pushq %rax + .byte 0x48, 0xB8 + .quad ASM_PFX(CommonInterruptEntry) + jmp *%rax Exception9Handle: - pushq $9 - jmp ASM_PFX(CommonInterruptEntry) + .byte 0x6a # push #VectorNum + .byte 9 + pushq %rax + .byte 0x48, 0xB8 + .quad ASM_PFX(CommonInterruptEntry) + jmp *%rax Exception10Handle: - pushq $10 - jmp ASM_PFX(CommonInterruptEntry) + .byte 0x6a # push #VectorNum + .byte 10 + pushq %rax + .byte 0x48, 0xB8 + .quad ASM_PFX(CommonInterruptEntry) + jmp *%rax Exception11Handle: - pushq $11 - jmp ASM_PFX(CommonInterruptEntry) + .byte 0x6a # push #VectorNum + .byte 11 + pushq %rax + .byte 0x48, 0xB8 + .quad ASM_PFX(CommonInterruptEntry) + jmp *%rax Exception12Handle: - pushq $12 - jmp ASM_PFX(CommonInterruptEntry) + .byte 0x6a # push #VectorNum + .byte 12 + pushq %rax + .byte 0x48, 0xB8 + .quad ASM_PFX(CommonInterruptEntry) + jmp *%rax Exception13Handle: - pushq $13 - jmp ASM_PFX(CommonInterruptEntry) + .byte 0x6a # push #VectorNum + .byte 13 + pushq %rax + .byte 0x48, 0xB8 + .quad ASM_PFX(CommonInterruptEntry) + jmp *%rax Exception14Handle: - pushq $14 - jmp ASM_PFX(CommonInterruptEntry) + .byte 0x6a # push #VectorNum + .byte 14 + pushq %rax + .byte 0x48, 0xB8 + .quad ASM_PFX(CommonInterruptEntry) + jmp *%rax Exception15Handle: - pushq $15 - jmp ASM_PFX(CommonInterruptEntry) + .byte 0x6a # push #VectorNum + .byte 15 + pushq %rax + .byte 0x48, 0xB8 + .quad ASM_PFX(CommonInterruptEntry) + jmp *%rax Exception16Handle: - pushq $16 - jmp ASM_PFX(CommonInterruptEntry) + .byte 0x6a # push #VectorNum + .byte 16 + pushq %rax + .byte 0x48, 0xB8 + .quad ASM_PFX(CommonInterruptEntry) + jmp *%rax Exception17Handle: - pushq $17 - jmp ASM_PFX(CommonInterruptEntry) + .byte 0x6a # push #VectorNum + .byte 17 + pushq %rax + .byte 0x48, 0xB8 + .quad ASM_PFX(CommonInterruptEntry) + jmp *%rax Exception18Handle: - pushq $18 - jmp ASM_PFX(CommonInterruptEntry) + .byte 0x6a # push #VectorNum + .byte 18 + pushq %rax + .byte 0x48, 0xB8 + .quad ASM_PFX(CommonInterruptEntry) + jmp *%rax Exception19Handle: - pushq $19 - jmp ASM_PFX(CommonInterruptEntry) + .byte 0x6a # push #VectorNum + .byte 19 + pushq %rax + .byte 0x48, 0xB8 + .quad ASM_PFX(CommonInterruptEntry) + jmp *%rax Exception20Handle: - pushq $20 - jmp ASM_PFX(CommonInterruptEntry) + .byte 0x6a # push #VectorNum + .byte 20 + pushq %rax + .byte 0x48, 0xB8 + .quad ASM_PFX(CommonInterruptEntry) + jmp *%rax Exception21Handle: - pushq $21 - jmp ASM_PFX(CommonInterruptEntry) + .byte 0x6a # push #VectorNum + .byte 21 + pushq %rax + .byte 0x48, 0xB8 + .quad ASM_PFX(CommonInterruptEntry) + jmp *%rax Exception22Handle: - pushq $22 - jmp ASM_PFX(CommonInterruptEntry) + .byte 0x6a # push #VectorNum + .byte 22 + pushq %rax + .byte 0x48, 0xB8 + .quad ASM_PFX(CommonInterruptEntry) + jmp *%rax Exception23Handle: - pushq $23 - jmp ASM_PFX(CommonInterruptEntry) + .byte 0x6a # push #VectorNum + .byte 23 + pushq %rax + .byte 0x48, 0xB8 + .quad ASM_PFX(CommonInterruptEntry) + jmp *%rax Exception24Handle: - pushq $24 - jmp ASM_PFX(CommonInterruptEntry) + .byte 0x6a # push #VectorNum + .byte 24 + pushq %rax + .byte 0x48, 0xB8 + .quad ASM_PFX(CommonInterruptEntry) + jmp *%rax Exception25Handle: - pushq $25 - jmp ASM_PFX(CommonInterruptEntry) + .byte 0x6a # push #VectorNum + .byte 25 + pushq %rax + .byte 0x48, 0xB8 + .quad ASM_PFX(CommonInterruptEntry) + jmp *%rax Exception26Handle: - pushq $26 - jmp ASM_PFX(CommonInterruptEntry) + .byte 0x6a # push #VectorNum + .byte 26 + pushq %rax + .byte 0x48, 0xB8 + .quad ASM_PFX(CommonInterruptEntry) + jmp *%rax Exception27Handle: - pushq $27 - jmp ASM_PFX(CommonInterruptEntry) + .byte 0x6a # push #VectorNum + .byte 27 + pushq %rax + .byte 0x48, 0xB8 + .quad ASM_PFX(CommonInterruptEntry) + jmp *%rax Exception28Handle: - pushq $28 - jmp ASM_PFX(CommonInterruptEntry) + .byte 0x6a # push #VectorNum + .byte 28 + pushq %rax + .byte 0x48, 0xB8 + .quad ASM_PFX(CommonInterruptEntry) + jmp *%rax Exception29Handle: - pushq $29 - jmp ASM_PFX(CommonInterruptEntry) + .byte 0x6a # push #VectorNum + .byte 29 + pushq %rax + .byte 0x48, 0xB8 + .quad ASM_PFX(CommonInterruptEntry) + jmp *%rax Exception30Handle: - pushq $30 - jmp ASM_PFX(CommonInterruptEntry) + .byte 0x6a # push #VectorNum + .byte 30 + pushq %rax + .byte 0x48, 0xB8 + .quad ASM_PFX(CommonInterruptEntry) + jmp *%rax Exception31Handle: - pushq $31 - jmp ASM_PFX(CommonInterruptEntry) - + .byte 0x6a # push #VectorNum + .byte 31 + pushq %rax + .byte 0x48, 0xB8 + .quad ASM_PFX(CommonInterruptEntry) + jmp *%rax + +HookAfterStubHeaderBegin: + .byte 0x6a # push +VectorNum: + .byte 0 # 0 will be fixed + pushq %rax + .byte 0x48, 0xB8 # movq ASM_PFX(HookAfterStubHeaderEnd), %rax + .quad ASM_PFX(HookAfterStubHeaderEnd) + jmp *%rax +ASM_GLOBAL ASM_PFX(HookAfterStubHeaderEnd) +ASM_PFX(HookAfterStubHeaderEnd): + movq %rsp, %rax + subq $8, %rsp + andl $0x0fffffff0, %esp + pushq %rcx + movq 8(%rax), %rcx + bt %ecx, ASM_PFX(mErrorCodeFlag) + jc NoErrorData + pushq (%rsp) # push additional rcx to make stack alignment +NoErrorData: + xchgq (%rsp), %rcx # restore rcx, save Exception Number in stack + pushq (%rax) # push rax into stack to keep code consistence #---------------------------------------; # CommonInterruptEntry ; @@ -138,6 +288,7 @@ Exception31Handle: ASM_GLOBAL ASM_PFX(CommonInterruptEntry) ASM_PFX(CommonInterruptEntry): cli + popq %rax # # All interrupt handlers are invoked through interrupt gates, so # IF flag automatically cleared at the entry point @@ -145,7 +296,8 @@ ASM_PFX(CommonInterruptEntry): # # Calculate vector number # - xchgq (%rsp), %rcx # get the return address of call, actually, it is the address of vector number. + xchgq (%rsp), %rcx # get the return address of call, actually, it is the address of vector number. + andq $0x0FF, %rcx cmp $32, %ecx # Intel reserved vector for exceptions? jae NoErrorCode pushq %rax @@ -165,6 +317,8 @@ NoErrorCode: CommonInterruptEntry_al_0000: pushq %rbp movq %rsp, %rbp + pushq $0 # check EXCEPTION_HANDLER_CONTEXT.OldIdtHandler + pushq $0 # check EXCEPTION_HANDLER_CONTEXT.ExceptionDataFlag # # Stack: @@ -385,20 +539,53 @@ CommonInterruptEntry_al_0000: movq %rbp, %rsp popq %rbp addq $16, %rsp + cmpq $0, -32(%rsp) # check EXCEPTION_HANDLER_CONTEXT.OldIdtHandler + jz DoReturn # check EXCEPTION_HANDLER_CONTEXT.ExceptionDataFlag + cmpb $1, -40(%rsp) + jz ErrorCode + jmp *-32(%rsp) +ErrorCode: + subq $8, %rsp + jmp *-24(%rsp) + +DoReturn: + cmpq $0, ASM_PFX(mDoFarReturnFlag) # Check if need to do far return instead of IRET + jz DoIret + pushq %rax + movq %rsp, %rax # save old RSP to rax + movq 0x20(%rsp), %rsp + pushq 0x10(%rax) # save CS in new location + pushq 0x8(%rax) # save EIP in new location + pushq 0x18(%rax) # save EFLAGS in new location + movq (%rax), %rax # restore rax + popfq # restore EFLAGS + .byte 0x48 # prefix to composite "retq" with next "retf" + retf # far return +DoIret: iretq #------------------------------------------------------------------------------------- -# AsmGetAddressMap (&AddressMap); +# AsmGetTemplateAddressMap (&AddressMap); #------------------------------------------------------------------------------------- # comments here for definition of address map -ASM_GLOBAL ASM_PFX(GetTemplateAddressMap) -ASM_PFX(GetTemplateAddressMap): +ASM_GLOBAL ASM_PFX(AsmGetTemplateAddressMap) +ASM_PFX(AsmGetTemplateAddressMap): movabsq $Exception0Handle, %rax movq %rax, (%rcx) movq $(Exception1Handle - Exception0Handle), 0x08(%rcx) + movabsq $HookAfterStubHeaderBegin, %rax + movq %rax, 0x10(%rcx) + ret +#------------------------------------------------------------------------------------- +# AsmVectorNumFixup (*VectorBase, VectorNum); +#------------------------------------------------------------------------------------- +ASM_GLOBAL ASM_PFX(AsmVectorNumFixup) +ASM_PFX(AsmVectorNumFixup): + movq %rdx, %rax + movb %al, (VectorNum - HookAfterStubHeaderBegin)(%rcx) ret #END diff --git a/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ExceptionHandlerAsm.asm b/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ExceptionHandlerAsm.asm index 2cc78db374..f348efe4be 100644 --- a/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ExceptionHandlerAsm.asm +++ b/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ExceptionHandlerAsm.asm @@ -25,133 +25,79 @@ ; externdef CommonExceptionHandler:near -EXTRN mErrorCodeFlag:DWORD ; Error code flags for exceptions +EXTRN mErrorCodeFlag:DWORD ; Error code flags for exceptions +EXTRN mDoFarReturnFlag:QWORD ; Do far return flag data SEGMENT -CommonEntryAddr dq CommonInterruptEntry; - .code -Exception0Handle: - push 0 - jmp qword ptr [CommonEntryAddr] -Exception1Handle: - push 1 - jmp qword ptr [CommonEntryAddr] -Exception2Handle: - push 2 - jmp qword ptr [CommonEntryAddr] -Exception3Handle: - push 3 - jmp qword ptr [CommonEntryAddr] -Exception4Handle: - push 4 - jmp qword ptr [CommonEntryAddr] -Exception5Handle: - push 5 - jmp qword ptr [CommonEntryAddr] -Exception6Handle: - push 6 - jmp qword ptr [CommonEntryAddr] -Exception7Handle: - push 7 - jmp qword ptr [CommonEntryAddr] -Exception8Handle: - push 8 - jmp qword ptr [CommonEntryAddr] -Exception9Handle: - push 9 - jmp qword ptr [CommonEntryAddr] -Exception10Handle: - push 10 - jmp qword ptr [CommonEntryAddr] -Exception11Handle: - push 11 - jmp qword ptr [CommonEntryAddr] -Exception12Handle: - push 12 - jmp qword ptr [CommonEntryAddr] -Exception13Handle: - push 13 - jmp qword ptr [CommonEntryAddr] -Exception14Handle: - push 14 - jmp qword ptr [CommonEntryAddr] -Exception15Handle: - push 15 - jmp qword ptr [CommonEntryAddr] -Exception16Handle: - push 16 - jmp qword ptr [CommonEntryAddr] -Exception17Handle: - push 17 - jmp qword ptr [CommonEntryAddr] -Exception18Handle: - push 18 - jmp qword ptr [CommonEntryAddr] -Exception19Handle: - push 19 - jmp qword ptr [CommonEntryAddr] -Exception20Handle: - push 20 - jmp qword ptr [CommonEntryAddr] -Exception21Handle: - push 21 - jmp qword ptr [CommonEntryAddr] -Exception22Handle: - push 22 - jmp qword ptr [CommonEntryAddr] -Exception23Handle: - push 23 - jmp qword ptr [CommonEntryAddr] -Exception24Handle: - push 24 - jmp qword ptr [CommonEntryAddr] -Exception25Handle: - push 25 - jmp qword ptr [CommonEntryAddr] -Exception26Handle: - push 26 - jmp qword ptr [CommonEntryAddr] -Exception27Handle: - push 27 - jmp qword ptr [CommonEntryAddr] -Exception28Handle: - push 28 - jmp qword ptr [CommonEntryAddr] -Exception29Handle: - push 29 - jmp qword ptr [CommonEntryAddr] -Exception30Handle: - push 30 - jmp qword ptr [CommonEntryAddr] -Exception31Handle: - push 31 - jmp qword ptr [CommonEntryAddr] - -;CommonInterruptEntrypoint: -;---------------------------------------; -; _CommonEntry ; -;----------------------------------------------------------------------------; -; The follow algorithm is used for the common interrupt routine. -; Entry from each interrupt with a push eax and eax=interrupt number +ALIGN 8 + +AsmIdtVectorBegin: +REPEAT 32 + db 6ah ; push #VectorNum + db ($ - AsmIdtVectorBegin) / ((AsmIdtVectorEnd - AsmIdtVectorBegin) / 32) ; VectorNum + push rax + mov rax, CommonInterruptEntry + jmp rax +ENDM +AsmIdtVectorEnd: + +HookAfterStubHeaderBegin: + db 6ah ; push +@VectorNum: + db 0 ; 0 will be fixed + push rax + mov rax, HookAfterStubHeaderEnd + jmp rax +HookAfterStubHeaderEnd: + mov rax, rsp + sub rsp, 8h + and sp, 0fff0h + push rcx + mov rcx, [rax + 8] + bt mErrorCodeFlag, ecx + jc @F + push [rsp] ; push additional rcx to make stack alignment +@@: + xchg rcx, [rsp] ; restore rcx, save Exception Number in stack + push [rax] ; push rax into stack to keep code consistence ;---------------------------------------; ; CommonInterruptEntry ; ;---------------------------------------; ; The follow algorithm is used for the common interrupt routine. - +; Entry from each interrupt with a push eax and eax=interrupt number +; Stack frame would be as follows as specified in IA32 manuals: +; +; +---------------------+ <-- 16-byte aligned ensured by processor +; + Old SS + +; +---------------------+ +; + Old RSP + +; +---------------------+ +; + RFlags + +; +---------------------+ +; + CS + +; +---------------------+ +; + RIP + +; +---------------------+ +; + Error Code + +; +---------------------+ +; + Vector Number + +; +---------------------+ +; + RBP + +; +---------------------+ <-- RBP, 16-byte aligned +; The follow algorithm is used for the common interrupt routine. CommonInterruptEntry PROC PUBLIC cli + pop rax ; ; 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. + xchg rcx, [rsp] ; Save rcx into stack and save vector number into rcx + and rcx, 0FFh cmp ecx, 32 ; Intel reserved vector for exceptions? jae NoErrorCode bt mErrorCodeFlag, ecx @@ -168,6 +114,8 @@ NoErrorCode: @@: push rbp mov rbp, rsp + push 0 ; clear EXCEPTION_HANDLER_CONTEXT.OldIdtHandler + push 0 ; clear EXCEPTION_HANDLER_CONTEXT.ExceptionDataFlag ; ; Stack: @@ -389,6 +337,29 @@ NoErrorCode: mov rsp, rbp pop rbp add rsp, 16 + cmp qword ptr [rsp - 32], 0 ; check EXCEPTION_HANDLER_CONTEXT.OldIdtHandler + jz DoReturn + cmp qword ptr [rsp - 40], 1 ; check EXCEPTION_HANDLER_CONTEXT.ExceptionDataFlag + jz ErrorCode + jmp qword ptr [rsp - 32] +ErrorCode: + sub rsp, 8 + jmp qword ptr [rsp - 24] + +DoReturn: + cmp mDoFarReturnFlag, 0 ; Check if need to do far return instead of IRET + jz DoIret + push rax + mov rax, rsp ; save old RSP to rax + mov rsp, [rsp + 20h] + push [rax + 10h] ; save CS in new location + push [rax + 8h] ; save EIP in new location + push [rax + 18h] ; save EFLAGS in new location + mov rax, [rax] ; restore rax + popfq ; restore EFLAGS + DB 48h ; prefix to composite "retq" with next "retf" + retf ; far return +DoIret: iretq CommonInterruptEntry ENDP @@ -397,11 +368,22 @@ CommonInterruptEntry ENDP ; GetTemplateAddressMap (&AddressMap); ;------------------------------------------------------------------------------------- ; comments here for definition of address map -GetTemplateAddressMap PROC - mov rax, offset Exception0Handle - mov qword ptr [rcx], rax - mov qword ptr [rcx+8h], Exception1Handle - Exception0Handle - ret -GetTemplateAddressMap ENDP +AsmGetTemplateAddressMap PROC + mov rax, offset AsmIdtVectorBegin + mov qword ptr [rcx], rax + mov qword ptr [rcx + 8h], (AsmIdtVectorEnd - AsmIdtVectorBegin) / 32 + mov rax, offset HookAfterStubHeaderBegin + mov qword ptr [rcx + 10h], rax + ret +AsmGetTemplateAddressMap ENDP + +;------------------------------------------------------------------------------------- +; AsmVectorNumFixup (*VectorBase, VectorNum); +;------------------------------------------------------------------------------------- +AsmVectorNumFixup PROC + mov rax, rdx + mov [rcx + (@VectorNum - HookAfterStubHeaderBegin)], al + ret +AsmVectorNumFixup ENDP END diff --git a/UefiCpuPkg/UefiCpuPkg.dsc b/UefiCpuPkg/UefiCpuPkg.dsc index 505c69e4c8..fa33c1342c 100644 --- a/UefiCpuPkg/UefiCpuPkg.dsc +++ b/UefiCpuPkg/UefiCpuPkg.dsc @@ -1,7 +1,7 @@ ## @file # UefiCpuPkg Package # -# Copyright (c) 2007 - 2012, Intel Corporation. All rights reserved.
+# Copyright (c) 2007 - 2013, 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 @@ -50,7 +50,8 @@ TimerLib|MdePkg/Library/BaseTimerLibNullTemplate/BaseTimerLibNullTemplate.inf DebugAgentLib|MdeModulePkg/Library/DebugAgentLibNull/DebugAgentLibNull.inf LocalApicLib|UefiCpuPkg/Library/BaseXApicX2ApicLib/BaseXApicX2ApicLib.inf - ReportStatusCodeLib|MdePkg/Library/BaseReportStatusCodeLibNull/BaseReportStatusCodeLibNull.inf + ReportStatusCodeLib|MdePkg/Library/BaseReportStatusCodeLibNull/BaseReportStatusCodeLibNull.inf + CpuExceptionHandlerLib|MdeModulePkg/Library/CpuExceptionHandlerLibNull/CpuExceptionHandlerLibNull.inf [LibraryClasses.common.PEIM] MemoryAllocationLib|MdePkg/Library/PeiMemoryAllocationLib/PeiMemoryAllocationLib.inf @@ -87,6 +88,7 @@ UefiCpuPkg/Library/BaseXApicX2ApicLib/BaseXApicX2ApicLib.inf UefiCpuPkg/Library/BaseXApicLib/BaseXApicLib.inf UefiCpuPkg/Library/CpuExceptionHandlerLib/SecPeiCpuExceptionHandlerLib.inf - UefiCpuPkg/Library/CpuExceptionHandlerLib/DxeSmmCpuExceptionHandlerLib.inf + UefiCpuPkg/Library/CpuExceptionHandlerLib/DxeCpuExceptionHandlerLib.inf + UefiCpuPkg/Library/CpuExceptionHandlerLib/SmmCpuExceptionHandlerLib.inf UefiCpuPkg/Universal/Acpi/S3Resume2Pei/S3Resume2Pei.inf -- 2.39.2