Author: tkreuzer Date: Mon Jul 25 00:01:29 2011 New Revision: 52855
URL: http://svn.reactos.org/svn/reactos?rev=52855&view=rev Log: [NTOSKRNL] - Convert KiCallUserMode from asm to C (with a small asm wrapper) - Convert KiGetUserModeStackAddress into a C inline function
Modified: trunk/reactos/ntoskrnl/include/internal/i386/ke.h trunk/reactos/ntoskrnl/include/internal/ke.h trunk/reactos/ntoskrnl/include/internal/mm.h trunk/reactos/ntoskrnl/ke/i386/usercall.c trunk/reactos/ntoskrnl/ke/i386/usercall_asm.S
Modified: trunk/reactos/ntoskrnl/include/internal/i386/ke.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/include/internal/i... ============================================================================== --- trunk/reactos/ntoskrnl/include/internal/i386/ke.h [iso-8859-1] (original) +++ trunk/reactos/ntoskrnl/include/internal/i386/ke.h [iso-8859-1] Mon Jul 25 00:01:29 2011 @@ -846,4 +846,11 @@ KeGetContextSwitches(KeGetCurrentPrcb())); }
+FORCEINLINE +PULONG +KiGetUserModeStackAddress(void) +{ + return &(KeGetCurrentThread()->TrapFrame->HardwareEsp); +} + #endif
Modified: trunk/reactos/ntoskrnl/include/internal/ke.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/include/internal/k... ============================================================================== --- trunk/reactos/ntoskrnl/include/internal/ke.h [iso-8859-1] (original) +++ trunk/reactos/ntoskrnl/include/internal/ke.h [iso-8859-1] Mon Jul 25 00:01:29 2011 @@ -164,7 +164,7 @@ #define TIMER_WAIT_BLOCK 0x3L
#ifdef _M_ARM // FIXME: remove this once our headers are cleaned up -// +// // A system call ID is formatted as such: // .________________________________________________________________. // | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | @@ -187,7 +187,7 @@ // // NB. From assembly code, the table number must be computed as an offset into // the service descriptor table. -// +// // Each entry into the table is 16 bytes long on 32-bit architectures, and // 32 bytes long on 64-bit architectures. // @@ -864,7 +864,7 @@ ULONG_PTR BugCheckParameter4, PKTRAP_FRAME Tf ); - + BOOLEAN NTAPI KiHandleNmi(VOID); @@ -1020,12 +1020,6 @@ IN PULONG OutputLength );
-PULONG -NTAPI -KiGetUserModeStackAddress( - VOID -); - VOID NTAPI KiInitMachineDependent(VOID);
Modified: trunk/reactos/ntoskrnl/include/internal/mm.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/include/internal/m... ============================================================================== --- trunk/reactos/ntoskrnl/include/internal/mm.h [iso-8859-1] (original) +++ trunk/reactos/ntoskrnl/include/internal/mm.h [iso-8859-1] Mon Jul 25 00:01:29 2011 @@ -6,6 +6,7 @@
struct _EPROCESS;
+extern PMMSUPPORT MmKernelAddressSpace; extern PFN_NUMBER MiFreeSwapPages; extern PFN_NUMBER MiUsedSwapPages; extern SIZE_T MmTotalPagedPoolQuota; @@ -1134,7 +1135,7 @@
/* Make sure the PFN number is valid */ if (Pfn > MmHighestPhysicalPage) return NULL; - + /* Make sure this page actually has a PFN entry */ if ((MiPfnBitMap.Buffer) && !(RtlTestBit(&MiPfnBitMap, (ULONG)Pfn))) return NULL;
@@ -1338,7 +1339,7 @@ VOID NTAPI MmGetPageFileMapping( - struct _EPROCESS *Process, + struct _EPROCESS *Process, PVOID Address, SWAPENTRY* SwapEntry);
@@ -1735,7 +1736,15 @@ IN PLIST_ENTRY ListHead );
-extern PMMSUPPORT MmKernelAddressSpace; + +/* procsup.c *****************************************************************/ + +NTSTATUS +NTAPI +MmGrowKernelStack( + IN PVOID StackPointer +); +
FORCEINLINE VOID
Modified: trunk/reactos/ntoskrnl/ke/i386/usercall.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ke/i386/usercall.c... ============================================================================== --- trunk/reactos/ntoskrnl/ke/i386/usercall.c [iso-8859-1] (original) +++ trunk/reactos/ntoskrnl/ke/i386/usercall.c [iso-8859-1] Mon Jul 25 00:01:29 2011 @@ -208,4 +208,146 @@ return CallbackStatus; }
+/* Stack layout: + * + * ---------------------------------- + * KCALLOUT_FRAME.ResultLength <= 2nd Parameter to KiCallUserMode + * KCALLOUT_FRAME.Result <= 1st Parameter to KiCallUserMode + * KCALLOUT_FRAME.ReturnAddress <= Return address of KiCallUserMode + * KCALLOUT_FRAME.Ebp \ + * KCALLOUT_FRAME.Ebx | = volatile registers, pushed + * KCALLOUT_FRAME.Esi | by KiCallUserMode + * KCALLOUT_FRAME.Edi / + * KCALLOUT_FRAME.CallbackStack + * KCALLOUT_FRAME.TrapFrame + * KCALLOUT_FRAME.InitialStack <= CalloutFrame points here + * ---------------------------------- + * ~~ optional alignment ~~ + * ---------------------------------- + * FX_SAVE_AREA + * ---------------------------------- + * KTRAP_FRAME + * ---------------------------------- + * ~~ begin of stack frame for KiUserModeCallout ~~ + * + */ + +NTSTATUS +FASTCALL +KiUserModeCallout(PKCALLOUT_FRAME CalloutFrame) +{ + PKTHREAD CurrentThread; + PKTRAP_FRAME TrapFrame, CallbackTrapFrame; + PFX_SAVE_AREA FxSaveArea, OldFxSaveArea; + PKPCR Pcr; + PKTSS Tss; + ULONG_PTR InitialStack; + NTSTATUS Status; + + /* Get the current thread */ + CurrentThread = KeGetCurrentThread(); + +#if DBG + /* Check if we are at pasive level */ + if (KeGetCurrentIrql() != PASSIVE_LEVEL) + { + /* We're not, bugcheck */ + KeBugCheckEx(IRQL_GT_ZERO_AT_SYSTEM_SERVICE, + 0, + KeGetCurrentIrql(), + 0, + 0); + } + + /* Check if we are attached or APCs are disabled */ + if ((CurrentThread->ApcStateIndex != OriginalApcEnvironment) || + (CurrentThread->CombinedApcDisable > 0)) + { + KeBugCheckEx(APC_INDEX_MISMATCH, + 0, + CurrentThread->ApcStateIndex, + CurrentThread->CombinedApcDisable, + 0); + } +#endif + + /* Align stack on 16-byte boundary */ + InitialStack = (ULONG_PTR)CalloutFrame & ~15; + + /* Check if we have enough space on the stack */ + if ((InitialStack - KERNEL_STACK_SIZE) < CurrentThread->StackLimit) + { + /* We don't, we'll have to grow our stack */ + Status = MmGrowKernelStack((PVOID)InitialStack); + + /* Quit if we failed */ + if (!NT_SUCCESS(Status)) return Status; + } + + /* Save the current callback stack and initial stack */ + CalloutFrame->CallbackStack = (ULONG_PTR)CurrentThread->CallbackStack; + CalloutFrame->InitialStack = (ULONG_PTR)CurrentThread->InitialStack; + + /* Get and save the trap frame */ + TrapFrame = CurrentThread->TrapFrame; + CalloutFrame->TrapFrame = (ULONG_PTR)TrapFrame; + + /* Set the new callback stack */ + CurrentThread->CallbackStack = CalloutFrame; + + /* Set destination and origin NPX Areas */ + OldFxSaveArea = (PVOID)(CalloutFrame->InitialStack - sizeof(FX_SAVE_AREA)); + FxSaveArea = (PVOID)(InitialStack - sizeof(FX_SAVE_AREA)); + + /* Disable interrupts so we can fill the NPX State */ + _disable(); + + /* Now copy the NPX State */ + FxSaveArea->U.FnArea.ControlWord = OldFxSaveArea->U.FnArea.ControlWord; + FxSaveArea->U.FnArea.StatusWord = OldFxSaveArea->U.FnArea.StatusWord; + FxSaveArea->U.FnArea.TagWord = OldFxSaveArea->U.FnArea.TagWord; + FxSaveArea->U.FnArea.DataSelector = OldFxSaveArea->U.FnArea.DataSelector; + FxSaveArea->Cr0NpxState = OldFxSaveArea->Cr0NpxState; + + /* Set the stack address */ + CurrentThread->InitialStack = (PVOID)InitialStack; + + /* Locate the trap frame on the callback stack */ + CallbackTrapFrame = (PVOID)((ULONG_PTR)FxSaveArea - sizeof(KTRAP_FRAME)); + + /* Copy the trap frame to the new location */ + *CallbackTrapFrame = *TrapFrame; + + /* Get PCR */ + Pcr = KeGetPcr(); + + /* Update the exception list */ + CallbackTrapFrame->ExceptionList = Pcr->Used_ExceptionList; + + /* Get TSS */ + Tss = Pcr->TSS; + + /* Bias the stack for V86 mode */ + if (CallbackTrapFrame->EFlags & EFLAGS_V86_MASK) + { + /* Set new stack address in TSS */ + Tss->Esp0 = (ULONG_PTR)(CallbackTrapFrame + 1); + } + else + { + /* Set new stack address in TSS */ + Tss->Esp0 = (ULONG_PTR)&CallbackTrapFrame->V86Es; + } + + /* Set user-mode dispatcher address as EIP */ + CallbackTrapFrame->Eip = (ULONG_PTR)KeUserCallbackDispatcher; + + /* Bring interrupts back */ + _enable(); + + /* Exit to user-mode */ + KiServiceExit(CallbackTrapFrame, 0); +} + + /* EOF */
Modified: trunk/reactos/ntoskrnl/ke/i386/usercall_asm.S URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ke/i386/usercall_a... ============================================================================== --- trunk/reactos/ntoskrnl/ke/i386/usercall_asm.S [iso-8859-1] (original) +++ trunk/reactos/ntoskrnl/ke/i386/usercall_asm.S [iso-8859-1] Mon Jul 25 00:01:29 2011 @@ -17,19 +17,10 @@ EXTERN @KiServiceExit@8:PROC EXTERN _KeGetCurrentIrql@0:PROC EXTERN _KeBugCheckEx@20:PROC +EXTERN @KiUserModeCallout@4:PROC
/* FUNCTIONS ****************************************************************/ .code - -PUBLIC _KiGetUserModeStackAddress@0 -_KiGetUserModeStackAddress@0: - - /* Get the current thread's trapframe and return the esp */ - mov eax, fs:[KPCR_CURRENT_THREAD] - mov eax, [eax+KTHREAD_TRAP_FRAME] - lea eax, [eax+KTRAP_FRAME_ESP] - ret -
/*++ * @name KiCallUserMode @@ -58,166 +49,23 @@ PUBLIC _KiCallUserMode@8 _KiCallUserMode@8:
- /* Save volatile registers */ + /* Push volatile registers on the stack. + This is part of the KCALLOUT_FRAME */ push ebp push ebx push esi push edi
- /* Get the current thread */ - mov ebx, fs:[KPCR_CURRENT_THREAD] - - /* Make sure we're at passive */ -#if DBG - call _KeGetCurrentIrql@0 - or al, al - jz AtPassive - - /* We're not, bugcheck! */ - push 0 - push 0 - push eax - push 0 - push IRQL_GT_ZERO_AT_SYSTEM_SERVICE - call _KeBugCheckEx@20 - -AtPassive: - - /* Make sure that we are not attached and that APCs are not disabled */ - movzx eax, byte ptr [ebx+KTHREAD_APC_STATE_INDEX] - mov edx, [ebx+KTHREAD_COMBINED_APC_DISABLE] - or eax, eax - jnz InvalidIndex - or edx, edx - jz ApcsEnabled - -InvalidIndex: - - push 0 - push edx - push eax - push 0 - push APC_INDEX_MISMATCH - call _KeBugCheckEx@20 -ApcsEnabled: -#endif - - /* Get the lowest stack limit and check if we can handle it */ - lea eax, [esp-HEX(3000)] - cmp eax, [ebx+KTHREAD_STACK_LIMIT] - jnb StackOk - - /* We can't, we'll have to grow our stack */ - push esp - call _MmGrowKernelStack@4 - - /* Quit if we failed */ - or eax, eax - jnz GrowFailed - - /* Save the current callback stack */ -StackOk: - push [ebx+KTHREAD_CALLBACK_STACK] - - /* Get and save the trap frame */ - mov edx, [ebx+KTHREAD_TRAP_FRAME] - push edx - - /* Get and save the initial stack */ - mov esi, [ebx+KTHREAD_INITIAL_STACK] - push esi - - /* Set the new callback stack */ - mov [ebx+KTHREAD_CALLBACK_STACK], esp - - /* Align stack on 16-byte boundary */ - and esp, NOT 15 - mov edi, esp - - /* Set destination and origin NPX Areas */ - sub esp, NPX_FRAME_LENGTH - sub esi, NPX_FRAME_LENGTH - - /* Disable interrupts so we can fill the NPX State */ - cli - - /* Now copy the NPX State */ - mov ecx, [esi+FP_CONTROL_WORD] - mov [esp+FP_CONTROL_WORD], ecx - mov ecx, [esi+FP_STATUS_WORD] - mov [esp+FP_STATUS_WORD], ecx - mov ecx, [esi+FP_TAG_WORD] - mov [esp+FP_TAG_WORD], ecx - mov ecx, [esi+FP_DATA_SELECTOR] - mov [esp+FP_DATA_SELECTOR], ecx - mov ecx, [esi+FN_CR0_NPX_STATE] - mov [esp+FN_CR0_NPX_STATE], ecx - - /* Get TSS */ - mov esi, fs:[KPCR_TSS] - - /* Set the stack address */ - mov [ebx+KTHREAD_INITIAL_STACK], edi - - /* Bias the stack for V86 mode */ - mov ecx, esp - sub esp, 16 - test dword ptr [edx+KTRAP_FRAME_EFLAGS], EFLAGS_V86_MASK - jnz DontBias - mov ecx, esp - -DontBias: - /* Set new stack address in TSS */ - mov [esi+KTSS_ESP0], ecx - - /* Allocate the trap frame and set it */ - sub esp, KTRAP_FRAME_V86_ES - mov ebp, esp - - /* Set copy iterator and dest/origin parameters and do the copy */ - mov ecx, (KTRAP_FRAME_V86_ES - KTRAP_FRAME_FS) / 4 - lea edi, [esp+KTRAP_FRAME_FS] - lea esi, [edx+KTRAP_FRAME_FS] - rep movsd - - /* Copy DR7 */ - mov edi, [edx+KTRAP_FRAME_DR7] - test edi, NOT DR7_RESERVED_MASK - mov [esp+KTRAP_FRAME_DR7], edi - - /* Check if we need to save debug registers */ - jnz SaveDebug - - /* Get user-mode dispatcher address and set it as EIP */ -SetEip: - mov eax, dword ptr [_KeUserCallbackDispatcher] - mov [esp+KTRAP_FRAME_EIP], eax - - /* Set the exception list */ - mov eax, fs:[KPCR_EXCEPTION_LIST] - mov [esp+KTRAP_FRAME_EXCEPTION_LIST], eax - - /* Set the previous mode */ - mov eax, [edx+KTRAP_FRAME_PREVIOUS_MODE] - mov [esp+KTRAP_FRAME_PREVIOUS_MODE], eax - - /* Bring interrupts back */ - sti - - /* Exit to user-mode */ - mov ecx, esp - jmp @KiServiceExit@8 - -SaveDebug: - - /* Copy all 5 DRs */ - mov ecx, 5 - lea edi, [esp+KTRAP_FRAME_DR0] - lea esi, [edx+KTRAP_FRAME_DR0] - rep movsd - jmp SetEip - -GrowFailed: + /* load the address of the callout frame into ecx */ + lea ecx, [esp - 12] + + /* Allocate space for the inital stack */ + sub esp, 12 + NPX_FRAME_LENGTH + KTRAP_FRAME_LENGTH + 16 + + call @KiUserModeCallout@4 + + add esp, 12 + NPX_FRAME_LENGTH + KTRAP_FRAME_LENGTH + 16 + /* Restore registers */ pop edi pop esi