APIC_EOI = HEX(0FFFFFFFFFFFE00B0) TF_VOLATILES = HEX(01) TF_NONVOLATILES = HEX(02) TF_XMM = HEX(04) TF_SEGMENTS = HEX(08) TF_DEBUG = HEX(10) TF_IRQL = HEX(20) TF_SAVE_ALL = (TF_VOLATILES OR TF_NONVOLATILES OR TF_XMM OR TF_SEGMENTS) TF_HAS_ERROR_CODE = HEX(40) TF_SEND_EOI = HEX(80) //TF_SYSTEMSERVICE = (TRAPFLAG_VOLATILES or TRAPFLAG_DEBUG) /* * Stack Layout: * |-------------------| * | KTRAP_FRAME | * |-------------------| <- rbp * | EXCEPTION_RECORD | * |-------------------| * | KEXCEPTION_FRAME | * |-------------------| <- rsp * */ /* * EnterTrap - Allocate KTRAP_FRAME_LENGTH and save registers to it */ MACRO(EnterTrap, Flags) LOCAL dont_swap /* Save the trap flags for this trap */ CurrentTrapFlags = VAL(Flags) /* Size of hardware trap frame */ if (Flags AND TF_HAS_ERROR_CODE) .pushframe code SIZE_INITIAL_FRAME = 6 * 8 else .pushframe SIZE_INITIAL_FRAME = 5 * 8 endif /* Make room for a KTRAP_FRAME */ sub rsp, (KTRAP_FRAME_LENGTH - SIZE_INITIAL_FRAME) .allocstack (KTRAP_FRAME_LENGTH - SIZE_INITIAL_FRAME) .endprolog /* Save rbp and rax */ mov [rsp + KTRAP_FRAME_Rbp], rbp mov [rsp + KTRAP_FRAME_Rax], rax /* Point rbp to the KTRAP_FRAME */ lea rbp, [rsp] if (Flags AND TF_NONVOLATILES) /* Save non-volatile registers */ mov [rbp + KTRAP_FRAME_Rbx], rbx mov [rbp + KTRAP_FRAME_Rdi], rdi mov [rbp + KTRAP_FRAME_Rsi], rsi endif if (Flags AND TF_VOLATILES) /* Save volatile registers */ mov [rbp + KTRAP_FRAME_Rcx], rcx mov [rbp + KTRAP_FRAME_Rdx], rdx mov [rbp + KTRAP_FRAME_R8], r8 mov [rbp + KTRAP_FRAME_R9], r9 mov [rbp + KTRAP_FRAME_R10], r10 mov [rbp + KTRAP_FRAME_R11], r11 endif if (Flags AND TF_XMM) /* Save xmm registers */ movdqa [rbp + KTRAP_FRAME_Xmm0], xmm0 movdqa [rbp + KTRAP_FRAME_Xmm1], xmm1 movdqa [rbp + KTRAP_FRAME_Xmm2], xmm2 movdqa [rbp + KTRAP_FRAME_Xmm3], xmm3 movdqa [rbp + KTRAP_FRAME_Xmm4], xmm4 movdqa [rbp + KTRAP_FRAME_Xmm5], xmm5 endif if (Flags AND TF_SEGMENTS) /* Save segment selectors */ mov [rbp + KTRAP_FRAME_SegDs], ds mov [rbp + KTRAP_FRAME_SegEs], es mov [rbp + KTRAP_FRAME_SegFs], fs mov [rbp + KTRAP_FRAME_SegGs], gs endif /* Save previous mode and swap gs when it was UserMode */ mov ax, [rbp + KTRAP_FRAME_SegCs] and al, 1 mov [rbp + KTRAP_FRAME_PreviousMode], al jz dont_swap swapgs dont_swap: if (Flags AND TF_IRQL) /* Save previous irql */ mov rax, cr8 mov [rbp + KTRAP_FRAME_PreviousIrql], al endif if (Flags AND TF_DEBUG) /* Save debug registers */ mov rax, dr0 mov [rbp + KTRAP_FRAME_Dr0], rax mov rax, dr1 mov [rbp + KTRAP_FRAME_Dr1], rax mov rax, dr2 mov [rbp + KTRAP_FRAME_Dr2], rax mov rax, dr3 mov [rbp + KTRAP_FRAME_Dr3], rax mov rax, dr6 mov [rbp + KTRAP_FRAME_Dr6], rax mov rax, dr7 mov [rbp + KTRAP_FRAME_Dr7], rax endif /* Make sure the direction flag is cleared */ cld ENDM /* * ExitTrap - Restore registers and free stack space */ MACRO(ExitTrap, Flags) LOCAL dont_swap_back if (Flags AND TF_SEGMENTS) /* Restore segment selectors */ mov ds, [rbp + KTRAP_FRAME_SegDs] mov es, [rbp + KTRAP_FRAME_SegEs] mov fs, [rbp + KTRAP_FRAME_SegFs] endif if (Flags AND TF_IRQL) /* Restore previous irql */ movzx rax, byte ptr [rbp + KTRAP_FRAME_PreviousIrql] mov cr8, rax endif test byte ptr [rbp + KTRAP_FRAME_PreviousMode], 1 jz dont_swap_back swapgs dont_swap_back: if (Flags AND TF_NONVOLATILES) /* Restore non-volatile registers */ mov rbx, [rbp + KTRAP_FRAME_Rbx] mov rdi, [rbp + KTRAP_FRAME_Rdi] mov rsi, [rbp + KTRAP_FRAME_Rsi] endif if (Flags AND TF_VOLATILES) /* Restore volatile registers */ mov rax, [rbp + KTRAP_FRAME_Rax] mov rcx, [rbp + KTRAP_FRAME_Rcx] mov rdx, [rbp + KTRAP_FRAME_Rdx] mov r8, [rbp + KTRAP_FRAME_R8] mov r9, [rbp + KTRAP_FRAME_R9] mov r10, [rbp + KTRAP_FRAME_R10] mov r11, [rbp + KTRAP_FRAME_R11] endif if (Flags AND TF_XMM) /* Restore xmm registers */ movdqa xmm0, [rbp + KTRAP_FRAME_Xmm0] movdqa xmm1, [rbp + KTRAP_FRAME_Xmm1] movdqa xmm2, [rbp + KTRAP_FRAME_Xmm2] movdqa xmm3, [rbp + KTRAP_FRAME_Xmm3] movdqa xmm4, [rbp + KTRAP_FRAME_Xmm4] movdqa xmm5, [rbp + KTRAP_FRAME_Xmm5] endif /* Restore rbp */ mov rbp, [rbp + KTRAP_FRAME_Rbp] /* Adjust stack pointer */ add rsp, KTRAP_FRAME_Rip if (Flags AND TF_SEND_EOI) /* Write 0 to the local APIC EOI register */ mov dword ptr [APIC_EOI], 0 endif /* Return from the trap */ iretq ENDM MACRO(TRAP_ENTRY, Trap, Flags) EXTERN Trap&Handler :PROC PUBLIC &Trap FUNC &Trap /* Common code to create the trap frame */ EnterTrap Flags /* Call the C handler */ mov rcx, rbp call Trap&Handler /* Leave */ ExitTrap Flags ENDFUNC &Trap ENDM