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