]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/DebugSupportDxe/Ia32/AsmFuncs.S
A complement fix for revision 11664 to update GCC assembly files : clear the directio...
[mirror_edk2.git] / MdeModulePkg / Universal / DebugSupportDxe / Ia32 / AsmFuncs.S
CommitLineData
7b414b4e 1#/**@file\r
2# Low leve IA32 specific debug support functions.\r
3#\r
24f7e42c 4# Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.<BR>\r
e5eed7d3 5# This program and the accompanying materials\r
7b414b4e 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
c1f23d63 14\r
132f41f0 15ASM_GLOBAL ASM_PFX(OrigVector)\r
16ASM_GLOBAL ASM_PFX(InterruptEntryStub)\r
17ASM_GLOBAL ASM_PFX(StubSize)\r
18ASM_GLOBAL ASM_PFX(CommonIdtEntry)\r
19ASM_GLOBAL ASM_PFX(FxStorSupport)\r
c1f23d63 20\r
509bc208 21ASM_PFX(StubSize): .long ASM_PFX(InterruptEntryStubEnd) - ASM_PFX(InterruptEntryStub)\r
c1f23d63 22ASM_PFX(AppEsp): .long 0x11111111 # ?\r
23ASM_PFX(DebugEsp): .long 0x22222222 # ?\r
24ASM_PFX(ExtraPush): .long 0x33333333 # ?\r
25ASM_PFX(ExceptData): .long 0x44444444 # ?\r
26ASM_PFX(Eflags): .long 0x55555555 # ?\r
27ASM_PFX(OrigVector): .long 0x66666666 # ?\r
c1f23d63 28\r
509bc208 29#------------------------------------------------------------------------------\r
30# BOOLEAN\r
31# FxStorSupport (\r
32# void\r
33# )\r
34#\r
35# Abstract: Returns TRUE if FxStor instructions are supported\r
36#\r
132f41f0 37ASM_GLOBAL ASM_PFX(FxStorSupport)\r
c1f23d63 38ASM_PFX(FxStorSupport):\r
509bc208 39#\r
40# cpuid corrupts ebx which must be preserved per the C calling convention\r
41#\r
c1f23d63 42 push %ebx\r
43 mov $0x1,%eax\r
7b414b4e 44 cpuid\r
c1f23d63 45 mov %edx,%eax\r
46 and $0x1000000,%eax\r
47 shr $0x18,%eax\r
48 pop %ebx\r
7b414b4e 49 ret\r
509bc208 50#------------------------------------------------------------------------------\r
51# void\r
52# Vect2Desc (\r
53# DESCRIPTOR * DestDesc,\r
54# void (*Vector) (void)\r
55# )\r
56#\r
57# Abstract: Encodes an IDT descriptor with the given physical address\r
58#\r
c1f23d63 59\r
132f41f0 60ASM_GLOBAL ASM_PFX(Vect2Desc)\r
c1f23d63 61ASM_PFX(Vect2Desc):\r
62 push %ebp\r
63 mov %esp,%ebp\r
64 mov 0xc(%ebp),%eax\r
65 mov 0x8(%ebp),%ecx\r
66 mov %ax,(%ecx)\r
67 movw $0x20,0x2(%ecx)\r
68 movw $0x8e00,0x4(%ecx)\r
69 shr $0x10,%eax\r
70 mov %ax,0x6(%ecx)\r
7b414b4e 71 leave\r
72 ret\r
c1f23d63 73\r
132f41f0 74ASM_GLOBAL ASM_PFX(InterruptEntryStub)\r
c1f23d63 75ASM_PFX(InterruptEntryStub):\r
509bc208 76 mov %esp,0x0 # save stack top\r
77 mov $0x0,%esp # switch to debugger stack\r
78 push $0x0 # push vector number - will be modified before installed\r
79 jmp ASM_PFX(CommonIdtEntry) # jump CommonIdtEntry\r
132f41f0 80ASM_GLOBAL ASM_PFX(InterruptEntryStubEnd)\r
c1f23d63 81ASM_PFX(InterruptEntryStubEnd):\r
82\r
509bc208 83#------------------------------------------------------------------------------\r
84# CommonIdtEntry\r
85#\r
86# Abstract: This code is not a function, but is the common part for all IDT\r
87# vectors.\r
88#\r
132f41f0 89ASM_GLOBAL ASM_PFX(CommonIdtEntry)\r
c1f23d63 90ASM_PFX(CommonIdtEntry):\r
509bc208 91##\r
92## At this point, the stub has saved the current application stack esp into AppEsp\r
93## and switched stacks to the debug stack, where it pushed the vector number\r
94##\r
95## The application stack looks like this:\r
96##\r
97## ...\r
98## (last application stack entry)\r
99## eflags from interrupted task\r
100## CS from interrupted task\r
101## EIP from interrupted task\r
102## Error code <-------------------- Only present for some exeption types\r
103##\r
104##\r
105\r
106\r
107## The stub switched us to the debug stack and pushed the interrupt number.\r
108##\r
109## Next, construct the context record. It will be build on the debug stack by\r
110## pushing the registers in the correct order so as to create the context structure\r
111## on the debug stack. The context record must be built from the end back to the\r
112## beginning because the stack grows down...\r
113#\r
114## For reference, the context record looks like this:\r
115##\r
116## typedef\r
117## struct {\r
118## UINT32 ExceptionData;\r
119## FX_SAVE_STATE_IA32 FxSaveState;\r
120## UINT32 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;\r
121## UINT32 Cr0, Cr2, Cr3, Cr4;\r
122## UINT32 EFlags;\r
123## UINT32 Ldtr, Tr;\r
124## UINT32 Gdtr[2], Idtr[2];\r
125## UINT32 Eip;\r
126## UINT32 Gs, Fs, Es, Ds, Cs, Ss;\r
127## UINT32 Edi, Esi, Ebp, Esp, Ebx, Edx, Ecx, Eax;\r
128## } SYSTEM_CONTEXT_IA32; // 32 bit system context record\r
129\r
130## UINT32 Edi, Esi, Ebp, Esp, Ebx, Edx, Ecx, Eax;\r
7b414b4e 131 pusha\r
509bc208 132## Save interrupt state eflags register...\r
7b414b4e 133 pushf\r
c1f23d63 134 pop %eax\r
509bc208 135## We need to determine if any extra data was pushed by the exception, and if so, save it\r
136## To do this, we check the exception number pushed by the stub, and cache the\r
137## result in a variable since we'll need this again.\r
c1f23d63 138 mov %eax,0x0\r
139 cmpl $0x8,0x0\r
140 jne ASM_PFX(CommonIdtEntry+0x20)\r
141 movl $0x1,0x0\r
142 jmp ASM_PFX(CommonIdtEntry+0xa8)\r
143 cmpl $0xa,0x0\r
144 jne ASM_PFX(CommonIdtEntry+0x35)\r
145 movl $0x1,0x0\r
146 jmp ASM_PFX(CommonIdtEntry+0xa8)\r
147 cmpl $0xb,0x0\r
148 jne ASM_PFX(CommonIdtEntry+0x4a)\r
149 movl $0x1,0x0\r
150 jmp ASM_PFX(CommonIdtEntry+0xa8)\r
151 cmpl $0xc,0x0\r
152 jne ASM_PFX(CommonIdtEntry+0x5f)\r
153 movl $0x1,0x0\r
154 jmp ASM_PFX(CommonIdtEntry+0xa8)\r
155 cmpl $0xd,0x0\r
156 jne ASM_PFX(CommonIdtEntry+0x74)\r
157 movl $0x1,0x0\r
158 jmp ASM_PFX(CommonIdtEntry+0xa8)\r
159 cmpl $0xe,0x0\r
160 jne ASM_PFX(CommonIdtEntry+0x89)\r
161 movl $0x1,0x0\r
162 jmp ASM_PFX(CommonIdtEntry+0xa8)\r
163 cmpl $0x11,0x0\r
164 jne ASM_PFX(CommonIdtEntry+0x9e)\r
165 movl $0x1,0x0\r
166 jmp ASM_PFX(CommonIdtEntry+0xa8)\r
167 movl $0x0,0x0\r
509bc208 168## If there's some extra data, save it also, and modify the saved AppEsp to effectively\r
169## pop this value off the application's stack.\r
170\r
c1f23d63 171 cmpl $0x1,0x0\r
172 jne ASM_PFX(CommonIdtEntry+0xc8)\r
173 mov 0x0,%eax\r
174 mov (%eax),%ebx\r
175 mov %ebx,0x0\r
176 add $0x4,%eax\r
177 mov %eax,0x0\r
178 jmp ASM_PFX(CommonIdtEntry+0xd2)\r
179 movl $0x0,0x0\r
509bc208 180## The "pushad" above pushed the debug stack esp. Since what we're actually doing\r
181## is building the context record on the debug stack, we need to save the pushed\r
182## debug ESP, and replace it with the application's last stack entry...\r
c1f23d63 183 mov 0xc(%esp),%eax\r
184 mov %eax,0x0\r
185 mov 0x0,%eax\r
186 add $0xc,%eax\r
509bc208 187 # application stack has eflags, cs, & eip, so\r
188 # last actual application stack entry is\r
189 # 12 bytes into the application stack.\r
c1f23d63 190 mov %eax,0xc(%esp)\r
509bc208 191## continue building context record\r
192## UINT32 Gs, Fs, Es, Ds, Cs, Ss; insure high 16 bits of each is zero\r
c1f23d63 193 mov %ss,%eax\r
194 push %eax\r
509bc208 195 \r
196 # CS from application is one entry back in application stack\r
c1f23d63 197 mov 0x0,%eax\r
198 movzwl 0x4(%eax),%eax\r
199 push %eax\r
200 mov %ds,%eax\r
201 push %eax\r
202 mov %es,%eax\r
203 push %eax\r
204 mov %fs,%eax\r
205 push %eax\r
206 mov %gs,%eax\r
207 push %eax\r
509bc208 208\r
209## UINT32 Eip;\r
210 # Eip from application is on top of application stack\r
c1f23d63 211 mov 0x0,%eax\r
212 pushl (%eax)\r
509bc208 213\r
214## UINT32 Gdtr[2], Idtr[2];\r
c1f23d63 215 push $0x0\r
216 push $0x0\r
217 sidtl (%esp)\r
218 push $0x0\r
219 push $0x0\r
220 sgdtl (%esp)\r
509bc208 221\r
222## UINT32 Ldtr, Tr;\r
c1f23d63 223 xor %eax,%eax\r
224 str %eax\r
225 push %eax\r
226 sldt %eax\r
227 push %eax\r
509bc208 228\r
229## UINT32 EFlags;\r
230## Eflags from application is two entries back in application stack\r
c1f23d63 231 mov 0x0,%eax\r
232 pushl 0x8(%eax)\r
509bc208 233\r
234## UINT32 Cr0, Cr1, Cr2, Cr3, Cr4;\r
235## insure FXSAVE/FXRSTOR is enabled in CR4...\r
236## ... while we're at it, make sure DE is also enabled...\r
c1f23d63 237 mov %cr4,%eax\r
238 or $0x208,%eax\r
239 mov %eax,%cr4\r
240 push %eax\r
241 mov %cr3,%eax\r
242 push %eax\r
243 mov %cr2,%eax\r
244 push %eax\r
245 push $0x0\r
246 mov %cr0,%eax\r
247 push %eax\r
509bc208 248\r
249## UINT32 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;\r
c1f23d63 250 mov %db7,%eax\r
251 push %eax\r
509bc208 252\r
253## clear Dr7 while executing debugger itself\r
c1f23d63 254 xor %eax,%eax\r
255 mov %eax,%db7\r
256 mov %db6,%eax\r
257 push %eax\r
509bc208 258\r
259## insure all status bits in dr6 are clear...\r
c1f23d63 260 xor %eax,%eax\r
261 mov %eax,%db6\r
262 mov %db3,%eax\r
263 push %eax\r
264 mov %db2,%eax\r
265 push %eax\r
266 mov %db1,%eax\r
267 push %eax\r
268 mov %db0,%eax\r
269 push %eax\r
509bc208 270\r
271## FX_SAVE_STATE_IA32 FxSaveState;\r
c1f23d63 272 sub $0x200,%esp\r
273 mov %esp,%edi\r
509bc208 274 # IMPORTANT!! The debug stack has been carefully constructed to\r
275 # insure that esp and edi are 16 byte aligned when we get here.\r
276 # They MUST be. If they are not, a GP fault will occur.\r
c1f23d63 277 fxsave (%edi)\r
509bc208 278\r
24f7e42c 279## UEFI calling convention for IA32 requires that Direction flag in EFLAGs is clear\r
280 cld\r
281 \r
509bc208 282## UINT32 ExceptionData;\r
c1f23d63 283 mov 0x0,%eax\r
284 push %eax\r
509bc208 285\r
286# call to C code which will in turn call registered handler\r
287# pass in the vector number\r
c1f23d63 288 mov %esp,%eax\r
289 push %eax\r
290 mov 0x0,%eax\r
291 push %eax\r
292 call ASM_PFX(CommonIdtEntry+0x184)\r
293 add $0x8,%esp\r
509bc208 294\r
295# restore context...\r
296## UINT32 ExceptionData;\r
c1f23d63 297 add $0x4,%esp\r
509bc208 298\r
299## FX_SAVE_STATE_IA32 FxSaveState;\r
c1f23d63 300 mov %esp,%esi\r
301 fxrstor (%esi)\r
302 add $0x200,%esp\r
509bc208 303\r
304## UINT32 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;\r
c1f23d63 305 pop %eax\r
306 mov %eax,%db0\r
307 pop %eax\r
308 mov %eax,%db1\r
309 pop %eax\r
310 mov %eax,%db2\r
311 pop %eax\r
312 mov %eax,%db3\r
509bc208 313\r
314## skip restore of dr6. We cleared dr6 during the context save.\r
c1f23d63 315 add $0x4,%esp\r
316 pop %eax\r
317 mov %eax,%db7\r
509bc208 318\r
319## UINT32 Cr0, Cr1, Cr2, Cr3, Cr4;\r
c1f23d63 320 pop %eax\r
321 mov %eax,%cr0\r
322 add $0x4,%esp\r
323 pop %eax\r
324 mov %eax,%cr2\r
325 pop %eax\r
326 mov %eax,%cr3\r
327 pop %eax\r
328 mov %eax,%cr4\r
509bc208 329\r
330## UINT32 EFlags;\r
c1f23d63 331 mov 0x0,%eax\r
332 popl 0x8(%eax)\r
509bc208 333\r
334## UINT32 Ldtr, Tr;\r
335## UINT32 Gdtr[2], Idtr[2];\r
336## Best not let anyone mess with these particular registers...\r
c1f23d63 337 add $0x18,%esp\r
509bc208 338\r
339## UINT32 Eip;\r
c1f23d63 340 popl (%eax)\r
509bc208 341\r
342## UINT32 SegGs, SegFs, SegEs, SegDs, SegCs, SegSs;\r
343## NOTE - modified segment registers could hang the debugger... We\r
344## could attempt to insulate ourselves against this possibility,\r
345## but that poses risks as well.\r
346##\r
347\r
c1f23d63 348 pop %gs\r
349 pop %fs\r
350 pop %es\r
351 pop %ds\r
352 popl 0x4(%eax)\r
353 pop %ss\r
354 mov 0xc(%esp),%ebx\r
509bc208 355\r
356## The next stuff to restore is the general purpose registers that were pushed\r
357## using the "pushad" instruction.\r
358##\r
359## The value of ESP as stored in the context record is the application ESP\r
360## including the 3 entries on the application stack caused by the exception\r
361## itself. It may have been modified by the debug agent, so we need to\r
362## determine if we need to relocate the application stack.\r
363\r
364 mov 0x0,%eax # move the potentially modified AppEsp into ebx\r
c1f23d63 365 add $0xc,%eax\r
366 cmp %eax,%ebx\r
367 je ASM_PFX(CommonIdtEntry+0x202)\r
368 mov 0x0,%eax\r
509bc208 369 mov (%eax),%ecx # EIP\r
c1f23d63 370 mov %ecx,(%ebx)\r
509bc208 371 mov 0x4(%eax),%ecx # CS\r
c1f23d63 372 mov %ecx,0x4(%ebx)\r
509bc208 373 mov 0x8(%eax),%ecx # EFLAGS\r
c1f23d63 374 mov %ecx,0x8(%ebx)\r
509bc208 375 \r
376 mov %ebx,%eax # modify the saved AppEsp to the new AppEsp\r
c1f23d63 377 mov %eax,0x0\r
509bc208 378 mov 0x0,%eax # restore the DebugEsp on the debug stack\r
379 # so our "popad" will not cause a stack switch\r
380 mov %eax,0xc(%esp) \r
c1f23d63 381 cmpl $0x68,0x0\r
382 jne PhonyIretd+0xd\r
509bc208 383## Restore eflags so when we chain, the flags will be exactly as if we were never here.\r
384## We gin up the stack to do an iretd so we can get ALL the flags.\r
c1f23d63 385 mov 0x0,%eax\r
386 mov 0x8(%eax),%ebx\r
509bc208 387 and $0xfffffcff,%ebx # special handling for IF and TF\r
c1f23d63 388 push %ebx\r
389 push %cs\r
390 push $0x0\r
7b414b4e 391 iret\r
c1f23d63 392\r
393PhonyIretd:\r
509bc208 394## UINT32 Edi, Esi, Ebp, Esp, Ebx, Edx, Ecx, Eax;\r
7b414b4e 395 popa\r
509bc208 396\r
397## Switch back to application stack\r
c1f23d63 398 mov 0x0,%esp\r
399 jmp *0x0\r
509bc208 400## Jump to original handler\r
401## UINT32 Edi, Esi, Ebp, Esp, Ebx, Edx, Ecx, Eax;\r
7b414b4e 402 popa\r
509bc208 403## Switch back to application stack\r
c1f23d63 404 mov 0x0,%esp\r
509bc208 405\r
406## We're outa here...\r
7b414b4e 407 iret\r