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