123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437 |
- /** @file
- IA32 CPU Exception Handler functons.
- Copyright (c) 2012 - 2019, Intel Corporation. All rights reserved.<BR>
- SPDX-License-Identifier: BSD-2-Clause-Patent
- **/
- #include "CpuExceptionCommon.h"
- /**
- 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
- ArchUpdateIdtEntry (
- OUT IA32_IDT_GATE_DESCRIPTOR *IdtEntry,
- IN UINTN InterruptHandler
- )
- {
- IdtEntry->Bits.OffsetLow = (UINT16)(UINTN)InterruptHandler;
- IdtEntry->Bits.OffsetHigh = (UINT16)((UINTN)InterruptHandler >> 16);
- IdtEntry->Bits.GateType = IA32_IDT_GATE_TYPE_INTERRUPT_32;
- }
- /**
- Read IDT handler value from IDT entry.
- @param IdtEntry Pointer to IDT entry to be read.
- **/
- UINTN
- ArchGetIdtHandler (
- IN IA32_IDT_GATE_DESCRIPTOR *IdtEntry
- )
- {
- return (UINTN)IdtEntry->Bits.OffsetLow + (((UINTN)IdtEntry->Bits.OffsetHigh) << 16);
- }
- /**
- Save CPU exception context when handling EFI_VECTOR_HANDOFF_HOOK_AFTER case.
- @param[in] ExceptionType Exception type.
- @param[in] SystemContext Pointer to EFI_SYSTEM_CONTEXT.
- @param[in] ExceptionHandlerData Pointer to exception handler data.
- **/
- VOID
- ArchSaveExceptionContext (
- IN UINTN ExceptionType,
- IN EFI_SYSTEM_CONTEXT SystemContext,
- IN EXCEPTION_HANDLER_DATA *ExceptionHandlerData
- )
- {
- IA32_EFLAGS32 Eflags;
- RESERVED_VECTORS_DATA *ReservedVectors;
- ReservedVectors = ExceptionHandlerData->ReservedVectors;
- //
- // Save Exception context in global variable in first entry of the exception handler.
- // So when original exception handler returns to the new exception handler (second entry),
- // the Eflags/Cs/Eip/ExceptionData can be used.
- //
- ReservedVectors[ExceptionType].OldFlags = SystemContext.SystemContextIa32->Eflags;
- ReservedVectors[ExceptionType].OldCs = SystemContext.SystemContextIa32->Cs;
- ReservedVectors[ExceptionType].OldIp = SystemContext.SystemContextIa32->Eip;
- ReservedVectors[ExceptionType].ExceptionData = SystemContext.SystemContextIa32->ExceptionData;
- //
- // Clear IF flag to avoid old IDT handler enable interrupt by IRET
- //
- Eflags.UintN = SystemContext.SystemContextIa32->Eflags;
- Eflags.Bits.IF = 0;
- SystemContext.SystemContextIa32->Eflags = Eflags.UintN;
- //
- // Modify the EIP in stack, then old IDT handler will return to HookAfterStubBegin.
- //
- SystemContext.SystemContextIa32->Eip = (UINTN)ReservedVectors[ExceptionType].HookAfterStubHeaderCode;
- }
- /**
- Restore CPU exception context when handling EFI_VECTOR_HANDOFF_HOOK_AFTER case.
- @param[in] ExceptionType Exception type.
- @param[in] SystemContext Pointer to EFI_SYSTEM_CONTEXT.
- @param[in] ExceptionHandlerData Pointer to exception handler data.
- **/
- VOID
- ArchRestoreExceptionContext (
- IN UINTN ExceptionType,
- IN EFI_SYSTEM_CONTEXT SystemContext,
- IN EXCEPTION_HANDLER_DATA *ExceptionHandlerData
- )
- {
- RESERVED_VECTORS_DATA *ReservedVectors;
- ReservedVectors = ExceptionHandlerData->ReservedVectors;
- SystemContext.SystemContextIa32->Eflags = ReservedVectors[ExceptionType].OldFlags;
- SystemContext.SystemContextIa32->Cs = ReservedVectors[ExceptionType].OldCs;
- SystemContext.SystemContextIa32->Eip = ReservedVectors[ExceptionType].OldIp;
- SystemContext.SystemContextIa32->ExceptionData = ReservedVectors[ExceptionType].ExceptionData;
- }
- /**
- Setup separate stack for given exceptions.
- @param[in] StackSwitchData Pointer to data required for setuping up
- stack switch.
- @retval EFI_SUCCESS The exceptions have been successfully
- initialized with new stack.
- @retval EFI_INVALID_PARAMETER StackSwitchData contains invalid content.
- **/
- EFI_STATUS
- ArchSetupExceptionStack (
- IN CPU_EXCEPTION_INIT_DATA *StackSwitchData
- )
- {
- IA32_DESCRIPTOR Gdtr;
- IA32_DESCRIPTOR Idtr;
- IA32_IDT_GATE_DESCRIPTOR *IdtTable;
- IA32_TSS_DESCRIPTOR *TssDesc;
- IA32_TASK_STATE_SEGMENT *Tss;
- UINTN StackTop;
- UINTN Index;
- UINTN Vector;
- UINTN TssBase;
- UINTN GdtSize;
- EXCEPTION_HANDLER_TEMPLATE_MAP TemplateMap;
- if ((StackSwitchData == NULL) ||
- (StackSwitchData->Ia32.Revision != CPU_EXCEPTION_INIT_DATA_REV) ||
- (StackSwitchData->Ia32.KnownGoodStackTop == 0) ||
- (StackSwitchData->Ia32.KnownGoodStackSize == 0) ||
- (StackSwitchData->Ia32.StackSwitchExceptions == NULL) ||
- (StackSwitchData->Ia32.StackSwitchExceptionNumber == 0) ||
- (StackSwitchData->Ia32.StackSwitchExceptionNumber > CPU_EXCEPTION_NUM) ||
- (StackSwitchData->Ia32.GdtTable == NULL) ||
- (StackSwitchData->Ia32.IdtTable == NULL) ||
- (StackSwitchData->Ia32.ExceptionTssDesc == NULL) ||
- (StackSwitchData->Ia32.ExceptionTss == NULL))
- {
- return EFI_INVALID_PARAMETER;
- }
- //
- // The caller is responsible for that the GDT table, no matter the existing
- // one or newly allocated, has enough space to hold descriptors for exception
- // task-state segments.
- //
- if (((UINTN)StackSwitchData->Ia32.GdtTable & (IA32_GDT_ALIGNMENT - 1)) != 0) {
- return EFI_INVALID_PARAMETER;
- }
- if ((UINTN)StackSwitchData->Ia32.ExceptionTssDesc < (UINTN)(StackSwitchData->Ia32.GdtTable)) {
- return EFI_INVALID_PARAMETER;
- }
- if ((UINTN)StackSwitchData->Ia32.ExceptionTssDesc + StackSwitchData->Ia32.ExceptionTssDescSize >
- ((UINTN)(StackSwitchData->Ia32.GdtTable) + StackSwitchData->Ia32.GdtTableSize))
- {
- return EFI_INVALID_PARAMETER;
- }
- //
- // We need one descriptor and one TSS for current task and every exception
- // specified.
- //
- if (StackSwitchData->Ia32.ExceptionTssDescSize <
- sizeof (IA32_TSS_DESCRIPTOR) * (StackSwitchData->Ia32.StackSwitchExceptionNumber + 1))
- {
- return EFI_INVALID_PARAMETER;
- }
- if (StackSwitchData->Ia32.ExceptionTssSize <
- sizeof (IA32_TASK_STATE_SEGMENT) * (StackSwitchData->Ia32.StackSwitchExceptionNumber + 1))
- {
- return EFI_INVALID_PARAMETER;
- }
- TssDesc = StackSwitchData->Ia32.ExceptionTssDesc;
- Tss = StackSwitchData->Ia32.ExceptionTss;
- //
- // Initialize new GDT table and/or IDT table, if any
- //
- AsmReadIdtr (&Idtr);
- AsmReadGdtr (&Gdtr);
- GdtSize = (UINTN)TssDesc +
- sizeof (IA32_TSS_DESCRIPTOR) *
- (StackSwitchData->Ia32.StackSwitchExceptionNumber + 1) -
- (UINTN)(StackSwitchData->Ia32.GdtTable);
- if ((UINTN)StackSwitchData->Ia32.GdtTable != Gdtr.Base) {
- CopyMem (StackSwitchData->Ia32.GdtTable, (VOID *)Gdtr.Base, Gdtr.Limit + 1);
- Gdtr.Base = (UINTN)StackSwitchData->Ia32.GdtTable;
- Gdtr.Limit = (UINT16)GdtSize - 1;
- }
- if ((UINTN)StackSwitchData->Ia32.IdtTable != Idtr.Base) {
- Idtr.Base = (UINTN)StackSwitchData->Ia32.IdtTable;
- }
- if (StackSwitchData->Ia32.IdtTableSize > 0) {
- Idtr.Limit = (UINT16)(StackSwitchData->Ia32.IdtTableSize - 1);
- }
- //
- // Fixup current task descriptor. Task-state segment for current task will
- // be filled by processor during task switching.
- //
- TssBase = (UINTN)Tss;
- TssDesc->Uint64 = 0;
- TssDesc->Bits.LimitLow = sizeof (IA32_TASK_STATE_SEGMENT) - 1;
- TssDesc->Bits.BaseLow = (UINT16)TssBase;
- TssDesc->Bits.BaseMid = (UINT8)(TssBase >> 16);
- TssDesc->Bits.Type = IA32_GDT_TYPE_TSS;
- TssDesc->Bits.P = 1;
- TssDesc->Bits.LimitHigh = 0;
- TssDesc->Bits.BaseHigh = (UINT8)(TssBase >> 24);
- //
- // Fixup exception task descriptor and task-state segment
- //
- AsmGetTssTemplateMap (&TemplateMap);
- StackTop = StackSwitchData->Ia32.KnownGoodStackTop - CPU_STACK_ALIGNMENT;
- StackTop = (UINTN)ALIGN_POINTER (StackTop, CPU_STACK_ALIGNMENT);
- IdtTable = StackSwitchData->Ia32.IdtTable;
- for (Index = 0; Index < StackSwitchData->Ia32.StackSwitchExceptionNumber; ++Index) {
- TssDesc += 1;
- Tss += 1;
- //
- // Fixup TSS descriptor
- //
- TssBase = (UINTN)Tss;
- TssDesc->Uint64 = 0;
- TssDesc->Bits.LimitLow = sizeof (IA32_TASK_STATE_SEGMENT) - 1;
- TssDesc->Bits.BaseLow = (UINT16)TssBase;
- TssDesc->Bits.BaseMid = (UINT8)(TssBase >> 16);
- TssDesc->Bits.Type = IA32_GDT_TYPE_TSS;
- TssDesc->Bits.P = 1;
- TssDesc->Bits.LimitHigh = 0;
- TssDesc->Bits.BaseHigh = (UINT8)(TssBase >> 24);
- //
- // Fixup TSS
- //
- Vector = StackSwitchData->Ia32.StackSwitchExceptions[Index];
- if ((Vector >= CPU_EXCEPTION_NUM) ||
- (Vector >= (Idtr.Limit + 1) / sizeof (IA32_IDT_GATE_DESCRIPTOR)))
- {
- continue;
- }
- ZeroMem (Tss, sizeof (*Tss));
- Tss->EIP = (UINT32)(TemplateMap.ExceptionStart
- + Vector * TemplateMap.ExceptionStubHeaderSize);
- Tss->EFLAGS = 0x2;
- Tss->ESP = StackTop;
- Tss->CR3 = AsmReadCr3 ();
- Tss->ES = AsmReadEs ();
- Tss->CS = AsmReadCs ();
- Tss->SS = AsmReadSs ();
- Tss->DS = AsmReadDs ();
- Tss->FS = AsmReadFs ();
- Tss->GS = AsmReadGs ();
- StackTop -= StackSwitchData->Ia32.KnownGoodStackSize;
- //
- // Update IDT to use Task Gate for given exception
- //
- IdtTable[Vector].Bits.OffsetLow = 0;
- IdtTable[Vector].Bits.Selector = (UINT16)((UINTN)TssDesc - Gdtr.Base);
- IdtTable[Vector].Bits.Reserved_0 = 0;
- IdtTable[Vector].Bits.GateType = IA32_IDT_GATE_TYPE_TASK;
- IdtTable[Vector].Bits.OffsetHigh = 0;
- }
- //
- // Publish GDT
- //
- AsmWriteGdtr (&Gdtr);
- //
- // Load current task
- //
- AsmWriteTr ((UINT16)((UINTN)StackSwitchData->Ia32.ExceptionTssDesc - Gdtr.Base));
- //
- // Publish IDT
- //
- AsmWriteIdtr (&Idtr);
- return EFI_SUCCESS;
- }
- /**
- Display processor context.
- @param[in] ExceptionType Exception type.
- @param[in] SystemContext Processor context to be display.
- **/
- VOID
- EFIAPI
- DumpCpuContext (
- IN EFI_EXCEPTION_TYPE ExceptionType,
- IN EFI_SYSTEM_CONTEXT SystemContext
- )
- {
- InternalPrintMessage (
- "!!!! IA32 Exception Type - %02x(%a) CPU Apic ID - %08x !!!!\n",
- ExceptionType,
- GetExceptionNameStr (ExceptionType),
- GetApicId ()
- );
- if ((mErrorCodeFlag & (1 << ExceptionType)) != 0) {
- InternalPrintMessage (
- "ExceptionData - %08x",
- SystemContext.SystemContextIa32->ExceptionData
- );
- if (ExceptionType == EXCEPT_IA32_PAGE_FAULT) {
- InternalPrintMessage (
- " I:%x R:%x U:%x W:%x P:%x PK:%x SS:%x SGX:%x",
- (SystemContext.SystemContextIa32->ExceptionData & IA32_PF_EC_ID) != 0,
- (SystemContext.SystemContextIa32->ExceptionData & IA32_PF_EC_RSVD) != 0,
- (SystemContext.SystemContextIa32->ExceptionData & IA32_PF_EC_US) != 0,
- (SystemContext.SystemContextIa32->ExceptionData & IA32_PF_EC_WR) != 0,
- (SystemContext.SystemContextIa32->ExceptionData & IA32_PF_EC_P) != 0,
- (SystemContext.SystemContextIa32->ExceptionData & IA32_PF_EC_PK) != 0,
- (SystemContext.SystemContextIa32->ExceptionData & IA32_PF_EC_SS) != 0,
- (SystemContext.SystemContextIa32->ExceptionData & IA32_PF_EC_SGX) != 0
- );
- }
- InternalPrintMessage ("\n");
- }
- InternalPrintMessage (
- "EIP - %08x, CS - %08x, EFLAGS - %08x\n",
- SystemContext.SystemContextIa32->Eip,
- SystemContext.SystemContextIa32->Cs,
- SystemContext.SystemContextIa32->Eflags
- );
- 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
- );
- }
- /**
- Display CPU information.
- @param ExceptionType Exception type.
- @param SystemContext Pointer to EFI_SYSTEM_CONTEXT.
- **/
- VOID
- DumpImageAndCpuContent (
- IN EFI_EXCEPTION_TYPE ExceptionType,
- IN EFI_SYSTEM_CONTEXT SystemContext
- )
- {
- DumpCpuContext (ExceptionType, SystemContext);
- //
- // Dump module image base and module entry point by EIP
- //
- if ((ExceptionType == EXCEPT_IA32_PAGE_FAULT) &&
- ((SystemContext.SystemContextIa32->ExceptionData & IA32_PF_EC_ID) != 0))
- {
- //
- // The EIP in SystemContext could not be used
- // if it is page fault with I/D set.
- //
- DumpModuleImageInfo ((*(UINTN *)(UINTN)SystemContext.SystemContextIa32->Esp));
- } else {
- DumpModuleImageInfo (SystemContext.SystemContextIa32->Eip);
- }
- }
|