[uxtheme]
[reactos.git] / reactos / ntoskrnl / ke / amd64 / trap.S
1 /*
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)
6 */
7
8 /* INCLUDES ******************************************************************/
9
10 #include <asm.inc>
11 #include <ksamd64.inc>
12 #include <trapamd64.inc>
13
14 EXTERN KiDispatchException:PROC
15 EXTERN FrLdrDbgPrint:DWORD
16 EXTERN KeBugCheckWithTf:PROC
17 EXTERN MmAccessFault:PROC
18 EXTERN KiSystemFatalException:PROC
19 EXTERN KiNpxNotAvailableFaultHandler:PROC
20 EXTERN KiGeneralProtectionFaultHandler:PROC
21 EXTERN KiXmmExceptionHandler:PROC
22 EXTERN KiDeliverApc:PROC
23 EXTERN KiDispatchInterrupt:PROC
24
25 /* GLOBALS *******************************************************************/
26
27 .data
28
29 PUBLIC MsgUnimplemented
30 MsgUnimplemented:
31 .asciz "WARNING: %s at %s:%d is UNIMPLEMENTED!\n"
32
33
34 /* Helper Macros *************************************************************/
35
36 MACRO(DispatchException, Status, Number, P1, P2, P3)
37 mov eax, Status
38 mov edx, Number
39 mov r9, P1
40 mov r10, P2
41 mov r11, P3
42 call InternalDispatchException
43 ENDM
44
45 MACRO(Fatal, BugcheckCode)
46 /* Bugcheck */
47 mov ecx, BugcheckCode
48 mov rdx, rbp
49 call KiSystemFatalException
50 ENDM
51
52
53 /* FUNCTIONS *****************************************************************/
54
55 .code64
56
57 ALIGN 8
58
59 PUBLIC InterruptDispatchTable
60 InterruptDispatchTable:
61 Vector = 0
62 REPEAT 256
63 push Vector
64 jmp KiUnexpectedInterrupt
65 ALIGN 8
66 Vector = Vector+1
67 ENDR
68
69 // rbp = TrapFrame, eax = ExceptionCode, edx = NumParams, r9,r10,r11 = params
70 .PROC InternalDispatchException
71
72 /* Allocate stack space for EXCEPTION_RECORD and KEXCEPTION_FRAME */
73 sub rsp, EXCEPTION_RECORD_LENGTH + KEXCEPTION_FRAME_LENGTH
74 .allocstack (EXCEPTION_RECORD_LENGTH + KEXCEPTION_FRAME_LENGTH)
75 .endprolog
76
77 /* Set up EXCEPTION_RECORD */
78 lea rcx, [rsp + KEXCEPTION_FRAME_LENGTH]
79 mov [rcx + EXCEPTION_RECORD_ExceptionCode], eax
80 xor rax, rax
81 mov [rcx + EXCEPTION_RECORD_ExceptionFlags], eax
82 mov [rcx + EXCEPTION_RECORD_ExceptionRecord], rax
83 mov rax, [rbp + KTRAP_FRAME_Rip]
84 mov [rcx + EXCEPTION_RECORD_ExceptionAddress], rax
85 mov [rcx + EXCEPTION_RECORD_NumberParameters], edx
86 mov [rcx + EXCEPTION_RECORD_ExceptionInformation + HEX(00)], r9
87 mov [rcx + EXCEPTION_RECORD_ExceptionInformation + HEX(08)], r10
88 mov [rcx + EXCEPTION_RECORD_ExceptionInformation + HEX(10)], r11
89
90 /* Set up KEXCEPTION_FRAME */
91 mov rax, [rbp + KTRAP_FRAME_Rbp]
92 mov [rsp + KEXCEPTION_FRAME_Rbp], rax
93 mov [rsp + KEXCEPTION_FRAME_Rbx], rbx
94 mov [rsp + KEXCEPTION_FRAME_Rdi], rdi
95 mov [rsp + KEXCEPTION_FRAME_Rsi], rsi
96 mov [rsp + KEXCEPTION_FRAME_R12], r12
97 mov [rsp + KEXCEPTION_FRAME_R13], r13
98 mov [rsp + KEXCEPTION_FRAME_R14], r14
99 mov [rsp + KEXCEPTION_FRAME_R15], r15
100 movdqa [rsp + KEXCEPTION_FRAME_Xmm6], xmm6
101 movdqa [rsp + KEXCEPTION_FRAME_Xmm7], xmm7
102 movdqa [rsp + KEXCEPTION_FRAME_Xmm8], xmm8
103 movdqa [rsp + KEXCEPTION_FRAME_Xmm9], xmm9
104 movdqa [rsp + KEXCEPTION_FRAME_Xmm10], xmm10
105 movdqa [rsp + KEXCEPTION_FRAME_Xmm11], xmm11
106 movdqa [rsp + KEXCEPTION_FRAME_Xmm12], xmm12
107 movdqa [rsp + KEXCEPTION_FRAME_Xmm13], xmm13
108 movdqa [rsp + KEXCEPTION_FRAME_Xmm14], xmm14
109 movdqa [rsp + KEXCEPTION_FRAME_Xmm15], xmm15
110 mov qword ptr [rsp + KEXCEPTION_FRAME_Return], 0
111
112 /* Call KiDispatchException */
113 // rcx already points to ExceptionRecord
114 mov rdx, rsp // ExceptionFrame
115 mov r8, rbp // TrapFrame
116 mov r9b, [r8 + KTRAP_FRAME_PreviousMode] // PreviousMode
117 mov byte ptr [rsp + KEXCEPTION_FRAME_P5], 1 // FirstChance
118 call KiDispatchException
119
120 /* Restore registers */
121 mov r12, [rsp + KEXCEPTION_FRAME_R12]
122 mov r13, [rsp + KEXCEPTION_FRAME_R13]
123 mov r14, [rsp + KEXCEPTION_FRAME_R14]
124 mov r15, [rsp + KEXCEPTION_FRAME_R15]
125 movdqa xmm6, [rsp + KEXCEPTION_FRAME_Xmm6]
126 movdqa xmm7, [rsp + KEXCEPTION_FRAME_Xmm7]
127 movdqa xmm8, [rsp + KEXCEPTION_FRAME_Xmm8]
128 movdqa xmm9, [rsp + KEXCEPTION_FRAME_Xmm9]
129 movdqa xmm10, [rsp + KEXCEPTION_FRAME_Xmm10]
130 movdqa xmm11, [rsp + KEXCEPTION_FRAME_Xmm11]
131 movdqa xmm12, [rsp + KEXCEPTION_FRAME_Xmm12]
132 movdqa xmm13, [rsp + KEXCEPTION_FRAME_Xmm13]
133 movdqa xmm14, [rsp + KEXCEPTION_FRAME_Xmm14]
134 movdqa xmm15, [rsp + KEXCEPTION_FRAME_Xmm15]
135
136 add rsp, EXCEPTION_RECORD_LENGTH + KEXCEPTION_FRAME_LENGTH
137 ret
138 .ENDP InternalDispatchException
139
140
141 /* SOFTWARE INTERRUPT SERVICES ***********************************************/
142
143 PUBLIC KiDivideErrorFault
144 FUNC KiDivideErrorFault
145 /* Push pseudo error code */
146 EnterTrap TF_SAVE_ALL
147
148 /* Enable interrupts */
149 sti
150
151 /* Dispatch the exception */
152 DispatchException STATUS_INTEGER_DIVIDE_BY_ZERO, 0, 0, 0, 0
153
154 /* Return */
155 ExitTrap TF_SAVE_ALL
156 ENDFUNC KiDivideErrorFault
157
158
159 PUBLIC KiDebugTrapOrFault
160 FUNC KiDebugTrapOrFault
161 /* Push pseudo error code */
162 EnterTrap TF_SAVE_ALL
163
164 /* Check if the frame was from kernelmode */
165 test word ptr [rbp + KTRAP_FRAME_SegCs], 3
166 jz KiDebugTrapOrFaultKMode
167
168 /* Enable interrupts for user-mode */
169 sti
170
171 KiDebugTrapOrFaultKMode:
172 /* Dispatch the exception */
173 DispatchException STATUS_SINGLE_STEP, 0, 0, 0, 0
174
175 /* Return */
176 ExitTrap TF_SAVE_ALL
177 ENDFUNC KiDebugTrapOrFault
178
179
180 PUBLIC KiNmiInterrupt
181 FUNC KiNmiInterrupt
182 /* Push pseudo error code */
183 EnterTrap TF_SAVE_ALL
184
185 UNIMPLEMENTED KiNmiInterrupt
186 int 3
187
188 /* Return */
189 ExitTrap TF_SAVE_ALL
190 ENDFUNC KiNmiInterrupt
191
192
193 PUBLIC KiBreakpointTrap
194 FUNC KiBreakpointTrap
195 /* Push pseudo error code */
196 EnterTrap TF_SAVE_ALL
197
198 /* Dispatch the exception */
199 DispatchException STATUS_BREAKPOINT, 3, 0, 0, 0
200
201 /* Return */
202 ExitTrap TF_SAVE_ALL
203 ENDFUNC KiBreakpointTrap
204
205
206 PUBLIC KiOverflowTrap
207 FUNC KiOverflowTrap
208 /* Push pseudo error code */
209 EnterTrap TF_SAVE_ALL
210
211 /* Enable interrupts */
212 sti
213
214 /* Dispatch the exception */
215 DispatchException STATUS_INTEGER_OVERFLOW, 3, 0, 0, 0
216
217 /* Return */
218 ExitTrap TF_SAVE_ALL
219 ENDFUNC KiOverflowTrap
220
221
222 PUBLIC KiBoundFault
223 FUNC KiBoundFault
224 /* No error code */
225 EnterTrap TF_SAVE_ALL
226
227 /* Check if the frame was from kernelmode */
228 test word ptr [rbp + KTRAP_FRAME_SegCs], 3
229 jnz KiBoundFaultUserMode
230
231 /* Bugcheck */
232 Fatal EXCEPTION_BOUND_CHECK
233
234 KiBoundFaultUserMode:
235 /* Enable interrupts for user-mode */
236 sti
237
238 /* Dispatch the exception */
239 DispatchException STATUS_ARRAY_BOUNDS_EXCEEDED, 0, 0, 0, 0
240
241 /* Return */
242 ExitTrap TF_SAVE_ALL
243 ENDFUNC KiBoundFault
244
245
246 PUBLIC KiInvalidOpcodeFault
247 FUNC KiInvalidOpcodeFault
248 /* No error code */
249 EnterTrap TF_SAVE_ALL
250
251 /* Enable interrupts */
252 sti
253
254 /* Check if the frame was from kernelmode */
255 test word ptr [rbp + KTRAP_FRAME_SegCs], 3
256 jz KiInvalidOpcodeKernel
257
258 // FIXME: handle STATUS_INVALID_LOCK_SEQUENCE
259
260 KiInvalidOpcodeKernel:
261 /* Kernel mode fault */
262
263 /* Dispatch the exception */
264 DispatchException STATUS_ILLEGAL_INSTRUCTION, 3, 0, 0, 0
265
266 /* Return */
267 ExitTrap TF_SAVE_ALL
268 ENDFUNC KiInvalidOpcodeFault
269
270
271 PUBLIC KiNpxNotAvailableFault
272 FUNC KiNpxNotAvailableFault
273 /* No error code */
274 EnterTrap TF_SAVE_ALL
275
276 /* Call the C handler */
277 mov rcx, rbp
278 call KiNpxNotAvailableFaultHandler
279
280 /* Check the return status code */
281 test eax, eax
282 jz KiNpxNotAvailableFaultExit
283
284 /* Dispatch the exception */
285 DispatchException eax, 3, 0, 0, 0
286
287 KiNpxNotAvailableFaultExit:
288 /* Return */
289 ExitTrap TF_SAVE_ALL
290 ENDFUNC KiNpxNotAvailableFault
291
292
293 PUBLIC KiDoubleFaultAbort
294 FUNC KiDoubleFaultAbort
295 /* No error code */
296 EnterTrap TF_SAVE_ALL
297
298 /* Bugcheck */
299 Fatal 8 // EXCEPTION_DOUBLE_FAULT
300 jmp $
301 ENDFUNC KiDoubleFaultAbort
302
303
304 PUBLIC KiNpxSegmentOverrunAbort
305 FUNC KiNpxSegmentOverrunAbort
306 /* No error code */
307 EnterTrap TF_SAVE_ALL
308
309 /* Bugcheck */
310 Fatal EXCEPTION_NPX_OVERRUN
311 jmp $
312 ENDFUNC KiNpxSegmentOverrunAbort
313
314
315 PUBLIC KiInvalidTssFault
316 FUNC KiInvalidTssFault
317 /* We have an error code */
318 EnterTrap (TF_HAS_ERROR_CODE OR TF_SAVE_ALL)
319
320 /* Bugcheck */
321 Fatal EXCEPTION_INVALID_TSS
322 jmp $
323 ENDFUNC KiInvalidTssFault
324
325
326 PUBLIC KiSegmentNotPresentFault
327 FUNC KiSegmentNotPresentFault
328 /* We have an error code */
329 EnterTrap (TF_HAS_ERROR_CODE OR TF_SAVE_ALL)
330
331 /* Bugcheck */
332 Fatal EXCEPTION_SEGMENT_NOT_PRESENT
333 jmp $
334 ENDFUNC KiSegmentNotPresentFault
335
336
337 PUBLIC KiStackFault
338 FUNC KiStackFault
339 /* We have an error code */
340 EnterTrap (TF_HAS_ERROR_CODE OR TF_SAVE_ALL)
341
342 /* Bugcheck */
343 Fatal EXCEPTION_STACK_FAULT
344 jmp $
345 ENDFUNC KiStackFault
346
347
348 PUBLIC KiGeneralProtectionFault
349 FUNC KiGeneralProtectionFault
350 /* We have an error code */
351 EnterTrap (TF_HAS_ERROR_CODE OR TF_SAVE_ALL)
352
353 /* Call the C handler */
354 mov rcx, rbp
355 call KiGeneralProtectionFaultHandler
356
357 /* Check for success */
358 test eax, eax
359 jge KiGpfExit
360
361 /* Dispatch the exception */
362 DispatchException eax, 3, 0, 0, 0
363
364 KiGpfFatal:
365
366 /* Bugcheck */
367 mov ecx, UNEXPECTED_KERNEL_MODE_TRAP
368 mov rdx, HEX(000D) // EXCEPTION_GP_FAULT
369 xor r8, r8
370 mov r9, [rbp + KTRAP_FRAME_ErrorCode] // error code
371 sub rsp, 8
372 mov [rsp + KTRAP_FRAME_P5+8], rbp // trap frame
373 call KeBugCheckWithTf
374
375 KiGpfExit:
376 /* Return */
377 /* Return */
378 ExitTrap TF_SAVE_ALL
379 ENDFUNC KiGeneralProtectionFault
380
381
382 PUBLIC KiPageFault
383 FUNC KiPageFault
384 /* We have an error code */
385 EnterTrap (TF_HAS_ERROR_CODE OR TF_SAVE_ALL)
386
387 /* Save page fault address */
388 mov rdx, cr2
389 mov [rbp + KTRAP_FRAME_FaultAddress], rdx
390
391 /* Call page fault handler */
392 mov ecx, [rbp + KTRAP_FRAME_ErrorCode] // StoreInstruction
393 and ecx, 1
394 // rdx == Address
395 mov r8b, [rbp + KTRAP_FRAME_SegCs] // Mode
396 and r8b, 1
397 mov r9, rbp // TrapInformation
398 call MmAccessFault
399
400 /* Check for success */
401 test eax, eax
402 jge PageFaultReturn
403
404 /* Set parameter 1 to error code */
405 mov r9d, [rbp + KTRAP_FRAME_ErrorCode]
406
407 /* Set parameter2 to faulting address */
408 mov r10, cr2 // Param2 = faulting address
409
410 cmp eax, STATUS_ACCESS_VIOLATION
411 je AccessViolation
412 cmp eax, STATUS_GUARD_PAGE_VIOLATION
413 je SpecialCode
414 cmp eax, STATUS_STACK_OVERFLOW
415 je SpecialCode
416
417 InPageException:
418
419 /* Dispatch in-page exception */
420 mov r11d, eax // Param3 = Status
421 mov eax, STATUS_IN_PAGE_ERROR // ExceptionCode
422 mov edx, 3 // ParamCount
423 call InternalDispatchException
424 jmp PageFaultReturn
425
426 AccessViolation:
427 /* Use more proper status code */
428 mov eax, KI_EXCEPTION_ACCESS_VIOLATION
429
430 SpecialCode:
431 /* Setup a normal page fault exception */
432 mov edx, 2 // ParamCount
433 call InternalDispatchException
434
435 PageFaultReturn:
436 /* Return */
437 ExitTrap TF_SAVE_ALL
438 ENDFUNC KiPageFault
439
440
441 PUBLIC KiFloatingErrorFault
442 FUNC KiFloatingErrorFault
443 /* No error code */
444 EnterTrap TF_SAVE_ALL
445
446 UNIMPLEMENTED KiFloatingErrorFault
447 int 3
448
449 /* Return */
450 ExitTrap TF_SAVE_ALL
451 ENDFUNC KiFloatingErrorFault
452
453
454 PUBLIC KiAlignmentFault
455 FUNC KiAlignmentFault
456 /* We have an error code */
457 EnterTrap (TF_HAS_ERROR_CODE OR TF_SAVE_ALL)
458
459 /* Bugcheck */
460 Fatal EXCEPTION_ALIGNMENT_CHECK
461 jmp $
462 ENDFUNC KiAlignmentFault
463
464
465 PUBLIC KiMcheckAbort
466 FUNC KiMcheckAbort
467 /* No error code */
468 EnterTrap TF_SAVE_ALL
469
470 /* Bugcheck */
471 Fatal HEX(12)
472 jmp $
473 ENDFUNC KiMcheckAbort
474
475
476 PUBLIC KiXmmException
477 FUNC KiXmmException
478 /* No error code */
479 EnterTrap TF_SAVE_ALL
480
481 /* Call the C handler */
482 mov rcx, rbp
483 call KiXmmExceptionHandler
484
485 /* Check for success */
486 test eax, eax
487 jge KiXmmExit
488
489 /* Dispatch the exception */
490 DispatchException eax, 3, 0, 0, 0
491
492 KiXmmExit:
493 /* Return */
494 ExitTrap TF_SAVE_ALL
495 ENDFUNC KiXmmException
496
497
498 PUBLIC KiRaiseAssertion
499 FUNC KiRaiseAssertion
500 /* We have an error code */
501 EnterTrap (TF_HAS_ERROR_CODE OR TF_SAVE_ALL)
502
503 /* Decrement RIP to point to the INT2C instruction (2 bytes, not 1 like INT3) */
504 sub qword ptr [rbp + KTRAP_FRAME_Rip], 2
505
506 /* Dispatch the exception */
507 DispatchException STATUS_ASSERTION_FAILURE, 0, 0, 0, 0
508
509 /* Return */
510 ExitTrap TF_SAVE_ALL
511 ENDFUNC KiRaiseAssertion
512
513
514 PUBLIC KiDebugServiceTrap
515 .PROC KiDebugServiceTrap
516 /* No error code */
517 EnterTrap TF_SAVE_ALL
518
519 /* Increase Rip to skip the int3 */
520 inc qword ptr [rbp + KTRAP_FRAME_Rip]
521
522 /* Dispatch the exception (Params = service, buffer, legth) */
523 DispatchException STATUS_BREAKPOINT, 3, [rbp+KTRAP_FRAME_Rax], [rbp+KTRAP_FRAME_Rcx], [rbp+KTRAP_FRAME_Rdx]
524
525 /* Return */
526 ExitTrap TF_SAVE_ALL
527 .ENDP KiDebugServiceTrap
528
529
530 PUBLIC KiApcInterrupt
531 .PROC KiApcInterrupt
532 /* No error code */
533 EnterTrap (TF_VOLATILES or TF_IRQL)
534
535 /* Raise to APC_LEVEL */
536 mov rax, APC_LEVEL
537 mov cr8, rax
538
539 /* End the interrupt */
540 mov dword ptr [APIC_EOI], 0
541
542 /* Enable interrupts */
543 sti
544
545 /* Call the worker routine */
546 mov cl, [rbp + KTRAP_FRAME_SegCs] // ProcessorMode
547 and cl, 1
548 mov rdx, 0 // ExceptionFrame
549 mov r8, rdx // TrapFrame
550 call KiDeliverApc
551
552 /* Disable interrupts */
553 cli
554
555 /* Return */
556 ExitTrap (TF_VOLATILES or TF_IRQL)
557 .ENDP KiApcInterrupt
558
559
560 PUBLIC KiDpcInterrupt
561 .PROC KiDpcInterrupt
562 /* No error code */
563 EnterTrap (TF_VOLATILES or TF_IRQL)
564
565 /* Raise to DISPATCH_LEVEL */
566 mov rax, DISPATCH_LEVEL
567 mov cr8, rax
568
569 /* End the interrupt */
570 mov dword ptr [APIC_EOI], 0
571
572 /* Call the worker routine */
573 sti
574 call KiDispatchInterrupt
575 cli
576
577 /* Return */
578 ExitTrap (TF_VOLATILES or TF_IRQL)
579 .ENDP KiDpcInterrupt
580
581
582 PUBLIC KiIpiInterrupt
583 .PROC KiIpiInterrupt
584 /* No error code */
585 EnterTrap (TF_VOLATILES or TF_IRQL)
586
587 /* Raise to IPI_LEVEL */
588 mov rax, IPI_LEVEL
589 mov cr8, rax
590
591 /* End the interrupt */
592 mov dword ptr [APIC_EOI], 0
593
594 int 3
595
596 /* Return */
597 ExitTrap (TF_VOLATILES or TF_IRQL)
598 .ENDP KiIpiInterrupt
599
600
601 PUBLIC KiUnexpectedInterrupt
602 FUNC KiUnexpectedInterrupt
603 /* The error code is the vector */
604 EnterTrap (TF_HAS_ERROR_CODE OR TF_SAVE_ALL)
605
606 #if 0
607 /* Set bugcheck parameters */
608 mov ecx, TRAP_CAUSE_UNKNOWN
609 mov rdx, [rbp + KTRAP_FRAME_ErrorCode] // the vector
610 mov r8, 0 // The unknown floating-point exception
611 mov r9, 0 // The enabled and asserted status bits
612 sub rsp, 8
613 mov [rbp + KTRAP_FRAME_P5 + 8], rbp // trap frame
614 call KeBugCheckWithTf
615 jmp $
616 #endif
617 /* Return */
618 ExitTrap TF_SAVE_ALL
619 ENDFUNC KiUnexpectedInterrupt
620
621 #ifdef _MSC_VER
622 #undef lgdt
623 #undef lidt
624
625 //void __lgdt(void *Source);
626 PUBLIC __lgdt
627 __lgdt:
628 lgdt fword ptr [rcx]
629 ret
630
631 //void __sgdt(void *Destination);
632 PUBLIC __sgdt
633 __sgdt:
634 sgdt fword ptr [rcx]
635 ret
636
637 // void __lldt(unsigned short Value)
638 PUBLIC __lldt
639 __lldt:
640 lldt cx
641 ret
642
643 //void __sldt(void *Destination);
644 PUBLIC __sldt
645 __sldt:
646 sldt word ptr [rcx]
647 ret
648
649 //void __ltr(unsigned short Source);
650 PUBLIC __ltr
651 __ltr:
652 ltr cx
653 ret
654
655 //void __str(unsigned short *Destination);
656 PUBLIC __str
657 __str:
658 str word ptr [rcx]
659 ret
660
661 #endif
662
663 END