]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/DebugSupportDxe/X64/AsmFuncs.S
Port AsmFuncs.s to pass CYGWINGCC build for x64.
[mirror_edk2.git] / MdeModulePkg / Universal / DebugSupportDxe / X64 / AsmFuncs.S
CommitLineData
7b414b4e 1#/**@file\r
2# Low leve x64 specific debug support functions.\r
3#\r
43a99f08 4# Copyright (c) 2006 - 2008, Intel Corporation\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
43a99f08 13#**/ \r
c1f23d63 14\r
43a99f08 15.intel_syntax noprefix\r
c1f23d63 16\r
c1f23d63 17\r
43a99f08 18.globl ASM_PFX(OrigVector)\r
19.globl ASM_PFX(InterruptEntryStub)\r
20.globl ASM_PFX(StubSize)\r
21.globl ASM_PFX(CommonIdtEntry)\r
22.globl ASM_PFX(FxStorSupport)\r
23 \r
24.data \r
c1f23d63 25\r
43a99f08 26ASM_PFX(StubSize): .long ASM_PFX(InterruptEntryStubEnd) - ASM_PFX(InterruptEntryStub)\r
27ASM_PFX(AppRsp): .long 0x11111111 # ?\r
28 .long 0x11111111 # ?\r
29ASM_PFX(DebugRsp): .long 0x22222222 # ?\r
30 .long 0x22222222 # ?\r
31ASM_PFX(ExtraPush): .long 0x33333333 # ?\r
32 .long 0x33333333 # ?\r
33ASM_PFX(ExceptData): .long 0x44444444 # ?\r
34 .long 0x44444444 # ?\r
35ASM_PFX(Rflags): .long 0x55555555 # ?\r
36 .long 0x55555555 # ?\r
37ASM_PFX(OrigVector): .long 0x66666666 # ?\r
38 .long 0x66666666 # ?\r
c1f23d63 39\r
43a99f08 40## The declarations below define the memory region that will be used for the debug stack.\r
41## The context record will be built by pushing register values onto this stack.\r
42## It is imparitive that alignment be carefully managed, since the FXSTOR and\r
43## FXRSTOR instructions will GP fault if their memory operand is not 16 byte aligned.\r
44##\r
45## The stub will switch stacks from the application stack to the debuger stack\r
46## and pushes the exception number.\r
47##\r
48## Then we building the context record on the stack. Since the stack grows down,\r
49## we push the fields of the context record from the back to the front. There\r
50## are 336 bytes of stack used prior allocating the 512 bytes of stack to be\r
51## used as the memory buffer for the fxstor instruction. Therefore address of\r
52## the buffer used for the FXSTOR instruction is &Eax - 336 - 512, which\r
53## must be 16 byte aligned.\r
54##\r
55## We carefully locate the stack to make this happen.\r
56##\r
57## For reference, the context structure looks like this:\r
58## struct {\r
59## UINT64 ExceptionData;\r
60## FX_SAVE_STATE_X64 FxSaveState; // 512 bytes, must be 16 byte aligned\r
61## UINT64 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;\r
62## UINT64 Cr0, Cr1, Cr2, Cr3, Cr4, Cr8;\r
63## UINT64 RFlags;\r
64## UINT64 Ldtr, Tr;\r
65## UINT64 Gdtr[2], Idtr[2];\r
66## UINT64 Rip;\r
67## UINT64 Gs, Fs, Es, Ds, Cs, Ss;\r
68## UINT64 Rdi, Rsi, Rbp, Rsp, Rbx, Rdx, Rcx, Rax;\r
69## UINT64 R8, R9, R10, R11, R12, R13, R14, R15;\r
70## } SYSTEM_CONTEXT_X64; // 64 bit system context record\r
71\r
72.align 16\r
73DebugStackEnd : .ascii "DbgStkEnd >>>>>>" # 16 byte long string - must be 16 bytes to preserve alignment\r
74 .rept 0x1ffc\r
75 .long 0x00000000 \r
76 .endr\r
77 # 32K should be enough stack\r
78 # This allocation is coocked to insure\r
79 # that the the buffer for the FXSTORE instruction\r
80 # will be 16 byte aligned also.\r
81 #\r
82ASM_PFX(ExceptionNumber): .long 0x77777777 # first entry will be the vector number pushed by the stub\r
83 .long 0x77777777 # ?\r
84\r
85DebugStackBegin : .ascii "<<<< DbgStkBegin" # initial debug ESP == DebugStackBegin, set in stub\r
86 \r
87\r
88.text\r
89\r
90#------------------------------------------------------------------------------\r
91# BOOLEAN\r
92# FxStorSupport (\r
93# void\r
94# )\r
95#\r
96# Abstract: Returns TRUE if FxStor instructions are supported\r
97#\r
98.globl ASM_PFX(FxStorSupport)\r
99ASM_PFX(FxStorSupport): \r
100#\r
101# cpuid corrupts rbx which must be preserved per the C calling convention\r
102#\r
103 push rbx\r
104 mov rax, 1\r
105 cpuid\r
106 mov eax, edx\r
107 and rax, 0x01000000\r
108 shr rax, 24\r
109 pop rbx\r
110 ret\r
111#------------------------------------------------------------------------------\r
112# void\r
113# Vect2Desc (\r
114# IA32_IDT_GATE_DESCRIPTOR * DestDesc, // rcx\r
115# void (*Vector) (void) // rdx\r
116# )\r
117#\r
118# Abstract: Encodes an IDT descriptor with the given physical address\r
119#\r
120.globl ASM_PFX(Vect2Desc)\r
121ASM_PFX(Vect2Desc):\r
122 mov rax, rdx\r
123 mov word ptr [rcx], ax # write bits 15..0 of offset\r
124 mov dx, cs\r
125 mov word ptr [rcx+2], dx # SYS_CODE_SEL from GDT\r
126 mov word ptr [rcx+4], 0x0e00 OR 0x8000 # type = 386 interrupt gate, present\r
127 shr rax, 16\r
128 mov word ptr [rcx+6], ax # write bits 31..16 of offset\r
129 shr rax, 16\r
130 mov dword ptr [rcx+8], eax # write bits 63..32 of offset\r
131\r
132 ret\r
133\r
134#------------------------------------------------------------------------------\r
135# InterruptEntryStub\r
136#\r
137# Abstract: This code is not a function, but is a small piece of code that is\r
138# copied and fixed up once for each IDT entry that is hooked.\r
139#\r
140.globl ASM_PFX(InterruptEntryStub)\r
141ASM_PFX(InterruptEntryStub):\r
142\r
143 push 0 # push vector number - will be modified before installed\r
144 jmp ASM_PFX(CommonIdtEntry)\r
145 \r
146.globl ASM_PFX(InterruptEntryStubEnd)\r
147ASM_PFX(InterruptEntryStubEnd):\r
c1f23d63 148\r
7b414b4e 149 ret\r
c1f23d63 150\r
43a99f08 151#------------------------------------------------------------------------------\r
152# CommonIdtEntry\r
153#\r
154# Abstract: This code is not a function, but is the common part for all IDT\r
155# vectors.\r
156#\r
157.globl ASM_PFX(CommonIdtEntry)\r
158##\r
159## At this point, the stub has saved the current application stack esp into AppRsp\r
160## and switched stacks to the debug stack, where it pushed the vector number\r
161##\r
162## The application stack looks like this:\r
163##\r
164## ...\r
165## (last application stack entry)\r
166## [16 bytes alignment, do not care it]\r
167## SS from interrupted task\r
168## RSP from interrupted task\r
169## rflags from interrupted task\r
170## CS from interrupted task\r
171## RIP from interrupted task\r
172## Error code <-------------------- Only present for some exeption types\r
173##\r
174## Vector Number <----------------- pushed in our IDT Entry\r
175##\r
176\r
177\r
178## The stub switched us to the debug stack and pushed the interrupt number.\r
179##\r
180## Next, construct the context record. It will be build on the debug stack by\r
181## pushing the registers in the correct order so as to create the context structure\r
182## on the debug stack. The context record must be built from the end back to the\r
183## beginning because the stack grows down...\r
184#\r
185## For reference, the context record looks like this:\r
186##\r
187## typedef\r
188## struct {\r
189## UINT64 ExceptionData;\r
190## FX_SAVE_STATE_X64 FxSaveState;\r
191## UINT64 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;\r
192## UINT64 Cr0, Cr2, Cr3, Cr4, Cr8;\r
193## UINT64 RFlags;\r
194## UINT64 Ldtr, Tr;\r
195## UINT64 Gdtr[2], Idtr[2];\r
196## UINT64 Rip;\r
197## UINT64 Gs, Fs, Es, Ds, Cs, Ss;\r
198## UINT64 Rdi, Rsi, Rbp, Rsp, Rbx, Rdx, Rcx, Rax;\r
199## UINT64 R8, R9, R10, R11, R12, R13, R14, R15;\r
200## } SYSTEM_CONTEXT_X64; // 64\r
201ASM_PFX(CommonIdtEntry):\r
202\r
7b414b4e 203 ret\r
c1f23d63 204\r
43a99f08 205## NOTE: we save rsp here to prevent compiler put rip reference cause error AppRsp\r
206 push rax\r
207 mov rax, qword ptr [rsp][8] # save vector number\r
208 mov ASM_PFX(ExceptionNumber), rax # save vector number\r
209 pop rax\r
210 add rsp, 8 # pop vector number\r
211 mov ASM_PFX(AppRsp), rsp # save stack top\r
212 mov rsp, offset DebugStackBegin # switch to debugger stack\r
213 sub rsp, 8 # leave space for vector number\r
214## UINT64 Rdi, Rsi, Rbp, Rsp, Rbx, Rdx, Rcx, Rax;\r
215## UINT64 R8, R9, R10, R11, R12, R13, R14, R15;\r
216 push r15\r
217 push r14\r
218 push r13\r
219 push r12\r
220 push r11\r
221 push r10\r
222 push r9\r
223 push r8\r
224 push rax\r
225 push rcx\r
226 push rdx\r
227 push rbx\r
228 push rsp\r
229 push rbp\r
230 push rsi\r
231 push rdi\r
232## Save interrupt state rflags register...\r
233 pushfq\r
234 pop rax\r
235 mov qword ptr ASM_PFX(Rflags), rax\r
236## We need to determine if any extra data was pushed by the exception, and if so, save it\r
237## To do this, we check the exception number pushed by the stub, and cache the\r
238## result in a variable since we'll need this again.\r
239 cmp dword ptr ASM_PFX(ExceptionNumber), 0\r
240 jz ExtraPushOne\r
241 cmp dword ptr ASM_PFX(ExceptionNumber), 10\r
242 jz ExtraPushOne\r
243 cmp dword ptr ASM_PFX(ExceptionNumber), 11\r
244 jz ExtraPushOne\r
245 cmp dword ptr ASM_PFX(ExceptionNumber), 12\r
246 jz ExtraPushOne\r
247 cmp dword ptr ASM_PFX(ExceptionNumber), 13\r
248 jz ExtraPushOne\r
249 cmp dword ptr ASM_PFX(ExceptionNumber), 14\r
250 jz ExtraPushOne\r
251 cmp dword ptr ASM_PFX(ExceptionNumber), 17\r
252 jz ExtraPushOne\r
253 mov dword ptr ASM_PFX(ExtraPush), 0\r
254 mov dword ptr ASM_PFX(ExceptData), 0\r
255 jmp ExtraPushDone\r
256ExtraPushOne:\r
257 mov dword ptr ASM_PFX(ExtraPush), 1\r
258\r
259## If there's some extra data, save it also, and modify the saved AppRsp to effectively\r
260## pop this value off the application's stack.\r
261 mov rax, ASM_PFX(AppRsp)\r
262 mov rbx, [rax]\r
263 mov ASM_PFX(ExceptData), rbx\r
264 add rax, 8\r
265 mov ASM_PFX(AppRsp), rax\r
266\r
267ExtraPushDone:\r
268\r
269## The "push" above pushed the debug stack rsp. Since what we're actually doing\r
270## is building the context record on the debug stack, we need to save the pushed\r
271## debug RSP, and replace it with the application's last stack entry...\r
272 mov rax, [rsp + 24]\r
273 mov ASM_PFX(DebugRsp), rax\r
274 mov rax, ASM_PFX(AppRsp)\r
275 add rax, 40\r
276 # application stack has ss, rsp, rflags, cs, & rip, so\r
277 # last actual application stack entry is\r
278 # 40 bytes into the application stack.\r
279 mov [rsp + 24], rax\r
280## continue building context record\r
281## UINT64 Gs, Fs, Es, Ds, Cs, Ss; insure high 16 bits of each is zero\r
282 mov rax, ss\r
283 push rax\r
284 # CS from application is one entry back in application stack\r
285 mov rax, ASM_PFX(AppRsp)\r
286 movzx rax, word ptr [rax + 8]\r
287 push rax\r
288\r
289 mov rax, ds\r
290 push rax\r
291 mov rax, es\r
292 push rax\r
293 mov rax, fs\r
294 push rax\r
295 mov rax, gs\r
296 push rax\r
297## UINT64 Rip;\r
298 # Rip from application is on top of application stack\r
299 mov rax, ASM_PFX(AppRsp)\r
300 push qword ptr [rax]\r
301## UINT64 Gdtr[2], Idtr[2];\r
302 push 0\r
303 push 0\r
304 sidt qword ptr [rsp]\r
305 push 0\r
306 push 0\r
307 sgdt qword ptr [rsp]\r
308\r
309## UINT64 Ldtr, Tr;\r
310 xor rax, rax\r
311 str ax\r
312 push rax\r
313 sldt ax\r
314 push rax\r
315\r
316## UINT64 RFlags;\r
317## Rflags from application is two entries back in application stack\r
318 mov rax, ASM_PFX(AppRsp)\r
319 push qword ptr [rax + 16]\r
320## UINT64 Cr0, Cr1, Cr2, Cr3, Cr4, Cr8;\r
321## insure FXSAVE/FXRSTOR is enabled in CR4...\r
322## ... while we're at it, make sure DE is also enabled...\r
323 mov rax, cr8\r
324 push rax\r
325 mov rax, cr4\r
326 or rax, 0x208\r
327 mov cr4, rax\r
328 push rax\r
329 mov rax, cr3\r
330 push rax\r
331 mov rax, cr2\r
332 push rax\r
333 push 0\r
334 mov rax, cr0\r
335 push rax\r
336## UINT64 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;\r
337 mov rax, dr7\r
338 push rax\r
339## clear Dr7 while executing debugger itself\r
340 xor rax, rax\r
341 mov dr7, rax\r
342\r
343 mov rax, dr6\r
344 push rax\r
345## insure all status bits in dr6 are clear...\r
346 xor rax, rax\r
347 mov dr6, rax\r
348\r
349 mov rax, dr3\r
350 push rax\r
351 mov rax, dr2\r
352 push rax\r
353 mov rax, dr1\r
354 push rax\r
355 mov rax, dr0\r
356 push rax\r
357\r
358## FX_SAVE_STATE_X64 FxSaveState;\r
359 sub rsp, 512\r
360 mov rdi, rsp\r
361 # IMPORTANT!! The debug stack has been carefully constructed to\r
362 # insure that rsp and rdi are 16 byte aligned when we get here.\r
363 # They MUST be. If they are not, a GP fault will occur.\r
364 # FXSTOR_RDI\r
365 .byte 0x0f\r
366 .byte 0xae\r
367 .byte 0x07\r
368\r
369## UINT64 ExceptionData;\r
370 mov rax, ASM_PFX(ExceptData)\r
371 push rax\r
372# call to C code which will in turn call registered handler\r
373# pass in the vector number\r
374 mov rdx, rsp\r
375 mov rcx, ASM_PFX(ExceptionNumber)\r
376 sub rsp, 40\r
377 call ASM_PFX(InterruptDistrubutionHub)\r
378 add rsp, 40\r
379# restore context...\r
380## UINT64 ExceptionData;\r
381 add rsp, 8\r
382## FX_SAVE_STATE_X64 FxSaveState;\r
383 mov rsi, rsp\r
384 # FXRSTOR_RSI\r
385 .byte 0x0f\r
386 .byte 0xae\r
387 .byte 0x0e\r
388 add rsp, 512\r
389;; UINT64 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;\r
390 pop rax\r
391 mov dr0, rax\r
392 pop rax\r
393 mov dr1, rax\r
394 pop rax\r
395 mov dr2, rax\r
396 pop rax\r
397 mov dr3, rax\r
398## skip restore of dr6. We cleared dr6 during the context save.\r
399 add rsp, 8\r
400 pop rax\r
401 mov dr7, rax\r
402## UINT64 Cr0, Cr1, Cr2, Cr3, Cr4, Cr8;\r
403 pop rax\r
404 mov cr0, rax\r
405 add rsp, 8\r
406 pop rax\r
407 mov cr2, rax\r
408 pop rax\r
409 mov cr3, rax\r
410 pop rax\r
411 mov cr4, rax\r
412 pop rax\r
413 mov cr8, rax\r
414## UINT64 RFlags;\r
415 mov rax, ASM_PFX(AppRsp)\r
416 pop qword ptr [rax + 16]\r
417## UINT64 Ldtr, Tr;\r
418## UINT64 Gdtr[2], Idtr[2];\r
419## Best not let anyone mess with these particular registers...\r
420 add rsp, 48\r
421## UINT64 Rip;\r
422 pop qword ptr [rax]\r
423\r
424## UINT64 Gs, Fs, Es, Ds, Cs, Ss;\r
425## NOTE - modified segment registers could hang the debugger... We\r
426## could attempt to insulate ourselves against this possibility,\r
427## but that poses risks as well.\r
428##\r
429\r
430 pop rax\r
431 # mov gs, rax\r
432 pop rax\r
433 # mov fs, rax\r
434 pop rax\r
435 mov es, rax\r
436 pop rax\r
437 mov ds, rax\r
438 mov rax, ASM_PFX(AppRsp)\r
439 pop qword ptr [rax + 8]\r
440 pop rax\r
441 mov ss, rax\r
442## The next stuff to restore is the general purpose registers that were pushed\r
443## using the "push" instruction.\r
444##\r
445## The value of RSP as stored in the context record is the application RSP\r
446## including the 5 entries on the application stack caused by the exception\r
447## itself. It may have been modified by the debug agent, so we need to\r
448## determine if we need to relocate the application stack.\r
449\r
450 mov rbx, [rsp + 24] # move the potentially modified AppRsp into rbx\r
451 mov rax, ASM_PFX(AppRsp)\r
452 add rax, 40\r
453 cmp rbx, rax\r
454 je NoAppStackMove\r
455\r
456 mov rax, ASM_PFX(AppRsp)\r
457 mov rcx, [rax] # RIP\r
458 mov [rbx], rcx\r
459\r
460 mov rcx, [rax + 8] # CS\r
461 mov [rbx + 8], rcx\r
462\r
463 mov rcx, [rax + 16] # RFLAGS\r
464 mov [rbx + 16], rcx\r
465\r
466 mov rcx, [rax + 24] # RSP\r
467 mov [rbx + 24], rcx\r
468\r
469 mov rcx, [rax + 32] # SS\r
470 mov [rbx + 32], rcx\r
471\r
472 mov rax, rbx # modify the saved AppRsp to the new AppRsp\r
473 mov ASM_PFX(AppRsp), rax\r
474NoAppStackMove:\r
475 mov rax, ASM_PFX(DebugRsp) # restore the DebugRsp on the debug stack\r
476 # so our "pop" will not cause a stack switch\r
477 mov [rsp + 24], rax\r
478\r
479 cmp dword ptr ASM_PFX(ExceptionNumber), 0x068\r
480 jne NoChain\r
481\r
482Chain:\r
483\r
484## Restore rflags so when we chain, the flags will be exactly as if we were never here.\r
485## We gin up the stack to do an iretq so we can get ALL the flags.\r
486 mov rax, ASM_PFX(AppRsp)\r
487 mov rbx, [rax + 40]\r
488 push rbx\r
489 mov rax, ss\r
490 push rax\r
491 mov rax, rsp\r
492 add rax, 16\r
493 push rax\r
494 mov rax, ASM_PFX(AppRsp)\r
495 mov rbx, [rax + 16]\r
496 and rbx, NOT 0x300 # special handling for IF and TF\r
497 push rbx\r
498 mov rax, cs\r
499 push rax\r
500 mov rax, offset PhonyIretq\r
501 push rax\r
502 iretq\r
503PhonyIretq:\r
504\r
505## UINT64 Rdi, Rsi, Rbp, Rsp, Rbx, Rdx, Rcx, Rax;\r
506## UINT64 R8, R9, R10, R11, R12, R13, R14, R15;\r
507 pop rdi\r
508 pop rsi\r
509 pop rbp\r
510 pop rsp\r
511 pop rbx\r
512 pop rdx\r
513 pop rcx\r
514 pop rax\r
515 pop r8\r
516 pop r9\r
517 pop r10\r
518 pop r11\r
519 pop r12\r
520 pop r13\r
521 pop r14\r
522 pop r15\r
523\r
524## Switch back to application stack\r
525 mov rsp, ASM_PFX(AppRsp)\r
526## Jump to original handler\r
527 jmp ASM_PFX(OrigVector)\r
528NoChain:\r
529## UINT64 Rdi, Rsi, Rbp, Rsp, Rbx, Rdx, Rcx, Rax;\r
530## UINT64 R8, R9, R10, R11, R12, R13, R14, R15;\r
531 pop rdi\r
532 pop rsi\r
533 pop rbp\r
534 pop rsp\r
535 pop rbx\r
536 pop rdx\r
537 pop rcx\r
538 pop rax\r
539 pop r8\r
540 pop r9\r
541 pop r10\r
542 pop r11\r
543 pop r12\r
544 pop r13\r
545 pop r14\r
546 pop r15\r
547\r
548## Switch back to application stack\r
549 mov rsp, ASM_PFX(AppRsp)\r
550\r
551## We're outa here...\r
552 iret\r