1 /** @file 2 Supporting functions for X64 architecture. 3 4 Copyright (c) 2010 - 2015, Intel Corporation. All rights reserved.<BR> 5 This program and the accompanying materials 6 are licensed and made available under the terms and conditions of the BSD License 7 which accompanies this distribution. The full text of the license may be found at 8 http://opensource.org/licenses/bsd-license.php. 9 10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, 11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. 12 13 **/ 14 15 #include "DebugAgent.h" 16 17 /** 18 Initialize IDT entries to support source level debug. 19 20 **/ 21 VOID 22 InitializeDebugIdt ( 23 VOID 24 ) 25 { 26 IA32_IDT_GATE_DESCRIPTOR *IdtEntry; 27 UINTN InterruptHandler; 28 IA32_DESCRIPTOR IdtDescriptor; 29 UINTN Index; 30 UINT16 CodeSegment; 31 UINT32 RegEdx; 32 33 AsmReadIdtr (&IdtDescriptor); 34 35 // 36 // Use current CS as the segment selector of interrupt gate in IDT 37 // 38 CodeSegment = AsmReadCs (); 39 40 IdtEntry = (IA32_IDT_GATE_DESCRIPTOR *) IdtDescriptor.Base; 41 42 for (Index = 0; Index < 20; Index ++) { 43 if (((PcdGet32 (PcdExceptionsIgnoredByDebugger) & ~(BIT1 | BIT3)) & (1 << Index)) != 0) { 44 // 45 // If the exception is masked to be reserved except for INT1 and INT3, skip it 46 // 47 continue; 48 } 49 InterruptHandler = (UINTN)&Exception0Handle + Index * ExceptionStubHeaderSize; 50 IdtEntry[Index].Bits.OffsetLow = (UINT16)(UINTN)InterruptHandler; 51 IdtEntry[Index].Bits.OffsetHigh = (UINT16)((UINTN)InterruptHandler >> 16); 52 IdtEntry[Index].Bits.OffsetUpper = (UINT32)((UINTN)InterruptHandler >> 32); 53 IdtEntry[Index].Bits.Selector = CodeSegment; 54 IdtEntry[Index].Bits.GateType = IA32_IDT_GATE_TYPE_INTERRUPT_32; 55 } 56 57 InterruptHandler = (UINTN) &TimerInterruptHandle; 58 IdtEntry[DEBUG_TIMER_VECTOR].Bits.OffsetLow = (UINT16)(UINTN)InterruptHandler; 59 IdtEntry[DEBUG_TIMER_VECTOR].Bits.OffsetHigh = (UINT16)((UINTN)InterruptHandler >> 16); 60 IdtEntry[DEBUG_TIMER_VECTOR].Bits.OffsetUpper = (UINT32)((UINTN)InterruptHandler >> 32); 61 IdtEntry[DEBUG_TIMER_VECTOR].Bits.Selector = CodeSegment; 62 IdtEntry[DEBUG_TIMER_VECTOR].Bits.GateType = IA32_IDT_GATE_TYPE_INTERRUPT_32; 63 64 // 65 // If the CPU supports Debug Extensions(CPUID:01 EDX:BIT2), then 66 // Set DE flag in CR4 to enable IO breakpoint 67 // 68 AsmCpuid (1, NULL, NULL, NULL, &RegEdx); 69 if ((RegEdx & BIT2) != 0) { 70 AsmWriteCr4 (AsmReadCr4 () | BIT3); 71 } 72 } 73 74 /** 75 Retrieve exception handler from IDT table by ExceptionNum. 76 77 @param[in] ExceptionNum Exception number 78 79 @return Exception handler 80 81 **/ 82 VOID * 83 GetExceptionHandlerInIdtEntry ( 84 IN UINTN ExceptionNum 85 ) 86 { 87 IA32_IDT_GATE_DESCRIPTOR *IdtEntry; 88 IA32_DESCRIPTOR IdtDescriptor; 89 90 AsmReadIdtr (&IdtDescriptor); 91 IdtEntry = (IA32_IDT_GATE_DESCRIPTOR *) IdtDescriptor.Base; 92 93 return (VOID *) (IdtEntry[ExceptionNum].Bits.OffsetLow | 94 (((UINTN)IdtEntry[ExceptionNum].Bits.OffsetHigh) << 16) | 95 (((UINTN)IdtEntry[ExceptionNum].Bits.OffsetUpper) << 32)); 96 } 97 98 /** 99 Set exception handler in IDT table by ExceptionNum. 100 101 @param[in] ExceptionNum Exception number 102 @param[in] ExceptionHandler Exception Handler to be set 103 104 **/ 105 VOID 106 SetExceptionHandlerInIdtEntry ( 107 IN UINTN ExceptionNum, 108 IN VOID *ExceptionHandler 109 ) 110 { 111 IA32_IDT_GATE_DESCRIPTOR *IdtEntry; 112 IA32_DESCRIPTOR IdtDescriptor; 113 114 AsmReadIdtr (&IdtDescriptor); 115 IdtEntry = (IA32_IDT_GATE_DESCRIPTOR *) IdtDescriptor.Base; 116 117 IdtEntry[ExceptionNum].Bits.OffsetLow = (UINT16)(UINTN)ExceptionHandler; 118 IdtEntry[ExceptionNum].Bits.OffsetHigh = (UINT16)((UINTN)ExceptionHandler >> 16); 119 IdtEntry[ExceptionNum].Bits.OffsetUpper = (UINT32)((UINTN)ExceptionHandler >> 32); 120 } 121