- Fix MmCreateKernelStack to actually take into account the GuiStack parameter. - Implement KeSwitchKernelStack - Enable code in PsConvertToGuiThread to create a new stack and switch to it. GUI Threads now get the 60KB of kernel stack space they deserve. - Define exported DDK constants for kernel stack size and undefine our own internal ones. Modified: trunk/reactos/ntoskrnl/include/internal/ntoskrnl.h Modified: trunk/reactos/ntoskrnl/ke/i386/usercall_asm.S Modified: trunk/reactos/ntoskrnl/mm/process.c Modified: trunk/reactos/ntoskrnl/ps/win32.c Modified: trunk/reactos/w32api/include/ddk/winddk.h _____
Modified: trunk/reactos/ntoskrnl/include/internal/ntoskrnl.h --- trunk/reactos/ntoskrnl/include/internal/ntoskrnl.h 2006-01-11 05:42:32 UTC (rev 20779) +++ trunk/reactos/ntoskrnl/include/internal/ntoskrnl.h 2006-01-11 05:55:49 UTC (rev 20780) @@ -254,9 +254,5 @@
#endif
#endif -/* - * - */ -#define MM_STACK_SIZE (3*4096)
#endif /* INCLUDE_INTERNAL_NTOSKRNL_H */ _____
Modified: trunk/reactos/ntoskrnl/ke/i386/usercall_asm.S --- trunk/reactos/ntoskrnl/ke/i386/usercall_asm.S 2006-01-11 05:42:32 UTC (rev 20779) +++ trunk/reactos/ntoskrnl/ke/i386/usercall_asm.S 2006-01-11 05:55:49 UTC (rev 20780) @@ -1,53 +1,439 @@
/* * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS kernel - * FILE: ntoskrnl/ke/i386s/usercall.S + * PROJECT: ReactOS Kernel + * FILE: ntoskrnl/ke/i386/usercall_asm.S * PURPOSE: User-Mode callbacks and return. - * * PROGRAMMERS: Alex Ionescu (alex@relsoft.net) */
/* INCLUDES ******************************************************************/
-#include <roscfg.h> +#include <asm.h> +//#include <bugcodes.h> +#define APC_INDEX_MISMATCH 1 +#define IRQL_GT_ZERO_AT_SYSTEM_SERVICE 0x4A +#define STATUS_NO_CALLBACK_ACTIVE 0xC0000258 .intel_syntax noprefix
+// This file is a work in progress. Most of the code is currently disabled. + /* GLOBALS ****************************************************************/ -.extern PVOID _SystemDllCallbackDispatcher +.extern PVOID _KeUserCallbackDispatcher
-#define CBSTACK_BUFFER_ADDRESS 0x20 -#define CBSTACK_BUFFER_LENGTH 0x24 /* FUNCTIONS ****************************************************************/
+.globl _KiGetUserModeStackAddress@0 +.func 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] + +.endfunc + /*++ - * KiSwitchToUserMode + * @name KiCallUserMode * * The KiSwitchToUserMode routine sets up a Trap Frame and a Callback stack * for the purpose of switching to user mode. The actual final jump is done * by KiServiceExit which will treat this as a syscall return. * - * Params: - * OutputBuffer - Pointer to a caller-allocated buffer where to receive - * the return data from the user-mode function + * @param OutputBuffer + * Pointer to a caller-allocated buffer where to receive the return data + * from the user-mode function * - * OutputLength - Size of the Output Buffer described above. + * @param OutputLength + * Size of the Output Buffer described above. * - * Returns: - * Jumps into KiServiceExit. + * @return None. Jumps into KiServiceExit. * - * Remarks: - * If there is not enough Kernel Stack space, the routine will increase the - * Kernel Stack. + * @remark If there is not enough Kernel Stack space, the routine will increase the + * Kernel Stack. * - * User mode execution resumes at ntdll!KiUserCallbackDispatcher. + * User mode execution resumes at ntdll!KiUserCallbackDispatcher. * - * This call MUST be paired by interrupt 0x2B or NtCallbackReturn. + * This call MUST be paired by interrupt 0x2B or NtCallbackReturn. * *--*/ -.globl _KiSwitchToUserMode@8 -.func KiSwitchToUserMode@8 -_KiSwitchToUserMode@8: +.globl _KiCallUserMode@8 +.func KiCallUserMode@8 +_KiCallUserMode@8:
+ /* Save volatile registers */ + push ebp + push ebx + push esi + push edi + + /* Get the current thread */ + mov ebx, fs:[KPCR_CURRENT_THREAD] + + /* Make sure we're at passive */ + 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 + jz InvalidIndex + or edx, edx + jz ApcsEnabled + +InvalidIndex: + + push 0 + push edx + push eax + push 0 + push APC_INDEX_MISMATCH + call _KeBugCheckEx@20 + +ApcsEnabled: + + /* Get the lowest stack limit and check if we can handle it */ + lea eax, [esp-0x3000] + 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, ~16 + 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+FN_CONTROL_WORD] + mov [esi+FN_CONTROL_WORD], ecx + mov ecx, [esi+FN_STATUS_WORD] + mov [esi+FN_STATUS_WORD], ecx + mov ecx, [esi+FN_TAG_WORD] + mov [esi+FN_TAG_WORD], ecx + mov ecx, [esi+FN_DATA_SELECTOR] + mov [esi+FN_DATA_SELECTOR], ecx + mov ecx, [esi+FN_CR0_NPX_STATE] + mov [esi+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, [esp+KTRAP_FRAME_FS] + rep movsd + + /* FIXME: Copy debug registers if needed */ + + /* Get user-mode dispatcher address and set it as EIP */ + mov eax, _KeUserCallbackDispatcher + mov [esp+KTRAP_FRAME_EIP], eax + + /* Set the exception list */ + mov eax, [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 + + /* Write the debug data */ + mov edi, [ebp+KTRAP_FRAME_EBP] + mov edx, [ebp+KTRAP_FRAME_EIP] + mov [ebp+KTRAP_FRAME_DEBUGPOINTER], edx + mov dword ptr [ebp+KTRAP_FRAME_DEBUGARGMARK], 0xBADB0D00 + mov [ebp+KTRAP_FRAME_DEBUGEBP], ebx + mov [ebp+KTRAP_FRAME_DEBUGEIP], edi + + /* Exit to user-mode */ + jmp _KiServiceExit + +GrowFailed: + /* Restore registers */ + pop edi + pop esi + pop ebx + pop ebp + + /* Return */ + ret 8 + .endfunc
+/*++ + * @name NtCallbackReturn + * + * The NtCallbackReturn routine returns to kernel mode after a user-mode + * callback was done through KeUserModeCallback. It uses the callback frame + * which was setup in order to return the information, restores the stack, + * and resumes execution where it was left off. + * + * @param Result + * Pointer to a caller-allocated buffer where the return data + * from the user-mode function is located. + * + * @param ResultLength + * Size of the Output Buffer described above. + * + * @param CallbackStatus + * Status code of the callback operation. + * + * @return Status code of the callback operation. + * + * @remark This call MUST be paired with KeUserModeCallback. + * + *--*/ +.globl _NtCallbackReturn2@12 +.func NtCallbackReturn2@12 +_NtCallbackReturn2@12:
+ /* Get the current thread and make sure we have a callback stack */ + mov eax, fs:[KPCR_CURRENT_THREAD] + mov ecx, [eax+KTHREAD_CALLBACK_STACK] + test ecx, ecx + jz NoStack + + /* Get the trap frame */ + mov ebx, [eax+KTHREAD_TRAP_FRAME] + + /* Restore the exception list */ + mov edx, [ebx+KTRAP_FRAME_EXCEPTION_LIST] + mov fs:[KPCR_EXCEPTION_LIST], edx + + /* Get the result, the result length and the status */ + mov edi, [esp+4] + mov esi, [esp+8] + mov ebp, [esp+12] + + /* Store the results in the callback stack */ + mov ebx, [ecx+CBSTACK_RESULT] + mov [ebx], edi + mov ebx, [ecx+CBSTACK_RESULT_LENGTH] + mov [ebx], esi + + /* Get the previous stack */ + mov ebx, [ecx] + + /* Disable interrupts for NPX save and stack switch */ + cli + + /* Get the initial stack and restore it */ + mov esi, fs:[KPCR_INITIAL_STACK] + mov [eax+KTHREAD_INITIAL_STACK], ebx + + /* Set desination and origin NPX Frames */ + sub esi, NPX_FRAME_LENGTH + sub ebx, NPX_FRAME_LENGTH + + /* Copy NPX Data */ + mov edx, [esi+FN_CONTROL_WORD] + mov [ebx+FN_CONTROL_WORD], edx + mov edx, [esi+FN_STATUS_WORD] + mov [ebx+FN_STATUS_WORD], edx + mov edx, [esi+FN_TAG_WORD] + mov [ebx+FN_TAG_WORD], edx + mov edx, [esi+FN_DATA_SELECTOR] + mov [ebx+FN_DATA_SELECTOR], edx + mov edx, [esi+FN_CR0_NPX_STATE] + mov [ebx+FN_CR0_NPX_STATE], edx + + /* Get saved trap frame and clear DR7 */ + mov edi, [ecx+CBSTACK_TRAP_FRAME] + and dword ptr [edi+KTRAP_FRAME_DR7], 0 + + /* FIXME: Restore debug regs */ + + /* Get TSS */ + mov edx, fs:[KPCR_TSS] + + /* Restore stack pointer */ + lea esp, [ecx+CBSTACK_CALLBACK_STACK] + + /* Check if we were in V86 mode */ + test dword ptr [edi+KTRAP_FRAME_EFLAGS], EFLAGS_V86_MASK + jnz V86Ret + sub ebx, 16 + +V86Ret: + /* Restore the ESP in TSS */ + mov [edx+KTSS_ESP0], ebx + + /* Restore the trap frame */ + mov [eax+KTHREAD_TRAP_FRAME], edi + + /* Bring interrupts back */ + sti + + /* Restore the callback stack*/ + pop [eax+KTHREAD_CALLBACK_STACK] + + /* Set status and return */ + mov eax, ebp + pop edi + pop esi + pop ebx + pop ebp + pop edx + + /* Clean stack and jump back */ + add esp, 8 + jmp edx + +NoStack: + + /* Return failure */ + mov eax, STATUS_NO_CALLBACK_ACTIVE + ret 12 + +.endfunc + +.globl _KeSwitchKernelStack@8 +.func KeSwitchKernelStack@8 +_KeSwitchKernelStack@8: + + /* Save volatiles */ + push esi + push edi + + /* Get current thread */ + mov edx, fs:[KPCR_CURRENT_THREAD] + + /* Get new and current base */ + mov edi, [esp+12] + mov ecx, [edx+KTHREAD_STACK_BASE] + + /* Fixup the frame pointer */ + sub ebp, ecx + add ebp, edi + + /* Fixup the trap frame */ + mov eax, [edx+KTHREAD_TRAP_FRAME] + sub eax, ecx + add eax, edi + mov [edx+KTHREAD_TRAP_FRAME], eax + + /* Calculate stack size */ + sub ecx, esp + + /* Get desination and origin */ + sub edi, ecx + mov esi, esp + + /* Save stack pointer */ + push edi + + /* Copy stack */ + rep movsb + + /* Restore stack pointer */ + pop edi + + /* Save old stack base and get new limit/base */ + mov eax, [edx+KTHREAD_STACK_BASE] + mov ecx, [esp+12] + mov esi, [esp+16] + + /* Disable interrupts for stack switch */ + cli + + /* Set new base/limit */ + mov [edx+KTHREAD_STACK_BASE], ecx + mov [edx+KTHREAD_STACK_LIMIT], esi + + /* Set LargeStack */ + mov byte ptr [edx+KTHREAD_LARGE_STACK], 1 + + /* Set new initial stack */ + mov [edx+KTHREAD_INITIAL_STACK], ecx + + /* Get trap frame */ + mov esi, [edx+KTHREAD_TRAP_FRAME] + + /* Get TSS */ + mov edx, fs:[KPCR_TSS] + + /* Check if we came from V86 mode */ + test dword ptr [esi+KTRAP_FRAME_EFLAGS], EFLAGS_V86_MASK + + /* Bias for NPX Area */ + lea ecx, [ecx-NPX_FRAME_LENGTH] + jnz V86Switch + sub ecx, 16 + +V86Switch: + + /* Update ESP in TSS */ + mov [edx+KTSS_ESP0], ecx + + /* Update stack pointer */ + mov esp, edi + + /* Bring back interrupts and return */ + sti + pop edi + pop esi + ret 8 + +.endfunc _____
Modified: trunk/reactos/ntoskrnl/mm/process.c --- trunk/reactos/ntoskrnl/mm/process.c 2006-01-11 05:42:32 UTC (rev 20779) +++ trunk/reactos/ntoskrnl/mm/process.c 2006-01-11 05:55:49 UTC (rev 20780) @@ -134,7 +134,8 @@
PMEMORY_AREA StackArea; ULONG i; PHYSICAL_ADDRESS BoundaryAddressMultiple; - PFN_TYPE Page[MM_STACK_SIZE / PAGE_SIZE]; + ULONG StackSize = GuiStack ? KERNEL_LARGE_STACK_SIZE : KERNEL_STACK_SIZE; + PFN_TYPE Page[KERNEL_LARGE_STACK_SIZE / PAGE_SIZE]; PVOID KernelStack = NULL; NTSTATUS Status;
@@ -148,7 +149,7 @@ Status = MmCreateMemoryArea(MmGetKernelAddressSpace(), MEMORY_AREA_KERNEL_STACK, &KernelStack, - MM_STACK_SIZE, + StackSize, PAGE_READWRITE, &StackArea, FALSE, @@ -166,7 +167,7 @@ }
/* Mark the Stack in use */ - for (i = 0; i < (MM_STACK_SIZE / PAGE_SIZE); i++) + for (i = 0; i < (StackSize / PAGE_SIZE); i++) { Status = MmRequestPageMemoryConsumer(MC_NPPOOL, TRUE, &Page[i]); } @@ -176,7 +177,7 @@ KernelStack, PAGE_READWRITE, Page, - MM_STACK_SIZE / PAGE_SIZE); + StackSize / PAGE_SIZE);
/* Check for success */ if (!NT_SUCCESS(Status)) _____
Modified: trunk/reactos/ntoskrnl/ps/win32.c --- trunk/reactos/ntoskrnl/ps/win32.c 2006-01-11 05:42:32 UTC (rev 20779) +++ trunk/reactos/ntoskrnl/ps/win32.c 2006-01-11 05:55:49 UTC (rev 20780) @@ -71,7 +71,7 @@
NTAPI PsConvertToGuiThread(VOID) { - //PVOID NewStack, OldStack; + PVOID NewStack, OldStack; PETHREAD Thread = PsGetCurrentThread(); PEPROCESS Process = PsGetCurrentProcess(); NTSTATUS Status; @@ -99,11 +99,9 @@ }
/* Check if we don't already have a kernel-mode stack */ -#if 0 if (!Thread->Tcb.LargeStack) { /* We don't create one */ - DPRINT1("Creating large stack\n"); NewStack = MmCreateKernelStack(TRUE); if (!NewStack) { @@ -116,28 +114,15 @@ KeEnterCriticalRegion();
/* Switch stacks */ - DPRINT1("Switching stacks. NS IT, SL, SB, KS %p %p %p %p %p\n", - NewStack, - Thread->Tcb.InitialStack, - Thread->Tcb.StackLimit, - Thread->Tcb.StackBase, - Thread->Tcb.KernelStack); OldStack = KeSwitchKernelStack((PVOID)((ULONG_PTR)NewStack + 0x3000), NewStack);
/* Leave the critical region */ KeLeaveCriticalRegion(); - DPRINT1("We made it!\n");
/* Delete the old stack */ //MmDeleteKernelStack(OldStack, FALSE); - DPRINT1("Old stack deleted. IT, SL, SB, KS %p %p %p %p\n", - Thread->Tcb.InitialStack, - Thread->Tcb.StackLimit, - Thread->Tcb.StackBase, - Thread->Tcb.KernelStack); } -#endif
/* This check is bizare. Check out win32k later */ if (!Process->Win32Process) _____
Modified: trunk/reactos/w32api/include/ddk/winddk.h --- trunk/reactos/w32api/include/ddk/winddk.h 2006-01-11 05:42:32 UTC (rev 20779) +++ trunk/reactos/w32api/include/ddk/winddk.h 2006-01-11 05:55:49 UTC (rev 20780) @@ -204,6 +204,10 @@
#define NtCurrentThread() ( (HANDLE)(LONG_PTR) -2 ) #define ZwCurrentThread() NtCurrentThread()
+#define KERNEL_STACK_SIZE 12288 +#define KERNEL_LARGE_STACK_SIZE 61440 + + #define DPFLTR_ERROR_LEVEL 0 #define DPFLTR_WARNING_LEVEL 1 #define DPFLTR_TRACE_LEVEL 2