cleanup/reformat syscall code, save return value as soon as possible so that eax is freed up, which also simplifies the implementation of KiAfterSystemCallHook(), also removes a couple redundant instructions.

svn path=/trunk/; revision=9955
This commit is contained in:
Royce Mitchell III 2004-07-01 01:52:37 +00:00
parent aa33e15965
commit 209e1d7692
2 changed files with 222 additions and 203 deletions

View file

@ -16,7 +16,7 @@
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/ */
/* $Id: syscall.S,v 1.14 2004/04/07 15:35:14 ekohl Exp $ /* $Id: syscall.S,v 1.15 2004/07/01 01:52:37 royce Exp $
* *
* FILE: ntoskrnl/hal/x86/syscall.s * FILE: ntoskrnl/hal/x86/syscall.s
* PURPOSE: 2E trap handler * PURPOSE: 2E trap handler
@ -28,6 +28,7 @@
#include <ddk/status.h> #include <ddk/status.h>
#include <internal/i386/segment.h> #include <internal/i386/segment.h>
#include <internal/ps.h> #include <internal/ps.h>
#include <internal/i386/ke.h>
#include <roscfg.h> #include <roscfg.h>
#define KernelMode (0) #define KernelMode (0)
@ -41,250 +42,266 @@
.globl _interrupt_handler2e .globl _interrupt_handler2e
_interrupt_handler2e: _interrupt_handler2e:
/* Construct a trap frame on the stack */ /* Construct a trap frame on the stack */
/* Error code */ /* Error code */
pushl $0 pushl $0
pushl %ebp pushl %ebp
pushl %ebx pushl %ebx
pushl %esi pushl %esi
pushl %edi pushl %edi
pushl %fs pushl %fs
/* Load PCR selector into fs */ /* Load PCR selector into fs */
movl $PCR_SELECTOR, %ebx movl $PCR_SELECTOR, %ebx
movl %ebx, %fs movl %ebx, %fs
/* Save the old exception list */ /* Save the old exception list */
movl %fs:KPCR_EXCEPTION_LIST, %ebx movl %fs:KPCR_EXCEPTION_LIST, %ebx
pushl %ebx pushl %ebx
/* Set the exception handler chain terminator */ /* Set the exception handler chain terminator */
movl $0xffffffff, %fs:KPCR_EXCEPTION_LIST movl $0xffffffff, %fs:KPCR_EXCEPTION_LIST
/* Get a pointer to the current thread */ /* Get a pointer to the current thread */
movl %fs:KPCR_CURRENT_THREAD, %esi movl %fs:KPCR_CURRENT_THREAD, %esi
/* Save the old previous mode */ /* Save the old previous mode */
movl $0, %ebx movl $0, %ebx
movb %ss:KTHREAD_PREVIOUS_MODE(%esi), %bl movb %ss:KTHREAD_PREVIOUS_MODE(%esi), %bl
pushl %ebx pushl %ebx
/* Set the new previous mode based on the saved CS selector */ /* Set the new previous mode based on the saved CS selector */
movl 0x24(%esp), %ebx movl 0x24(%esp), %ebx
andl $0x0000FFFF, %ebx andl $0x0000FFFF, %ebx
cmpl $KERNEL_CS, %ebx cmpl $KERNEL_CS, %ebx
jne L1 jne L1
movb $KernelMode, %ss:KTHREAD_PREVIOUS_MODE(%esi) movb $KernelMode, %ss:KTHREAD_PREVIOUS_MODE(%esi)
jmp L3 jmp L3
L1: L1:
movb $UserMode, %ss:KTHREAD_PREVIOUS_MODE(%esi) movb $UserMode, %ss:KTHREAD_PREVIOUS_MODE(%esi)
L3: L3:
/* Save other registers */ /* Save other registers */
pushl %eax pushl %eax
pushl %ecx pushl %ecx
pushl %edx pushl %edx
pushl %ds pushl %ds
pushl %es pushl %es
pushl %gs pushl %gs
pushl $0 /* DR7 */ pushl $0 /* DR7 */
pushl $0 /* DR6 */ pushl $0 /* DR6 */
pushl $0 /* DR3 */ pushl $0 /* DR3 */
pushl $0 /* DR2 */ pushl $0 /* DR2 */
pushl $0 /* DR1 */ pushl $0 /* DR1 */
pushl $0 /* DR0 */ pushl $0 /* DR0 */
pushl $0 /* XXX: TempESP */ pushl $0 /* XXX: TempESP */
pushl $0 /* XXX: TempCS */ pushl $0 /* XXX: TempCS */
pushl $0 /* XXX: DebugPointer */ pushl $0 /* XXX: DebugPointer */
pushl $0 /* XXX: DebugArgMark */ pushl $0 /* XXX: DebugArgMark */
#ifdef DBG #ifdef DBG
/* Trick gdb 6 into backtracing over the system call */ /* Trick gdb 6 into backtracing over the system call */
movl 4(%ebp), %ebx movl 4(%ebp), %ebx
pushl %ebx /* DebugEIP */ pushl %ebx /* DebugEIP */
movl (%ebp), %ebx movl (%ebp), %ebx
pushl %ebx /* DebugEBP */ pushl %ebx /* DebugEBP */
#else #else
movl 0x60(%esp), %ebx movl 0x60(%esp), %ebx
pushl %ebx /* DebugEIP */ pushl %ebx /* DebugEIP */
pushl %ebp /* DebugEBP */ pushl %ebp /* DebugEBP */
#endif #endif
/* Load the segment registers */ /* Load the segment registers */
movl $KERNEL_DS, %ebx movl $KERNEL_DS, %ebx
movl %ebx, %ds movl %ebx, %ds
movl %ebx, %es movl %ebx, %es
movl %ebx, %gs movl %ebx, %gs
/* /*
* Save the old trap frame pointer over where we would save the EDX * Save the old trap frame pointer over where we would save the EDX
* register. * register.
*/ */
movl KTHREAD_TRAP_FRAME(%esi), %ebx movl KTHREAD_TRAP_FRAME(%esi), %ebx
movl %ebx, 0x3C(%esp) movl %ebx, KTRAP_FRAME_EDX(%esp)
/* Save a pointer to the trap frame in the TCB */
movl %esp, KTHREAD_TRAP_FRAME(%esi)
/* Set ES to kernel segment */
movw $KERNEL_DS,%bx
movw %bx,%es
/* Allocate new Kernel stack frame */ /* Allocate new Kernel stack frame */
movl %esp,%ebp movl %esp,%ebp
/* Users's current stack frame pointer is source */ /* Save a pointer to the trap frame in the TCB */
movl %edx,%esi movl %ebp, KTHREAD_TRAP_FRAME(%esi)
/* Determine system service table to use */ /* Set ES to kernel segment */
cmpl $0x0fff, %eax movw $KERNEL_DS,%bx
ja new_useShadowTable movw %bx,%es
/* Check to see if EAX is valid/inrange */ /* Users's current stack frame pointer is source */
cmpl %es:_KeServiceDescriptorTable + 8, %eax movl %edx,%esi
jbe new_serviceInRange
movl $STATUS_INVALID_SYSTEM_SERVICE, %eax /* Determine system service table to use */
jmp KeReturnFromSystemCall cmpl $0x0fff, %eax
ja new_useShadowTable
/* Check to see if EAX is valid/inrange */
cmpl %es:_KeServiceDescriptorTable + 8, %eax
jbe new_serviceInRange
movl $STATUS_INVALID_SYSTEM_SERVICE, %eax
movl %eax, KTRAP_FRAME_EAX(%ebp) /* save our return value in PKTRAP_FRAME->Eax */
jmp KeReturnFromSystemCall
new_serviceInRange: new_serviceInRange:
#ifdef DBG #ifdef DBG
/* GDB thinks the function starts here and /* GDB thinks the function starts here and
wants a standard prolog, so let's give it */ wants a standard prolog, so let's give it */
pushl %ebp pushl %ebp
movl %esp,%ebp movl %esp,%ebp
popl %ebp popl %ebp
#endif #endif
/* Allocate room for argument list from kernel stack */ /* Allocate room for argument list from kernel stack */
movl %es:_KeServiceDescriptorTable + 12, %ecx movl %es:_KeServiceDescriptorTable + 12, %ecx
movb %es:(%ecx, %eax), %cl movb %es:(%ecx, %eax), %cl
movzx %cl, %ecx movzx %cl, %ecx
subl %ecx, %esp subl %ecx, %esp
/* Copy the arguments from the user stack to the kernel stack */ /* Copy the arguments from the user stack to the kernel stack */
movl %esp,%edi movl %esp,%edi
cld cld
rep movsb rep movsb
/* DS is now also kernel segment */ /* DS is now also kernel segment */
movw %bx, %ds movw %bx, %ds
/* Call system call hook */
pushl %eax
call _KiSystemCallHook
popl %eax
/* Make the system service call */ /* Call system call hook */
movl %es:_KeServiceDescriptorTable, %ecx pushl %eax
movl %es:(%ecx, %eax, 4), %eax call _KiSystemCallHook
call *%eax popl %eax
/* Make the system service call */
movl %es:_KeServiceDescriptorTable, %ecx
movl %es:(%ecx, %eax, 4), %eax
call *%eax
movl %eax, KTRAP_FRAME_EAX(%ebp) /* save our return value in PKTRAP_FRAME->Eax */
#if CHECKED #if CHECKED
/* Bump Service Counter */ /* Bump Service Counter */
#endif #endif
/* Deallocate the kernel stack frame */ jmp KeDeallocateStackAndReturnFromSystemCallWithHook
movl %ebp,%esp
/* Call the post system call hook and deliver any pending APCs */
pushl %ebp
pushl %eax
call _KiAfterSystemCallHook
addl $8,%esp
jmp KeReturnFromSystemCall
new_useShadowTable: new_useShadowTable:
subl $0x1000, %eax subl $0x1000, %eax
/* Check to see if EAX is valid/inrange */ /* Check to see if EAX is valid/inrange */
cmpl %es:_KeServiceDescriptorTableShadow + 24, %eax cmpl %es:_KeServiceDescriptorTableShadow + 24, %eax
jbe new_shadowServiceInRange jbe new_shadowServiceInRange
movl $STATUS_INVALID_SYSTEM_SERVICE, %eax movl $STATUS_INVALID_SYSTEM_SERVICE, %eax
jmp KeReturnFromSystemCall movl %eax, KTRAP_FRAME_EAX(%ebp) /* save our return value in PKTRAP_FRAME->Eax */
jmp KeReturnFromSystemCall
new_shadowServiceInRange: new_shadowServiceInRange:
#ifdef DBG #ifdef DBG
/* GDB thinks the function starts here and /* GDB thinks the function starts here and
wants a standard prolog, so let's give it */ wants a standard prolog, so let's give it */
pushl %ebp pushl %ebp
movl %esp,%ebp movl %esp,%ebp
popl %ebp popl %ebp
#endif #endif
/* Allocate room for argument list from kernel stack */ /* Allocate room for argument list from kernel stack */
movl %es:_KeServiceDescriptorTableShadow + 28, %ecx movl %es:_KeServiceDescriptorTableShadow + 28, %ecx
movb %es:(%ecx, %eax), %cl movb %es:(%ecx, %eax), %cl
movzx %cl, %ecx movzx %cl, %ecx
subl %ecx, %esp subl %ecx, %esp
/* Copy the arguments from the user stack to the kernel stack */ /* Copy the arguments from the user stack to the kernel stack */
movl %esp,%edi movl %esp,%edi
cld cld
rep movsb rep movsb
/* DS is now also kernel segment */ /* DS is now also kernel segment */
movw %bx,%ds movw %bx,%ds
/* Call system call hook */ /* Call system call hook */
// pushl %eax // pushl %eax
// call _KiSystemCallHook // call _KiSystemCallHook
// popl %eax // popl %eax
/* Call service check routine */ /* Call service check routine */
pushl %eax pushl %eax
call _KiServiceCheck call _KiServiceCheck
popl %eax popl %eax
/* Make the system service call */ /* Make the system service call */
movl %es:_KeServiceDescriptorTableShadow + 16, %ecx movl %es:_KeServiceDescriptorTableShadow + 16, %ecx
movl %es:(%ecx, %eax, 4), %eax movl %es:(%ecx, %eax, 4), %eax
call *%eax call *%eax
movl %eax, KTRAP_FRAME_EAX(%ebp) /* save our return value in PKTRAP_FRAME->Eax */
#if CHECKED #if CHECKED
/* Bump Service Counter */ /* Bump Service Counter */
#endif #endif
/* Deallocate the kernel stack frame */ KeDeallocateStackAndReturnFromSystemCallWithHook:
movl %ebp,%esp /* Deallocate the kernel stack frame */
movl %ebp,%esp
KeReturnFromSystemCallWithHook: KeReturnFromSystemCallWithHook:
/* Call the post system call hook and deliver any pending APCs */ /* Call the post system call hook and deliver any pending APCs */
pushl %esp pushl %esp
pushl %eax call _KiAfterSystemCallHook
call _KiAfterSystemCallHook addl $4,%esp
addl $8,%esp
KeReturnFromSystemCall: KeReturnFromSystemCall:
/* Restore the user context */
/* Get a pointer to the current thread */
movl %fs:0x124, %esi
/* Restore the old trap frame pointer */
movl 0x3c(%esp), %ebx
movl %ebx, KTHREAD_TRAP_FRAME(%esi)
/* Skip debug information and unsaved registers */
addl $0x30, %esp
popl %gs
popl %es
popl %ds
popl %edx
popl %ecx
addl $0x4, %esp /* Don't restore eax */
/* Restore the old previous mode */ /* Restore the user context */
popl %ebx /* Get a pointer to the current thread */
movb %bl, %ss:KTHREAD_PREVIOUS_MODE(%esi) movl %fs:0x124, %esi
/* Restore the old exception handler list */ /* Restore the old trap frame pointer */
popl %ebx movl KTRAP_FRAME_EDX(%esp), %ebx
movl %ebx, %fs:KPCR_EXCEPTION_LIST movl %ebx, KTHREAD_TRAP_FRAME(%esi)
popl %fs KiRosTrapReturn:
popl %edi /* Skip debug information and unsaved registers */
popl %esi addl $0x30, %esp
popl %ebx popl %gs
popl %ebp popl %es
addl $0x4, %esp /* Ignore error code */ popl %ds
popl %edx
iret popl %ecx
popl %eax
/* Restore the old previous mode */
popl %ebx
movb %bl, %ss:KTHREAD_PREVIOUS_MODE(%esi)
/* Restore the old exception handler list */
popl %ebx
movl %ebx, %fs:KPCR_EXCEPTION_LIST
popl %fs
popl %edi
popl %esi
popl %ebx
popl %ebp
addl $0x4, %esp /* Ignore error code */
iret
/* R3: NOTE: This is part of my in-progress attempt at correcting NtContinue
* It is not being called, yet...
*/
.globl @KeRosTrapReturn@8
@KeRosTrapReturn@8:
/* Call the post system call hook and deliver any pending APCs */
pushl %esp
call _KiAfterSystemCallHook
addl $4,%esp
/* Restore the user context */
/* Get a pointer to the current thread */
movl %fs:0x124, %esi
/* Restore the old trap frame pointer */
movl %edx, KTHREAD_TRAP_FRAME(%esi)
/* point %esp to the trap frame to restore */
movl %ecx, %esp
jmp KiRosTrapReturn;

View file

@ -1,4 +1,4 @@
/* $Id: usercall.c,v 1.26 2004/06/23 22:32:24 ion Exp $ /* $Id: usercall.c,v 1.27 2004/07/01 01:52:37 royce Exp $
* *
* COPYRIGHT: See COPYING in the top level directory * COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel * PROJECT: ReactOS kernel
@ -26,7 +26,8 @@
/* FUNCTIONS *****************************************************************/ /* FUNCTIONS *****************************************************************/
VOID KiSystemCallHook(ULONG Nr, ...) VOID
KiSystemCallHook(ULONG Nr, ...)
{ {
#if 0 #if 0
va_list ap; va_list ap;
@ -46,7 +47,8 @@ VOID KiSystemCallHook(ULONG Nr, ...)
#endif #endif
} }
ULONG KiAfterSystemCallHook(ULONG NtStatus, PKTRAP_FRAME TrapFrame) VOID
KiAfterSystemCallHook(PKTRAP_FRAME TrapFrame)
{ {
if (KeGetCurrentThread()->Alerted[1] != 0 && TrapFrame->Cs != KERNEL_CS) if (KeGetCurrentThread()->Alerted[1] != 0 && TrapFrame->Cs != KERNEL_CS)
{ {
@ -56,11 +58,11 @@ ULONG KiAfterSystemCallHook(ULONG NtStatus, PKTRAP_FRAME TrapFrame)
{ {
KiDeliverUserApc(TrapFrame); KiDeliverUserApc(TrapFrame);
} }
return(NtStatus);
} }
VOID KiServiceCheck (ULONG Nr) VOID
KiServiceCheck (ULONG Nr)
{ {
PETHREAD Thread; PETHREAD Thread;