diff --git a/SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/X64/AsmFuncs.nasm b/SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/X64/AsmFuncs.nasm new file mode 100644 index 0000000000..dcb5f9dbb9 --- /dev/null +++ b/SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/X64/AsmFuncs.nasm @@ -0,0 +1,405 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2016, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; Module Name: +; +; AsmFuncs.nasm +; +; Abstract: +; +; Debug interrupt handle functions. +; +;------------------------------------------------------------------------------ + +#include "DebugException.h" + +SECTION .data + +extern ASM_PFX(InterruptProcess) +global ASM_PFX(Exception0Handle) +global ASM_PFX(TimerInterruptHandle) +global ASM_PFX(ExceptionStubHeaderSize) + +%macro AGENT_HANDLER_SIGNATURE 0 + db 0x41, 0x47, 0x54, 0x48 ; SIGNATURE_32('A','G','T','H') +%endmacro + +ASM_PFX(ExceptionStubHeaderSize): dd Exception1Handle - ASM_PFX(Exception0Handle) ; +CommonEntryAddr: dq CommonEntry ; + +DEFAULT REL +SECTION .text + +AGENT_HANDLER_SIGNATURE +ASM_PFX(Exception0Handle): + cli + push rcx + mov rcx, dword 0 + jmp qword [CommonEntryAddr] +AGENT_HANDLER_SIGNATURE +Exception1Handle: + cli + push rcx + mov rcx, dword 1 + jmp qword [CommonEntryAddr] +AGENT_HANDLER_SIGNATURE +Exception2Handle: + cli + push rcx + mov rcx, dword 2 + jmp qword [CommonEntryAddr] +AGENT_HANDLER_SIGNATURE +Exception3Handle: + cli + push rcx + mov rcx, dword 3 + jmp qword [CommonEntryAddr] +AGENT_HANDLER_SIGNATURE +Exception4Handle: + cli + push rcx + mov rcx, dword 4 + jmp qword [CommonEntryAddr] +AGENT_HANDLER_SIGNATURE +Exception5Handle: + cli + push rcx + mov rcx, dword 5 + jmp qword [CommonEntryAddr] +AGENT_HANDLER_SIGNATURE +Exception6Handle: + cli + push rcx + mov rcx, dword 6 + jmp qword [CommonEntryAddr] +AGENT_HANDLER_SIGNATURE +Exception7Handle: + cli + push rcx + mov rcx, dword 7 + jmp qword [CommonEntryAddr] +AGENT_HANDLER_SIGNATURE +Exception8Handle: + cli + push rcx + mov rcx, dword 8 + jmp qword [CommonEntryAddr] +AGENT_HANDLER_SIGNATURE +Exception9Handle: + cli + push rcx + mov rcx, dword 9 + jmp qword [CommonEntryAddr] +AGENT_HANDLER_SIGNATURE +Exception10Handle: + cli + push rcx + mov rcx, dword 10 + jmp qword [CommonEntryAddr] +AGENT_HANDLER_SIGNATURE +Exception11Handle: + cli + push rcx + mov rcx, dword 11 + jmp qword [CommonEntryAddr] +AGENT_HANDLER_SIGNATURE +Exception12Handle: + cli + push rcx + mov rcx, dword 12 + jmp qword [CommonEntryAddr] +AGENT_HANDLER_SIGNATURE +Exception13Handle: + cli + push rcx + mov rcx, dword 13 + jmp qword [CommonEntryAddr] +AGENT_HANDLER_SIGNATURE +Exception14Handle: + cli + push rcx + mov rcx, dword 14 + jmp qword [CommonEntryAddr] +AGENT_HANDLER_SIGNATURE +Exception15Handle: + cli + push rcx + mov rcx, dword 15 + jmp qword [CommonEntryAddr] +AGENT_HANDLER_SIGNATURE +Exception16Handle: + cli + push rcx + mov rcx, dword 16 + jmp qword [CommonEntryAddr] +AGENT_HANDLER_SIGNATURE +Exception17Handle: + cli + push rcx + mov rcx, dword 17 + jmp qword [CommonEntryAddr] +AGENT_HANDLER_SIGNATURE +Exception18Handle: + cli + push rcx + mov rcx, dword 18 + jmp qword [CommonEntryAddr] +AGENT_HANDLER_SIGNATURE +Exception19Handle: + cli + push rcx + mov rcx, dword 19 + jmp qword [CommonEntryAddr] +AGENT_HANDLER_SIGNATURE +ASM_PFX(TimerInterruptHandle): + cli + push rcx + mov rcx, dword 32 + jmp qword [CommonEntryAddr] + +CommonEntry: + ; We need to determine if any extra data was pushed by the exception + cmp rcx, DEBUG_EXCEPT_DOUBLE_FAULT + je NoExtrPush + cmp rcx, DEBUG_EXCEPT_INVALID_TSS + je NoExtrPush + cmp rcx, DEBUG_EXCEPT_SEG_NOT_PRESENT + je NoExtrPush + cmp rcx, DEBUG_EXCEPT_STACK_FAULT + je NoExtrPush + cmp rcx, DEBUG_EXCEPT_GP_FAULT + je NoExtrPush + cmp rcx, DEBUG_EXCEPT_PAGE_FAULT + je NoExtrPush + cmp rcx, DEBUG_EXCEPT_ALIGNMENT_CHECK + je NoExtrPush + + push qword [rsp] + mov qword [rsp + 8], 0 + +NoExtrPush: + push rbp + mov rbp, rsp + + ; store UINT64 r8, r9, r10, r11, r12, r13, r14, r15; + push r15 + push r14 + push r13 + push r12 + push r11 + push r10 + push r9 + push r8 + + mov r8, cr8 + push r8 + + ; store UINT64 Rdi, Rsi, Rbp, Rsp, Rdx, Rcx, Rbx, Rax; + push rax + push rbx + push qword [rbp + 8] ; original rcx + push rdx + push qword [rbp + 6 * 8] ; original rsp + push qword [rbp] ; original rbp + push rsi + push rdi + + ;; UINT32 Cr0, Cr1, Cr2, Cr3, Cr4; + ;; insure FXSAVE/FXRSTOR is enabled in CR4... + ;; ... while we're at it, make sure DE is also enabled... + mov rax, cr4 + or rax, 0x208 + mov cr4, rax + push rax + mov rax, cr3 + push rax + mov rax, cr2 + push rax + push 0 + mov rax, cr0 + push rax + + xor rax, rax + mov rax, Ss + push rax + mov rax, Cs + push rax + mov rax, Ds + push rax + mov rax, Es + push rax + mov rax, Fs + push rax + mov rax, Gs + push rax + + ;; EIP + mov rax, [rbp + 8 * 3] ; EIP + push rax + + ;; UINT64 Gdtr[2], Idtr[2]; + sub rsp, 16 + sidt [rsp] + sub rsp, 16 + sgdt [rsp] + + ;; UINT64 Ldtr, Tr; + xor rax, rax + str ax + push rax + sldt ax + push rax + + ;; EFlags + mov rax, [rbp + 8 * 5] + push rax + + ;; UINT64 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7; + mov rax, dr7 + push rax + + ;; clear Dr7 while executing debugger itself + xor rax, rax + mov dr7, rax + + ;; Dr6 + mov rax, dr6 + push rax + + ;; insure all status bits in dr6 are clear... + xor rax, rax + mov dr6, rax + + mov rax, dr3 + push rax + mov rax, dr2 + push rax + mov rax, dr1 + push rax + mov rax, dr0 + push rax + + ;; Clear Direction Flag + cld + + sub rsp, 512 + mov rdi, rsp + ;; Clear the buffer + xor rax, rax + push rcx + mov rcx, dword 64 ;= 512 / 8 + rep stosq + pop rcx + mov rdi, rsp + db 0xf, 0xae, 00000111y ;fxsave [rdi] + + ;; save the exception data + push qword [rbp + 16] + + ; call the C interrupt process function + mov rdx, rsp ; Structure + mov r15, rcx ; save vector in r15 + + ; + ; Per X64 calling convention, allocate maximum parameter stack space + ; and make sure RSP is 16-byte aligned + ; + sub rsp, 32 + 8 + call ASM_PFX(InterruptProcess) + add rsp, 32 + 8 + + ;; skip the exception data + add rsp, 8 + + mov rsi, rsp + db 0xf, 0xae, 00001110y ; fxrstor [rsi] + add rsp, 512 + + ;; UINT64 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7; + pop rax + mov dr0, rax + pop rax + mov dr1, rax + pop rax + mov dr2, rax + pop rax + mov dr3, rax + ;; skip restore of dr6. We cleared dr6 during the context save. + add rsp, 8 + pop rax + mov dr7, rax + + ;; set EFlags + pop qword [rbp + 8 * 5] + + ;; UINT64 Ldtr, Tr; + ;; UINT64 Gdtr[2], Idtr[2]; + ;; Best not let anyone mess with these particular registers... + add rsp, 24 * 2 + + ;; UINT64 Eip; + pop qword [rbp + 8 * 3] ; set EIP in stack + + ;; UINT64 Gs, Fs, Es, Ds, Cs, Ss; + ;; NOTE - modified segment registers could hang the debugger... We + ;; could attempt to insulate ourselves against this possibility, + ;; but that poses risks as well. + ;; + pop rax + pop rax + pop rax + mov es, rax + pop rax + mov ds, rax + pop qword [rbp + 8 * 4] ; Set CS in stack + pop rax + mov ss, rax + + ;; UINT64 Cr0, Cr1, Cr2, Cr3, Cr4; + pop rax + mov cr0, rax + add rsp, 8 ; skip for Cr1 + pop rax + mov cr2, rax + pop rax + mov cr3, rax + pop rax + mov cr4, rax + + ;; restore general register + pop rdi + pop rsi + add rsp, 8 ; skip rbp + add rsp, 8 ; skip rsp + pop rdx + pop rcx + pop rbx + pop rax + + pop r8 + mov cr8, r8 + + ; store UINT64 r8, r9, r10, r11, r12, r13, r14, r15; + pop r8 + pop r9 + pop r10 + pop r11 + pop r12 + pop r13 + pop r14 + pop r15 + + mov rsp, rbp + pop rbp + add rsp, 16 ; skip rcx and error code + + iretq +