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 <jeff.fan@intel.com>
Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
Reviewed-by: Feng Tian <feng.tian@intel.com>
Reviewed-by: Hot Tian <hot.tian@intel.com>



git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@14885 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
Jeff Fan 2013-11-22 06:24:41 +00:00 committed by vanjeff
parent 57f360f261
commit e41aad1521
27 changed files with 1906 additions and 3036 deletions

@ -1,7 +1,7 @@
/** @file
CPU DXE Module.
Copyright (c) 2008 - 2012, Intel Corporation. All rights reserved.<BR>
Copyright (c) 2008 - 2013, Intel Corporation. All rights reserved.<BR>
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;
EFI_STATUS Status;
EFI_VECTOR_HANDOFF_INFO *VectorInfoList;
EFI_VECTOR_HANDOFF_INFO *VectorInfo;
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;
VectorInfo = NULL;
Status = EfiGetSystemConfigurationTable (&gEfiVectorHandoffTableGuid, (VOID **) &VectorInfoList);
if (Status == EFI_SUCCESS && VectorInfoList != NULL) {
VectorInfo = VectorInfoList;
}
//
// 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);
}
//
// Set the pointer to the array of C based exception handling routines.
//
InitializeExternalVectorTablePtr (ExternalVectorTable);
Status = InitializeCpuInterruptHandlers (VectorInfo);
ASSERT_EFI_ERROR (Status);
}

@ -1,7 +1,7 @@
/** @file
CPU DXE Module.
Copyright (c) 2008 - 2012, Intel Corporation. All rights reserved.<BR>
Copyright (c) 2008 - 2013, Intel Corporation. All rights reserved.<BR>
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 <Library/MtrrLib.h>
#include <Library/LocalApicLib.h>
#include <Library/UefiCpuLib.h>
#include <Library/UefiLib.h>
#include <Library/CpuExceptionHandlerLib.h>
#include <Guid/IdleLoopEvent.h>
//
//
//
#define INTERRUPT_VECTOR_NUMBER 256
#include <Guid/VectorHandoffTable.h>
#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

@ -2,7 +2,7 @@
#
# Component description file for simple CPU driver
#
# Copyright (c) 2008 - 2012, Intel Corporation. All rights reserved.<BR>
# Copyright (c) 2008 - 2013, Intel Corporation. All rights reserved.<BR>
# 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

@ -1,6 +1,6 @@
#------------------------------------------------------------------------------
#*
#* Copyright (c) 2006 - 2012, Intel Corporation. All rights reserved.<BR>
#* Copyright (c) 2006 - 2013, Intel Corporation. All rights reserved.<BR>
#* 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

@ -1,7 +1,7 @@
TITLE CpuAsm.asm:
;------------------------------------------------------------------------------
;*
;* Copyright (c) 2006 - 2012, Intel Corporation. All rights reserved.<BR>
;* Copyright (c) 2006 - 2013, Intel Corporation. All rights reserved.<BR>
;* 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

@ -1,818 +0,0 @@
#------------------------------------------------------------------------------
#
# Copyright (c) 2006 - 2009, Intel Corporation. All rights reserved.<BR>
# 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

@ -1,51 +0,0 @@
TITLE IvtAsm.asm:
;------------------------------------------------------------------------------
;*
;* Copyright (c) 2008 - 2009, Intel Corporation. All rights reserved.<BR>
;* This program and the accompanying materials
;* are licensed and made available under the terms and conditions of the BSD License
;* which accompanies this distribution. The full text of the license may be found at
;* http://opensource.org/licenses/bsd-license.php
;*
;* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
;* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
;*
;* IvtAsm.asm
;*
;* Abstract:
;*
;------------------------------------------------------------------------------
#include <Base.h>
#ifdef MDE_CPU_IA32
.686
.model flat,C
#endif
.code
;------------------------------------------------------------------------------
; Generic IDT Vector Handlers for the Host. They are all the same so they
; will compress really well.
;
; By knowing the return address for Vector 00 you can can calculate the
; vector number by looking at the call CommonInterruptEntry return address.
; (return address - (AsmIdtVector00 + 5))/8 == IDT index
;
;------------------------------------------------------------------------------
EXTRN CommonInterruptEntry:PROC
ALIGN 8
PUBLIC AsmIdtVector00
AsmIdtVector00 LABEL BYTE
REPEAT 256
call CommonInterruptEntry
dw ($ - AsmIdtVector00 - 5) / 8 ; vector number
nop
ENDM
END

@ -2,7 +2,7 @@
#------------------------------------------------------------------------------
#*
#* Copyright (c) 2008 - 2011, Intel Corporation. All rights reserved.<BR>
#* Copyright (c) 2008 - 2013, Intel Corporation. All rights reserved.<BR>
#* 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

@ -1,7 +1,7 @@
TITLE CpuAsm.asm:
;------------------------------------------------------------------------------
;*
;* Copyright (c) 2008 - 2011, Intel Corporation. All rights reserved.<BR>
;* Copyright (c) 2008 - 2013, Intel Corporation. All rights reserved.<BR>
;* 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

@ -1,7 +1,7 @@
/** @file
CPU Exception Hanlder Library common functions.
Copyright (c) 2012, Intel Corporation. All rights reserved.<BR>
Copyright (c) 2012 - 2013, Intel Corporation. All rights reserved.<BR>
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;
}

@ -1,7 +1,7 @@
/** @file
Common header file for CPU Exception Handler Library.
Copyright (c) 2012, Intel Corporation. All rights reserved.<BR>
Copyright (c) 2012 - 2013, Intel Corporation. All rights reserved.<BR>
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 <Ppi/VectorHandoffInfo.h>
#include <Protocol/Cpu.h>
#include <Library/BaseLib.h>
#include <Library/SerialPortLib.h>
#include <Library/PrintLib.h>
#include <Library/LocalApicLib.h>
#include <Library/PeCoffGetEntryPointLib.h>
#include <Library/ReportStatusCodeLib.h>
#include <Library/BaseMemoryLib.h>
#include <Library/SynchronizationLib.h>
#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

@ -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.<BR>
# Copyright (c) 2013, Intel Corporation. All rights reserved.<BR>
# 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

@ -0,0 +1,170 @@
/** @file
CPU exception handler library implemenation for DXE modules.
Copyright (c) 2013, Intel Corporation. All rights reserved.<BR>
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 <PiDxe.h>
#include "CpuExceptionCommon.h"
#include <Library/DebugLib.h>
#include <Library/MemoryAllocationLib.h>
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);
}

@ -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.<BR>
Copyright (c) 2012 - 2013, Intel Corporation. All rights reserved.<BR>
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 <PiDxe.h>
#include "CpuExceptionCommon.h"
#include <Library/SynchronizationLib.h>
#include <Library/DebugLib.h>
//
// 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);
//
// Release Spinlock
//
ReleaseSpinLock (&mDisplayMessageSpinLock);
//
// Enter a dead loop.
//
CpuDeadLoop ();
}
/**
Setup CPU exception handlers.
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.
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().
**/
VOID
EFIAPI
SetupCpuExceptionHandlers (
IN VOID
UpdateIdtTable (
IN IA32_IDT_GATE_DESCRIPTOR *IdtTable,
IN EXCEPTION_HANDLER_TEMPLATE_MAP *TemplateMap,
IN UINTN IdtEntryCount
)
{
InitializeSpinLock (&mDisplayMessageSpinLock);
InternalSetupCpuExceptionHandlers ();
UINT16 CodeSegment;
UINTN Index;
UINTN InterruptHandler;
//
// Use current CS as the segment selector of interrupt gate in IDT
//
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;
}
}
//
// Save Interrupt number to global variable used for RegisterCpuInterruptHandler ()
//
mEnabledInterruptNum = IdtEntryCount;
}
/**
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
)
{
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);
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;
}

@ -1,7 +1,7 @@
/** @file
IA32 CPU Exception Hanlder functons.
Copyright (c) 2012, Intel Corporation. All rights reserved.<BR>
Copyright (c) 2012 - 2013, Intel Corporation. All rights reserved.<BR>
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
)
{
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.GateType = IA32_IDT_GATE_TYPE_INTERRUPT_32;
}
//
// Read IDT descriptor and calculate IDT size
//
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;
}
/**
Read IDT handler value from IDT entry.
//
// Use current CS as the segment selector of interrupt gate in IDT
//
CodeSegment = AsmReadCs ();
IdtEntry = (IA32_IDT_GATE_DESCRIPTOR *) IdtDescriptor.Base;
@param IdtEntry Pointer to IDT entry to be read.
GetTemplateAddressMap (&TemplateMap);
**/
UINTN
ArchGetIdtHandler (
IN IA32_IDT_GATE_DESCRIPTOR *IdtEntry
)
{
return (UINTN)IdtEntry->Bits.OffsetLow + (((UINTN)IdtEntry->Bits.OffsetHigh) << 16);
}
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;
}
/**
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;
//
// Save Exception context in global variable
//
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
//
Eflags.UintN = SystemContext.SystemContextIa32->Eflags;
Eflags.Bits.IF = 0;
SystemContext.SystemContextIa32->Eflags = Eflags.UintN;
//
// Modify the EIP in stack, then old IDT handler will return to the stub code
//
SystemContext.SystemContextIa32->Eip = (UINTN) mReservedVectors[ExceptionType].HookAfterStubHeaderCode;
}
/**
Restore CPU exception context when handling EFI_VECTOR_HANDOFF_HOOK_AFTER case.
@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
)
{

@ -0,0 +1,44 @@
/** @file
Ia32 arch definition for CPU Exception Handler Library.
Copyright (c) 2013, Intel Corporation. All rights reserved.<BR>
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

@ -1,6 +1,6 @@
#------------------------------------------------------------------------------
#*
#* Copyright (c) 2012, Intel Corporation. All rights reserved.<BR>
#* Copyright (c) 2012 - 2013, Intel Corporation. All rights reserved.<BR>
#* 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

@ -1,5 +1,5 @@
;------------------------------------------------------------------------------ ;
; Copyright (c) 2012, Intel Corporation. All rights reserved.<BR>
; Copyright (c) 2012 - 2013, Intel Corporation. All rights reserved.<BR>
; 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

@ -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.<BR>
Copyright (c) 2012 - 2013, Intel Corporation. All rights reserved.<BR>
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
SetupCpuExceptionHandlers (
IN VOID
InitializeCpuExceptionHandlers (
IN EFI_VECTOR_HANDOFF_INFO *VectorInfo OPTIONAL
)
{
InternalSetupCpuExceptionHandlers ();
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
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 EFI_UNSUPPORTED;
}

@ -3,7 +3,7 @@
#
# This library instance supports SEC/PEI module only.
#
# Copyright (c) 2012, Intel Corporation. All rights reserved.<BR>
# Copyright (c) 2012 - 2013, Intel Corporation. All rights reserved.<BR>
# 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

@ -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.<BR>
# 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

@ -0,0 +1,101 @@
/** @file
CPU exception handler library implemenation for SMM modules.
Copyright (c) 2013, Intel Corporation. All rights reserved.<BR>
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 <PiSmm.h>
#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);
}

@ -1,7 +1,7 @@
/** @file
x64 CPU Exception Hanlder.
Copyright (c) 2012, Intel Corporation. All rights reserved.<BR>
Copyright (c) 2012 - 2013, Intel Corporation. All rights reserved.<BR>
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;
//
// Read IDT descriptor and calculate IDT size
//
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;
}
//
// Use current CS as the segment selector of interrupt gate in IDT
//
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;
}
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;
}
/**
Common exception handler.
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;
//
// Save Exception context in global variable
//
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;
//
// Clear IF flag to avoid old IDT handler enable interrupt by IRET
//
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;
}
/**
Restore CPU exception context when handling EFI_VECTOR_HANDOFF_HOOK_AFTER case.
@param ExceptionType Exception type.
@param SystemContext Pointer to EFI_SYSTEM_CONTEXT.
**/
VOID
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 UINTN ExceptionType,
IN EFI_EXCEPTION_TYPE ExceptionType,
IN EFI_SYSTEM_CONTEXT SystemContext
)
{

@ -0,0 +1,46 @@
/** @file
X64 arch definition for CPU Exception Handler Library.
Copyright (c) 2013, Intel Corporation. All rights reserved.<BR>
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

@ -1,5 +1,5 @@
#------------------------------------------------------------------------------ ;
# Copyright (c) 2012, Intel Corporation. All rights reserved.<BR>
# Copyright (c) 2012 - 2013, Intel Corporation. All rights reserved.<BR>
# 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

@ -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]
ALIGN 8
;CommonInterruptEntrypoint:
;---------------------------------------;
; _CommonEntry ;
;----------------------------------------------------------------------------;
; The follow algorithm is used for the common interrupt routine.
; Entry from each interrupt with a push eax and eax=interrupt number
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

@ -1,7 +1,7 @@
## @file
# UefiCpuPkg Package
#
# Copyright (c) 2007 - 2012, Intel Corporation. All rights reserved.<BR>
# Copyright (c) 2007 - 2013, Intel Corporation. All rights reserved.<BR>
#
# 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