]> git.proxmox.com Git - mirror_edk2.git/blob - SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/Ia32/ArchDebugSupport.c
ab724ff3d6ffd35206151649060384c45c954e35
[mirror_edk2.git] / SourceLevelDebugPkg / Library / DebugAgent / DebugAgentCommon / Ia32 / ArchDebugSupport.c
1 /** @file
2 Public include file for Debug Port Library.
3
4 Copyright (c) 2010, 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 Read the offset of FP / MMX / XMM registers by register index.
19
20 @param[in] Index Register index.
21 @param[out] Width Register width returned.
22
23 @return Offset in register address range.
24
25 **/
26 UINT16
27 ArchReadFxStatOffset (
28 IN UINT8 Index,
29 OUT UINT8 *Width
30 )
31 {
32 if (Index < SOFT_DEBUGGER_REGISTER_ST0) {
33 switch (Index) {
34 case SOFT_DEBUGGER_REGISTER_FP_FCW:
35 *Width = (UINT8) sizeof (UINT16);
36 return (UINT16)OFFSET_OF(DEBUG_DATA_IA32_FX_SAVE_STATE, Fcw);
37
38 case SOFT_DEBUGGER_REGISTER_FP_FSW:
39 *Width = (UINT8) sizeof (UINT16);
40 return (UINT16)OFFSET_OF(DEBUG_DATA_IA32_FX_SAVE_STATE, Fsw);
41
42 case SOFT_DEBUGGER_REGISTER_FP_FTW:
43 *Width = (UINT8) sizeof (UINT16);
44 return (UINT16)OFFSET_OF(DEBUG_DATA_IA32_FX_SAVE_STATE, Ftw);
45
46 case SOFT_DEBUGGER_REGISTER_FP_OPCODE:
47 *Width = (UINT8) sizeof (UINT16);
48 return (UINT16)OFFSET_OF(DEBUG_DATA_IA32_FX_SAVE_STATE, Opcode);
49
50 case SOFT_DEBUGGER_REGISTER_FP_EIP:
51 *Width = (UINT8) sizeof (UINTN);
52 return (UINT16)OFFSET_OF(DEBUG_DATA_IA32_FX_SAVE_STATE, Eip);
53
54 case SOFT_DEBUGGER_REGISTER_FP_CS:
55 *Width = (UINT8) sizeof (UINT16);
56 return (UINT16)OFFSET_OF(DEBUG_DATA_IA32_FX_SAVE_STATE, Cs);
57
58 case SOFT_DEBUGGER_REGISTER_FP_DATAOFFSET:
59 *Width = (UINT8) sizeof (UINTN);
60 return (UINT16)OFFSET_OF(DEBUG_DATA_IA32_FX_SAVE_STATE, DataOffset);
61
62 case SOFT_DEBUGGER_REGISTER_FP_DS:
63 *Width = (UINT8) sizeof (UINT16);
64 return (UINT16)OFFSET_OF(DEBUG_DATA_IA32_FX_SAVE_STATE, Ds);
65
66 case SOFT_DEBUGGER_REGISTER_FP_MXCSR:
67 *Width = (UINT8) sizeof (UINTN);
68 return (UINT16)OFFSET_OF(DEBUG_DATA_IA32_FX_SAVE_STATE, Mxcsr);
69
70 case SOFT_DEBUGGER_REGISTER_FP_MXCSR_MASK:
71 *Width = (UINT8) sizeof (UINTN);
72 return (UINT16)OFFSET_OF(DEBUG_DATA_IA32_FX_SAVE_STATE, Mxcsr_Mask);
73 }
74 }
75
76 if (Index < SOFT_DEBUGGER_REGISTER_XMM0) {
77 *Width = 10;
78 } else if (Index < SOFT_DEBUGGER_REGISTER_MM0 ) {
79 *Width = 16;
80 } else {
81 *Width = 8;
82 Index -= SOFT_DEBUGGER_REGISTER_MM0 - SOFT_DEBUGGER_REGISTER_ST0;
83 }
84
85 return (UINT16)(OFFSET_OF(DEBUG_DATA_IA32_FX_SAVE_STATE, St0Mm0) + (Index - SOFT_DEBUGGER_REGISTER_ST0) * 16);
86 }
87
88 /**
89 Write specified register into save CPU context.
90
91 @param[in] CpuContext Pointer to saved CPU context.
92 @param[in] Index Register index value.
93 @param[in] Offset Offset in register address range.
94 @param[in] Width Data width to read.
95 @param[in] RegisterBuffer Pointer to input buffer with data.
96
97 **/
98 VOID
99 ArchWriteRegisterBuffer (
100 IN DEBUG_CPU_CONTEXT *CpuContext,
101 IN UINT8 Index,
102 IN UINT8 Offset,
103 IN UINT8 Width,
104 IN UINT8 *RegisterBuffer
105 )
106 {
107 UINT8 *Buffer;
108 if (Index < SOFT_DEBUGGER_REGISTER_FP_BASE) {
109 Buffer = (UINT8 *) CpuContext + sizeof (DEBUG_DATA_IA32_FX_SAVE_STATE) + Index * 4;
110 } else {
111 //
112 // If it is MMX register, adjust its index position
113 //
114 if (Index >= SOFT_DEBUGGER_REGISTER_MM0) {
115 Index -= SOFT_DEBUGGER_REGISTER_MM0 - SOFT_DEBUGGER_REGISTER_ST0;
116 }
117 //
118 // FPU/MMX/XMM registers
119 //
120 Buffer = (UINT8 *) CpuContext + ArchReadFxStatOffset (Index, &Width);
121 }
122
123 CopyMem (Buffer + Offset, RegisterBuffer, Width);
124 }
125
126 /**
127 Read register value from saved CPU context.
128
129 @param[in] CpuContext Pointer to saved CPU context.
130 @param[in] Index Register index value.
131 @param[in] Offset Offset in register address range
132 @param[in] Width Data width to read.
133
134 @return The address of register value.
135
136 **/
137 UINT8 *
138 ArchReadRegisterBuffer (
139 IN DEBUG_CPU_CONTEXT *CpuContext,
140 IN UINT8 Index,
141 IN UINT8 Offset,
142 IN UINT8 *Width
143 )
144 {
145 UINT8 *Buffer;
146
147 if (Index < SOFT_DEBUGGER_REGISTER_FP_BASE) {
148 Buffer = (UINT8 *) CpuContext + sizeof (DEBUG_DATA_IA32_FX_SAVE_STATE) + Index * 4;
149 if (*Width == 0) {
150 *Width = (UINT8) sizeof (UINTN);
151 }
152 } else {
153 //
154 // FPU/MMX/XMM registers
155 //
156 Buffer = (UINT8 *) CpuContext + ArchReadFxStatOffset (Index, Width);
157 }
158
159 return Buffer;
160 }
161
162 /**
163 Read group register of common registers.
164
165 @param[in] CpuContext Pointer to saved CPU context.
166 @param[in] RegisterGroup Pointer to Group registers.
167
168 **/
169 VOID
170 ReadRegisterGroup (
171 IN DEBUG_CPU_CONTEXT *CpuContext,
172 IN DEBUG_DATA_REPONSE_READ_REGISTER_GROUP *RegisterGroup
173 )
174 {
175 RegisterGroup->Cs = (UINT16) CpuContext->Cs;
176 RegisterGroup->Ds = (UINT16) CpuContext->Ds;
177 RegisterGroup->Es = (UINT16) CpuContext->Es;
178 RegisterGroup->Fs = (UINT16) CpuContext->Fs;
179 RegisterGroup->Gs = (UINT16) CpuContext->Gs;
180 RegisterGroup->Ss = (UINT16) CpuContext->Ss;
181 RegisterGroup->Eflags = CpuContext->Eflags;
182 RegisterGroup->Ebp = CpuContext->Ebp;
183 RegisterGroup->Eip = CpuContext->Eip;
184 RegisterGroup->Esp = CpuContext->Esp;
185 RegisterGroup->Eax = CpuContext->Eax;
186 RegisterGroup->Ebx = CpuContext->Ebx;
187 RegisterGroup->Ecx = CpuContext->Ecx;
188 RegisterGroup->Edx = CpuContext->Edx;
189 RegisterGroup->Esi = CpuContext->Esi;
190 RegisterGroup->Edi = CpuContext->Edi;
191 RegisterGroup->Dr0 = CpuContext->Dr0;
192 RegisterGroup->Dr1 = CpuContext->Dr1;
193 RegisterGroup->Dr2 = CpuContext->Dr2;
194 RegisterGroup->Dr3 = CpuContext->Dr3;
195 RegisterGroup->Dr6 = CpuContext->Dr6;
196 RegisterGroup->Dr7 = CpuContext->Dr7;
197 }
198
199 /**
200 Initialize IDT entries to support source level debug.
201
202 **/
203 VOID
204 InitializeDebugIdt (
205 VOID
206 )
207 {
208 IA32_IDT_GATE_DESCRIPTOR *IdtEntry;
209 UINTN InterruptHandler;
210 IA32_DESCRIPTOR IdtDescriptor;
211 UINTN Index;
212 UINT16 CodeSegment;
213
214 AsmReadIdtr (&IdtDescriptor);
215
216 //
217 // Use current CS as the segment selector of interrupt gate in IDT
218 //
219 CodeSegment = AsmReadCs ();
220
221 IdtEntry = (IA32_IDT_GATE_DESCRIPTOR *) IdtDescriptor.Base;
222
223 for (Index = 0; Index < 20; Index ++) {
224 if ((PcdGet32 (PcdExceptionsIgnoredByDebugger) & (1 << Index)) != 0) {
225 //
226 // If the exception is masked to be reserved, skip it
227 //
228 continue;
229 }
230 InterruptHandler = (UINTN)&Exception0Handle + Index * ExceptionStubHeaderSize;
231 IdtEntry[Index].Bits.OffsetLow = (UINT16)(UINTN)InterruptHandler;
232 IdtEntry[Index].Bits.OffsetHigh = (UINT16)((UINTN)InterruptHandler >> 16);
233 IdtEntry[Index].Bits.Selector = CodeSegment;
234 IdtEntry[Index].Bits.GateType = IA32_IDT_GATE_TYPE_INTERRUPT_32;
235 }
236
237 InterruptHandler = (UINTN) &TimerInterruptHandle;
238 IdtEntry[DEBUG_TIMER_VECTOR].Bits.OffsetLow = (UINT16)(UINTN)InterruptHandler;
239 IdtEntry[DEBUG_TIMER_VECTOR].Bits.OffsetHigh = (UINT16)((UINTN)InterruptHandler >> 16);
240 IdtEntry[Index].Bits.Selector = CodeSegment;
241 IdtEntry[Index].Bits.GateType = IA32_IDT_GATE_TYPE_INTERRUPT_32;
242 }