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