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/…
==============================================================================
--- 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/…
==============================================================================
--- 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/…
==============================================================================
--- 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.…
==============================================================================
--- 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_…
==============================================================================
--- 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