/** @file Supporting functions for X64 architecture. Copyright (c) 2010 - 2018, Intel Corporation. All rights reserved.
SPDX-License-Identifier: BSD-2-Clause-Patent **/ #include "DebugAgent.h" /** Initialize IDT entries to support source level debug. **/ VOID InitializeDebugIdt ( VOID ) { IA32_IDT_GATE_DESCRIPTOR *IdtEntry; UINTN InterruptHandler; IA32_DESCRIPTOR IdtDescriptor; UINTN Index; UINT16 CodeSegment; UINT32 RegEdx; AsmReadIdtr (&IdtDescriptor); // // Use current CS as the segment selector of interrupt gate in IDT // CodeSegment = AsmReadCs (); IdtEntry = (IA32_IDT_GATE_DESCRIPTOR *)IdtDescriptor.Base; for (Index = 0; Index < 20; Index++) { if (((PcdGet32 (PcdExceptionsIgnoredByDebugger) & ~(BIT1 | BIT3)) & (1 << Index)) != 0) { // // If the exception is masked to be reserved except for INT1 and INT3, skip it // continue; } InterruptHandler = (UINTN)&Exception0Handle + Index * 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; } InterruptHandler = (UINTN)&TimerInterruptHandle; IdtEntry[DEBUG_TIMER_VECTOR].Bits.OffsetLow = (UINT16)(UINTN)InterruptHandler; IdtEntry[DEBUG_TIMER_VECTOR].Bits.OffsetHigh = (UINT16)((UINTN)InterruptHandler >> 16); IdtEntry[DEBUG_TIMER_VECTOR].Bits.OffsetUpper = (UINT32)((UINTN)InterruptHandler >> 32); IdtEntry[DEBUG_TIMER_VECTOR].Bits.Selector = CodeSegment; IdtEntry[DEBUG_TIMER_VECTOR].Bits.GateType = IA32_IDT_GATE_TYPE_INTERRUPT_32; // // If the CPU supports Debug Extensions(CPUID:01 EDX:BIT2), then // Set DE flag in CR4 to enable IO breakpoint // AsmCpuid (1, NULL, NULL, NULL, &RegEdx); if ((RegEdx & BIT2) != 0) { AsmWriteCr4 (AsmReadCr4 () | BIT3); } } /** Retrieve exception handler from IDT table by ExceptionNum. @param[in] ExceptionNum Exception number @return Exception handler **/ VOID * GetExceptionHandlerInIdtEntry ( IN UINTN ExceptionNum ) { IA32_IDT_GATE_DESCRIPTOR *IdtEntry; IA32_DESCRIPTOR IdtDescriptor; AsmReadIdtr (&IdtDescriptor); IdtEntry = (IA32_IDT_GATE_DESCRIPTOR *)IdtDescriptor.Base; return (VOID *)(IdtEntry[ExceptionNum].Bits.OffsetLow | (((UINTN)IdtEntry[ExceptionNum].Bits.OffsetHigh) << 16) | (((UINTN)IdtEntry[ExceptionNum].Bits.OffsetUpper) << 32)); } /** Set exception handler in IDT table by ExceptionNum. @param[in] ExceptionNum Exception number @param[in] ExceptionHandler Exception Handler to be set **/ VOID SetExceptionHandlerInIdtEntry ( IN UINTN ExceptionNum, IN VOID *ExceptionHandler ) { IA32_IDT_GATE_DESCRIPTOR *IdtEntry; IA32_DESCRIPTOR IdtDescriptor; AsmReadIdtr (&IdtDescriptor); IdtEntry = (IA32_IDT_GATE_DESCRIPTOR *)IdtDescriptor.Base; IdtEntry[ExceptionNum].Bits.OffsetLow = (UINT16)(UINTN)ExceptionHandler; IdtEntry[ExceptionNum].Bits.OffsetHigh = (UINT16)((UINTN)ExceptionHandler >> 16); IdtEntry[ExceptionNum].Bits.OffsetUpper = (UINT32)((UINTN)ExceptionHandler >> 32); }