3 * Copyright (C) 2000 David Welch <welch@cwcom.net>
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.
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.
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.
19 /* $Id: syscall.S,v 1.16 2004/07/02 00:47:57 royce Exp $
21 * FILE: ntoskrnl/hal/x86/syscall.s
22 * PURPOSE: 2E trap handler
23 * PROGRAMMER: David Welch (david.welch@seh.ox.ac.uk)
28 #include <ddk/status.h>
29 #include <internal/i386/segment.h>
30 #include <internal/ps.h>
31 #include <internal/i386/ke.h>
34 #define KernelMode (0)
40 .globl KeReturnFromSystemCall
41 .globl KeReturnFromSystemCallWithHook
42 .globl _interrupt_handler2e
45 /* Construct a trap frame on the stack */
54 /* Load PCR selector into fs */
55 movl $PCR_SELECTOR, %ebx
58 /* Save the old exception list */
59 movl %fs:KPCR_EXCEPTION_LIST, %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 */
67 movb %ss:KTHREAD_PREVIOUS_MODE(%esi), %bl
69 /* Set the new previous mode based on the saved CS selector */
71 andl $0x0000FFFF, %ebx
74 movb $KernelMode, %ss:KTHREAD_PREVIOUS_MODE(%esi)
77 movb $UserMode, %ss:KTHREAD_PREVIOUS_MODE(%esi)
80 /* Save other registers */
93 pushl $0 /* XXX: TempESP */
94 pushl $0 /* XXX: TempCS */
95 pushl $0 /* XXX: DebugPointer */
96 pushl $0 /* XXX: DebugArgMark */
99 /* Trick gdb 6 into backtracing over the system call */
101 pushl %ebx /* DebugEIP */
103 pushl %ebx /* DebugEBP */
105 movl 0x60(%esp), %ebx
106 pushl %ebx /* DebugEIP */
107 pushl %ebp /* DebugEBP */
110 /* Load the segment registers */
111 movl $KERNEL_DS, %ebx
117 * Save the old trap frame pointer over where we would save the EDX
120 movl KTHREAD_TRAP_FRAME(%esi), %ebx
121 movl %ebx, KTRAP_FRAME_EDX(%esp)
123 /* Allocate new Kernel stack frame */
126 /* Save a pointer to the trap frame in the TCB */
127 movl %ebp, KTHREAD_TRAP_FRAME(%esi)
129 /* Set ES to kernel segment */
133 /* Users's current stack frame pointer is source */
136 /* Determine system service table to use */
138 ja new_useShadowTable
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
150 /* GDB thinks the function starts here and
151 wants a standard prolog, so let's give it */
157 /* Allocate room for argument list from kernel stack */
158 movl %es:_KeServiceDescriptorTable + 12, %ecx
159 movb %es:(%ecx, %eax), %cl
163 /* Copy the arguments from the user stack to the kernel stack */
168 /* DS is now also kernel segment */
171 /* Call system call hook */
173 call _KiSystemCallHook
176 /* Make the system service call */
177 movl %es:_KeServiceDescriptorTable, %ecx
178 movl %es:(%ecx, %eax, 4), %eax
180 movl %eax, KTRAP_FRAME_EAX(%ebp) /* save our return value in PKTRAP_FRAME->Eax */
183 /* Bump Service Counter */
186 jmp KeDeallocateStackAndReturnFromSystemCallWithHook
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
199 new_shadowServiceInRange:
202 /* GDB thinks the function starts here and
203 wants a standard prolog, so let's give it */
209 /* Allocate room for argument list from kernel stack */
210 movl %es:_KeServiceDescriptorTableShadow + 28, %ecx
211 movb %es:(%ecx, %eax), %cl
215 /* Copy the arguments from the user stack to the kernel stack */
220 /* DS is now also kernel segment */
223 /* Call system call hook */
225 // call _KiSystemCallHook
228 /* Call service check routine */
233 /* Make the system service call */
234 movl %es:_KeServiceDescriptorTableShadow + 16, %ecx
235 movl %es:(%ecx, %eax, 4), %eax
237 movl %eax, KTRAP_FRAME_EAX(%ebp) /* save our return value in PKTRAP_FRAME->Eax */
240 /* Bump Service Counter */
243 KeDeallocateStackAndReturnFromSystemCallWithHook:
244 /* Deallocate the kernel stack frame */
247 KeReturnFromSystemCallWithHook:
248 /* Call the post system call hook and deliver any pending APCs */
250 call _KiAfterSystemCallHook
253 KeReturnFromSystemCall:
255 /* Restore the user context */
256 /* Get a pointer to the current thread */
259 /* Restore the old trap frame pointer */
260 movl KTRAP_FRAME_EDX(%esp), %ebx
261 movl %ebx, KTHREAD_TRAP_FRAME(%esi)
266 mov KTRAP_FRAME_RESERVED1(%ebp), %ax
267 cmp %ax, SSIDX_NTCONTINUE
269 movl KTRAP_FRAME_ESP(%ebp), %ecx
270 movl KTRAP_FRAME_EBP(%ebp), %edx
271 call @KeRosPrintEspEbp@8
275 /* Skip debug information and unsaved registers */
284 /* Restore the old previous mode */
286 movb %bl, %ss:KTHREAD_PREVIOUS_MODE(%esi)
288 /* Restore the old exception handler list */
290 movl %ebx, %fs:KPCR_EXCEPTION_LIST
297 addl $0x4, %esp /* Ignore error code */
301 /* R3: NOTE: This is part of my in-progress attempt at correcting NtContinue
302 * It is not being called, yet...
304 .globl @KeRosTrapReturn@8
307 /* point %esp to the trap frame to restore */
311 /* Call the post system call hook and deliver any pending APCs */
313 call _KiAfterSystemCallHook
316 /* Restore the user context */
317 /* Get a pointer to the current thread */
319 /* Restore the old trap frame pointer */
320 movl %edx, KTHREAD_TRAP_FRAME(%esi)