2002-07-04 David Welch <welch@computer2.darkstar.org>
[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.6 2002/07/04 19:56:36 dwelch Exp $
20 *
21 * FILE: ntoskrnl/hal/x86/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 <ddk/defines.h>
32
33 /*
34 *
35 */
36 .globl KeReturnFromSystemCall
37 .globl _interrupt_handler2e
38 _interrupt_handler2e:
39
40 /* Construct a trap frame on the stack */
41
42 /* Error code */
43 pushl $0
44 pushl %ebp
45 pushl %ebx
46 pushl %esi
47 pushl %edi
48 pushl %fs
49 /* Load PCR selector into fs */
50 movl $PCR_SELECTOR, %ebx
51 movl %ebx, %fs
52
53 /* Save the old exception list */
54 movl %fs:KPCR_EXCEPTION_LIST, %ebx
55 pushl %ebx
56 /* Set the exception handler chain terminator */
57 movl $0xffffffff, %fs:KPCR_EXCEPTION_LIST
58 /* Get a pointer to the current thread */
59 movl %fs:KPCR_CURRENT_THREAD, %esi
60 /* Save the old previous mode */
61 movl $0, %ebx
62 movb %ss:KTHREAD_PREVIOUS_MODE(%esi), %bl
63 pushl %ebx
64 /* Set the new previous mode based on the saved CS selector */
65 movl 0x24(%esp), %ebx
66 andl $0x0000FFFF, %ebx
67 cmpl $KERNEL_CS, %ebx
68 jne L1
69 movb $KernelMode, %ss:KTHREAD_PREVIOUS_MODE(%esi)
70 jmp L3
71 L1:
72 movb $UserMode, %ss:KTHREAD_PREVIOUS_MODE(%esi)
73 L3:
74
75 /* Save other registers */
76 pushl %eax
77 pushl %ecx
78 pushl %edx
79 pushl %ds
80 pushl %es
81 pushl %gs
82 pushl $0 /* DR7 */
83 pushl $0 /* DR6 */
84 pushl $0 /* DR3 */
85 pushl $0 /* DR2 */
86 pushl $0 /* DR1 */
87 pushl $0 /* DR0 */
88 pushl $0 /* XXX: TempESP */
89 pushl $0 /* XXX: TempCS */
90 pushl $0 /* XXX: DebugPointer */
91 pushl $0 /* XXX: DebugArgMark */
92 movl 0x60(%esp), %ebx
93 pushl %ebx /* DebugEIP */
94 pushl %ebp /* DebugEBP */
95
96 /* Load the segment registers */
97 movl $KERNEL_DS, %ebx
98 movl %ebx, %ds
99 movl %ebx, %es
100 movl %ebx, %gs
101
102 /*
103 * Save the old trap frame pointer over where we would save the EDX
104 * register.
105 */
106 movl KTHREAD_TRAP_FRAME(%esi), %ebx
107 movl %ebx, 0x3C(%esp)
108
109 /* Save a pointer to the trap frame in the TCB */
110 movl %esp, KTHREAD_TRAP_FRAME(%esi)
111
112 /* Set ES to kernel segment */
113 movw $KERNEL_DS,%bx
114 movw %bx,%es
115
116 /* Allocate new Kernel stack frame */
117 movl %esp,%ebp
118
119 /* Users's current stack frame pointer is source */
120 movl %edx,%esi
121
122 /* Determine system service table to use */
123 cmpl $0x0fff, %eax
124 ja new_useShadowTable
125
126 /* Check to see if EAX is valid/inrange */
127 cmpl %es:_KeServiceDescriptorTable + 8, %eax
128 jbe new_serviceInRange
129 movl $STATUS_INVALID_SYSTEM_SERVICE, %eax
130 jmp KeReturnFromSystemCall
131
132 new_serviceInRange:
133
134 /* Allocate room for argument list from kernel stack */
135 movl %es:_KeServiceDescriptorTable + 12, %ecx
136 movl %es:(%ecx, %eax, 4), %ecx
137 subl %ecx, %esp
138
139 /* Copy the arguments from the user stack to the kernel stack */
140 movl %esp,%edi
141 rep movsb
142
143 /* DS is now also kernel segment */
144 movw %bx, %ds
145
146 /* Call system call hook */
147 pushl %eax
148 call _KiSystemCallHook
149 popl %eax
150
151 /* Make the system service call */
152 movl %es:_KeServiceDescriptorTable, %ecx
153 movl %es:(%ecx, %eax, 4), %eax
154 call *%eax
155
156 #if CHECKED
157 /* Bump Service Counter */
158 #endif
159
160 /* Deallocate the kernel stack frame */
161 movl %ebp,%esp
162
163 /* Call the post system call hook and deliver any pending APCs */
164 pushl %ebp
165 pushl %eax
166 call _KiAfterSystemCallHook
167 addl $8,%esp
168
169 jmp KeReturnFromSystemCall
170
171 new_useShadowTable:
172
173 subl $0x1000, %eax
174
175 /* Check to see if EAX is valid/inrange */
176 cmpl %es:_KeServiceDescriptorTableShadow + 24, %eax
177 jbe new_shadowServiceInRange
178 movl $STATUS_INVALID_SYSTEM_SERVICE, %eax
179 jmp KeReturnFromSystemCall
180
181 new_shadowServiceInRange:
182
183 /* Allocate room for argument list from kernel stack */
184 movl %es:_KeServiceDescriptorTableShadow + 28, %ecx
185 movl %es:(%ecx, %eax, 4), %ecx
186 subl %ecx, %esp
187
188 /* Copy the arguments from the user stack to the kernel stack */
189 movl %esp,%edi
190 rep movsb
191
192 /* DS is now also kernel segment */
193 movw %bx,%ds
194
195 /* Call system call hook */
196 pushl %eax
197 call _KiSystemCallHook
198 popl %eax
199
200 /* Make the system service call */
201 movl %es:_KeServiceDescriptorTableShadow + 16, %ecx
202 movl %es:(%ecx, %eax, 4), %eax
203 call *%eax
204
205 #if CHECKED
206 /* Bump Service Counter */
207 #endif
208
209 /* Deallocate the kernel stack frame */
210 movl %ebp,%esp
211
212 /* Call the post system call hook and deliver any pending APCs */
213 pushl %esp
214 pushl %eax
215 call _KiAfterSystemCallHook
216 addl $8,%esp
217
218 KeReturnFromSystemCall:
219
220 /* Restore the user context */
221 /* Get a pointer to the current thread */
222 movl %fs:0x124, %esi
223
224 /* Restore the old trap frame pointer */
225 movl 0x3c(%esp), %ebx
226 movl %ebx, KTHREAD_TRAP_FRAME(%esi)
227
228 /* Skip debug information and unsaved registers */
229 addl $0x30, %esp
230 popl %gs
231 popl %es
232 popl %ds
233 popl %edx
234 popl %ecx
235 addl $0x4, %esp /* Don't restore eax */
236
237 /* Restore the old previous mode */
238 popl %ebx
239 movb %bl, %ss:KTHREAD_PREVIOUS_MODE(%esi)
240
241 /* Restore the old exception handler list */
242 popl %ebx
243 movl %ebx, %fs:KPCR_EXCEPTION_LIST
244
245 popl %fs
246 popl %edi
247 popl %esi
248 popl %ebx
249 popl %ebp
250 addl $0x4, %esp /* Ignore error code */
251
252 iret