From 93c504407b9af886f8addef8e8a8bf7a490700ed Mon Sep 17 00:00:00 2001 From: Alex Ionescu Date: Tue, 17 Jan 2006 05:54:35 +0000 Subject: [PATCH] - Implement SYSCALL_PROLOG for the main handler and the three fast-system calls (ints 2b, 2c, 2d) which are not yet implemented. - Document the macros. svn path=/trunk/; revision=20935 --- .../ntoskrnl/include/internal/i386/asmmacro.S | 120 +++++++++++++++++- reactos/ntoskrnl/ke/i386/syscall.S | 96 ++++---------- 2 files changed, 138 insertions(+), 78 deletions(-) diff --git a/reactos/ntoskrnl/include/internal/i386/asmmacro.S b/reactos/ntoskrnl/include/internal/i386/asmmacro.S index 11ce086be16..d0cf360f6f1 100644 --- a/reactos/ntoskrnl/include/internal/i386/asmmacro.S +++ b/reactos/ntoskrnl/include/internal/i386/asmmacro.S @@ -234,15 +234,123 @@ SET_TF_DEBUG_HEADER // -// @name TRAP_EPILOG +// @name SYSCALL_PROLOG // -// This macro creates a standard trap entry prologue. -// It should be used for entry into any kernel trap (KiTrapXx), but not for -// system calls, which require special handling. +// This macro creates a system call entry prologue. +// It should be used for entry into any fast-system call (KiGetTickCount, +// KiCallbackReturn, KiRaiseAssertion) and the generic system call handler +// (KiSystemService) // // @param Label -// Identifying name of the caller function; will be used to append -// to the name V86 and DR helper functions, which must already exist. +// Unique label identifying the name of the caller function; will be +// used to append to the name of the DR helper function, which must +// already exist. +// +// @remark None. +// +.macro SYSCALL_PROLOG + /* Create a trap frame */ + push 0 + push ebp + push ebx + push esi + push edi + push fs + + /* Load PCR Selector into fs */ + mov ebx, KGDT_R0_PCR + mov fs, bx + + /* Get a pointer to the current thread */ + mov esi, [fs:KPCR_CURRENT_THREAD] + + /* Save the previous exception list */ + push [fs:KPCR_EXCEPTION_LIST] + + /* Set the exception handler chain terminator */ + mov dword ptr [fs:KPCR_EXCEPTION_LIST], -1 + + /* Save the old previous mode */ + push ss:[esi+KTHREAD_PREVIOUS_MODE] + + /* Skip the other registers */ + sub esp, 0x48 + + /* Hack: it seems that on VMWare someone damages ES/DS on exit. Investigate! */ + mov [esp+KTRAP_FRAME_DS], ds + mov [esp+KTRAP_FRAME_ES], es + + /* Set the new previous mode based on the saved CS selector */ + mov ebx, [esp+0x6C] + and ebx, 1 + mov byte ptr ss:[esi+KTHREAD_PREVIOUS_MODE], bl + + /* Go on the Kernel stack frame */ + mov ebp, esp + + /* Save the old trap frame pointer where EDX would be saved */ + mov ebx, [esi+KTHREAD_TRAP_FRAME] + mov [ebp+KTRAP_FRAME_EDX], ebx + + /* Flush DR7 */ + and dword ptr [ebp+KTRAP_FRAME_DR7], 0 + + /* Check if the thread was being debugged */ + test byte ptr [esi+KTHREAD_DEBUG_ACTIVE], 0xFF + + /* Set the thread's trap frame and clear direction flag */ + mov [esi+KTHREAD_TRAP_FRAME], ebp + cld + + /* Save DR registers if needed */ + //jnz Dr_kss_&Label + + /* Set the trap frame debug header */ + SET_TF_DEBUG_HEADER + +#ifdef DBG // FIXME: Is this for GDB? Can it be moved in the stub? + /* + * We want to know the address from where the syscall stub was called. + * If PrevMode is KernelMode, that address is stored in our own (kernel) + * stack, at location KTRAP_FRAME_ESP. + * If we're coming from UserMode, we load the usermode stack pointer + * and go back two frames (first frame is the syscall stub, second call + * is the caller of the stub). + */ + mov edi, [ebp+KTRAP_FRAME_ESP] + test byte ptr [esi+KTHREAD_PREVIOUS_MODE], 0x01 + jz 0f + mov edi, [edi+4] +0: + mov [ebp+KTRAP_FRAME_DEBUGEIP], edi +#endif + + /* Enable interrupts */ + sti +.endm + +// +// @name TRAP_EPILOG +// +// This macro creates an epilogue for leaving any system trap. +// It is used for exiting system calls, exceptions, interrupts and generic +// traps. +// +// @param SystemCall +// Specifies whether this trap will exit a system call. If so, special +// code will be assembled to potentially use SYSEXIT instead of IRETD. +// +// @param RestorePreviousMode +// Specifies if the previous mode should be restored. +// +// @param RestoreSegments +// Specifies if the segment registers should be restored. +// +// @param RestoreVolatiles +// Specifies if the volatile registers should be restored. +// +// @param RestoreAllRegs +// Specifies if volatiles and segments should both be restored. // // @remark // diff --git a/reactos/ntoskrnl/ke/i386/syscall.S b/reactos/ntoskrnl/ke/i386/syscall.S index 8c6275c8e3c..7d2ab15e141 100644 --- a/reactos/ntoskrnl/ke/i386/syscall.S +++ b/reactos/ntoskrnl/ke/i386/syscall.S @@ -13,22 +13,33 @@ .globl _KiFastCallEntry .globl _KiSystemService .globl _KiDebugService +.globl _Kei386EoiHelper@0 +.globl _NtRaiseException@12 +.globl _NtContinue@8 .intel_syntax noprefix /* * FIXMEs: * - Figure out why ES/DS gets messed up in VMWare, when doing KiServiceExit only, * and only when called from user-mode, and returning to user-mode. - * - Implement SYSCALL_PROLOG macro. - */ - - /*** This file is a mess; it is being worked on. Please contact Alex: - *** alex@relsoft.net if you want to make any changes to it before this - *** message goes away + * - Merge with trap.S and document all traps. + * - Use MmProbe when copying arguments to syscall. + * - Add DR macro/save and VM macro/save. + * - Implement KiCallbackReturn, KiGetTickCount, KiRaiseAssertion */ /* FUNCTIONS ***************************************************************/ +.func KiSystemService +_KiSystemService: + + /* Enter the shared system call prolog */ + SYSCALL_PROLOG + + /* Jump to the actual handler */ + jmp SharedCode +.endfunc + BadStack: /* Restore ESP0 stack */ @@ -123,68 +134,12 @@ _KiFastCallEntry: /* Check if the thread was being debugged */ test byte ptr [esi+KTHREAD_DEBUG_ACTIVE], 0xFF - /* Jump to shared code or DR Save */ - //jnz Dr_FastCallDrSave - jmp SharedCode -.endfunc - -.func KiSystemService -_KiSystemService: - -// ==================== COMMON SYSTEM CALL CODE ============// - /* Create a trap frame */ - push 0 - push ebp - push ebx - push esi - push edi - push fs - - /* Load PCR Selector into fs */ - mov ebx, KGDT_R0_PCR - mov fs, bx - - /* Get a pointer to the current thread */ - mov esi, [fs:KPCR_CURRENT_THREAD] - - /* Save the previous exception list */ - push [fs:KPCR_EXCEPTION_LIST] - - /* Set the exception handler chain terminator */ - mov dword ptr [fs:KPCR_EXCEPTION_LIST], -1 - - /* Save the old previous mode */ - push ss:[esi+KTHREAD_PREVIOUS_MODE] - - /* Skip the other registers */ - sub esp, 0x48 - - /* Hack: it seems that on VMWare someone damages ES/DS on exit. Investigate! */ - mov [esp+KTRAP_FRAME_DS], ds - mov [esp+KTRAP_FRAME_ES], es - - /* Set the new previous mode based on the saved CS selector */ - mov ebx, [esp+0x6C] - and ebx, 1 - mov byte ptr ss:[esi+KTHREAD_PREVIOUS_MODE], bl - - /* Go on the Kernel stack frame */ - mov ebp, esp - - /* Save the old trap frame pointer where EDX would be saved */ - mov ebx, [esi+KTHREAD_TRAP_FRAME] - mov [ebp+KTRAP_FRAME_EDX], ebx - - /* Flush DR7 */ - and dword ptr [ebp+KTRAP_FRAME_DR7], 0 - - /* Check if the thread was being debugged */ - test byte ptr [esi+KTHREAD_DEBUG_ACTIVE], 0xFF - //jnz Dr_kss_a - -SharedCode: + /* Set the thread's trap frame */ mov [esi+KTHREAD_TRAP_FRAME], ebp + /* Save DR registers if needed */ + //jnz Dr_FastCallDrSave + /* Set the trap frame debug header */ SET_TF_DEBUG_HEADER @@ -208,7 +163,7 @@ PrevWasKernelMode: /* Enable interrupts */ sti -CheckValidCall: +SharedCode: /* * Find out which table offset to use. Converts 0x1124 into 0x10. @@ -389,14 +344,14 @@ KiBBTUnexpectedRange: mov [esi+KTHREAD_TRAP_FRAME], ebp /* Try the Call again */ - jmp CheckValidCall + jmp SharedCode InvalidCall: /* Invalid System Call */ mov eax, STATUS_INVALID_SYSTEM_SERVICE jmp KeReturnFromSystemCall - + #ifdef DBG InvalidIrql: /* Save current IRQL */ @@ -443,7 +398,6 @@ _KiServiceExit2: TRAP_EPILOG NotFromSystemCall, DoRestorePreviousMode, DoRestoreSegments, DoRestoreVolatiles, DoNotRestoreEverything .endfunc -.globl _Kei386EoiHelper@0 .func Kei386EoiHelper@0 _Kei386EoiHelper@0: @@ -535,7 +489,6 @@ NotUserMode: /* Exit through common routine */ jmp _Kei386EoiHelper@0 -.globl _NtRaiseException@12 _NtRaiseException@12: /* NOTE: We -must- be called by Zw* to have the right frame! */ @@ -581,7 +534,6 @@ _NtRaiseException@12: /* Restore debug registers too */ jmp _KiServiceExit -.globl _NtContinue@8 _NtContinue@8: /* NOTE: We -must- be called by Zw* to have the right frame! */