xref: /reactos/ntoskrnl/ke/i386/trap.s (revision 682f85ad)
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
16MACRO(GENERATE_IDT_STUB, Vector)
17idt _KiUnexpectedInterrupt&Vector, INT_32_DPL0
18ENDM
19
20MACRO(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
28ENDM
29
30/* GLOBALS *******************************************************************/
31
32.data
33ASSUME CS:nothing
34
35.align 16
36
37PUBLIC _KiIdt
38_KiIdt:
39/* This is the Software Interrupt Table that we handle in this file:        */
40idt _KiTrap00,         INT_32_DPL0  /* INT 00: Divide Error (#DE)           */
41idt _KiTrap01,         INT_32_DPL0  /* INT 01: Debug Exception (#DB)        */
42idt _KiTrap02,         INT_32_DPL0  /* INT 02: NMI Interrupt                */
43idt _KiTrap03,         INT_32_DPL3  /* INT 03: Breakpoint Exception (#BP)   */
44idt _KiTrap04,         INT_32_DPL3  /* INT 04: Overflow Exception (#OF)     */
45idt _KiTrap05,         INT_32_DPL0  /* INT 05: BOUND Range Exceeded (#BR)   */
46idt _KiTrap06,         INT_32_DPL0  /* INT 06: Invalid Opcode Code (#UD)    */
47idt _KiTrap07,         INT_32_DPL0  /* INT 07: Device Not Available (#NM)   */
48idt _KiTrap08,         INT_32_DPL0  /* INT 08: Double Fault Exception (#DF) */
49idt _KiTrap09,         INT_32_DPL0  /* INT 09: RESERVED                     */
50idt _KiTrap0A,         INT_32_DPL0  /* INT 0A: Invalid TSS Exception (#TS)  */
51idt _KiTrap0B,         INT_32_DPL0  /* INT 0B: Segment Not Present (#NP)    */
52idt _KiTrap0C,         INT_32_DPL0  /* INT 0C: Stack Fault Exception (#SS)  */
53idt _KiTrap0D,         INT_32_DPL0  /* INT 0D: General Protection (#GP)     */
54idt _KiTrap0E,         INT_32_DPL0  /* INT 0E: Page-Fault Exception (#PF)   */
55idt _KiTrap0F,         INT_32_DPL0  /* INT 0F: RESERVED                     */
56idt _KiTrap10,         INT_32_DPL0  /* INT 10: x87 FPU Error (#MF)          */
57idt _KiTrap11,         INT_32_DPL0  /* INT 11: Align Check Exception (#AC)  */
58idt _KiTrap0F,         INT_32_DPL0  /* INT 12: Machine Check Exception (#MC)*/
59idt _KiTrap0F,         INT_32_DPL0  /* INT 13: SIMD FPU Exception (#XF)     */
60REPEAT 21
61idt _KiTrap0F,         INT_32_DPL0  /* INT 14-28: UNDEFINED INTERRUPTS      */
62ENDR
63idt _KiRaiseSecurityCheckFailure, INT_32_DPL3
64                                    /* INT 29: Handler for __fastfail       */
65idt _KiGetTickCount,   INT_32_DPL3  /* INT 2A: Get Tick Count Handler       */
66idt _KiCallbackReturn, INT_32_DPL3  /* INT 2B: User-Mode Callback Return    */
67idt _KiRaiseAssertion, INT_32_DPL3  /* INT 2C: Debug Assertion Handler      */
68idt _KiDebugService,   INT_32_DPL3  /* INT 2D: Debug Service Handler        */
69idt _KiSystemService,  INT_32_DPL3  /* INT 2E: System Call Service Handler  */
70idt _KiTrap0F,         INT_32_DPL0  /* INT 2F: RESERVED                     */
71i = HEX(30)
72REPEAT 208
73    GENERATE_IDT_STUB %i
74    i = i + 1
75ENDR
76
77PUBLIC _KiIdtDescriptor
78_KiIdtDescriptor:
79    .short 0
80    .short HEX(7FF)
81    .long _KiIdt
82
83PUBLIC _KiUnexpectedEntrySize
84_KiUnexpectedEntrySize:
85    .long _KiUnexpectedInterrupt49 - _KiUnexpectedInterrupt48
86
87/******************************************************************************/
88.code
89
90PUBLIC _KiStartUnexpectedRange@0
91_KiStartUnexpectedRange@0:
92i = HEX(30)
93REPEAT 208
94    GENERATE_INT_HANDLER %i
95    i = i + 1
96ENDR
97
98TRAP_ENTRY KiTrap00, KI_PUSH_FAKE_ERROR_CODE
99TRAP_ENTRY KiTrap01, KI_PUSH_FAKE_ERROR_CODE
100TASK_ENTRY KiTrap02, KI_NMI
101TRAP_ENTRY KiTrap03, KI_PUSH_FAKE_ERROR_CODE
102TRAP_ENTRY KiTrap04, KI_PUSH_FAKE_ERROR_CODE
103TRAP_ENTRY KiTrap05, KI_PUSH_FAKE_ERROR_CODE
104TRAP_ENTRY KiTrap06, KI_PUSH_FAKE_ERROR_CODE
105TRAP_ENTRY KiTrap07, KI_PUSH_FAKE_ERROR_CODE
106TASK_ENTRY KiTrap08, 0
107TRAP_ENTRY KiTrap09, KI_PUSH_FAKE_ERROR_CODE
108TRAP_ENTRY KiTrap0A, 0
109TRAP_ENTRY KiTrap0B, 0
110TRAP_ENTRY KiTrap0C, 0
111TRAP_ENTRY KiTrap0D, 0
112TRAP_ENTRY KiTrap0E, 0
113TRAP_ENTRY KiTrap0F, KI_PUSH_FAKE_ERROR_CODE
114TRAP_ENTRY KiTrap10, KI_PUSH_FAKE_ERROR_CODE
115TRAP_ENTRY KiTrap11, KI_PUSH_FAKE_ERROR_CODE
116TRAP_ENTRY KiTrap13, KI_PUSH_FAKE_ERROR_CODE
117TRAP_ENTRY KiRaiseSecurityCheckFailure, KI_PUSH_FAKE_ERROR_CODE
118TRAP_ENTRY KiGetTickCount, KI_PUSH_FAKE_ERROR_CODE
119TRAP_ENTRY KiCallbackReturn, KI_PUSH_FAKE_ERROR_CODE
120TRAP_ENTRY KiRaiseAssertion, KI_PUSH_FAKE_ERROR_CODE
121TRAP_ENTRY KiDebugService, KI_PUSH_FAKE_ERROR_CODE
122TRAP_ENTRY KiUnexpectedInterruptTail, 0
123
124ALIGN 4
125EXTERN @KiInterruptTemplateHandler@8:PROC
126PUBLIC _KiInterruptTemplate
127_KiInterruptTemplate:
128    KiEnterTrap KI_PUSH_FAKE_ERROR_CODE
129PUBLIC _KiInterruptTemplate2ndDispatch
130_KiInterruptTemplate2ndDispatch:
131    mov edx, 0
132PUBLIC _KiInterruptTemplateObject
133_KiInterruptTemplateObject:
134    mov eax, offset @KiInterruptTemplateHandler@8
135    jmp eax
136PUBLIC _KiInterruptTemplateDispatch
137_KiInterruptTemplateDispatch:
138
139EXTERN @KiSystemServiceHandler@8:PROC
140PUBLIC _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
147PUBLIC _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
154PUBLIC _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
162PUBLIC _KiEndUnexpectedRange@0
163_KiEndUnexpectedRange@0:
164    add dword ptr[esp], 128
165    jmp _KiUnexpectedInterruptTail
166
167
168/* EXIT CODE *****************************************************************/
169
170KiTrapExitStub KiSystemCallReturn,        (KI_RESTORE_EAX OR KI_RESTORE_EFLAGS OR KI_EXIT_JMP)
171KiTrapExitStub KiSystemCallSysExitReturn, (KI_RESTORE_EAX OR KI_RESTORE_FS OR KI_RESTORE_EFLAGS OR KI_EXIT_SYSCALL)
172KiTrapExitStub KiSystemCallTrapReturn,    (KI_RESTORE_EAX OR KI_RESTORE_FS OR KI_EXIT_IRET)
173
174KiTrapExitStub KiEditedTrapReturn,        (KI_RESTORE_VOLATILES OR KI_RESTORE_EFLAGS OR KI_EDITED_FRAME OR KI_EXIT_RET)
175KiTrapExitStub KiTrapReturn,              (KI_RESTORE_VOLATILES OR KI_RESTORE_SEGMENTS OR KI_EXIT_IRET)
176KiTrapExitStub KiTrapReturnNoSegments,    (KI_RESTORE_VOLATILES OR KI_EXIT_IRET)
177KiTrapExitStub KiTrapReturnNoSegmentsRet8,(KI_RESTORE_VOLATILES OR KI_RESTORE_EFLAGS OR KI_EXIT_RET8)
178
179EXTERN _PsConvertToGuiThread@0:PROC
180
181PUBLIC _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
221END
222