summaryrefslogtreecommitdiff
path: root/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64
diff options
context:
space:
mode:
Diffstat (limited to 'UefiCpuPkg/Library/CpuExceptionHandlerLib/X64')
-rw-r--r--UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ArchExceptionHandler.c115
-rw-r--r--UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ArchInterruptDefs.h46
-rw-r--r--UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ExceptionHandlerAsm.S333
-rw-r--r--UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ExceptionHandlerAsm.asm216
4 files changed, 483 insertions, 227 deletions
diff --git a/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ArchExceptionHandler.c b/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ArchExceptionHandler.c
index 664472a667..1af2999ac0 100644
--- a/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ArchExceptionHandler.c
+++ b/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ArchExceptionHandler.c
@@ -1,7 +1,7 @@
/** @file
x64 CPU Exception Hanlder.
- Copyright (c) 2012, Intel Corporation. All rights reserved.<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;
+ IdtEntry->Bits.OffsetLow = (UINT16)(UINTN)InterruptHandler;
+ IdtEntry->Bits.OffsetHigh = (UINT16)((UINTN)InterruptHandler >> 16);
+ IdtEntry->Bits.OffsetUpper = (UINT32)((UINTN)InterruptHandler >> 32);
+ IdtEntry->Bits.GateType = IA32_IDT_GATE_TYPE_INTERRUPT_32;
+}
+
+/**
+ Read IDT handler value from IDT entry.
+
+ @param IdtEntry Pointer to IDT entry to be read.
+
+**/
+UINTN
+ArchGetIdtHandler (
+ IN IA32_IDT_GATE_DESCRIPTOR *IdtEntry
+ )
+{
+ return IdtEntry->Bits.OffsetLow + (((UINTN) IdtEntry->Bits.OffsetHigh) << 16) +
+ (((UINTN) IdtEntry->Bits.OffsetUpper) << 32);
+}
+/**
+ Save CPU exception context when handling EFI_VECTOR_HANDOFF_HOOK_AFTER case.
+
+ @param ExceptionType Exception type.
+ @param SystemContext Pointer to EFI_SYSTEM_CONTEXT.
+**/
+VOID
+ArchSaveExceptionContext (
+ IN UINTN ExceptionType,
+ IN EFI_SYSTEM_CONTEXT SystemContext
+ )
+{
+ IA32_EFLAGS32 Eflags;
//
- // Read IDT descriptor and calculate IDT size
+ // Save Exception context in global variable
//
- AsmReadIdtr (&IdtDescriptor);
- IdtSize = (IdtDescriptor.Limit + 1) / sizeof (IA32_IDT_GATE_DESCRIPTOR);
- if (IdtSize > CPU_EXCEPTION_NUM) {
- //
- // CPU exeption library only setup CPU_EXCEPTION_NUM exception handler at most
- //
- IdtSize = CPU_EXCEPTION_NUM;
- }
-
+ mReservedVectors[ExceptionType].OldSs = SystemContext.SystemContextX64->Ss;
+ mReservedVectors[ExceptionType].OldSp = SystemContext.SystemContextX64->Rsp;
+ mReservedVectors[ExceptionType].OldFlags = SystemContext.SystemContextX64->Rflags;
+ mReservedVectors[ExceptionType].OldCs = SystemContext.SystemContextX64->Cs;
+ mReservedVectors[ExceptionType].OldIp = SystemContext.SystemContextX64->Rip;
+ mReservedVectors[ExceptionType].ExceptionData = SystemContext.SystemContextX64->ExceptionData;
//
- // Use current CS as the segment selector of interrupt gate in IDT
+ // Clear IF flag to avoid old IDT handler enable interrupt by IRET
//
- CodeSegment = AsmReadCs ();
- IdtEntry = (IA32_IDT_GATE_DESCRIPTOR *) IdtDescriptor.Base;
-
- GetTemplateAddressMap (&TemplateMap);
-
- for (Index = 0; Index < IdtSize; Index ++) {
- InterruptHandler = TemplateMap.ExceptionStart + Index * TemplateMap.ExceptionStubHeaderSize;
- IdtEntry[Index].Bits.OffsetLow = (UINT16)(UINTN)InterruptHandler;
- IdtEntry[Index].Bits.OffsetHigh = (UINT16)((UINTN)InterruptHandler >> 16);
- IdtEntry[Index].Bits.OffsetUpper = (UINT32)((UINTN)InterruptHandler >> 32);
- IdtEntry[Index].Bits.Selector = CodeSegment;
- IdtEntry[Index].Bits.GateType = IA32_IDT_GATE_TYPE_INTERRUPT_32;
- }
+ Eflags.UintN = SystemContext.SystemContextX64->Rflags;
+ Eflags.Bits.IF = 0;
+ SystemContext.SystemContextX64->Rflags = Eflags.UintN;
+ //
+ // Modify the EIP in stack, then old IDT handler will return to the stub code
+ //
+ SystemContext.SystemContextX64->Rip = (UINTN) mReservedVectors[ExceptionType].HookAfterStubHeaderCode;
}
/**
- Common exception handler.
+ Restore CPU exception context when handling EFI_VECTOR_HANDOFF_HOOK_AFTER case.
@param ExceptionType Exception type.
@param SystemContext Pointer to EFI_SYSTEM_CONTEXT.
**/
VOID
-DumpCpuContent (
+ArchRestoreExceptionContext (
IN UINTN ExceptionType,
+ IN EFI_SYSTEM_CONTEXT SystemContext
+ )
+{
+ SystemContext.SystemContextX64->Ss = mReservedVectors[ExceptionType].OldSs;
+ SystemContext.SystemContextX64->Rsp = mReservedVectors[ExceptionType].OldSp;
+ SystemContext.SystemContextX64->Rflags = mReservedVectors[ExceptionType].OldFlags;
+ SystemContext.SystemContextX64->Cs = mReservedVectors[ExceptionType].OldCs;
+ SystemContext.SystemContextX64->Rip = mReservedVectors[ExceptionType].OldIp;
+ SystemContext.SystemContextX64->ExceptionData = mReservedVectors[ExceptionType].ExceptionData;
+}
+
+/**
+ Dump CPU content information.
+
+ @param ExceptionType Exception type.
+ @param SystemContext Pointer to EFI_SYSTEM_CONTEXT.
+**/
+VOID
+DumpCpuContent (
+ IN EFI_EXCEPTION_TYPE ExceptionType,
IN EFI_SYSTEM_CONTEXT SystemContext
)
{
diff --git a/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ArchInterruptDefs.h b/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ArchInterruptDefs.h
new file mode 100644
index 0000000000..906480134a
--- /dev/null
+++ b/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ArchInterruptDefs.h
@@ -0,0 +1,46 @@
+/** @file
+ X64 arch definition for CPU Exception Handler Library.
+
+ Copyright (c) 2013, Intel Corporation. All rights reserved.<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
diff --git a/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ExceptionHandlerAsm.S b/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ExceptionHandlerAsm.S
index cd101475a7..7d5672f892 100644
--- a/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ExceptionHandlerAsm.S
+++ b/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ExceptionHandlerAsm.S
@@ -1,5 +1,5 @@
#------------------------------------------------------------------------------ ;
-# Copyright (c) 2012, Intel Corporation. All rights reserved.<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
diff --git a/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ExceptionHandlerAsm.asm b/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ExceptionHandlerAsm.asm
index 2cc78db374..f348efe4be 100644
--- a/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ExceptionHandlerAsm.asm
+++ b/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ExceptionHandlerAsm.asm
@@ -25,133 +25,79 @@
;
externdef CommonExceptionHandler:near
-EXTRN mErrorCodeFlag:DWORD ; Error code flags for exceptions
+EXTRN mErrorCodeFlag:DWORD ; Error code flags for exceptions
+EXTRN mDoFarReturnFlag:QWORD ; Do far return flag
data SEGMENT
-CommonEntryAddr dq CommonInterruptEntry;
-
.code
-Exception0Handle:
- push 0
- jmp qword ptr [CommonEntryAddr]
-Exception1Handle:
- push 1
- jmp qword ptr [CommonEntryAddr]
-Exception2Handle:
- push 2
- jmp qword ptr [CommonEntryAddr]
-Exception3Handle:
- push 3
- jmp qword ptr [CommonEntryAddr]
-Exception4Handle:
- push 4
- jmp qword ptr [CommonEntryAddr]
-Exception5Handle:
- push 5
- jmp qword ptr [CommonEntryAddr]
-Exception6Handle:
- push 6
- jmp qword ptr [CommonEntryAddr]
-Exception7Handle:
- push 7
- jmp qword ptr [CommonEntryAddr]
-Exception8Handle:
- push 8
- jmp qword ptr [CommonEntryAddr]
-Exception9Handle:
- push 9
- jmp qword ptr [CommonEntryAddr]
-Exception10Handle:
- push 10
- jmp qword ptr [CommonEntryAddr]
-Exception11Handle:
- push 11
- jmp qword ptr [CommonEntryAddr]
-Exception12Handle:
- push 12
- jmp qword ptr [CommonEntryAddr]
-Exception13Handle:
- push 13
- jmp qword ptr [CommonEntryAddr]
-Exception14Handle:
- push 14
- jmp qword ptr [CommonEntryAddr]
-Exception15Handle:
- push 15
- jmp qword ptr [CommonEntryAddr]
-Exception16Handle:
- push 16
- jmp qword ptr [CommonEntryAddr]
-Exception17Handle:
- push 17
- jmp qword ptr [CommonEntryAddr]
-Exception18Handle:
- push 18
- jmp qword ptr [CommonEntryAddr]
-Exception19Handle:
- push 19
- jmp qword ptr [CommonEntryAddr]
-Exception20Handle:
- push 20
- jmp qword ptr [CommonEntryAddr]
-Exception21Handle:
- push 21
- jmp qword ptr [CommonEntryAddr]
-Exception22Handle:
- push 22
- jmp qword ptr [CommonEntryAddr]
-Exception23Handle:
- push 23
- jmp qword ptr [CommonEntryAddr]
-Exception24Handle:
- push 24
- jmp qword ptr [CommonEntryAddr]
-Exception25Handle:
- push 25
- jmp qword ptr [CommonEntryAddr]
-Exception26Handle:
- push 26
- jmp qword ptr [CommonEntryAddr]
-Exception27Handle:
- push 27
- jmp qword ptr [CommonEntryAddr]
-Exception28Handle:
- push 28
- jmp qword ptr [CommonEntryAddr]
-Exception29Handle:
- push 29
- jmp qword ptr [CommonEntryAddr]
-Exception30Handle:
- push 30
- jmp qword ptr [CommonEntryAddr]
-Exception31Handle:
- push 31
- jmp qword ptr [CommonEntryAddr]
-
-;CommonInterruptEntrypoint:
-;---------------------------------------;
-; _CommonEntry ;
-;----------------------------------------------------------------------------;
-; The follow algorithm is used for the common interrupt routine.
-; Entry from each interrupt with a push eax and eax=interrupt number
+ALIGN 8
+
+AsmIdtVectorBegin:
+REPEAT 32
+ db 6ah ; push #VectorNum
+ db ($ - AsmIdtVectorBegin) / ((AsmIdtVectorEnd - AsmIdtVectorBegin) / 32) ; VectorNum
+ push rax
+ mov rax, CommonInterruptEntry
+ jmp rax
+ENDM
+AsmIdtVectorEnd:
+
+HookAfterStubHeaderBegin:
+ db 6ah ; push
+@VectorNum:
+ db 0 ; 0 will be fixed
+ push rax
+ mov rax, HookAfterStubHeaderEnd
+ jmp rax
+HookAfterStubHeaderEnd:
+ mov rax, rsp
+ sub rsp, 8h
+ and sp, 0fff0h
+ push rcx
+ mov rcx, [rax + 8]
+ bt mErrorCodeFlag, ecx
+ jc @F
+ push [rsp] ; push additional rcx to make stack alignment
+@@:
+ xchg rcx, [rsp] ; restore rcx, save Exception Number in stack
+ push [rax] ; push rax into stack to keep code consistence
;---------------------------------------;
; CommonInterruptEntry ;
;---------------------------------------;
; The follow algorithm is used for the common interrupt routine.
-
+; Entry from each interrupt with a push eax and eax=interrupt number
+; Stack frame would be as follows as specified in IA32 manuals:
+;
+; +---------------------+ <-- 16-byte aligned ensured by processor
+; + Old SS +
+; +---------------------+
+; + Old RSP +
+; +---------------------+
+; + RFlags +
+; +---------------------+
+; + CS +
+; +---------------------+
+; + RIP +
+; +---------------------+
+; + Error Code +
+; +---------------------+
+; + Vector Number +
+; +---------------------+
+; + RBP +
+; +---------------------+ <-- RBP, 16-byte aligned
+; The follow algorithm is used for the common interrupt routine.
CommonInterruptEntry PROC PUBLIC
cli
+ pop rax
;
; All interrupt handlers are invoked through interrupt gates, so
; IF flag automatically cleared at the entry point
;
- ;
- ; Calculate vector number
- ;
- xchg rcx, [rsp] ; get the return address of call, actually, it is the address of vector number.
+ xchg rcx, [rsp] ; Save rcx into stack and save vector number into rcx
+ and rcx, 0FFh
cmp ecx, 32 ; Intel reserved vector for exceptions?
jae NoErrorCode
bt mErrorCodeFlag, ecx
@@ -168,6 +114,8 @@ NoErrorCode:
@@:
push rbp
mov rbp, rsp
+ push 0 ; clear EXCEPTION_HANDLER_CONTEXT.OldIdtHandler
+ push 0 ; clear EXCEPTION_HANDLER_CONTEXT.ExceptionDataFlag
;
; Stack:
@@ -389,6 +337,29 @@ NoErrorCode:
mov rsp, rbp
pop rbp
add rsp, 16
+ cmp qword ptr [rsp - 32], 0 ; check EXCEPTION_HANDLER_CONTEXT.OldIdtHandler
+ jz DoReturn
+ cmp qword ptr [rsp - 40], 1 ; check EXCEPTION_HANDLER_CONTEXT.ExceptionDataFlag
+ jz ErrorCode
+ jmp qword ptr [rsp - 32]
+ErrorCode:
+ sub rsp, 8
+ jmp qword ptr [rsp - 24]
+
+DoReturn:
+ cmp mDoFarReturnFlag, 0 ; Check if need to do far return instead of IRET
+ jz DoIret
+ push rax
+ mov rax, rsp ; save old RSP to rax
+ mov rsp, [rsp + 20h]
+ push [rax + 10h] ; save CS in new location
+ push [rax + 8h] ; save EIP in new location
+ push [rax + 18h] ; save EFLAGS in new location
+ mov rax, [rax] ; restore rax
+ popfq ; restore EFLAGS
+ DB 48h ; prefix to composite "retq" with next "retf"
+ retf ; far return
+DoIret:
iretq
CommonInterruptEntry ENDP
@@ -397,11 +368,22 @@ CommonInterruptEntry ENDP
; GetTemplateAddressMap (&AddressMap);
;-------------------------------------------------------------------------------------
; comments here for definition of address map
-GetTemplateAddressMap PROC
- mov rax, offset Exception0Handle
- mov qword ptr [rcx], rax
- mov qword ptr [rcx+8h], Exception1Handle - Exception0Handle
- ret
-GetTemplateAddressMap ENDP
+AsmGetTemplateAddressMap PROC
+ mov rax, offset AsmIdtVectorBegin
+ mov qword ptr [rcx], rax
+ mov qword ptr [rcx + 8h], (AsmIdtVectorEnd - AsmIdtVectorBegin) / 32
+ mov rax, offset HookAfterStubHeaderBegin
+ mov qword ptr [rcx + 10h], rax
+ ret
+AsmGetTemplateAddressMap ENDP
+
+;-------------------------------------------------------------------------------------
+; AsmVectorNumFixup (*VectorBase, VectorNum);
+;-------------------------------------------------------------------------------------
+AsmVectorNumFixup PROC
+ mov rax, rdx
+ mov [rcx + (@VectorNum - HookAfterStubHeaderBegin)], al
+ ret
+AsmVectorNumFixup ENDP
END