Import two CPU Exception Handler Library instances: SecPeiCpuExceptionHandler.inf and DxeSmmCpuExceptionHandler.inf.

Signed-off-by: vanjeff
Reviewed-by: jyao1


git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@13098 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
vanjeff 2012-03-15 05:24:07 +00:00
parent 1e172d6bbf
commit 8f07f895fb
13 changed files with 2598 additions and 1 deletions

View File

@ -0,0 +1,132 @@
/** @file
CPU Exception Hanlder Library common functions.
Copyright (c) 2012, 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 "CpuExceptionCommon.h"
//
// 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;
//
// Define the maximum message length
//
#define MAX_DEBUG_MESSAGE_LENGTH 0x100
/**
Prints a message to the serial port.
@param Format Format string for the message to print.
@param ... Variable argument list whose contents are accessed
based on the format string specified by Format.
**/
VOID
EFIAPI
InternalPrintMessage (
IN CONST CHAR8 *Format,
...
)
{
CHAR8 Buffer[MAX_DEBUG_MESSAGE_LENGTH];
VA_LIST Marker;
//
// Convert the message to an ASCII String
//
VA_START (Marker, Format);
AsciiVSPrint (Buffer, sizeof (Buffer), Format, Marker);
VA_END (Marker);
//
// Send the print string to a Serial Port
//
SerialPortWrite ((UINT8 *)Buffer, AsciiStrLen (Buffer));
}
/**
Find and display image base address and return image base and its entry point.
@return EFI_SUCCESS Image base address.
@return 0 Image header cannot be found.
**/
UINTN
FindModuleImageBase (
IN UINTN CurrentEip,
OUT UINTN *EntryPoint
)
{
UINTN Pe32Data;
EFI_IMAGE_DOS_HEADER *DosHdr;
EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr;
VOID *PdbPointer;
//
// Find Image Base
//
Pe32Data = CurrentEip & ~(mImageAlignSize - 1);
while (Pe32Data != 0) {
DosHdr = (EFI_IMAGE_DOS_HEADER *) Pe32Data;
if (DosHdr->e_magic == EFI_IMAGE_DOS_SIGNATURE) {
//
// DOS image header is present, so read the PE header after the DOS image header.
//
Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)(Pe32Data + (UINTN) ((DosHdr->e_lfanew) & 0x0ffff));
if (Hdr.Pe32->Signature == EFI_IMAGE_NT_SIGNATURE) {
//
// It's PE image.
//
InternalPrintMessage ("!!!! Find PE image ");
*EntryPoint = (UINTN)Pe32Data + (UINTN)(Hdr.Pe32->OptionalHeader.AddressOfEntryPoint & 0x0ffffffff);
break;
}
} else {
//
// DOS image header is not present, TE header is at the image base.
//
Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)Pe32Data;
if ((Hdr.Te->Signature == EFI_TE_IMAGE_HEADER_SIGNATURE) &&
((Hdr.Te->Machine == IMAGE_FILE_MACHINE_I386) || Hdr.Te->Machine == IMAGE_FILE_MACHINE_X64)) {
//
// It's TE image, it TE header and Machine type match
//
InternalPrintMessage ("!!!! Find TE image ");
*EntryPoint = (UINTN)Pe32Data + (UINTN)(Hdr.Te->AddressOfEntryPoint & 0x0ffffffff) + sizeof(EFI_TE_IMAGE_HEADER) - Hdr.Te->StrippedSize;
break;
}
}
//
// Not found the image base, check the previous aligned address
//
Pe32Data -= mImageAlignSize;
}
if (Pe32Data != 0) {
PdbPointer = PeCoffLoaderGetPdbPointer ((VOID *) Pe32Data);
if (PdbPointer != NULL) {
InternalPrintMessage ("%a", PdbPointer);
} else {
InternalPrintMessage ("(No PDB) " );
}
} else {
InternalPrintMessage ("!!!! Can't find image information. !!!!\n");
}
return Pe32Data;
}

View File

@ -0,0 +1,96 @@
/** @file
Common header file for CPU Exception Handler Library.
Copyright (c) 2012, 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 _CPU_EXCEPTION_COMMON_H_
#define _CPU_EXCEPTION_COMMON_H_
#include <Library/BaseLib.h>
#include <Library/SerialPortLib.h>
#include <Library/PrintLib.h>
#include <Library/LocalApicLib.h>
#include <Library/PeCoffGetEntryPointLib.h>
#define CPU_EXCEPTION_NUM 32
//
// Record exception handler information
//
typedef struct {
UINTN ExceptionStart;
UINTN ExceptionStubHeaderSize;
} EXCEPTION_HANDLER_TEMPLATE_MAP;
extern UINT32 mErrorCodeFlag;
extern CONST UINTN mImageAlignSize;
/**
Return address map of exception handler template so that C code can generate
exception tables.
@param AddressMap Pointer to a buffer where the address map is returned.
**/
VOID
EFIAPI
GetTemplateAddressMap (
OUT EXCEPTION_HANDLER_TEMPLATE_MAP *AddressMap
);
/**
Internal function to setup CPU exception handlers.
**/
VOID
InternalSetupCpuExceptionHandlers (
VOID
);
/**
Prints a message to the serial port.
@param Format Format string for the message to print.
@param ... Variable argument list whose contents are accessed
based on the format string specified by Format.
**/
VOID
EFIAPI
InternalPrintMessage (
IN CONST CHAR8 *Format,
...
);
/**
Find and display image base address and return image base and its entry point.
@return EFI_SUCCESS Image base address.
@return 0 Image header cannot be found.
**/
UINTN
FindModuleImageBase (
IN UINTN CurrentEip,
OUT UINTN *EntryPoint
);
/**
Display CPU information.
@param InterruptType Exception type.
@param SystemContext Pointer to EFI_SYSTEM_CONTEXT.
**/
VOID
DumpCpuContent (
IN UINTN InterruptType,
IN EFI_SYSTEM_CONTEXT SystemContext
);
#endif

View File

@ -0,0 +1,84 @@
/** @file
CPU Exception Library provides DXE/SMM CPU exception handler.
Copyright (c) 2012, 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
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/SynchronizationLib.h>
//
// Spinlock for CPU information display
//
SPIN_LOCK mDisplayMessageSpinLock;
//
// Image align size for DXE/SMM
//
CONST UINTN mImageAlignSize = SIZE_4KB;
/**
Common exception handler.
@param ExceptionType Exception type.
@param SystemContext Pointer to EFI_SYSTEM_CONTEXT.
**/
VOID
EFIAPI
CommonExceptionHandler (
IN EFI_EXCEPTION_TYPE ExceptionType,
IN EFI_SYSTEM_CONTEXT SystemContext
)
{
//
// Get Spinlock to display CPU information
//
while (!AcquireSpinLockOrFail (&mDisplayMessageSpinLock)) {
CpuPause ();
}
//
// Display ExceptionType, CPU information and Image information
//
DumpCpuContent (ExceptionType, SystemContext);
//
// Release Spinlock
//
ReleaseSpinLock (&mDisplayMessageSpinLock);
//
// Enter a dead loop.
//
CpuDeadLoop ();
}
/**
Setup CPU exception handlers.
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
)
{
InitializeSpinLock (&mDisplayMessageSpinLock);
InternalSetupCpuExceptionHandlers ();
}

View File

@ -0,0 +1,57 @@
## @file
# Component description file for DXE/SMM CPU Exception Handler Library instance.
#
# This library instance supports DXE SMM module only.
#
# Copyright (c) 2012, 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 = DxeSmmCpuExceptionHandlerLib
FILE_GUID = EC629480-BD36-4e8e-8AB2-D28BF0D45864
MODULE_TYPE = DXE_DRIVER
VERSION_STRING = 1.0
LIBRARY_CLASS = CpuExceptionHandlerLib|DXE_CORE DXE_DRIVER DXE_SMM_DRIVER UEFI_APPLICATION
#
# 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
[Sources.X64]
X64/ExceptionHandlerAsm.asm |MSFT
X64/ExceptionHandlerAsm.S |GCC
X64/ArchExceptionHandler.c
[Sources.common]
CpuExceptionCommon.h
CpuExceptionCommon.c
DxeSmmCpuException.c
[Packages]
MdePkg/MdePkg.dec
MdeModulePkg/MdeModulePkg.dec
UefiCpuPkg/UefiCpuPkg.dec
[LibraryClasses]
BaseLib
SerialPortLib
PrintLib
SynchronizationLib
LocalApicLib
PeCoffGetEntryPointLib

View File

@ -0,0 +1,164 @@
/** @file
IA32 CPU Exception Hanlder functons.
Copyright (c) 2012, 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 "CpuExceptionCommon.h"
/**
Internal function to setup CPU exception handlers.
**/
VOID
InternalSetupCpuExceptionHandlers (
VOID
)
{
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.Selector = CodeSegment;
IdtEntry[Index].Bits.GateType = IA32_IDT_GATE_TYPE_INTERRUPT_32;
}
}
/**
Dump CPU content information.
@param ExceptionType Exception type.
@param SystemContext Pointer to EFI_SYSTEM_CONTEXT.
**/
VOID
DumpCpuContent (
IN UINTN ExceptionType,
IN EFI_SYSTEM_CONTEXT SystemContext
)
{
UINTN ImageBase;
UINTN EntryPoint;
InternalPrintMessage (
"!!!! IA32 Exception Type - %08x CPU Apic ID - %08x !!!!\n",
ExceptionType,
GetApicId ()
);
InternalPrintMessage (
"EIP - %08x, CS - %08x, EFLAGS - %08x\n",
SystemContext.SystemContextIa32->Eip,
SystemContext.SystemContextIa32->Cs,
SystemContext.SystemContextIa32->Eflags
);
if ((mErrorCodeFlag & (1 << ExceptionType)) != 0) {
InternalPrintMessage (
"ExceptionData - %08x\n",
SystemContext.SystemContextIa32->ExceptionData
);
}
InternalPrintMessage (
"EAX - %08x, ECX - %08x, EDX - %08x, EBX - %08x\n",
SystemContext.SystemContextIa32->Eax,
SystemContext.SystemContextIa32->Ecx,
SystemContext.SystemContextIa32->Edx,
SystemContext.SystemContextIa32->Ebx
);
InternalPrintMessage (
"ESP - %08x, EBP - %08x, ESI - %08x, EDI - %08x\n",
SystemContext.SystemContextIa32->Esp,
SystemContext.SystemContextIa32->Ebp,
SystemContext.SystemContextIa32->Esi,
SystemContext.SystemContextIa32->Edi
);
InternalPrintMessage (
"DS - %08x, ES - %08x, FS - %08x, GS - %08x, SS - %08x\n",
SystemContext.SystemContextIa32->Ds,
SystemContext.SystemContextIa32->Es,
SystemContext.SystemContextIa32->Fs,
SystemContext.SystemContextIa32->Gs,
SystemContext.SystemContextIa32->Ss
);
InternalPrintMessage (
"CR0 - %08x, CR2 - %08x, CR3 - %08x, CR4 - %08x\n",
SystemContext.SystemContextIa32->Cr0,
SystemContext.SystemContextIa32->Cr2,
SystemContext.SystemContextIa32->Cr3,
SystemContext.SystemContextIa32->Cr4
);
InternalPrintMessage (
"DR0 - %08x, DR1 - %08x, DR2 - %08x, DR3 - %08x\n",
SystemContext.SystemContextIa32->Dr0,
SystemContext.SystemContextIa32->Dr1,
SystemContext.SystemContextIa32->Dr2,
SystemContext.SystemContextIa32->Dr3
);
InternalPrintMessage (
"DR6 - %08x, DR7 - %08x\n",
SystemContext.SystemContextIa32->Dr6,
SystemContext.SystemContextIa32->Dr7
);
InternalPrintMessage (
"GDTR - %08x %08x, IDTR - %08x %08x\n",
SystemContext.SystemContextIa32->Gdtr[0],
SystemContext.SystemContextIa32->Gdtr[1],
SystemContext.SystemContextIa32->Idtr[0],
SystemContext.SystemContextIa32->Idtr[1]
);
InternalPrintMessage (
"LDTR - %08x, TR - %08x\n",
SystemContext.SystemContextIa32->Ldtr,
SystemContext.SystemContextIa32->Tr
);
InternalPrintMessage (
"FXSAVE_STATE - %08x\n",
&SystemContext.SystemContextIa32->FxSaveState
);
//
// Find module image base and module entry point by RIP
//
ImageBase = FindModuleImageBase (SystemContext.SystemContextIa32->Eip, &EntryPoint);
if (ImageBase != 0) {
InternalPrintMessage (
" (ImageBase=%08x, EntryPoint=%08x) !!!!\n",
ImageBase,
EntryPoint
);
}
}

View File

@ -0,0 +1,467 @@
#------------------------------------------------------------------------------
#*
#* Copyright (c) 2012, 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.
#*
#* ExceptionHandlerAsm.S
#*
#* Abstract:
#*
#* IA32 CPU Exception Handler
#
#------------------------------------------------------------------------------
#.MMX
#.XMM
ASM_GLOBAL ASM_PFX(CommonExceptionHandler)
ASM_GLOBAL ASM_PFX(CommonInterruptEntry)
#EXTRN ASM_PFX(mErrorCodeFlag):DWORD # Error code flags for exceptions
.text
#
# exception handler stub table
#
Exception0Handle:
pushl $0
jmp ASM_PFX(CommonInterruptEntry)
Exception1Handle:
pushl $1
jmp ASM_PFX(CommonInterruptEntry)
Exception2Handle:
pushl $2
jmp ASM_PFX(CommonInterruptEntry)
Exception3Handle:
pushl $3
jmp ASM_PFX(CommonInterruptEntry)
Exception4Handle:
pushl $4
jmp ASM_PFX(CommonInterruptEntry)
Exception5Handle:
pushl $5
jmp ASM_PFX(CommonInterruptEntry)
Exception6Handle:
pushl $6
jmp ASM_PFX(CommonInterruptEntry)
Exception7Handle:
pushl $7
jmp ASM_PFX(CommonInterruptEntry)
Exception8Handle:
pushl $8
jmp ASM_PFX(CommonInterruptEntry)
Exception9Handle:
pushl $9
jmp ASM_PFX(CommonInterruptEntry)
Exception10Handle:
pushl $10
jmp ASM_PFX(CommonInterruptEntry)
Exception11Handle:
pushl $11
jmp ASM_PFX(CommonInterruptEntry)
Exception12Handle:
pushl $12
jmp ASM_PFX(CommonInterruptEntry)
Exception13Handle:
pushl $13
jmp ASM_PFX(CommonInterruptEntry)
Exception14Handle:
pushl $14
jmp ASM_PFX(CommonInterruptEntry)
Exception15Handle:
pushl $15
jmp ASM_PFX(CommonInterruptEntry)
Exception16Handle:
pushl $16
jmp ASM_PFX(CommonInterruptEntry)
Exception17Handle:
pushl $17
jmp ASM_PFX(CommonInterruptEntry)
Exception18Handle:
pushl $18
jmp ASM_PFX(CommonInterruptEntry)
Exception19Handle:
pushl $19
jmp ASM_PFX(CommonInterruptEntry)
Exception20Handle:
pushl $20
jmp ASM_PFX(CommonInterruptEntry)
Exception21Handle:
pushl $21
jmp ASM_PFX(CommonInterruptEntry)
Exception22Handle:
pushl $22
jmp ASM_PFX(CommonInterruptEntry)
Exception23Handle:
pushl $23
jmp ASM_PFX(CommonInterruptEntry)
Exception24Handle:
pushl $24
jmp ASM_PFX(CommonInterruptEntry)
Exception25Handle:
pushl $25
jmp ASM_PFX(CommonInterruptEntry)
Exception26Handle:
pushl $26
jmp ASM_PFX(CommonInterruptEntry)
Exception27Handle:
pushl $27
jmp ASM_PFX(CommonInterruptEntry)
Exception28Handle:
pushl $28
jmp ASM_PFX(CommonInterruptEntry)
Exception29Handle:
pushl $29
jmp ASM_PFX(CommonInterruptEntry)
Exception30Handle:
pushl $30
jmp ASM_PFX(CommonInterruptEntry)
Exception31Handle:
pushl $31
jmp ASM_PFX(CommonInterruptEntry)
#---------------------------------------;
# 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
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
#
# Fall through to join main routine code
# at ErrorCodeAndVectorOnStack
#
CommonInterruptEntry_al_0000:
jmp CommonInterruptEntry_al_0000
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)
#; Prepare parameter and call
movl %esp, %edx
pushl %edx
movl 4(%ebp), %edx
pushl %edx
#
# Call External Exception Handler
#
call ASM_PFX(CommonExceptionHandler)
addl $8, %esp
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
#---------------------------------------;
# _GetTemplateAddressMap ;
#----------------------------------------------------------------------------;
#
# Protocol prototype
# GetTemplateAddressMap (
# EXCEPTION_HANDLER_TEMPLATE_MAP *AddressMap
# );
#
# Routine Description:
#
# Return address map of interrupt handler template so that C code can generate
# interrupt table.
#
# Arguments:
#
#
# Returns:
#
# Nothing
#
#
# Input: [ebp][0] = Original ebp
# [ebp][4] = Return address
#
# Output: Nothing
#
# Destroys: Nothing
#-----------------------------------------------------------------------------;
#-------------------------------------------------------------------------------------
# AsmGetAddressMap (&AddressMap);
#-------------------------------------------------------------------------------------
ASM_GLOBAL ASM_PFX(GetTemplateAddressMap)
ASM_PFX(GetTemplateAddressMap):
pushl %ebp
movl %esp,%ebp
pushal
movl 0x8(%ebp), %ebx
movl $Exception0Handle, (%ebx)
movl $(Exception1Handle - Exception0Handle), 0x4(%ebx)
popal
popl %ebp
ret

View File

@ -0,0 +1,471 @@
;------------------------------------------------------------------------------ ;
; Copyright (c) 2012, 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:
;
; ExceptionHandlerAsm.Asm
;
; Abstract:
;
; IA32 CPU Exception Handler
;
; Notes:
;
;------------------------------------------------------------------------------
.686
.model flat,C
;
; CommonExceptionHandler()
;
CommonExceptionHandler PROTO C
.data
CommonEntryAddr DD CommonInterruptEntry
EXTRN mErrorCodeFlag:DWORD ; Error code flags for exceptions
.code
;
; 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]
;----------------------------------------------------------------------------;
; CommonInterruptEntry ;
;----------------------------------------------------------------------------;
; The follow algorithm is used for the common interrupt routine.
; Entry from each interrupt with a push eax and eax=interrupt number
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]
and ecx, 0FFFFh
cmp ecx, 32 ; Intel reserved vector for exceptions?
jae NoErrorCode
bt mErrorCodeFlag, ecx
jc HasErrorCode
NoErrorCode:
;
; Stack:
; +---------------------+
; + EFlags +
; +---------------------+
; + CS +
; +---------------------+
; + EIP +
; +---------------------+
; + ECX +
; +---------------------+ <-- ESP
;
; Registers:
; ECX - Vector Number
;
;
; Put Vector Number on stack
;
push ecx
;
; Put 0 (dummy) error code on stack, and restore ECX
;
xor ecx, ecx ; ECX = 0
xchg ecx, [esp+4]
jmp ErrorCodeAndVectorOnStack
HasErrorCode:
;
; Stack:
; +---------------------+
; + EFlags +
; +---------------------+
; + CS +
; +---------------------+
; + EIP +
; +---------------------+
; + Error Code +
; +---------------------+
; + ECX +
; +---------------------+ <-- ESP
;
; Registers:
; ECX - Vector Number
;
;
; Put Vector Number on stack and restore ECX
;
xchg ecx, [esp]
;
; Fall through to join main routine code
; at ErrorCodeAndVectorOnStack
;
@@:
jmp @B
ErrorCodeAndVectorOnStack:
push ebp
mov ebp, esp
;
; Stack:
; +---------------------+
; + EFlags +
; +---------------------+
; + CS +
; +---------------------+
; + EIP +
; +---------------------+
; + Error Code +
; +---------------------+
; + Vector Number +
; +---------------------+
; + EBP +
; +---------------------+ <-- EBP
;
;
; Align stack to make sure that EFI_FX_SAVE_STATE_IA32 of EFI_SYSTEM_CONTEXT_IA32
; is 16-byte aligned
;
and esp, 0fffffff0h
sub esp, 12
;; UINT32 Edi, Esi, Ebp, Esp, Ebx, Edx, Ecx, Eax;
push eax
push ecx
push edx
push ebx
lea ecx, [ebp + 6 * 4]
push ecx ; ESP
push dword ptr [ebp] ; EBP
push esi
push edi
;; UINT32 Gs, Fs, Es, Ds, Cs, Ss;
mov eax, ss
push eax
movzx eax, word ptr [ebp + 4 * 4]
push eax
mov eax, ds
push eax
mov eax, es
push eax
mov eax, fs
push eax
mov eax, gs
push eax
;; UINT32 Eip;
mov eax, [ebp + 3 * 4]
push eax
;; UINT32 Gdtr[2], Idtr[2];
sub esp, 8
sidt [esp]
mov eax, [esp + 2]
xchg eax, [esp]
and eax, 0FFFFh
mov [esp+4], eax
sub esp, 8
sgdt [esp]
mov eax, [esp + 2]
xchg eax, [esp]
and eax, 0FFFFh
mov [esp+4], eax
;; UINT32 Ldtr, Tr;
xor eax, eax
str ax
push eax
sldt ax
push eax
;; UINT32 EFlags;
mov eax, [ebp + 5 * 4]
push eax
;; UINT32 Cr0, Cr1, Cr2, Cr3, Cr4;
mov eax, cr4
or eax, 208h
mov cr4, eax
push eax
mov eax, cr3
push eax
mov eax, cr2
push eax
xor eax, eax
push eax
mov eax, cr0
push eax
;; UINT32 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;
mov eax, dr7
push eax
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]
;; Prepare parameter and call
mov edx, esp
push edx
mov edx, dword ptr [ebp + 1 * 4]
push edx
;
; Call External Exception Handler
;
mov eax, CommonExceptionHandler
call eax
add esp, 8
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
;---------------------------------------;
; _GetTemplateAddressMap ;
;----------------------------------------------------------------------------;
;
; Protocol prototype
; GetTemplateAddressMap (
; EXCEPTION_HANDLER_TEMPLATE_MAP *AddressMap
; );
;
; Routine Description:
;
; Return address map of interrupt handler template so that C code can generate
; interrupt table.
;
; Arguments:
;
;
; Returns:
;
; Nothing
;
;
; Input: [ebp][0] = Original ebp
; [ebp][4] = Return address
;
; Output: Nothing
;
; Destroys: Nothing
;-----------------------------------------------------------------------------;
GetTemplateAddressMap 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
popad
pop ebp
ret
GetTemplateAddressMap ENDP
END

View File

@ -0,0 +1,63 @@
/** @file
CPU Exception Library provides SEC/PEIM CPU exception handler.
Copyright (c) 2012, 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
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 <PiPei.h>
#include "CpuExceptionCommon.h"
//
// Image Aglinment size for SEC/PEI phase
//
CONST UINTN mImageAlignSize = 4;
/**
Common exception handler.
@param ExceptionType Exception type.
@param SystemContext Pointer to EFI_SYSTEM_CONTEXT.
**/
VOID
EFIAPI
CommonExceptionHandler (
IN EFI_EXCEPTION_TYPE ExceptionType,
IN EFI_SYSTEM_CONTEXT SystemContext
)
{
//
// Display ExceptionType, CPU information and Image information
//
DumpCpuContent (ExceptionType, SystemContext);
//
// Enter a dead loop.
//
CpuDeadLoop ();
}
/**
Setup CPU exception handlers.
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
)
{
InternalSetupCpuExceptionHandlers ();
}

View File

@ -0,0 +1,56 @@
## @file
# Component description file for SEC/PEI CPU Exception Handler Library instance
#
# This library instance supports SEC/PEI module only.
#
# Copyright (c) 2012, 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 = SecPeiCpuExceptionHandlerLib
FILE_GUID = CA4BBC99-DFC6-4234-B553-8B6586B7B113
MODULE_TYPE = PEIM
VERSION_STRING = 1.0
LIBRARY_CLASS = CpuExceptionHandlerLib|SEC PEIM_CORE PEIM
#
# 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
[Sources.X64]
X64/ExceptionHandlerAsm.asm |MSFT
X64/ExceptionHandlerAsm.S |GCC
X64/ArchExceptionHandler.c
[Sources.common]
CpuExceptionCommon.h
CpuExceptionCommon.c
SecPeiCpuException.c
[Packages]
MdePkg/MdePkg.dec
MdeModulePkg/MdeModulePkg.dec
UefiCpuPkg/UefiCpuPkg.dec
[LibraryClasses]
BaseLib
SerialPortLib
PrintLib
LocalApicLib
PeCoffGetEntryPointLib

View File

@ -0,0 +1,192 @@
/** @file
x64 CPU Exception Hanlder.
Copyright (c) 2012, 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 "CpuExceptionCommon.h"
/**
Internal function to setup CPU exception handlers.
**/
VOID
InternalSetupCpuExceptionHandlers (
VOID
)
{
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;
}
}
/**
Common exception handler.
@param ExceptionType Exception type.
@param SystemContext Pointer to EFI_SYSTEM_CONTEXT.
**/
VOID
DumpCpuContent (
IN UINTN ExceptionType,
IN EFI_SYSTEM_CONTEXT SystemContext
)
{
UINTN ImageBase;
UINTN EntryPoint;
InternalPrintMessage (
"!!!! X64 Exception Type - %016lx CPU Apic ID - %08x !!!!\n",
ExceptionType,
GetApicId ()
);
InternalPrintMessage (
"RIP - %016lx, CS - %016lx, RFLAGS - %016lx\n",
SystemContext.SystemContextX64->Rip,
SystemContext.SystemContextX64->Cs,
SystemContext.SystemContextX64->Rflags
);
if (mErrorCodeFlag & (1 << ExceptionType)) {
InternalPrintMessage (
"ExceptionData - %016lx\n",
SystemContext.SystemContextX64->ExceptionData
);
}
InternalPrintMessage (
"RAX - %016lx, RCX - %016lx, RDX - %016lx\n",
SystemContext.SystemContextX64->Rax,
SystemContext.SystemContextX64->Rcx,
SystemContext.SystemContextX64->Rdx
);
InternalPrintMessage (
"RBX - %016lx, RSP - %016lx, RBP - %016lx\n",
SystemContext.SystemContextX64->Rbx,
SystemContext.SystemContextX64->Rsp,
SystemContext.SystemContextX64->Rbp
);
InternalPrintMessage (
"RSI - %016lx, RDI - %016lx\n",
SystemContext.SystemContextX64->Rsi,
SystemContext.SystemContextX64->Rdi
);
InternalPrintMessage (
"R8 - %016lx, R9 - %016lx, R10 - %016lx\n",
SystemContext.SystemContextX64->R8,
SystemContext.SystemContextX64->R9,
SystemContext.SystemContextX64->R10
);
InternalPrintMessage (
"R11 - %016lx, R12 - %016lx, R13 - %016lx\n",
SystemContext.SystemContextX64->R11,
SystemContext.SystemContextX64->R12,
SystemContext.SystemContextX64->R13
);
InternalPrintMessage (
"R14 - %016lx, R15 - %016lx\n",
SystemContext.SystemContextX64->R14,
SystemContext.SystemContextX64->R15
);
InternalPrintMessage (
"DS - %016lx, ES - %016lx, FS - %016lx\n",
SystemContext.SystemContextX64->Ds,
SystemContext.SystemContextX64->Es,
SystemContext.SystemContextX64->Fs
);
InternalPrintMessage (
"GS - %016lx, SS - %016lx\n",
SystemContext.SystemContextX64->Gs,
SystemContext.SystemContextX64->Ss
);
InternalPrintMessage (
"CR0 - %016lx, CR2 - %016lx, CR3 - %016lx\n",
SystemContext.SystemContextX64->Cr0,
SystemContext.SystemContextX64->Cr2,
SystemContext.SystemContextX64->Cr3
);
InternalPrintMessage (
"CR4 - %016lx, CR8 - %016lx\n",
SystemContext.SystemContextX64->Cr4,
SystemContext.SystemContextX64->Cr8
);
InternalPrintMessage (
"DR0 - %016lx, DR1 - %016lx, DR2 - %016lx\n",
SystemContext.SystemContextX64->Dr0,
SystemContext.SystemContextX64->Dr1,
SystemContext.SystemContextX64->Dr2
);
InternalPrintMessage (
"DR3 - %016lx, DR6 - %016lx, DR7 - %016lx\n",
SystemContext.SystemContextX64->Dr3,
SystemContext.SystemContextX64->Dr6,
SystemContext.SystemContextX64->Dr7
);
InternalPrintMessage (
"GDTR - %016lx %016lx, LDTR - %016lx\n",
SystemContext.SystemContextX64->Gdtr[0],
SystemContext.SystemContextX64->Gdtr[1],
SystemContext.SystemContextX64->Ldtr
);
InternalPrintMessage (
"IDTR - %016lx %016lx, TR - %016lx\n",
SystemContext.SystemContextX64->Idtr[0],
SystemContext.SystemContextX64->Idtr[1],
SystemContext.SystemContextX64->Tr
);
InternalPrintMessage (
"FXSAVE_STATE - %016lx\n",
&SystemContext.SystemContextX64->FxSaveState
);
//
// Find module image base and module entry point by RIP
//
ImageBase = FindModuleImageBase (SystemContext.SystemContextX64->Rip, &EntryPoint);
if (ImageBase != 0) {
InternalPrintMessage (
" (ImageBase=%016lx, EntryPoint=%016lx) !!!!\n",
ImageBase,
EntryPoint
);
}
}

View File

@ -0,0 +1,406 @@
#------------------------------------------------------------------------------ ;
# Copyright (c) 2012, 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:
#
# ExceptionHandlerAsm.S
#
# Abstract:
#
# x64 CPU Exception Handler
#
# Notes:
#
#------------------------------------------------------------------------------
#EXTRN ASM_PFX(mErrorCodeFlag):DWORD # Error code flags for exceptions
ASM_GLOBAL ASM_PFX(CommonExceptionHandler)
ASM_GLOBAL ASM_PFX(CommonInterruptEntry)
.text
#
# point to the external interrupt vector table
#
Exception0Handle:
pushq $0
jmp ASM_PFX(CommonInterruptEntry)
Exception1Handle:
pushq $1
jmp ASM_PFX(CommonInterruptEntry)
Exception2Handle:
pushq $2
jmp ASM_PFX(CommonInterruptEntry)
Exception3Handle:
pushq $3
jmp ASM_PFX(CommonInterruptEntry)
Exception4Handle:
pushq $4
jmp ASM_PFX(CommonInterruptEntry)
Exception5Handle:
pushq $5
jmp ASM_PFX(CommonInterruptEntry)
Exception6Handle:
pushq $6
jmp ASM_PFX(CommonInterruptEntry)
Exception7Handle:
pushq $7
jmp ASM_PFX(CommonInterruptEntry)
Exception8Handle:
pushq $8
jmp ASM_PFX(CommonInterruptEntry)
Exception9Handle:
pushq $9
jmp ASM_PFX(CommonInterruptEntry)
Exception10Handle:
pushq $10
jmp ASM_PFX(CommonInterruptEntry)
Exception11Handle:
pushq $11
jmp ASM_PFX(CommonInterruptEntry)
Exception12Handle:
pushq $12
jmp ASM_PFX(CommonInterruptEntry)
Exception13Handle:
pushq $13
jmp ASM_PFX(CommonInterruptEntry)
Exception14Handle:
pushq $14
jmp ASM_PFX(CommonInterruptEntry)
Exception15Handle:
pushq $15
jmp ASM_PFX(CommonInterruptEntry)
Exception16Handle:
pushq $16
jmp ASM_PFX(CommonInterruptEntry)
Exception17Handle:
pushq $17
jmp ASM_PFX(CommonInterruptEntry)
Exception18Handle:
pushq $18
jmp ASM_PFX(CommonInterruptEntry)
Exception19Handle:
pushq $19
jmp ASM_PFX(CommonInterruptEntry)
Exception20Handle:
pushq $20
jmp ASM_PFX(CommonInterruptEntry)
Exception21Handle:
pushq $21
jmp ASM_PFX(CommonInterruptEntry)
Exception22Handle:
pushq $22
jmp ASM_PFX(CommonInterruptEntry)
Exception23Handle:
pushq $23
jmp ASM_PFX(CommonInterruptEntry)
Exception24Handle:
pushq $24
jmp ASM_PFX(CommonInterruptEntry)
Exception25Handle:
pushq $25
jmp ASM_PFX(CommonInterruptEntry)
Exception26Handle:
pushq $26
jmp ASM_PFX(CommonInterruptEntry)
Exception27Handle:
pushq $27
jmp ASM_PFX(CommonInterruptEntry)
Exception28Handle:
pushq $28
jmp ASM_PFX(CommonInterruptEntry)
Exception29Handle:
pushq $29
jmp ASM_PFX(CommonInterruptEntry)
Exception30Handle:
pushq $30
jmp ASM_PFX(CommonInterruptEntry)
Exception31Handle:
pushq $31
jmp ASM_PFX(CommonInterruptEntry)
#---------------------------------------;
# 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.
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)
#; Prepare parameter and call
mov 8(%rbp), %rcx
mov %rsp, %rdx
#
# Per X64 calling convention, allocate maximum parameter stack space
# and make sure RSP is 16-byte aligned
#
subq $40, %rsp
call ASM_PFX(CommonExceptionHandler)
addq $40, %rsp
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
#-------------------------------------------------------------------------------------
# AsmGetAddressMap (&AddressMap);
#-------------------------------------------------------------------------------------
# comments here for definition of address map
ASM_GLOBAL ASM_PFX(GetTemplateAddressMap)
ASM_PFX(GetTemplateAddressMap):
movabsq $Exception0Handle, %rax
movq %rax, (%rcx)
movq $(Exception1Handle - Exception0Handle), 0x08(%rcx)
ret
#END

View File

@ -0,0 +1,407 @@
;------------------------------------------------------------------------------ ;
; Copyright (c) 2012, 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:
;
; ExceptionHandlerAsm.Asm
;
; Abstract:
;
; x64 CPU Exception Handler
;
; Notes:
;
;------------------------------------------------------------------------------
;
; CommonExceptionHandler()
;
CommonExceptionHandler PROTO C
EXTRN mErrorCodeFlag:DWORD ; Error code flags for exceptions
data SEGMENT
CommonEntryAddr dq CommonInterruptEntry;
.code
Exception0Handle:
push 0
jmp qword ptr [CommonEntryAddr]
Exception1Handle:
push 1
jmp qword ptr [CommonEntryAddr]
Exception2Handle:
push 2
jmp qword ptr [CommonEntryAddr]
Exception3Handle:
push 3
jmp qword ptr [CommonEntryAddr]
Exception4Handle:
push 4
jmp qword ptr [CommonEntryAddr]
Exception5Handle:
push 5
jmp qword ptr [CommonEntryAddr]
Exception6Handle:
push 6
jmp qword ptr [CommonEntryAddr]
Exception7Handle:
push 7
jmp qword ptr [CommonEntryAddr]
Exception8Handle:
push 8
jmp qword ptr [CommonEntryAddr]
Exception9Handle:
push 9
jmp qword ptr [CommonEntryAddr]
Exception10Handle:
push 10
jmp qword ptr [CommonEntryAddr]
Exception11Handle:
push 11
jmp qword ptr [CommonEntryAddr]
Exception12Handle:
push 12
jmp qword ptr [CommonEntryAddr]
Exception13Handle:
push 13
jmp qword ptr [CommonEntryAddr]
Exception14Handle:
push 14
jmp qword ptr [CommonEntryAddr]
Exception15Handle:
push 15
jmp qword ptr [CommonEntryAddr]
Exception16Handle:
push 16
jmp qword ptr [CommonEntryAddr]
Exception17Handle:
push 17
jmp qword ptr [CommonEntryAddr]
Exception18Handle:
push 18
jmp qword ptr [CommonEntryAddr]
Exception19Handle:
push 19
jmp qword ptr [CommonEntryAddr]
Exception20Handle:
push 20
jmp qword ptr [CommonEntryAddr]
Exception21Handle:
push 21
jmp qword ptr [CommonEntryAddr]
Exception22Handle:
push 22
jmp qword ptr [CommonEntryAddr]
Exception23Handle:
push 23
jmp qword ptr [CommonEntryAddr]
Exception24Handle:
push 24
jmp qword ptr [CommonEntryAddr]
Exception25Handle:
push 25
jmp qword ptr [CommonEntryAddr]
Exception26Handle:
push 26
jmp qword ptr [CommonEntryAddr]
Exception27Handle:
push 27
jmp qword ptr [CommonEntryAddr]
Exception28Handle:
push 28
jmp qword ptr [CommonEntryAddr]
Exception29Handle:
push 29
jmp qword ptr [CommonEntryAddr]
Exception30Handle:
push 30
jmp qword ptr [CommonEntryAddr]
Exception31Handle:
push 31
jmp qword ptr [CommonEntryAddr]
;CommonInterruptEntrypoint:
;---------------------------------------;
; _CommonEntry ;
;----------------------------------------------------------------------------;
; The follow algorithm is used for the common interrupt routine.
; Entry from each interrupt with a push eax and eax=interrupt number
;---------------------------------------;
; 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.
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]
;; 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
mov rax, CommonExceptionHandler
call rax
add rsp, 4 * 8 + 8
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
;-------------------------------------------------------------------------------------
; 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
END

View File

@ -1,7 +1,7 @@
## @file
# UefiCpuPkg Package
#
# Copyright (c) 2007 - 2011, Intel Corporation. All rights reserved.<BR>
# Copyright (c) 2007 - 2012, 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
@ -85,5 +85,7 @@
UefiCpuPkg/Library/MtrrLib/MtrrLib.inf
UefiCpuPkg/Library/BaseXApicX2ApicLib/BaseXApicX2ApicLib.inf
UefiCpuPkg/Library/BaseXApicLib/BaseXApicLib.inf
UefiCpuPkg/Library/CpuExceptionHandlerLib/SecPeiCpuExceptionHandlerLib.inf
UefiCpuPkg/Library/CpuExceptionHandlerLib/DxeSmmCpuExceptionHandlerLib.inf
UefiCpuPkg/Universal/Acpi/S3Resume2Pei/S3Resume2Pei.inf