3 * Copyright (C) 2000 David Welch <welch@cwcom.net>
5 * Converted to MSVC-compatible inline assembler by Mike Nordell, 2003.
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 * FILE: MSVC6/ntoskrnl/ke_i386_syscall.c
23 * based on ntoskrnl/ke/i386/syscall.s
24 * PURPOSE: syscall dispatching and support
25 * PROGRAMMER: David Welch (welch@cwcom.net)
30 /* INCLUDES ******************************************************************/
34 #include <ddk/ntddk.h>
35 #include <ddk/status.h>
36 #include <internal/i386/segment.h>
37 #include <internal/i386/fpu.h>
38 #include <internal/ps.h>
39 #include <ddk/defines.h>
40 #include <internal/v86m.h>
42 //#include <ntos/service.h>
43 #include <internal/trap.h>
44 #include <internal/ps.h>
47 #include <internal/ntoskrnl.h>
48 #include <internal/i386/segment.h>
51 #define KernelMode (0)
55 // TMN: Replicated here to reduce mess-time
56 #ifdef STATUS_INVALID_SYSTEM_SERVICE
57 #undef STATUS_INVALID_SYSTEM_SERVICE
59 #define STATUS_INVALID_SYSTEM_SERVICE 0xc000001c
66 void KiServiceCheck (ULONG Nr
);
67 ULONG
KiAfterSystemCallHook(ULONG NtStatus
, PKTRAP_FRAME TrapFrame
);
68 VOID
KiSystemCallHook(ULONG Nr
, ...);
70 void KeReturnFromSystemCallWithHook();
71 void KeReturnFromSystemCall();
75 void interrupt_handler2e(void)
79 /* Construct a trap frame on the stack */
88 /* Load PCR selector into fs */
92 /* Save the old exception list */
93 mov ebx
, fs
:KPCR_EXCEPTION_LIST
95 /* Set the exception handler chain terminator */
96 mov dword ptr fs
:KPCR_EXCEPTION_LIST
, 0xffffffff
97 /* Get a pointer to the current thread */
98 mov esi
, fs
:KPCR_CURRENT_THREAD
99 /* Save the old previous mode */
101 mov bl
, ss
:KTHREAD_PREVIOUS_MODE
[esi
]
103 /* Set the new previous mode based on the saved CS selector */
108 // TODO: Verify implementation change and use this code path
109 // to remove two conditional jumps.
111 mov ss
:KTHREAD_PREVIOUS_MODE
[esi
], bl
114 mov ss
:KTHREAD_PREVIOUS_MODE
[esi
], KernelMode
117 mov ss
:KTHREAD_PREVIOUS_MODE
[esi
], UserMode
121 /* Save other registers */
134 push
0 /* XXX: TempESP */
135 push
0 /* XXX: TempCS */
136 push
0 /* XXX: DebugPointer */
137 push
0 /* XXX: DebugArgMark */
139 push ebx
/* DebugEIP */
140 push ebp
/* DebugEBP */
142 /* Load the segment registers */
149 * Save the old trap frame pointer over where we would save the EDX
152 mov ebx
, KTHREAD_TRAP_FRAME
[esi
]
155 /* Save a pointer to the trap frame in the TCB */
156 mov KTHREAD_TRAP_FRAME
[esi
], esp
158 /* Set ES to kernel segment */
162 /* Allocate new Kernel stack frame */
165 /* Users's current stack frame pointer is source */
168 /* Determine system service table to use */
170 ja new_useShadowTable
172 /* Check to see if EAX is valid/inrange */
173 cmp eax
, es
:KeServiceDescriptorTable
+ 8
174 jbe new_serviceInRange
175 mov eax
, STATUS_INVALID_SYSTEM_SERVICE
176 jmp KeReturnFromSystemCall
180 /* Allocate room for argument list from kernel stack */
181 mov ecx
, es
:KeServiceDescriptorTable
+ 12
182 mov ecx
, es
:[ecx
+ eax
* 4]
185 /* Copy the arguments from the user stack to the kernel stack */
190 /* DS is now also kernel segment */
193 /* Call system call hook */
195 call KiSystemCallHook
198 /* Make the system service call */
199 mov ecx
, es
:KeServiceDescriptorTable
200 mov eax
, es
:[ecx
+ eax
* 4]
204 /* Bump Service Counter */
207 /* Deallocate the kernel stack frame */
210 /* Call the post system call hook and deliver any pending APCs */
213 call KiAfterSystemCallHook
216 jmp KeReturnFromSystemCall
222 /* Check to see if EAX is valid/inrange */
223 cmp eax
, es
:KeServiceDescriptorTableShadow
+ 24
224 jbe new_shadowServiceInRange
225 mov eax
, STATUS_INVALID_SYSTEM_SERVICE
226 jmp KeReturnFromSystemCall
228 new_shadowServiceInRange
:
230 /* Allocate room for argument list from kernel stack */
231 mov ecx
, es
:KeServiceDescriptorTableShadow
+ 28
232 mov ecx
, es
:[ecx
+ eax
* 4]
235 /* Copy the arguments from the user stack to the kernel stack */
240 /* DS is now also kernel segment */
243 /* Call system call hook */
245 // call _KiSystemCallHook
248 /* Call service check routine */
253 /* Make the system service call */
254 mov ecx
, es
:KeServiceDescriptorTableShadow
+ 16
255 mov eax
, es
:[ecx
+ eax
* 4]
259 /* Bump Service Counter */
262 /* Deallocate the kernel stack frame */
265 // TMN: Added, to be able to separate this into different functions
266 jmp KeReturnFromSystemCallWithHook
271 void KeReturnFromSystemCallWithHook()
275 /* Call the post system call hook and deliver any pending APCs */
278 call KiAfterSystemCallHook
281 // TMN: Added, to be able to separate this into different functions
282 jmp KeReturnFromSystemCall
287 void KeReturnFromSystemCall()
291 /* Restore the user context */
292 /* Get a pointer to the current thread */
295 /* Restore the old trap frame pointer */
297 mov KTHREAD_TRAP_FRAME
[esi
], ebx
299 /* Skip debug information and unsaved registers */
306 add esp
, 4 /* Don't restore eax */
308 /* Restore the old previous mode */
310 mov ss
:KTHREAD_PREVIOUS_MODE
[esi
], bl
312 /* Restore the old exception handler list */
314 mov fs
:KPCR_EXCEPTION_LIST
, ebx
321 add esp
, 4 /* Ignore error code */