[NTOS:KE] Fixup for the NMI task handler: handle NMI recursion. -- Code was lost...
[reactos.git] / ntoskrnl / ke / i386 / trap.s
1 /*
2 * FILE: ntoskrnl/ke/i386/trap.s
3 * COPYRIGHT: See COPYING in the top level directory
4 * PURPOSE: System Traps, Entrypoints and Exitpoints
5 * PROGRAMMER: Alex Ionescu (alex@relsoft.net)
6 * Timo Kreuzer (timo.kreuzer@reactos.org)
7 * NOTE: See asmmacro.S for the shared entry/exit code.
8 */
9
10 /* INCLUDES ******************************************************************/
11
12 #include <asm.inc>
13 #include <ks386.inc>
14 #include <internal/i386/asmmacro.S>
15
16 MACRO(GENERATE_IDT_STUB, Vector)
17 idt _KiUnexpectedInterrupt&Vector, INT_32_DPL0
18 ENDM
19
20 MACRO(GENERATE_INT_HANDLER, Vector)
21 //.func KiUnexpectedInterrupt&Vector
22 _KiUnexpectedInterrupt&Vector:
23 /* This is a push instruction with 8bit operand. Since the instruction
24 sign extends the value to 32 bits, we need to offset it */
25 push (Vector - 128)
26 jmp _KiEndUnexpectedRange@0
27 //.endfunc
28 ENDM
29
30 /* GLOBALS *******************************************************************/
31
32 .data
33 ASSUME nothing
34
35 .align 16
36
37 PUBLIC _KiIdt
38 _KiIdt:
39 /* This is the Software Interrupt Table that we handle in this file: */
40 idt _KiTrap00, INT_32_DPL0 /* INT 00: Divide Error (#DE) */
41 idt _KiTrap01, INT_32_DPL0 /* INT 01: Debug Exception (#DB) */
42 idt _KiTrap02, INT_32_DPL0 /* INT 02: NMI Interrupt */
43 idt _KiTrap03, INT_32_DPL3 /* INT 03: Breakpoint Exception (#BP) */
44 idt _KiTrap04, INT_32_DPL3 /* INT 04: Overflow Exception (#OF) */
45 idt _KiTrap05, INT_32_DPL0 /* INT 05: BOUND Range Exceeded (#BR) */
46 idt _KiTrap06, INT_32_DPL0 /* INT 06: Invalid Opcode Code (#UD) */
47 idt _KiTrap07, INT_32_DPL0 /* INT 07: Device Not Available (#NM) */
48 idt _KiTrap08, INT_32_DPL0 /* INT 08: Double Fault Exception (#DF) */
49 idt _KiTrap09, INT_32_DPL0 /* INT 09: RESERVED */
50 idt _KiTrap0A, INT_32_DPL0 /* INT 0A: Invalid TSS Exception (#TS) */
51 idt _KiTrap0B, INT_32_DPL0 /* INT 0B: Segment Not Present (#NP) */
52 idt _KiTrap0C, INT_32_DPL0 /* INT 0C: Stack Fault Exception (#SS) */
53 idt _KiTrap0D, INT_32_DPL0 /* INT 0D: General Protection (#GP) */
54 idt _KiTrap0E, INT_32_DPL0 /* INT 0E: Page-Fault Exception (#PF) */
55 idt _KiTrap0F, INT_32_DPL0 /* INT 0F: RESERVED */
56 idt _KiTrap10, INT_32_DPL0 /* INT 10: x87 FPU Error (#MF) */
57 idt _KiTrap11, INT_32_DPL0 /* INT 11: Align Check Exception (#AC) */
58 idt _KiTrap0F, INT_32_DPL0 /* INT 12: Machine Check Exception (#MC)*/
59 idt _KiTrap0F, INT_32_DPL0 /* INT 13: SIMD FPU Exception (#XF) */
60 REPEAT 21
61 idt _KiTrap0F, INT_32_DPL0 /* INT 14-28: UNDEFINED INTERRUPTS */
62 ENDR
63 idt _KiRaiseSecurityCheckFailure, INT_32_DPL3
64 /* INT 29: Handler for __fastfail */
65 idt _KiGetTickCount, INT_32_DPL3 /* INT 2A: Get Tick Count Handler */
66 idt _KiCallbackReturn, INT_32_DPL3 /* INT 2B: User-Mode Callback Return */
67 idt _KiRaiseAssertion, INT_32_DPL3 /* INT 2C: Debug Assertion Handler */
68 idt _KiDebugService, INT_32_DPL3 /* INT 2D: Debug Service Handler */
69 idt _KiSystemService, INT_32_DPL3 /* INT 2E: System Call Service Handler */
70 idt _KiTrap0F, INT_32_DPL0 /* INT 2F: RESERVED */
71 i = HEX(30)
72 REPEAT 208
73 GENERATE_IDT_STUB %i
74 i = i + 1
75 ENDR
76
77 PUBLIC _KiIdtDescriptor
78 _KiIdtDescriptor:
79 .short 0
80 .short HEX(7FF)
81 .long _KiIdt
82
83 PUBLIC _KiUnexpectedEntrySize
84 _KiUnexpectedEntrySize:
85 .long _KiUnexpectedInterrupt49 - _KiUnexpectedInterrupt48
86
87 /******************************************************************************/
88 .code
89
90 PUBLIC _KiStartUnexpectedRange@0
91 _KiStartUnexpectedRange@0:
92 i = HEX(30)
93 REPEAT 208
94 GENERATE_INT_HANDLER %i
95 i = i + 1
96 ENDR
97
98 TRAP_ENTRY KiTrap00, KI_PUSH_FAKE_ERROR_CODE
99 TRAP_ENTRY KiTrap01, KI_PUSH_FAKE_ERROR_CODE
100 TASK_ENTRY KiTrap02, KI_NMI
101 TRAP_ENTRY KiTrap03, KI_PUSH_FAKE_ERROR_CODE
102 TRAP_ENTRY KiTrap04, KI_PUSH_FAKE_ERROR_CODE
103 TRAP_ENTRY KiTrap05, KI_PUSH_FAKE_ERROR_CODE
104 TRAP_ENTRY KiTrap06, KI_PUSH_FAKE_ERROR_CODE
105 TRAP_ENTRY KiTrap07, KI_PUSH_FAKE_ERROR_CODE
106 TASK_ENTRY KiTrap08, 0
107 TRAP_ENTRY KiTrap09, KI_PUSH_FAKE_ERROR_CODE
108 TRAP_ENTRY KiTrap0A, 0
109 TRAP_ENTRY KiTrap0B, 0
110 TRAP_ENTRY KiTrap0C, 0
111 TRAP_ENTRY KiTrap0D, 0
112 TRAP_ENTRY KiTrap0E, 0
113 TRAP_ENTRY KiTrap0F, KI_PUSH_FAKE_ERROR_CODE
114 TRAP_ENTRY KiTrap10, KI_PUSH_FAKE_ERROR_CODE
115 TRAP_ENTRY KiTrap11, KI_PUSH_FAKE_ERROR_CODE
116 TRAP_ENTRY KiTrap13, KI_PUSH_FAKE_ERROR_CODE
117 TRAP_ENTRY KiRaiseSecurityCheckFailure, KI_PUSH_FAKE_ERROR_CODE
118 TRAP_ENTRY KiGetTickCount, KI_PUSH_FAKE_ERROR_CODE
119 TRAP_ENTRY KiCallbackReturn, KI_PUSH_FAKE_ERROR_CODE
120 TRAP_ENTRY KiRaiseAssertion, KI_PUSH_FAKE_ERROR_CODE
121 TRAP_ENTRY KiDebugService, KI_PUSH_FAKE_ERROR_CODE
122 TRAP_ENTRY KiUnexpectedInterruptTail, 0
123
124 ALIGN 4
125 EXTERN @KiInterruptTemplateHandler@8:PROC
126 PUBLIC _KiInterruptTemplate
127 _KiInterruptTemplate:
128 KiEnterTrap KI_PUSH_FAKE_ERROR_CODE
129 PUBLIC _KiInterruptTemplate2ndDispatch
130 _KiInterruptTemplate2ndDispatch:
131 mov edx, 0
132 PUBLIC _KiInterruptTemplateObject
133 _KiInterruptTemplateObject:
134 mov eax, offset @KiInterruptTemplateHandler@8
135 jmp eax
136 PUBLIC _KiInterruptTemplateDispatch
137 _KiInterruptTemplateDispatch:
138
139 EXTERN @KiSystemServiceHandler@8:PROC
140 PUBLIC _KiSystemService
141 .PROC _KiSystemService
142 FPO 0, 0, 0, 0, 1, FRAME_TRAP
143 KiEnterTrap (KI_PUSH_FAKE_ERROR_CODE OR KI_NONVOLATILES_ONLY OR KI_DONT_SAVE_SEGS)
144 KiCallHandler @KiSystemServiceHandler@8
145 .ENDP
146
147 PUBLIC _KiFastCallEntry
148 .PROC _KiFastCallEntry
149 FPO 0, 0, 0, 0, 1, FRAME_TRAP
150 KiEnterTrap (KI_FAST_SYSTEM_CALL OR KI_NONVOLATILES_ONLY OR KI_DONT_SAVE_SEGS)
151 KiCallHandler @KiSystemServiceHandler@8
152 .ENDP
153
154 PUBLIC _KiFastCallEntryWithSingleStep
155 .PROC _KiFastCallEntryWithSingleStep
156 FPO 0, 0, 0, 0, 1, FRAME_TRAP
157 KiEnterTrap (KI_FAST_SYSTEM_CALL OR KI_NONVOLATILES_ONLY OR KI_DONT_SAVE_SEGS)
158 or dword ptr [ecx + KTRAP_FRAME_EFLAGS], EFLAGS_TF
159 KiCallHandler @KiSystemServiceHandler@8
160 .ENDP
161
162 PUBLIC _KiEndUnexpectedRange@0
163 _KiEndUnexpectedRange@0:
164 add dword ptr[esp], 128
165 jmp _KiUnexpectedInterruptTail
166
167
168 /* EXIT CODE *****************************************************************/
169
170 KiTrapExitStub KiSystemCallReturn, (KI_RESTORE_EAX OR KI_RESTORE_EFLAGS OR KI_EXIT_JMP)
171 KiTrapExitStub KiSystemCallSysExitReturn, (KI_RESTORE_EAX OR KI_RESTORE_FS OR KI_RESTORE_EFLAGS OR KI_EXIT_SYSCALL)
172 KiTrapExitStub KiSystemCallTrapReturn, (KI_RESTORE_EAX OR KI_RESTORE_FS OR KI_EXIT_IRET)
173
174 KiTrapExitStub KiEditedTrapReturn, (KI_RESTORE_VOLATILES OR KI_RESTORE_EFLAGS OR KI_EDITED_FRAME OR KI_EXIT_RET)
175 KiTrapExitStub KiTrapReturn, (KI_RESTORE_VOLATILES OR KI_RESTORE_SEGMENTS OR KI_EXIT_IRET)
176 KiTrapExitStub KiTrapReturnNoSegments, (KI_RESTORE_VOLATILES OR KI_EXIT_IRET)
177 KiTrapExitStub KiTrapReturnNoSegmentsRet8,(KI_RESTORE_VOLATILES OR KI_RESTORE_EFLAGS OR KI_EXIT_RET8)
178
179 EXTERN _PsConvertToGuiThread@0:PROC
180
181 PUBLIC _KiConvertToGuiThread@0
182 _KiConvertToGuiThread@0:
183
184 /*
185 * Converting to a GUI thread safely updates ESP in-place as well as the
186 * current Thread->TrapFrame and EBP when KeSwitchKernelStack is called.
187 *
188 * However, PsConvertToGuiThread "helpfully" restores EBP to the original
189 * caller's value, since it is considered a nonvolatile register. As such,
190 * as soon as we're back after the conversion and we try to store the result
191 * which will probably be in some stack variable (EBP-based), we'll crash as
192 * we are touching the de-allocated non-expanded stack.
193 *
194 * Thus we need a way to update our EBP before EBP is touched, and the only
195 * way to guarantee this is to do the call itself in assembly, use the EAX
196 * register to store the result, fixup EBP, and then let the C code continue
197 * on its merry way.
198 *
199 */
200
201 /* Save ebx */
202 push ebx
203
204 /* Calculate the stack frame offset in ebx */
205 mov ebx, ebp
206 sub ebx, esp
207
208 /* Call the worker function */
209 call _PsConvertToGuiThread@0
210
211 /* Adjust ebp to the new stack */
212 mov ebp, esp
213 add ebp, ebx
214
215 /* Restore ebx */
216 pop ebx
217
218 /* return to the caller */
219 ret
220
221 END