]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/DebugSupportDxe/Ia32/AsmFuncs.S
code scrub:
[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
509bc208 4# Copyright (c) 2006 - 2008, Intel Corporation. <BR>\r
7b414b4e 5# All rights reserved. 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
c1f23d63 14\r
15.globl ASM_PFX(OrigVector)\r
16.globl ASM_PFX(InterruptEntryStub)\r
17.globl ASM_PFX(StubSize)\r
18.globl ASM_PFX(CommonIdtEntry)\r
19.globl ASM_PFX(FxStorSupport)\r
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
c1f23d63 37.globl ASM_PFX(FxStorSupport)\r
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
c1f23d63 60.globl ASM_PFX(Vect2Desc)\r
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
74.globl ASM_PFX(InterruptEntryStub)\r
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
c1f23d63 80.globl ASM_PFX(InterruptEntryStubEnd)\r
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
c1f23d63 89.globl ASM_PFX(CommonIdtEntry)\r
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
279## UINT32 ExceptionData;\r
c1f23d63 280 mov 0x0,%eax\r
281 push %eax\r
509bc208 282\r
283# call to C code which will in turn call registered handler\r
284# pass in the vector number\r
c1f23d63 285 mov %esp,%eax\r
286 push %eax\r
287 mov 0x0,%eax\r
288 push %eax\r
289 call ASM_PFX(CommonIdtEntry+0x184)\r
290 add $0x8,%esp\r
509bc208 291\r
292# restore context...\r
293## UINT32 ExceptionData;\r
c1f23d63 294 add $0x4,%esp\r
509bc208 295\r
296## FX_SAVE_STATE_IA32 FxSaveState;\r
c1f23d63 297 mov %esp,%esi\r
298 fxrstor (%esi)\r
299 add $0x200,%esp\r
509bc208 300\r
301## UINT32 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;\r
c1f23d63 302 pop %eax\r
303 mov %eax,%db0\r
304 pop %eax\r
305 mov %eax,%db1\r
306 pop %eax\r
307 mov %eax,%db2\r
308 pop %eax\r
309 mov %eax,%db3\r
509bc208 310\r
311## skip restore of dr6. We cleared dr6 during the context save.\r
c1f23d63 312 add $0x4,%esp\r
313 pop %eax\r
314 mov %eax,%db7\r
509bc208 315\r
316## UINT32 Cr0, Cr1, Cr2, Cr3, Cr4;\r
c1f23d63 317 pop %eax\r
318 mov %eax,%cr0\r
319 add $0x4,%esp\r
320 pop %eax\r
321 mov %eax,%cr2\r
322 pop %eax\r
323 mov %eax,%cr3\r
324 pop %eax\r
325 mov %eax,%cr4\r
509bc208 326\r
327## UINT32 EFlags;\r
c1f23d63 328 mov 0x0,%eax\r
329 popl 0x8(%eax)\r
509bc208 330\r
331## UINT32 Ldtr, Tr;\r
332## UINT32 Gdtr[2], Idtr[2];\r
333## Best not let anyone mess with these particular registers...\r
c1f23d63 334 add $0x18,%esp\r
509bc208 335\r
336## UINT32 Eip;\r
c1f23d63 337 popl (%eax)\r
509bc208 338\r
339## UINT32 SegGs, SegFs, SegEs, SegDs, SegCs, SegSs;\r
340## NOTE - modified segment registers could hang the debugger... We\r
341## could attempt to insulate ourselves against this possibility,\r
342## but that poses risks as well.\r
343##\r
344\r
c1f23d63 345 pop %gs\r
346 pop %fs\r
347 pop %es\r
348 pop %ds\r
349 popl 0x4(%eax)\r
350 pop %ss\r
351 mov 0xc(%esp),%ebx\r
509bc208 352\r
353## The next stuff to restore is the general purpose registers that were pushed\r
354## using the "pushad" instruction.\r
355##\r
356## The value of ESP as stored in the context record is the application ESP\r
357## including the 3 entries on the application stack caused by the exception\r
358## itself. It may have been modified by the debug agent, so we need to\r
359## determine if we need to relocate the application stack.\r
360\r
361 mov 0x0,%eax # move the potentially modified AppEsp into ebx\r
c1f23d63 362 add $0xc,%eax\r
363 cmp %eax,%ebx\r
364 je ASM_PFX(CommonIdtEntry+0x202)\r
365 mov 0x0,%eax\r
509bc208 366 mov (%eax),%ecx # EIP\r
c1f23d63 367 mov %ecx,(%ebx)\r
509bc208 368 mov 0x4(%eax),%ecx # CS\r
c1f23d63 369 mov %ecx,0x4(%ebx)\r
509bc208 370 mov 0x8(%eax),%ecx # EFLAGS\r
c1f23d63 371 mov %ecx,0x8(%ebx)\r
509bc208 372 \r
373 mov %ebx,%eax # modify the saved AppEsp to the new AppEsp\r
c1f23d63 374 mov %eax,0x0\r
509bc208 375 mov 0x0,%eax # restore the DebugEsp on the debug stack\r
376 # so our "popad" will not cause a stack switch\r
377 mov %eax,0xc(%esp) \r
c1f23d63 378 cmpl $0x68,0x0\r
379 jne PhonyIretd+0xd\r
509bc208 380## Restore eflags so when we chain, the flags will be exactly as if we were never here.\r
381## We gin up the stack to do an iretd so we can get ALL the flags.\r
c1f23d63 382 mov 0x0,%eax\r
383 mov 0x8(%eax),%ebx\r
509bc208 384 and $0xfffffcff,%ebx # special handling for IF and TF\r
c1f23d63 385 push %ebx\r
386 push %cs\r
387 push $0x0\r
7b414b4e 388 iret\r
c1f23d63 389\r
390PhonyIretd:\r
509bc208 391## UINT32 Edi, Esi, Ebp, Esp, Ebx, Edx, Ecx, Eax;\r
7b414b4e 392 popa\r
509bc208 393\r
394## Switch back to application stack\r
c1f23d63 395 mov 0x0,%esp\r
396 jmp *0x0\r
509bc208 397## Jump to original handler\r
398## UINT32 Edi, Esi, Ebp, Esp, Ebx, Edx, Ecx, Eax;\r
7b414b4e 399 popa\r
509bc208 400## Switch back to application stack\r
c1f23d63 401 mov 0x0,%esp\r
509bc208 402\r
403## We're outa here...\r
7b414b4e 404 iret\r