summaryrefslogtreecommitdiff
path: root/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ArchExceptionHandler.c
diff options
context:
space:
mode:
Diffstat (limited to 'UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ArchExceptionHandler.c')
-rw-r--r--UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ArchExceptionHandler.c115
1 files changed, 78 insertions, 37 deletions
diff --git a/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ArchExceptionHandler.c b/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ArchExceptionHandler.c
index 664472a66..1af2999ac 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
)
{