Code clean-up.
[reactos.git] / reactos / ntoskrnl / ke / i386 / syscall.S
1 /*
2 * ReactOS kernel
3 * Copyright (C) 2000 David Welch <welch@cwcom.net>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 */
19 /* $Id: syscall.S,v 1.18 2004/10/31 19:46:10 ekohl Exp $
20 *
21 * FILE: ntoskrnl/ke/i386/syscall.S
22 * PURPOSE: 2E trap handler
23 * PROGRAMMER: David Welch (david.welch@seh.ox.ac.uk)
24 * UPDATE HISTORY:
25 * ???
26 */
27
28 #include <ddk/status.h>
29 #include <internal/i386/segment.h>
30 #include <internal/ps.h>
31 #include <internal/i386/ke.h>
32 #include <roscfg.h>
33
34 #define KernelMode (0)
35 #define UserMode (1)
36
37 /*
38 *
39 */
40 .globl KeReturnFromSystemCall
41 .globl KeReturnFromSystemCallWithHook
42 .globl _interrupt_handler2e
43 _interrupt_handler2e:
44
45 /* Construct a trap frame on the stack */
46
47 /* Error code */
48 pushl $0
49 pushl %ebp
50 pushl %ebx
51 pushl %esi
52 pushl %edi
53 pushl %fs
54 /* Load PCR selector into fs */
55 movl $PCR_SELECTOR, %ebx
56 movl %ebx, %fs
57
58 /* Save the old exception list */
59 movl %fs:KPCR_EXCEPTION_LIST, %ebx
60 pushl %ebx
61 /* Set the exception handler chain terminator */
62 movl $0xffffffff, %fs:KPCR_EXCEPTION_LIST
63 /* Get a pointer to the current thread */
64 movl %fs:KPCR_CURRENT_THREAD, %esi
65 /* Save the old previous mode */
66 movl $0, %ebx
67 movb %ss:KTHREAD_PREVIOUS_MODE(%esi), %bl
68 pushl %ebx
69 /* Set the new previous mode based on the saved CS selector */
70 movl 0x24(%esp), %ebx
71 andl $0x0000FFFF, %ebx
72 cmpl $KERNEL_CS, %ebx
73 jne L1
74 movb $KernelMode, %ss:KTHREAD_PREVIOUS_MODE(%esi)
75 jmp L3
76 L1:
77 movb $UserMode, %ss:KTHREAD_PREVIOUS_MODE(%esi)
78 L3:
79
80 /* Save other registers */
81 pushl %eax
82 pushl %ecx
83 pushl %edx
84 pushl %ds
85 pushl %es
86 pushl %gs
87 pushl $0 /* DR7 */
88 pushl $0 /* DR6 */
89 pushl $0 /* DR3 */
90 pushl $0 /* DR2 */
91 pushl $0 /* DR1 */
92 pushl $0 /* DR0 */
93 pushl $0 /* XXX: TempESP */
94 pushl $0 /* XXX: TempCS */
95 pushl $0 /* XXX: DebugPointer */
96 pushl $0 /* XXX: DebugArgMark */
97
98 #ifdef DBG
99 /* Trick gdb 6 into backtracing over the system call */
100 movl 4(%ebp), %ebx
101 pushl %ebx /* DebugEIP */
102 movl (%ebp), %ebx
103 pushl %ebx /* DebugEBP */
104 #else
105 movl 0x60(%esp), %ebx
106 pushl %ebx /* DebugEIP */
107 pushl %ebp /* DebugEBP */
108 #endif
109
110 /* Load the segment registers */
111 movl $KERNEL_DS, %ebx
112 movl %ebx, %ds
113 movl %ebx, %es
114 movl %ebx, %gs
115
116 /*
117 * Save the old trap frame pointer over where we would save the EDX
118 * register.
119 */
120 movl KTHREAD_TRAP_FRAME(%esi), %ebx
121 movl %ebx, KTRAP_FRAME_EDX(%esp)
122
123 /* Allocate new Kernel stack frame */
124 movl %esp,%ebp
125
126 /* Save a pointer to the trap frame in the TCB */
127 movl %ebp, KTHREAD_TRAP_FRAME(%esi)
128
129 /* Set ES to kernel segment */
130 movw $KERNEL_DS,%bx
131 movw %bx,%es
132
133 /* Users's current stack frame pointer is source */
134 movl %edx,%esi
135
136 /* Determine system service table to use */
137 cmpl $0x0fff, %eax
138 ja new_useShadowTable
139
140 /* Check to see if EAX is valid/inrange */
141 cmpl %es:_KeServiceDescriptorTable + 8, %eax
142 jbe new_serviceInRange
143 movl $STATUS_INVALID_SYSTEM_SERVICE, %eax
144 movl %eax, KTRAP_FRAME_EAX(%ebp) /* save our return value in PKTRAP_FRAME->Eax */
145 jmp KeReturnFromSystemCall
146
147 new_serviceInRange:
148
149 #ifdef DBG
150 /* GDB thinks the function starts here and
151 wants a standard prolog, so let's give it */
152 pushl %ebp
153 movl %esp,%ebp
154 popl %ebp
155 #endif
156
157 /* Allocate room for argument list from kernel stack */
158 movl %es:_KeServiceDescriptorTable + 12, %ecx
159 movb %es:(%ecx, %eax), %cl
160 movzx %cl, %ecx
161 subl %ecx, %esp
162
163 /* Copy the arguments from the user stack to the kernel stack */
164 movl %esp,%edi
165 cld
166 rep movsb
167
168 /* DS is now also kernel segment */
169 movw %bx, %ds
170
171 /* Call system call hook */
172 pushl %eax
173 call _KiSystemCallHook
174 popl %eax
175
176 /* Make the system service call */
177 movl %es:_KeServiceDescriptorTable, %ecx
178 movl %es:(%ecx, %eax, 4), %eax
179 call *%eax
180 movl %eax, KTRAP_FRAME_EAX(%ebp) /* save our return value in PKTRAP_FRAME->Eax */
181
182 #if CHECKED
183 /* Bump Service Counter */
184 #endif
185
186 jmp KeDeallocateStackAndReturnFromSystemCallWithHook
187
188 new_useShadowTable:
189
190 subl $0x1000, %eax
191
192 /* Check to see if EAX is valid/inrange */
193 cmpl %es:_KeServiceDescriptorTableShadow + 24, %eax
194 jbe new_shadowServiceInRange
195 movl $STATUS_INVALID_SYSTEM_SERVICE, %eax
196 movl %eax, KTRAP_FRAME_EAX(%ebp) /* save our return value in PKTRAP_FRAME->Eax */
197 jmp KeReturnFromSystemCall
198
199 new_shadowServiceInRange:
200
201 #ifdef DBG
202 /*
203 * GDB thinks the function starts here and
204 * wants a standard prolog, so let's give it
205 */
206 pushl %ebp
207 movl %esp,%ebp
208 popl %ebp
209 #endif
210
211 /* Allocate room for argument list from kernel stack */
212 movl %es:_KeServiceDescriptorTableShadow + 28, %ecx
213 movb %es:(%ecx, %eax), %cl
214 movzx %cl, %ecx
215 subl %ecx, %esp
216
217 /* Copy the arguments from the user stack to the kernel stack */
218 movl %esp,%edi
219 cld
220 rep movsb
221
222 /* DS is now also kernel segment */
223 movw %bx,%ds
224
225 /* Call system call hook */
226 // pushl %eax
227 // call _KiSystemCallHook
228 // popl %eax
229
230 /* Call service check routine */
231 pushl %eax
232 call _KiServiceCheck
233 popl %eax
234
235 /* Make the system service call */
236 movl %es:_KeServiceDescriptorTableShadow + 16, %ecx
237 movl %es:(%ecx, %eax, 4), %eax
238 call *%eax
239 movl %eax, KTRAP_FRAME_EAX(%ebp) /* save our return value in PKTRAP_FRAME->Eax */
240
241 #if CHECKED
242 /* Bump Service Counter */
243 #endif
244
245 KeDeallocateStackAndReturnFromSystemCallWithHook:
246 /* Deallocate the kernel stack frame */
247 movl %ebp,%esp
248
249 KeReturnFromSystemCallWithHook:
250 /* Call the post system call hook and deliver any pending APCs */
251 pushl %esp
252 call _KiAfterSystemCallHook
253 addl $4,%esp
254
255 KeReturnFromSystemCall:
256
257 /* Restore the user context */
258 /* Get a pointer to the current thread */
259 movl %fs:0x124, %esi
260
261 /* Restore the old trap frame pointer */
262 movl KTRAP_FRAME_EDX(%esp), %ebx
263 movl %ebx, KTHREAD_TRAP_FRAME(%esi)
264
265 KiRosTrapReturn:
266
267 #if 0
268 mov KTRAP_FRAME_RESERVED1(%ebp), %ax
269 cmp %ax, SSIDX_NTCONTINUE
270 jnz KeNoEpilogPrint
271 movl KTRAP_FRAME_ESP(%ebp), %ecx
272 movl KTRAP_FRAME_EBP(%ebp), %edx
273 call @KeRosPrintEspEbp@8
274 KeNoEpilogPrint:
275 #endif
276
277 /* Skip debug information and unsaved registers */
278 addl $0x30, %esp
279 popl %gs
280 popl %es
281 popl %ds
282 popl %edx
283 popl %ecx
284 popl %eax
285
286 /* Restore the old previous mode */
287 popl %ebx
288 movb %bl, %ss:KTHREAD_PREVIOUS_MODE(%esi)
289
290 /* Restore the old exception handler list */
291 popl %ebx
292 movl %ebx, %fs:KPCR_EXCEPTION_LIST
293
294 popl %fs
295 popl %edi
296 popl %esi
297 popl %ebx
298 popl %ebp
299 addl $0x4, %esp /* Ignore error code */
300
301 iret
302
303 /* R3: NOTE: This is part of my in-progress attempt at correcting NtContinue
304 * It is not being called, yet...
305 */
306 .globl @KeRosTrapReturn@8
307 @KeRosTrapReturn@8:
308
309 /* point %esp to the trap frame to restore */
310 movl %ecx, %esp
311 movl %esp, %ebp
312
313 /* Call the post system call hook and deliver any pending APCs */
314 pushl %esp
315 call _KiAfterSystemCallHook
316 addl $4,%esp
317
318 /* Restore the user context */
319 /* Get a pointer to the current thread */
320 movl %fs:0x124, %esi
321 /* Restore the old trap frame pointer */
322 movl %edx, KTHREAD_TRAP_FRAME(%esi)
323
324 jmp KiRosTrapReturn;