1 /** @file
2 Supporting functions for IA32 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
InitializeDebugIdt(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.Selector = CodeSegment;
53 IdtEntry[Index].Bits.GateType = IA32_IDT_GATE_TYPE_INTERRUPT_32;
54 }
55
56 InterruptHandler = (UINTN) &TimerInterruptHandle;
57 IdtEntry[DEBUG_TIMER_VECTOR].Bits.OffsetLow = (UINT16)(UINTN)InterruptHandler;
58 IdtEntry[DEBUG_TIMER_VECTOR].Bits.OffsetHigh = (UINT16)((UINTN)InterruptHandler >> 16);
59 IdtEntry[DEBUG_TIMER_VECTOR].Bits.Selector = CodeSegment;
60 IdtEntry[DEBUG_TIMER_VECTOR].Bits.GateType = IA32_IDT_GATE_TYPE_INTERRUPT_32;
61
62 //
63 // If the CPU supports Debug Extensions(CPUID:01 EDX:BIT2), then
64 // Set DE flag in CR4 to enable IO breakpoint
65 //
66 AsmCpuid (1, NULL, NULL, NULL, &RegEdx);
67 if ((RegEdx & BIT2) != 0) {
68 AsmWriteCr4 (AsmReadCr4 () | BIT3);
69 }
70 }
71
72 /**
73 Retrieve exception handler from IDT table by ExceptionNum.
74
75 @param[in] ExceptionNum Exception number
76
77 @return Exception handler
78
79 **/
80 VOID *
GetExceptionHandlerInIdtEntry(IN UINTN ExceptionNum)81 GetExceptionHandlerInIdtEntry (
82 IN UINTN ExceptionNum
83 )
84 {
85 IA32_IDT_GATE_DESCRIPTOR *IdtEntry;
86 IA32_DESCRIPTOR IdtDescriptor;
87
88 AsmReadIdtr (&IdtDescriptor);
89 IdtEntry = (IA32_IDT_GATE_DESCRIPTOR *) IdtDescriptor.Base;
90
91 return (VOID *) (((UINTN)IdtEntry[ExceptionNum].Bits.OffsetLow) |
92 (((UINTN)IdtEntry[ExceptionNum].Bits.OffsetHigh) << 16));
93 }
94
95 /**
96 Set exception handler in IDT table by ExceptionNum.
97
98 @param[in] ExceptionNum Exception number
99 @param[in] ExceptionHandler Exception Handler to be set
100
101 **/
102 VOID
SetExceptionHandlerInIdtEntry(IN UINTN ExceptionNum,IN VOID * ExceptionHandler)103 SetExceptionHandlerInIdtEntry (
104 IN UINTN ExceptionNum,
105 IN VOID *ExceptionHandler
106 )
107 {
108 IA32_IDT_GATE_DESCRIPTOR *IdtEntry;
109 IA32_DESCRIPTOR IdtDescriptor;
110
111 AsmReadIdtr (&IdtDescriptor);
112 IdtEntry = (IA32_IDT_GATE_DESCRIPTOR *) IdtDescriptor.Base;
113
114 IdtEntry[ExceptionNum].Bits.OffsetLow = (UINT16)(UINTN)ExceptionHandler;
115 IdtEntry[ExceptionNum].Bits.OffsetHigh = (UINT16)((UINTN)ExceptionHandler >> 16);
116 }
117