xref: /reactos/ntoskrnl/ke/i386/trap.s (revision ea6e7740)
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    CFI_STARTPROC
129    KiEnterTrap KI_PUSH_FAKE_ERROR_CODE
130PUBLIC _KiInterruptTemplate2ndDispatch
131_KiInterruptTemplate2ndDispatch:
132    mov edx, 0
133PUBLIC _KiInterruptTemplateObject
134_KiInterruptTemplateObject:
135    mov eax, offset @KiInterruptTemplateHandler@8
136    jmp eax
137PUBLIC _KiInterruptTemplateDispatch
138_KiInterruptTemplateDispatch:
139    CFI_ENDPROC
140
141EXTERN @KiSystemServiceHandler@8:PROC
142PUBLIC _KiSystemService
143.PROC _KiSystemService
144    FPO 0, 0, 0, 0, 1, FRAME_TRAP
145    KiEnterTrap (KI_PUSH_FAKE_ERROR_CODE OR KI_NONVOLATILES_ONLY OR KI_DONT_SAVE_SEGS)
146    KiCallHandler @KiSystemServiceHandler@8
147.ENDP
148
149PUBLIC _KiFastCallEntry
150.PROC _KiFastCallEntry
151    FPO 0, 0, 0, 0, 1, FRAME_TRAP
152    KiEnterTrap (KI_FAST_SYSTEM_CALL OR KI_NONVOLATILES_ONLY OR KI_DONT_SAVE_SEGS)
153    KiCallHandler @KiSystemServiceHandler@8
154.ENDP
155
156PUBLIC _KiFastCallEntryWithSingleStep
157.PROC _KiFastCallEntryWithSingleStep
158    FPO 0, 0, 0, 0, 1, FRAME_TRAP
159    KiEnterTrap (KI_FAST_SYSTEM_CALL OR KI_NONVOLATILES_ONLY OR KI_DONT_SAVE_SEGS)
160    or dword ptr [ecx + KTRAP_FRAME_EFLAGS], EFLAGS_TF
161    KiCallHandler @KiSystemServiceHandler@8
162.ENDP
163
164PUBLIC _KiEndUnexpectedRange@0
165_KiEndUnexpectedRange@0:
166    add dword ptr[esp], 128
167    jmp _KiUnexpectedInterruptTail
168
169
170/* EXIT CODE *****************************************************************/
171
172KiTrapExitStub KiSystemCallReturn,        (KI_RESTORE_EAX OR KI_RESTORE_EFLAGS OR KI_EXIT_JMP)
173KiTrapExitStub KiSystemCallSysExitReturn, (KI_RESTORE_EAX OR KI_RESTORE_FS OR KI_RESTORE_EFLAGS OR KI_EXIT_SYSCALL)
174KiTrapExitStub KiSystemCallTrapReturn,    (KI_RESTORE_EAX OR KI_RESTORE_FS OR KI_EXIT_IRET)
175
176KiTrapExitStub KiEditedTrapReturn,        (KI_RESTORE_VOLATILES OR KI_RESTORE_EFLAGS OR KI_EDITED_FRAME OR KI_EXIT_RET)
177KiTrapExitStub KiTrapReturn,              (KI_RESTORE_VOLATILES OR KI_RESTORE_SEGMENTS OR KI_EXIT_IRET)
178KiTrapExitStub KiTrapReturnNoSegments,    (KI_RESTORE_VOLATILES OR KI_EXIT_IRET)
179KiTrapExitStub KiTrapReturnNoSegmentsRet8,(KI_RESTORE_VOLATILES OR KI_RESTORE_EFLAGS OR KI_EXIT_RET8)
180
181EXTERN _PsConvertToGuiThread@0:PROC
182
183PUBLIC _KiConvertToGuiThread@0
184_KiConvertToGuiThread@0:
185
186    /*
187     * Converting to a GUI thread safely updates ESP in-place as well as the
188     * current Thread->TrapFrame and EBP when KeSwitchKernelStack is called.
189     *
190     * However, PsConvertToGuiThread "helpfully" restores EBP to the original
191     * caller's value, since it is considered a nonvolatile register. As such,
192     * as soon as we're back after the conversion and we try to store the result
193     * which will probably be in some stack variable (EBP-based), we'll crash as
194     * we are touching the de-allocated non-expanded stack.
195     *
196     * Thus we need a way to update our EBP before EBP is touched, and the only
197     * way to guarantee this is to do the call itself in assembly, use the EAX
198     * register to store the result, fixup EBP, and then let the C code continue
199     * on its merry way.
200     *
201     */
202
203    /* Save ebx */
204    push ebx
205
206    /* Calculate the stack frame offset in ebx */
207    mov ebx, ebp
208    sub ebx, esp
209
210    /* Call the worker function */
211    call _PsConvertToGuiThread@0
212
213    /* Adjust ebp to the new stack */
214    mov ebp, esp
215    add ebp, ebx
216
217    /* Restore ebx */
218    pop ebx
219
220    /* return to the caller */
221    ret
222
223/*
224NTSTATUS
225NTAPI
226KiSystemCallTrampoline(IN PVOID Handler,
227                       IN PVOID Arguments,
228                       IN ULONG StackBytes);
229*/
230PUBLIC _KiSystemCallTrampoline@12
231_KiSystemCallTrampoline@12:
232    push ebp
233    mov ebp, esp
234    push esi
235    push edi
236
237    /* Get handler */
238    mov eax, [ebp + 8]
239    /* Get arguments */
240    mov esi, [ebp + 12]
241    /* Get stack bytes */
242    mov ecx, [ebp + 16]
243
244    /* Copy args to the stack */
245    sub esp, ecx
246    mov edi, esp
247    shr ecx, 2
248    rep movsd
249
250    call eax
251
252    pop edi
253    pop esi
254    leave
255
256    ret 12
257END
258