2 * FILE: ntoskrnl/ke/amd64/trap.S
3 * COPYRIGHT: See COPYING in the top level directory
4 * PURPOSE: System Traps, Entrypoints and Exitpoints
5 * PROGRAMMER: Timo Kreuzer (timo.kreuzer@reactos.org)
8 /* INCLUDES ******************************************************************/
10 #include <ndk/amd64/asm.h>
11 #include <ndk/amd64/asmmacro.S>
13 /* GLOBALS *******************************************************************/
17 .global _MsgUnimplemented
19 .asciz "WARNING: %s at %s:%d is UNIMPLEMENTED!\n"
22 .ascii "Page fault! Code = 0x%x, RIP = %p, FaultingAddress = %p\n\0"
25 .ascii "General protection fault at %p!\n\0"
28 .ascii "BreakpointTrap at %p\n\0"
30 _MsgUnexpectedInterrupt:
31 .ascii "UnexpectedInterrupt\n\0"
33 _MsgInvalidOpcodeFault:
34 .ascii "General protection fault at %p!\n\0"
37 .ascii "Trap: %s at %p\n\0"
46 lea rcx, _MsgTrapInfo[rip]
48 mov r8, [rbp + KTRAP_FRAME_Rip]
49 call _FrLdrDbgPrint[rip]
54 /* Helper Macros *************************************************************/
56 #define TRAPFLAG_VOLATILES 0x01
57 #define TRAPFLAG_NONVOLATILES 0x02
58 #define TRAPFLAG_XMM 0x04
59 #define TRAPFLAG_SEGMENTS 0x08
60 #define TRAPFLAG_DEBUG 0x10
62 #define TRAPFLAG_SYSTEMSERVICE (TRAPFLAG_VOLATILES|TRAPFLAG_DEBUG)
63 #define TRAPFLAG_ALL 0xff
67 * |-------------------|
69 * |-------------------| <- rbp
70 * | EXCEPTION_RECORD |
71 * |-------------------|
72 * | KEXCEPTION_FRAME |
73 * |-------------------| <- rsp
78 * ENTER_TRAP_FRAME - Allocate SIZE_KTRAP_FRAME and save registers to it
80 .macro ENTER_TRAP_FRAME Flags
81 .set SIZE_INITIAL_FRAME, 7 * 8
82 //.set SIZE_LOCAL_DATA, SIZE_EXCEPTION_RECORD + 0x28
83 .set SIZE_TRAP_FRAME_ALLOC, SIZE_KTRAP_FRAME - SIZE_INITIAL_FRAME
84 .set TRAPFLAGS, \Flags
90 /* Make room for a KTRAP_FRAME and function parameters */
91 sub rsp, SIZE_TRAP_FRAME_ALLOC
92 .allocstack SIZE_TRAP_FRAME_ALLOC
94 /* Point rbp to the KTRAP_FRAME */
97 .if (TRAPFLAGS & TRAPFLAG_NONVOLATILES)
98 /* Save non-volatile registers */
99 mov [rbp + KTRAP_FRAME_Rbx], rbx
100 mov [rbp + KTRAP_FRAME_Rdi], rdi
101 mov [rbp + KTRAP_FRAME_Rsi], rsi
104 .if (TRAPFLAGS & TRAPFLAG_VOLATILES)
105 /* Save volatile registers */
106 mov [rbp + KTRAP_FRAME_Rax], rax
107 mov [rbp + KTRAP_FRAME_Rcx], rcx
108 mov [rbp + KTRAP_FRAME_Rdx], rdx
109 mov [rbp + KTRAP_FRAME_R8], r8
110 mov [rbp + KTRAP_FRAME_R9], r9
111 mov [rbp + KTRAP_FRAME_R10], r10
112 mov [rbp + KTRAP_FRAME_R11], r11
115 .if (TRAPFLAGS & TRAPFLAG_XMM)
116 /* Save xmm registers */
117 // movdqa [rbp + KTRAP_FRAME_Xmm0], xmm0
118 // movdqa [rbp + KTRAP_FRAME_Xmm1], xmm1
119 // movdqa [rbp + KTRAP_FRAME_Xmm2], xmm2
120 // movdqa [rbp + KTRAP_FRAME_Xmm3], xmm3
121 // movdqa [rbp + KTRAP_FRAME_Xmm4], xmm4
122 // movdqa [rbp + KTRAP_FRAME_Xmm5], xmm5
125 .if (TRAPFLAGS & TRAPFLAG_SEGMENTS)
126 /* Save segment selectors */
128 mov [rbp + KTRAP_FRAME_SegDs], ax
130 mov [rbp + KTRAP_FRAME_SegEs], ax
132 mov [rbp + KTRAP_FRAME_SegFs], ax
134 mov [rbp + KTRAP_FRAME_SegGs], ax
137 /* Save previous mode and swap gs when it was UserMode */
138 mov ax, [rbp + KTRAP_FRAME_SegCs]
140 mov [rbp + KTRAP_FRAME_PreviousMode], al
145 /* Save previous irql */
147 mov [rbp + KTRAP_FRAME_PreviousIrql], al
149 // KTRAP_FRAME_FaultIndicator
150 // KTRAP_FRAME_ExceptionActive
153 .if (TRAPFLAGS & TRAPFLAG_DEBUG)
154 /* Save debug registers */
156 mov [rbp + KTRAP_FRAME_Dr0], rax
158 mov [rbp + KTRAP_FRAME_Dr1], rax
160 mov [rbp + KTRAP_FRAME_Dr2], rax
162 mov [rbp + KTRAP_FRAME_Dr3], rax
164 mov [rbp + KTRAP_FRAME_Dr6], rax
166 mov [rbp + KTRAP_FRAME_Dr7], rax
169 // KTRAP_FRAME_DebugControl
170 // KTRAP_FRAME_LastBranchToRip
171 // KTRAP_FRAME_LastBranchFromRip
172 // KTRAP_FRAME_LastExceptionToRip
173 // KTRAP_FRAME_LastExceptionFromRip
174 // KTRAP_FRAME_TrapFrame
176 /* Make sure the direction flag is cleared */
182 * LEAVE_TRAP_FRAME - Restore registers and free stack space
184 .macro LEAVE_TRAP_FRAME
186 .if (TRAPFLAGS & TRAPFLAG_SEGMENTS)
187 /* Restore segment selectors */
188 mov ax, [rbp + KTRAP_FRAME_SegDs]
190 mov ax, [rbp + KTRAP_FRAME_SegEs]
192 mov ax, [rbp + KTRAP_FRAME_SegFs]
196 test byte ptr [rbp + KTRAP_FRAME_PreviousMode], 1
201 .if (TRAPFLAGS & TRAPFLAG_NONVOLATILES)
202 /* Restore non-volatile registers */
203 mov rbx, [rbp + KTRAP_FRAME_Rbx]
204 mov rdi, [rbp + KTRAP_FRAME_Rdi]
205 mov rsi, [rbp + KTRAP_FRAME_Rsi]
208 .if (TRAPFLAGS & TRAPFLAG_VOLATILES)
209 /* Restore volatile registers */
210 mov rax, [rbp + KTRAP_FRAME_Rax]
211 mov rcx, [rbp + KTRAP_FRAME_Rcx]
212 mov rdx, [rbp + KTRAP_FRAME_Rdx]
213 mov r8, [rbp + KTRAP_FRAME_R8]
214 mov r9, [rbp + KTRAP_FRAME_R9]
215 mov r10, [rbp + KTRAP_FRAME_R10]
216 mov r11, [rbp + KTRAP_FRAME_R11]
219 .if (TRAPFLAGS & TRAPFLAG_XMM)
220 /* Restore xmm registers */
221 // movdqa xmm0, [rbp + KTRAP_FRAME_Xmm0]
222 // movdqa xmm1, [rbp + KTRAP_FRAME_Xmm1]
223 // movdqa xmm2, [rbp + KTRAP_FRAME_Xmm2]
224 // movdqa xmm3, [rbp + KTRAP_FRAME_Xmm3]
225 // movdqa xmm4, [rbp + KTRAP_FRAME_Xmm4]
226 // movdqa xmm5, [rbp + KTRAP_FRAME_Xmm5]
230 mov rbp, [rbp + KTRAP_FRAME_Rbp]
232 /* Adjust stack pointer (plus one qword for rbp, one for error code) */
233 add rsp, SIZE_TRAP_FRAME_ALLOC + 0x10
237 /* FUNCTIONS *****************************************************************/
242 // rbp = TrapFrame, eax = ExceptionCode, edx = NumParams, r9,r10,r11 = params
243 _InternalDispatchException:
245 /* Allocate stack space for EXCEPTION_RECORD and KEXCEPTION_FRAME */
246 sub rsp, SIZE_EXCEPTION_RECORD + SIZE_KEXCEPTION_FRAME
248 /* Set up EXCEPTION_RECORD */
249 lea rcx, [rsp + SIZE_KEXCEPTION_FRAME]
250 mov [rcx + EXCEPTION_RECORD_ExceptionCode], eax
252 mov [rcx + EXCEPTION_RECORD_ExceptionFlags], eax
253 mov [rcx + EXCEPTION_RECORD_ExceptionRecord], rax
254 mov rax, [rbp + KTRAP_FRAME_Rip]
255 mov [rcx + EXCEPTION_RECORD_ExceptionAddress], rax
256 mov [rcx + EXCEPTION_RECORD_NumberParameters], edx
257 mov [rcx + EXCEPTION_RECORD_ExceptionInformation + 0x00], r9
258 mov [rcx + EXCEPTION_RECORD_ExceptionInformation + 0x08], r10
259 mov [rcx + EXCEPTION_RECORD_ExceptionInformation + 0x10], r11
261 /* Set up KEXCEPTION_FRAME */
262 mov rax, [rbp + KTRAP_FRAME_Rbp]
263 mov [rsp + KEXCEPTION_FRAME_Rbp], rax
264 mov [rsp + KEXCEPTION_FRAME_Rbx], rbx
265 mov [rsp + KEXCEPTION_FRAME_Rdi], rdi
266 mov [rsp + KEXCEPTION_FRAME_Rsi], rsi
267 mov [rsp + KEXCEPTION_FRAME_R12], r12
268 mov [rsp + KEXCEPTION_FRAME_R13], r13
269 mov [rsp + KEXCEPTION_FRAME_R14], r14
270 mov [rsp + KEXCEPTION_FRAME_R15], r15
271 mov qword ptr [rsp + KEXCEPTION_FRAME_Return], 0
273 /* Call KiDispatchException */
274 // rcx already points to ExceptionRecord
275 mov rdx, rsp // ExceptionFrame
276 mov r8, rbp // TrapFrame
277 mov r9b, [r8 + KTRAP_FRAME_PreviousMode] // PreviousMode
278 mov byte ptr [rsp + KEXCEPTION_FRAME_P5], 1 // FirstChance
279 call _KiDispatchException
281 add rsp, SIZE_EXCEPTION_RECORD + SIZE_KEXCEPTION_FRAME
284 /* SOFTWARE INTERRUPT SERVICES ***********************************************/
286 .proc KiDivideErrorFault
288 /* Push pseudo error code */
292 UNIMPLEMENTED KiDivideErrorFault
297 .proc KiDebugTrapOrFault
299 /* Push pseudo error code */
303 ENTER_TRAP_FRAME TRAPFLAG_ALL
305 TRAPINFO KiDebugTrapOrFault
307 /* Check if the frame was from kernelmode */
308 test word ptr [rbp + KTRAP_FRAME_SegCs], 3
309 jz KiDebugTrapOrFaultKMode
311 /* Enable interrupts for user-mode */
314 KiDebugTrapOrFaultKMode:
316 /* Dispatch the exception */
317 mov eax, STATUS_SINGLE_STEP
322 call _InternalDispatchException
331 /* Push pseudo error code */
335 UNIMPLEMENTED KiNmiInterrupt
340 .proc KiBreakpointTrap
342 /* Push pseudo error code */
346 ENTER_TRAP_FRAME TRAPFLAG_ALL
348 TRAPINFO KiBreakpointTrap
350 // lea rcx, _MsgBreakpointTrap[rip]
352 // call _FrLdrDbgPrint[rip]
354 /* Dispatch the exception */
355 mov eax, STATUS_BREAKPOINT
360 call _InternalDispatchException
369 /* Push pseudo error code */
373 UNIMPLEMENTED KiOverflowTrap
379 /* Push pseudo error code */
389 UNIMPLEMENTED KiBoundFault
394 .proc KiInvalidOpcodeFault
396 /* Push pseudo error code */
400 ENTER_TRAP_FRAME TRAPFLAG_ALL
402 TRAPINFO KiInvalidOpcodeFault
404 // DISPATCH_EXCEPTION STATUS_BREAKPOINT, 3, 0, 0, 0
406 mov rdx, [rbp + KTRAP_FRAME_Rip]
407 lea rcx, _MsgInvalidOpcodeFault[rip]
408 call _FrLdrDbgPrint[rip]
416 .proc KiNpxNotAvailableFault
418 /* Push pseudo error code */
422 UNIMPLEMENTED KiNpxNotAvailableFault
427 .proc KiDoubleFaultAbort
429 /* Push pseudo error code */
433 /* Reserve stack space for parameters */
437 /* Bugcheck code UNEXPECTED_KERNEL_MODE_TRAP */
440 /* Set double fault parameters */
444 mov qword ptr [rsp + 0x20], 0
451 .proc KiNpxSegmentOverrunAbort
453 /* Push pseudo error code */
457 UNIMPLEMENTED KiNpxSegmentOverrunAbort
462 .proc KiInvalidTssFault
464 /* We have an error code */
466 UNIMPLEMENTED KiInvalidTssFault
472 .proc KiSegmentNotPresentFault
474 /* We have an error code */
476 UNIMPLEMENTED KiSegmentNotPresentFault
483 /* We have an error code */
485 UNIMPLEMENTED KiStackFault
491 .proc KiGeneralProtectionFault
493 /* We have an error code */
496 ENTER_TRAP_FRAME TRAPFLAG_ALL
498 TRAPINFO KiGeneralProtectionFault
500 mov rdx, [rbp + KTRAP_FRAME_Rip]
501 lea rcx, _MsgGeneralProtFault[rip]
502 call _FrLdrDbgPrint[rip]
504 /* Check if this was from user-mode */
505 cmp byte ptr [rbp + KTRAP_FRAME_PreviousMode], KernelMode
508 /* Get instruction */
509 mov rax, [rbp + KTRAP_FRAME_Rip]
512 /* Check for MSR failure */
520 /* Check for pop ds/es/fs/gs */
532 mov dx, 0x002B // KGDT64_R3_DATA | RPL_MASK
533 cmp [rbp + KTRAP_FRAME_SegDs], dx
535 cmp [rbp + KTRAP_FRAME_SegEs], dx
537 cmp [rbp + KTRAP_FRAME_SegFs], dx
539 cmp [rbp + KTRAP_FRAME_SegGs], dx
545 mov ecx, UNEXPECTED_KERNEL_MODE_TRAP
546 mov rdx, 0x0000D // EXCEPTION_GP_FAULT
549 xor r9, r9 // Reserved
550 mov [rbp + KTRAP_FRAME_P5], rbp // trap frame
551 call _KeBugCheckWithTf
556 mov [rbp + KTRAP_FRAME_SegDs], dx
560 mov [rbp + KTRAP_FRAME_SegEs], dx
564 mov [rbp + KTRAP_FRAME_SegFs], dx
568 mov [rbp + KTRAP_FRAME_SegGs], dx
576 mov ax, [rbp + KTRAP_FRAME_ErrorCode]
586 /* Dispatch the exception */
587 mov eax, STATUS_ACCESS_VIOLATION
589 mov r9, [rbp + KTRAP_FRAME_ErrorCode]
592 call _InternalDispatchException
605 /* We have an error code */
607 ENTER_TRAP_FRAME TRAPFLAG_ALL
612 lea rcx, _MsgPageFault[rip]
613 mov rdx, [rbp + KTRAP_FRAME_ErrorCode]
614 mov r8, [rbp + KTRAP_FRAME_Rip]
615 mov r9, [rbp + KTRAP_FRAME_FaultAddress]
616 call _FrLdrDbgPrint[rip]
619 /* Save page fault address */
621 mov [rbp + KTRAP_FRAME_FaultAddress], rdx
623 /* Call page fault handler */
624 mov ecx, [rbp + KTRAP_FRAME_ErrorCode] // StoreInstruction
627 mov r8b, [rbp + KTRAP_FRAME_SegCs] // Mode
629 mov r9, rbp // TrapInformation
632 /* Check for success */
636 /* Set parameter 1 to error code */
637 mov r9d, [rbp + KTRAP_FRAME_ErrorCode]
639 /* Set parameter2 to faulting address */
640 mov r10, cr2 // Param2 = faulting address
642 cmp eax, STATUS_ACCESS_VIOLATION
644 cmp eax, STATUS_GUARD_PAGE_VIOLATION
646 cmp eax, STATUS_STACK_OVERFLOW
650 /* Dispatch in-page exception */
651 mov r11d, eax // Param3 = Status
652 mov eax, STATUS_IN_PAGE_ERROR // ExceptionCode
653 mov edx, 3 // ParamCount
654 call _InternalDispatchException
658 /* Use more proper status code */
659 mov eax, KI_EXCEPTION_ACCESS_VIOLATION
662 /* Setup a normal page fault exception */
663 mov edx, 2 // ParamCount
664 call _InternalDispatchException
672 .proc KiFloatingErrorFault
674 /* Push pseudo error code */
678 UNIMPLEMENTED KiFloatingErrorFault
683 .proc KiAlignmentFault
685 /* We have an error code */
687 UNIMPLEMENTED KiAlignmentFault
694 /* Push pseudo error code */
698 UNIMPLEMENTED KiMcheckAbort
705 /* Push pseudo error code */
709 UNIMPLEMENTED KiXmmException
717 UNIMPLEMENTED KiApcInterrupt
722 .proc KiRaiseAssertion
725 UNIMPLEMENTED KiRaiseAssertion
730 .proc KiDebugServiceTrap
732 /* Push pseudo error code */
736 ENTER_TRAP_FRAME TRAPFLAG_ALL
738 TRAPINFO KiDebugServiceTrap
740 /* Increase Rip to skip the int3 */
741 inc qword ptr [rbp + KTRAP_FRAME_Rip]
743 /* Dispatch the exception */
744 mov eax, STATUS_BREAKPOINT
746 mov r9, [rbp+KTRAP_FRAME_Rax] // Service
747 mov r10, [rbp+KTRAP_FRAME_Rcx] // Buffer
748 mov r11, [rbp+KTRAP_FRAME_Rdx] // Length
749 call _InternalDispatchException
759 UNIMPLEMENTED KiDpcInterrupt
768 UNIMPLEMENTED KiIpiInterrupt
774 .proc KiUnexpectedInterrupt
779 lea rcx, _MsgUnexpectedInterrupt[rip]
780 call _FrLdrDbgPrint[rip]
782 mov ecx, TRAP_CAUSE_UNKNOWN
783 // mov rdx, // The unexpected interrupt
784 // mov rdx, // The unknown floating-point exception
785 // mov r8, // The enabled and asserted status bits
786 xor r9, r9 // Reserved
787 mov [rbp + KTRAP_FRAME_P5], rbp // trap frame
788 call _KeBugCheckWithTf
793 .proc KiSystemFatalException