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
238 // rbp = TrapFrame, eax = ExceptionCode, edx = NumParams, r9,r10,r11 = params
239 _InternalDispatchException:
241 /* Allocate stack space for EXCEPTION_RECORD and KEXCEPTION_FRAME */
242 sub rsp, SIZE_EXCEPTION_RECORD + SIZE_KEXCEPTION_FRAME
244 /* Set up EXCEPTION_RECORD */
245 lea rcx, [rsp + SIZE_KEXCEPTION_FRAME]
246 mov [rcx + EXCEPTION_RECORD_ExceptionCode], eax
248 mov [rcx + EXCEPTION_RECORD_ExceptionFlags], eax
249 mov [rcx + EXCEPTION_RECORD_ExceptionRecord], rax
250 mov rax, [rbp + KTRAP_FRAME_Rip]
251 mov [rcx + EXCEPTION_RECORD_ExceptionAddress], rax
252 mov [rcx + EXCEPTION_RECORD_NumberParameters], edx
253 mov [rcx + EXCEPTION_RECORD_ExceptionInformation + 0x00], r9
254 mov [rcx + EXCEPTION_RECORD_ExceptionInformation + 0x08], r10
255 mov [rcx + EXCEPTION_RECORD_ExceptionInformation + 0x10], r11
257 /* Set up KEXCEPTION_FRAME */
258 mov rax, [rbp + KTRAP_FRAME_Rbp]
259 mov [rsp + KEXCEPTION_FRAME_Rbp], rax
260 mov [rsp + KEXCEPTION_FRAME_Rbx], rbx
261 mov [rsp + KEXCEPTION_FRAME_Rdi], rdi
262 mov [rsp + KEXCEPTION_FRAME_Rsi], rsi
263 mov [rsp + KEXCEPTION_FRAME_R12], r12
264 mov [rsp + KEXCEPTION_FRAME_R13], r13
265 mov [rsp + KEXCEPTION_FRAME_R14], r14
266 mov [rsp + KEXCEPTION_FRAME_R15], r15
267 mov qword ptr [rsp + KEXCEPTION_FRAME_Return], 0
269 /* Call KiDispatchException */
270 // rcx already points to ExceptionRecord
271 mov rdx, rsp // ExceptionFrame
272 mov r8, rbp // TrapFrame
273 mov r9b, [r8 + KTRAP_FRAME_PreviousMode] // PreviousMode
274 mov byte ptr [rsp + KEXCEPTION_FRAME_P5], 1 // FirstChance
275 call _KiDispatchException
277 add rsp, SIZE_EXCEPTION_RECORD + SIZE_KEXCEPTION_FRAME
280 /* SOFTWARE INTERRUPT SERVICES ***********************************************/
284 .proc KiDivideErrorFault
286 /* Push pseudo error code */
290 UNIMPLEMENTED KiDivideErrorFault
295 .proc KiDebugTrapOrFault
297 /* Push pseudo error code */
301 ENTER_TRAP_FRAME TRAPFLAG_ALL
303 TRAPINFO KiDebugTrapOrFault
305 /* Check if the frame was from kernelmode */
306 test word ptr [rbp + KTRAP_FRAME_SegCs], 3
307 jz KiDebugTrapOrFaultKMode
309 /* Enable interrupts for user-mode */
312 KiDebugTrapOrFaultKMode:
314 /* Dispatch the exception */
315 mov eax, STATUS_SINGLE_STEP
320 call _InternalDispatchException
329 /* Push pseudo error code */
333 UNIMPLEMENTED KiNmiInterrupt
338 .proc KiBreakpointTrap
340 /* Push pseudo error code */
344 ENTER_TRAP_FRAME TRAPFLAG_ALL
346 TRAPINFO KiBreakpointTrap
348 // lea rcx, _MsgBreakpointTrap[rip]
350 // call _FrLdrDbgPrint[rip]
352 /* Dispatch the exception */
353 mov eax, STATUS_BREAKPOINT
358 call _InternalDispatchException
367 /* Push pseudo error code */
371 UNIMPLEMENTED KiOverflowTrap
377 /* Push pseudo error code */
387 UNIMPLEMENTED KiBoundFault
392 .proc KiInvalidOpcodeFault
394 /* Push pseudo error code */
398 ENTER_TRAP_FRAME TRAPFLAG_ALL
400 TRAPINFO KiInvalidOpcodeFault
402 // DISPATCH_EXCEPTION STATUS_BREAKPOINT, 3, 0, 0, 0
404 mov rdx, [rbp + KTRAP_FRAME_Rip]
405 lea rcx, _MsgInvalidOpcodeFault[rip]
406 call _FrLdrDbgPrint[rip]
414 .proc KiNpxNotAvailableFault
416 /* Push pseudo error code */
420 UNIMPLEMENTED KiNpxNotAvailableFault
425 .proc KiDoubleFaultAbort
427 /* Push pseudo error code */
431 /* Reserve stack space for parameters */
435 /* Bugcheck code UNEXPECTED_KERNEL_MODE_TRAP */
438 /* Set double fault parameters */
442 mov qword ptr [rsp + 0x20], 0
449 .proc KiNpxSegmentOverrunAbort
451 /* Push pseudo error code */
455 UNIMPLEMENTED KiNpxSegmentOverrunAbort
460 .proc KiInvalidTssFault
462 /* We have an error code */
464 UNIMPLEMENTED KiInvalidTssFault
470 .proc KiSegmentNotPresentFault
472 /* We have an error code */
474 UNIMPLEMENTED KiSegmentNotPresentFault
481 /* We have an error code */
483 UNIMPLEMENTED KiStackFault
489 .proc KiGeneralProtectionFault
491 /* We have an error code */
494 ENTER_TRAP_FRAME TRAPFLAG_ALL
496 TRAPINFO KiGeneralProtectionFault
498 mov rdx, [rbp + KTRAP_FRAME_Rip]
499 lea rcx, _MsgGeneralProtFault[rip]
500 call _FrLdrDbgPrint[rip]
502 /* Check if this was from user-mode */
503 cmp byte ptr [rbp + KTRAP_FRAME_PreviousMode], KernelMode
506 /* Get instruction */
507 mov rax, [rbp + KTRAP_FRAME_Rip]
510 /* Check for MSR failure */
518 /* Check for pop ds/es/fs/gs */
530 mov dx, 0x002B // KGDT64_R3_DATA | RPL_MASK
531 cmp [rbp + KTRAP_FRAME_SegDs], dx
533 cmp [rbp + KTRAP_FRAME_SegEs], dx
535 cmp [rbp + KTRAP_FRAME_SegFs], dx
537 cmp [rbp + KTRAP_FRAME_SegGs], dx
543 mov ecx, UNEXPECTED_KERNEL_MODE_TRAP
544 mov rdx, 0x0000D // EXCEPTION_GP_FAULT
547 xor r9, r9 // Reserved
548 mov [rbp + KTRAP_FRAME_P5], rbp // trap frame
549 call _KeBugCheckWithTf
554 mov [rbp + KTRAP_FRAME_SegDs], dx
558 mov [rbp + KTRAP_FRAME_SegEs], dx
562 mov [rbp + KTRAP_FRAME_SegFs], dx
566 mov [rbp + KTRAP_FRAME_SegGs], dx
574 mov ax, [rbp + KTRAP_FRAME_ErrorCode]
584 /* Dispatch the exception */
585 mov eax, STATUS_ACCESS_VIOLATION
587 mov r9, [rbp + KTRAP_FRAME_ErrorCode]
590 call _InternalDispatchException
603 /* We have an error code */
605 ENTER_TRAP_FRAME TRAPFLAG_ALL
610 lea rcx, _MsgPageFault[rip]
611 mov rdx, [rbp + KTRAP_FRAME_ErrorCode]
612 mov r8, [rbp + KTRAP_FRAME_Rip]
613 mov r9, [rbp + KTRAP_FRAME_FaultAddress]
614 call _FrLdrDbgPrint[rip]
617 /* Save page fault address */
619 mov [rbp + KTRAP_FRAME_FaultAddress], rdx
621 /* Call page fault handler */
622 mov ecx, [rbp + KTRAP_FRAME_ErrorCode] // StoreInstruction
625 mov r8b, [rbp + KTRAP_FRAME_SegCs] // Mode
627 mov r9, rbp // TrapInformation
630 /* Check for success */
634 /* Set parameter 1 to error code */
635 mov r9d, [rbp + KTRAP_FRAME_ErrorCode]
637 /* Set parameter2 to faulting address */
638 mov r10, cr2 // Param2 = faulting address
640 cmp eax, STATUS_ACCESS_VIOLATION
642 cmp eax, STATUS_GUARD_PAGE_VIOLATION
644 cmp eax, STATUS_STACK_OVERFLOW
648 /* Dispatch in-page exception */
649 mov r11d, eax // Param3 = Status
650 mov eax, STATUS_IN_PAGE_ERROR // ExceptionCode
651 mov edx, 3 // ParamCount
652 call _InternalDispatchException
656 /* Use more proper status code */
657 mov eax, KI_EXCEPTION_ACCESS_VIOLATION
660 /* Setup a normal page fault exception */
661 mov edx, 2 // ParamCount
662 call _InternalDispatchException
670 .proc KiFloatingErrorFault
672 /* Push pseudo error code */
676 UNIMPLEMENTED KiFloatingErrorFault
681 .proc KiAlignmentFault
683 /* We have an error code */
685 UNIMPLEMENTED KiAlignmentFault
692 /* Push pseudo error code */
696 UNIMPLEMENTED KiMcheckAbort
703 /* Push pseudo error code */
707 UNIMPLEMENTED KiXmmException
715 UNIMPLEMENTED KiApcInterrupt
720 .proc KiRaiseAssertion
723 UNIMPLEMENTED KiRaiseAssertion
728 .proc KiDebugServiceTrap
730 /* Push pseudo error code */
734 ENTER_TRAP_FRAME TRAPFLAG_ALL
736 TRAPINFO KiDebugServiceTrap
738 /* Increase Rip to skip the int3 */
739 inc qword ptr [rbp + KTRAP_FRAME_Rip]
741 /* Dispatch the exception */
742 mov eax, STATUS_BREAKPOINT
744 mov r9, [rbp+KTRAP_FRAME_Rax] // Service
745 mov r10, [rbp+KTRAP_FRAME_Rcx] // Buffer
746 mov r11, [rbp+KTRAP_FRAME_Rdx] // Length
747 call _InternalDispatchException
757 UNIMPLEMENTED KiDpcInterrupt
766 UNIMPLEMENTED KiIpiInterrupt
772 .proc KiUnexpectedInterrupt
777 lea rcx, _MsgUnexpectedInterrupt[rip]
778 call _FrLdrDbgPrint[rip]
780 mov ecx, TRAP_CAUSE_UNKNOWN
781 // mov rdx, // The unexpected interrupt
782 // mov rdx, // The unknown floating-point exception
783 // mov r8, // The enabled and asserted status bits
784 xor r9, r9 // Reserved
785 mov [rbp + KTRAP_FRAME_P5], rbp // trap frame
786 call _KeBugCheckWithTf
791 .proc KiSystemFatalException