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

View File

@@ -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
)
{

View File

@@ -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

View File

@@ -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

View File

@@ -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