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