Thread Creation and Context Switching re-write, plus Idle/First Thread minimization attempt. Full changelog on ML, too large to post here Modified: trunk/reactos/ntoskrnl/Makefile.i386 Modified: trunk/reactos/ntoskrnl/include/internal/arch/ps.h Modified: trunk/reactos/ntoskrnl/include/internal/i386/ke.h Modified: trunk/reactos/ntoskrnl/include/internal/i386/ps.h Modified: trunk/reactos/ntoskrnl/include/internal/ke.h Modified: trunk/reactos/ntoskrnl/include/internal/mm.h Modified: trunk/reactos/ntoskrnl/include/internal/ps.h Modified: trunk/reactos/ntoskrnl/kd/gdbstub.c Modified: trunk/reactos/ntoskrnl/kd/kdebug.c Modified: trunk/reactos/ntoskrnl/ke/i386/bios.c Deleted: trunk/reactos/ntoskrnl/ke/i386/bthread.S Added: trunk/reactos/ntoskrnl/ke/i386/ctxswitch.S Modified: trunk/reactos/ntoskrnl/ke/i386/exp.c Modified: trunk/reactos/ntoskrnl/ke/i386/gdt.c Modified: trunk/reactos/ntoskrnl/ke/i386/idt.c Modified: trunk/reactos/ntoskrnl/ke/i386/kernel.c Modified: trunk/reactos/ntoskrnl/ke/i386/ldt.c Modified: trunk/reactos/ntoskrnl/ke/i386/thread.c Deleted: trunk/reactos/ntoskrnl/ke/i386/tskswitch.S Modified: trunk/reactos/ntoskrnl/ke/i386/v86m.c Modified: trunk/reactos/ntoskrnl/ke/kthread.c Modified: trunk/reactos/ntoskrnl/ke/main.c Modified: trunk/reactos/ntoskrnl/ps/debug.c Modified: trunk/reactos/ntoskrnl/ps/idle.c Modified: trunk/reactos/ntoskrnl/ps/kill.c Modified: trunk/reactos/ntoskrnl/ps/psmgr.c Modified: trunk/reactos/ntoskrnl/ps/thread.c _____
Modified: trunk/reactos/ntoskrnl/Makefile.i386 --- trunk/reactos/ntoskrnl/Makefile.i386 2005-04-22 12:46:27 UTC (rev 14741) +++ trunk/reactos/ntoskrnl/Makefile.i386 2005-04-22 12:52:25 UTC (rev 14742) @@ -17,9 +17,8 @@
ke/i386/thread.o \ ke/i386/usercall.o \ ke/i386/trap.o \ - ke/i386/bthread.o \ ke/i386/syscall.o \ - ke/i386/tskswitch.o \ + ke/i386/ctxswitch.o \ ke/i386/v86m.o \ ke/i386/v86m_sup.o \ ke/i386/vdm.o \ _____
Modified: trunk/reactos/ntoskrnl/include/internal/arch/ps.h --- trunk/reactos/ntoskrnl/include/internal/arch/ps.h 2005-04-22 12:46:27 UTC (rev 14741) +++ trunk/reactos/ntoskrnl/include/internal/arch/ps.h 2005-04-22 12:52:25 UTC (rev 14742) @@ -21,8 +21,7 @@
#ifdef i386 #include <internal/i386/ps.h> -#define KiArchContextSwitch Ki386ContextSwitch -#define KiArchInitThread Ke386InitThread +#define KiArchContextSwitch KiSwapContext #define KiArchInitThreadWithContext Ke386InitThreadWithContext #else #error "Unknown processor" _____
Modified: trunk/reactos/ntoskrnl/include/internal/i386/ke.h --- trunk/reactos/ntoskrnl/include/internal/i386/ke.h 2005-04-22 12:46:27 UTC (rev 14741) +++ trunk/reactos/ntoskrnl/include/internal/i386/ke.h 2005-04-22 12:52:25 UTC (rev 14742) @@ -203,6 +203,28 @@
VOID KeCreateApplicationProcessorIdleThread(ULONG Id);
+typedef +VOID +STDCALL +(*PKSYSTEM_ROUTINE)(PKSTART_ROUTINE StartRoutine, + PVOID StartContext); + +VOID +STDCALL +Ke386InitThreadWithContext(PKTHREAD Thread, + PKSYSTEM_ROUTINE SystemRoutine, + PKSTART_ROUTINE StartRoutine, + PVOID StartContext, + PCONTEXT Context); + +VOID +STDCALL +KiThreadStartup(PKSYSTEM_ROUTINE SystemRoutine, + PKSTART_ROUTINE StartRoutine, + PVOID StartContext, + BOOLEAN UserThread, + KTRAP_FRAME TrapFrame); + #ifdef CONFIG_SMP #define LOCK "lock ; " #else _____
Modified: trunk/reactos/ntoskrnl/include/internal/i386/ps.h --- trunk/reactos/ntoskrnl/include/internal/i386/ps.h 2005-04-22 12:46:27 UTC (rev 14741) +++ trunk/reactos/ntoskrnl/include/internal/i386/ps.h 2005-04-22 12:52:25 UTC (rev 14742) @@ -27,8 +27,12 @@
#define KTHREAD_TEB 0x20 #define KTHREAD_KERNEL_STACK 0x28 #define KTHREAD_NPX_STATE 0x31 +#define KTHREAD_STATE 0x2D +#define KTHREAD_APCSTATE_PROCESS 0x34 + 0x10 #define KTHREAD_PENDING_USER_APC 0x34 + 0x16 -#define KTHREAD_APCSTATE_PROCESS 0x44 +#define KTHREAD_PENDING_KERNEL_APC 0x34 + 0x15 +#define KTHREAD_CONTEXT_SWITCHES 0x4C +#define KTHREAD_WAIT_IRQL 0x54 #define KTHREAD_SERVICE_TABLE 0xDC #define KTHREAD_PREVIOUS_MODE 0x137 #define KTHREAD_TRAP_FRAME 0x128 @@ -44,7 +48,9 @@
#define KPCR_EXCEPTION_LIST 0x0 #define KPCR_INITIAL_STACK 0x4 +#define KPCR_STACK_LIMIT 0x8 #define KPCR_SELF 0x1C +#define KPCR_GDT 0x3C #define KPCR_TSS 0x40 #define KPCR_CURRENT_THREAD 0x124 #define KPCR_NPX_THREAD 0x2A4 @@ -298,17 +304,6 @@
#endif /* __USE_W32API */
-VOID -Ki386ContextSwitch(struct _KTHREAD* NewThread, - struct _KTHREAD* OldThread); -NTSTATUS -Ke386InitThread(struct _KTHREAD* Thread, PKSTART_ROUTINE fn, - PVOID StartContext); -NTSTATUS -Ke386InitThreadWithContext(struct _KTHREAD* Thread, PCONTEXT Context); -NTSTATUS -Ki386ValidateUserContext(PCONTEXT Context); - #endif /* __ASM__ */
#endif /* __NTOSKRNL_INCLUDE_INTERNAL_I386_PS_H */ _____
Modified: trunk/reactos/ntoskrnl/include/internal/ke.h --- trunk/reactos/ntoskrnl/include/internal/ke.h 2005-04-22 12:46:27 UTC (rev 14741) +++ trunk/reactos/ntoskrnl/include/internal/ke.h 2005-04-22 12:52:25 UTC (rev 14742) @@ -114,6 +114,10 @@
NTSTATUS STDCALL KeSuspendThread(PKTHREAD Thread); + +NTSTATUS +FASTCALL +KiSwapContext(PKTHREAD NewThread);
/* gmutex.c ********************************************************************/
@@ -238,9 +242,16 @@ VOID inline FASTCALL KeReleaseDispatcherDatabaseLock(KIRQL Irql); VOID inline FASTCALL KeReleaseDispatcherDatabaseLockFromDpcLevel(VOID);
-VOID +VOID STDCALL -KeInitializeThread(struct _KPROCESS* Process, PKTHREAD Thread, BOOLEAN First); +KeInitializeThread(struct _KPROCESS* Process, + PKTHREAD Thread, + PKSYSTEM_ROUTINE SystemRoutine, + PKSTART_ROUTINE StartRoutine, + PVOID StartContext, + PCONTEXT Context, + PVOID Teb, + PVOID KernelStack);
VOID STDCALL _____
Modified: trunk/reactos/ntoskrnl/include/internal/mm.h --- trunk/reactos/ntoskrnl/include/internal/mm.h 2005-04-22 12:46:27 UTC (rev 14741) +++ trunk/reactos/ntoskrnl/include/internal/mm.h 2005-04-22 12:52:25 UTC (rev 14742) @@ -508,6 +508,17 @@
STDCALL MmCreatePeb(PEPROCESS Process);
+PTEB +STDCALL +MmCreateTeb(PEPROCESS Process, + PCLIENT_ID ClientId, + PINITIAL_TEB InitialTeb); + +VOID +STDCALL +MmDeleteTeb(PEPROCESS Process, + PTEB Teb); + /* i386/pfault.c *************************************************************/
NTSTATUS MmPageFault(ULONG Cs, _____
Modified: trunk/reactos/ntoskrnl/include/internal/ps.h --- trunk/reactos/ntoskrnl/include/internal/ps.h 2005-04-22 12:46:27 UTC (rev 14741) +++ trunk/reactos/ntoskrnl/include/internal/ps.h 2005-04-22 12:52:25 UTC (rev 14742) @@ -497,7 +497,18 @@
PEPROCESS Parent OPTIONAL);
- +VOID +STDCALL +PspSystemThreadStartup(PKSTART_ROUTINE StartRoutine, + PVOID StartContext); + +NTSTATUS +PsInitializeIdleOrFirstThread ( + PEPROCESS Process, + PETHREAD* ThreadPtr, + PKSTART_ROUTINE StartRoutine, + KPROCESSOR_MODE AccessMode, + BOOLEAN First); /* * Internal thread priorities, added by Phillip Susi * TODO: rebalence these to make use of all priorities... the ones above 16 _____
Modified: trunk/reactos/ntoskrnl/kd/gdbstub.c --- trunk/reactos/ntoskrnl/kd/gdbstub.c 2005-04-22 12:46:27 UTC (rev 14741) +++ trunk/reactos/ntoskrnl/kd/gdbstub.c 2005-04-22 12:52:25 UTC (rev 14742) @@ -131,6 +131,20 @@
#define EIP_REGNO 8
+typedef +VOID +STDCALL_FUNC +(*PKSYSTEM_ROUTINE)(PKSTART_ROUTINE StartRoutine, + PVOID StartContext); + +VOID +STDCALL +KiThreadStartup(PKSYSTEM_ROUTINE SystemRoutine, + PKSTART_ROUTINE StartRoutine, + PVOID StartContext, + BOOLEAN UserThread, + KTRAP_FRAME TrapFrame); + static CPU_REGISTER GspRegisters[NUMREGS] = { { 4, FIELD_OFFSET (KTRAP_FRAME_X86, Eax), FIELD_OFFSET (CONTEXT, Eax), TRUE }, @@ -582,7 +596,7 @@ * This thread has not been sheduled yet so assume it * is still in PsBeginThreadWithContextInternal(). */ - Value = (ULONG) PsBeginThreadWithContextInternal; + Value = (ULONG)KiThreadStartup; } else { _____
Modified: trunk/reactos/ntoskrnl/kd/kdebug.c --- trunk/reactos/ntoskrnl/kd/kdebug.c 2005-04-22 12:46:27 UTC (rev 14741) +++ trunk/reactos/ntoskrnl/kd/kdebug.c 2005-04-22 12:52:25 UTC (rev 14742) @@ -426,7 +426,7 @@
VOID STDCALL KdSystemDebugControl(ULONG Code) { - extern VOID PsDumpThreads(BOOLEAN IncludeSystem); + extern VOID STDCALL PspDumpThreads(BOOLEAN IncludeSystem);
/* A - Dump the entire contents of the non-paged pool. */ if (Code == 0) @@ -462,12 +462,12 @@ /* F */ else if (Code == 5) { - PsDumpThreads(TRUE); + PspDumpThreads(TRUE); } /* G */ else if (Code == 6) { - PsDumpThreads(FALSE); + PspDumpThreads(FALSE); } /* H */ else if (Code == 7) _____
Modified: trunk/reactos/ntoskrnl/ke/i386/bios.c --- trunk/reactos/ntoskrnl/ke/i386/bios.c 2005-04-22 12:46:27 UTC (rev 14741) +++ trunk/reactos/ntoskrnl/ke/i386/bios.c 2005-04-22 12:52:25 UTC (rev 14742) @@ -1,4 +1,4 @@
-/* $Id:$ +/* $Id$ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel _____
Deleted: trunk/reactos/ntoskrnl/ke/i386/bthread.S --- trunk/reactos/ntoskrnl/ke/i386/bthread.S 2005-04-22 12:46:27 UTC (rev 14741) +++ trunk/reactos/ntoskrnl/ke/i386/bthread.S 2005-04-22 12:52:25 UTC (rev 14742) @@ -1,146 +0,0 @@
-/* - * ReactOS kernel - * Copyright (C) 2000 David Welch welch@cwcom.net - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ -/* $Id$ - * - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS kernel - * FILE: ntoskrnl/ke/i386/bthread.S - * PURPOSE: Trap handlers - * PROGRAMMER: David Welch (david.welch@seh.ox.ac.uk) - */ - -/* INCLUDES ******************************************************************/ - -#include <ddk/status.h> -#include <internal/i386/segment.h> -#include <internal/ps.h> -#include <ddk/defines.h> - -/* Values for contextflags */ -#define CONTEXT_i386 0x10000 -#ifndef CONTEXT_CONTROL -#define CONTEXT_CONTROL (CONTEXT_i386 | 1) -#endif -#ifndef CONTEXT_INTEGER -#define CONTEXT_INTEGER (CONTEXT_i386 | 2) -#endif -#ifndef CONTEXT_SEGMENTS -#define CONTEXT_SEGMENTS (CONTEXT_i386 | 4) -#endif -#ifndef CONTEXT_FLOATING_POINT -#define CONTEXT_FLOATING_POINT (CONTEXT_i386 | 8) -#endif -#ifndef CONTEXT_DEBUG_REGISTERS -#define CONTEXT_DEBUG_REGISTERS (CONTEXT_i386 | 0x10) -#endif -#ifndef CONTEXT_FULL -#define CONTEXT_FULL (CONTEXT_CONTROL | CONTEXT_INTEGER | CONTEXT_SEGMENTS) -#endif - -/* FUNCTIONS *****************************************************************/ - -/* - * - */ - -.globl _PsBeginThreadWithContextInternal -.globl _PsBeginThread - -_PsBeginThread: - /* - * This isn't really a function, we are called as the return address - * of the context switch function - */ - - /* - * Do the necessary prolog after a context switch - */ - call _PiBeforeBeginThread - - /* - * Call the actual start of the thread - */ - movl 4(%esp), %ebx /* Start routine */ - movl 8(%esp), %eax /* Start context */ - pushl %eax - call *%ebx /* Call the start routine */ - addl $4, %esp - - /* - * Terminate the thread - */ - pushl %eax - call _PsTerminateSystemThread@4 - addl $4, %esp - - /* - * If that fails then bug check - */ - pushl $0 - call _KeBugCheck@4 - addl $4, %esp - - /* - * And if that fails then loop - */ -.1: - jmp .1 - - -_PsBeginThreadWithContextInternal: - /* - * This isn't really a function, we are called as the return - * address of a context switch - */ - - /* - * Do the necessary prolog before the context switch - */ - call _PiBeforeBeginThread - - /* - * Load the context flags. - */ - popl %ebx - - /* - * Load the debugging registers - */ - testl $(CONTEXT_DEBUG_REGISTERS & ~CONTEXT_i386), %ebx - jz .L1 - popl %eax /* Dr0 */ - movl %eax, %dr0 - popl %eax /* Dr1 */ - movl %eax, %dr1 - popl %eax /* Dr2 */ - movl %eax, %dr2 - popl %eax /* Dr3 */ - movl %eax, %dr3 - popl %eax /* Dr6 */ - movl %eax, %dr6 - popl %eax /* Dr7 */ - movl %eax, %dr7 - jmp .L3 -.L1: - addl $24, %esp -.L3: - - /* Load the rest of the thread's user mode context. */ - movl $0, %eax - jmp _KiServiceExit _____
Added: trunk/reactos/ntoskrnl/ke/i386/ctxswitch.S --- trunk/reactos/ntoskrnl/ke/i386/ctxswitch.S 2005-04-22 12:46:27 UTC (rev 14741) +++ trunk/reactos/ntoskrnl/ke/i386/ctxswitch.S 2005-04-22 12:52:25 UTC (rev 14742) @@ -0,0 +1,290 @@
+/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/ke/i386/ctxswitch.S + * PURPOSE: Thread Context Switching + * + * PROGRAMMERS: Alex Ionescu (alex@relsoft.net) + */ + +/* INCLUDES ******************************************************************/ + +#include <roscfg.h> +#include <internal/i386/segment.h> +#include <internal/i386/ke.h> +#include <internal/i386/fpu.h> +#include <internal/ps.h> +#include <ntos/tss.h> +#include <internal/ntoskrnl.h> +.intel_syntax noprefix + +#define Running 2 +#define SIZEOF_TRAP_FRAME 0x8c +#define APC_LEVEL 1 + +/* GLOBALS ****************************************************************/ + +/* FUNCTIONS ****************************************************************/ + +/*++ + * KiThreadStartup + * + * The KiThreadStartup routine is the beginning of any thread. + * + * Params: + * SystemRoutine - Pointer to the System Startup Routine. Either + * PspUserThreadStartup or PspSystemThreadStartup + * + * StartRoutine - For Kernel Threads only, specifies the starting execution + * point of the new thread. + * + * StartContext - For Kernel Threads only, specifies a pointer to variable + * context data to be sent to the StartRoutine above. + * + * UserThread - Indicates whether or not this is a user thread. This tells + * us if the thread has a context or not. + * + * TrapFrame - Pointer to the KTHREAD to which the caller wishes to + * switch from. + * + * Returns: + * Should never return for a system thread. Returns through the System Call + * Exit Dispatcher for a user thread. + * + * Remarks: + * If a return from a system thread is detected, a bug check will occur. + * + *--*/ +.globl _KiThreadStartup@156 +_KiThreadStartup@156: + + /* + * Clear all the non-volatile registers, so the thread won't be tempted to + * expect any static data (like some badly coded usermode/win9x apps do) + */ + xor ebx, ebx + xor esi, edi + xor edi, edi + xor ebp, ebp + + /* It's now safe to go to APC */ + mov ecx, APC_LEVEL + call @KfLowerIrql@4 + + /* + * Call the System Routine which is right on our stack now. + * After we pop the pointer, the Start Routine/Context will be on the + * stack, as parameters to the System Routine + */ + pop eax + call eax + + /* The thread returned... was it a user-thread? */ + pop ecx + or ecx, ecx + jz BadThread + + /* Yes it was, set our trapframe for the System Call Exit Dispatcher */ + mov ebp, esp + + /* Exit back to user-mode */ + jmp _KiServiceExit + +BadThread: + + /* A system thread returned...this is very bad! */ + int 3 + +/*++ + * KiSwapContextInternal + * + * The KiSwapContextInternal routine switches context to another thread. + * + * Params: + * ESI - Pointer to the KTHREAD to which the caller wishes to + * switch to. + * EDI - Pointer to the KTHREAD to which the caller wishes to + * switch from. + * + * Returns: + * None. + * + * Remarks: + * Absolutely all registers except ESP can be trampled here for maximum code flexibility. + * + *--*/ +.globl @KiSwapContextInternal@0 +@KiSwapContextInternal@0: + + /* Get the PCR. It's faster to use ebx+offset then fs:offset */ + mov ebx, [fs:0x1C] + + /* Set the Thread to running */ + mov byte ptr [esi+KTHREAD_STATE], Running + + /* Save the Exception list */ + push [ebx+KPCR_EXCEPTION_LIST] + + /* Switching, disable interrupts now */ + cli + +#ifdef CONFIG_SMP + /* Save FPU state if the thread has used it. */ + mov [ebx+KPCR_NPX_THREAD], 0 + test byte ptr [edi+KTHREAD_NPX_STATE], NPX_STATE_DIRTY + jz 3f + mov eax, [edi+KTHREAD_INITIAL_STACK] + cmp _FxsrSupport, 0 + je 1f + fxsave [eax-SIZEOF_FX_SAVE_AREA] + jmp 2f +1: + fnsave [eax-SIZEOF_FX_SAVE_AREA] +2: + mov byte ptr [edi+KTHREAD_INITIAL_STACK], NPX_STATE_VALID +3: +#endif /* CONFIG_SMP */ + + /* Save the stack pointer in this processors TSS */ + mov ebp, [ebx+KPCR_TSS] + push ss:[ebp+KTSS_ESP0] + + /* Switch stacks */ + mov [edi+KTHREAD_KERNEL_STACK], esp + mov esp, [esi+KTHREAD_KERNEL_STACK] + + /* Stack is OK, safe to enable interrupts now */ + sti + + /* Check if address space switch is needed */ + mov eax, [edi+KTHREAD_APCSTATE_PROCESS] + cmp eax, [esi+KTHREAD_APCSTATE_PROCESS] + + /* If they match, then use the fast-path and skip all this */ + jz SameProcess + + /* Get the new Process. */ + mov edi, [esi+KTHREAD_APCSTATE_PROCESS] + + /* Check if we need an LDT */ + xor eax, eax + cmp [edi+KPROCESS_LDT_DESCRIPTOR0], eax + jz NoLdt + + /* Write the LDT Selector */ + mov ebp, [ebx+KPCR_GDT] + mov eax, [edi+KPROCESS_LDT_DESCRIPTOR0] + mov [ebp+LDT_SELECTOR], eax + mov eax, [edi+KPROCESS_LDT_DESCRIPTOR1] + mov [ebp+LDT_SELECTOR+4], eax + + /* Save LDT Selector */ + mov eax, LDT_SELECTOR + +NoLdt: + + /* Load LDT */ + lldt ax + + /* Get the IOPM */ + mov ecx, [edi+KPROCESS_IOPM_OFFSET] + + /* Set current IOPM offset in the TSS */ + mov [ebp+KTSS_IOMAPBASE], cx + + /* Change the address space */ + mov eax, [edi+KPROCESS_DIRECTORY_TABLE_BASE] + mov cr3, eax + +SameProcess: + + /* Set the TEB */ + mov eax, [esi+KTHREAD_TEB] + mov ecx, [ebx+KPCR_GDT] + mov [ecx+0x3A], ax + shr eax, 16 + mov [ecx+0x3C], al + mov [ecx+0x3F], ah + + /* Increase context switches */ + inc dword ptr [esi+KTHREAD_CONTEXT_SWITCHES] + + /* Set TS in cr0 to catch FPU code and load the FPU state when needed */ +#ifndef CONFIG_SMP + cmp [ebx+KPCR_NPX_THREAD], esi + je 4f +#endif /* !CONFIG_SMP */ + mov eax, cr0 + or eax, X86_CR0_TS + mov cr0, eax +4: + + /* Restore the stack pointer in this processors TSS */ + pop ss:[ebp+KTSS_ESP0] + + /* Restore exception list */ + pop [ebx+KPCR_EXCEPTION_LIST] + + call @KeReleaseDispatcherDatabaseLockFromDpcLevel@0 + + /* Return */ + ret + +/*++ + * KiSwapContext + * + * The KiSwapContext routine switches context to another thread. + * + * Params: + * TargetThread - Pointer to the KTHREAD to which the caller wishes to + * switch to. + * + * Returns: + * The WaitStatus of the Target Thread. NOT YET SUPPORTED. + * + * Remarks: + * This is a wrapper around KiSwapContextInternal which will save all the + * non-volatile registers so that the Internal function can use all of + * them. It will also save the old current thread and set the new one. + * + * The calling thread does not return after KiSwapContextInternal until + * another thread switches to IT. + * + *--*/ +.globl @KiSwapContext@4 +@KiSwapContext@4: + + /* Note, we CANNOT touch ebp */ + + /* Save 4 registers */ + sub esp, 4 * 4 + + /* Save all the non-volatile ones */ + mov [esp+12], ebx + mov [esp+8], esi + mov [esp+4], edi + mov [esp+0], ebp + + /* Get the Current Thread */ + mov edi, fs:[KPCR_CURRENT_THREAD] + + /* Get the New Thread */ + mov esi, ecx + + /* Save it as Current thread */ + mov fs:[KPCR_CURRENT_THREAD], esi + + /* Do the swap with the registers correctly setup */ + call @KiSwapContextInternal@0 + + /* Return the registers */ + mov ebp, [esp+0] + mov esi, [esp+4] + mov edi, [esp+8] + mov ebx, [esp+12] + + /* Clean stack */ + add esp, 4 * 4 + + ret + _____
Modified: trunk/reactos/ntoskrnl/ke/i386/exp.c --- trunk/reactos/ntoskrnl/ke/i386/exp.c 2005-04-22 12:46:27 UTC (rev 14741) +++ trunk/reactos/ntoskrnl/ke/i386/exp.c 2005-04-22 12:52:25 UTC (rev 14742) @@ -502,6 +502,7 @@
*/ if (Tf->Eflags & (1 << 17)) { + DPRINT("Tf->Eflags, %x, Tf->Eip %x, ExceptionNr: %d\n", Tf->Eflags, Tf->Eip, ExceptionNr); return(KeV86Exception(ExceptionNr, Tf, cr2)); }
@@ -511,7 +512,7 @@ if (PsGetCurrentThread() != NULL && Esp0 < (ULONG)PsGetCurrentThread()->Tcb.StackLimit) { - DbgPrint("Stack underflow (tf->esp %x Limit %x)\n", + DPRINT1("Stack underflow (tf->esp %x Limit %x)\n", Esp0, (ULONG)PsGetCurrentThread()->Tcb.StackLimit); ExceptionNr = 12; } _____
Modified: trunk/reactos/ntoskrnl/ke/i386/gdt.c --- trunk/reactos/ntoskrnl/ke/i386/gdt.c 2005-04-22 12:46:27 UTC (rev 14741) +++ trunk/reactos/ntoskrnl/ke/i386/gdt.c 2005-04-22 12:52:25 UTC (rev 14742) @@ -1,4 +1,4 @@
-/* $Id:$ +/* $Id$ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel _____
Modified: trunk/reactos/ntoskrnl/ke/i386/idt.c --- trunk/reactos/ntoskrnl/ke/i386/idt.c 2005-04-22 12:46:27 UTC (rev 14741) +++ trunk/reactos/ntoskrnl/ke/i386/idt.c 2005-04-22 12:52:25 UTC (rev 14742) @@ -1,4 +1,4 @@
-/* $Id:$ +/* $Id$ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel _____
Modified: trunk/reactos/ntoskrnl/ke/i386/kernel.c --- trunk/reactos/ntoskrnl/ke/i386/kernel.c 2005-04-22 12:46:27 UTC (rev 14741) +++ trunk/reactos/ntoskrnl/ke/i386/kernel.c 2005-04-22 12:52:25 UTC (rev 14742) @@ -133,7 +133,7 @@
IdleProcessorMask |= (1 << KeGetCurrentProcessorNumber()); KeReleaseDispatcherDatabaseLock(oldIrql); } - + VOID INIT_FUNCTION KeCreateApplicationProcessorIdleThread(ULONG Id) @@ -141,11 +141,11 @@ PETHREAD IdleThread; PKPRCB Prcb = ((PKPCR)((ULONG_PTR)KPCR_BASE + Id * PAGE_SIZE))->Prcb;
- PsInitializeThread(PsIdleProcess, + PsInitializeIdleOrFirstThread(PsIdleProcess, &IdleThread, NULL, - KernelMode, - FALSE); + KernelMode, + FALSE); IdleThread->Tcb.State = Running; IdleThread->Tcb.FreezeCount = 0; IdleThread->Tcb.Affinity = 1 << Id; _____
Modified: trunk/reactos/ntoskrnl/ke/i386/ldt.c --- trunk/reactos/ntoskrnl/ke/i386/ldt.c 2005-04-22 12:46:27 UTC (rev 14741) +++ trunk/reactos/ntoskrnl/ke/i386/ldt.c 2005-04-22 12:52:25 UTC (rev 14742) @@ -1,4 +1,4 @@
-/* $Id:$ +/* $Id$ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel _____
Modified: trunk/reactos/ntoskrnl/ke/i386/thread.c --- trunk/reactos/ntoskrnl/ke/i386/thread.c 2005-04-22 12:46:27 UTC (rev 14741) +++ trunk/reactos/ntoskrnl/ke/i386/thread.c 2005-04-22 12:52:25 UTC (rev 14742) @@ -1,11 +1,10 @@
-/* $Id:$ - * +/* * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel * FILE: ntoskrnl/ke/i386/thread.c - * PURPOSE: Architecture multitasking functions + * PURPOSE: i386 Thread Context Creation * - * PROGRAMMERS: David Welch (welch@cwcom.net) + * PROGRAMMERS: Alex Ionescu (alex@relsoft.net) */
/* INCLUDES ****************************************************************/ @@ -13,172 +12,177 @@ #include <ntoskrnl.h> #define NDEBUG #include <internal/debug.h> + +typedef struct _KSHARED_CTXSWITCH_FRAME { + ULONG Esp0; + PVOID ExceptionList; + PVOID RetEip; +} KSHARED_CTXSWITCH_FRAME, *PKSHARED_CTXSWITCH_FRAME;
-/* FUNCTIONS *****************************************************************/ +typedef struct _KSTART_FRAME { + PKSYSTEM_ROUTINE SystemRoutine; + PKSTART_ROUTINE StartRoutine; + PVOID StartContext; + BOOLEAN UserThread; +} KSTART_FRAME, *PKSTART_FRAME;
-NTSTATUS -Ki386ValidateUserContext(PCONTEXT Context) /* - * FUNCTION: Validates a processor context - * ARGUMENTS: - * Context = Context to validate - * RETURNS: Status - * NOTE: This only validates the context as not violating system security, it - * doesn't guararantee the thread won't crash at some point - * NOTE2: This relies on there only being two selectors which can access - * system space + * This is the Initial Thread Stack Frame on i386. + * + * It is composed of : + * + * - A shared Thread Switching frame so that we can use + * the context-switching code when initializing the thread. + * + * - The Stack Frame for KiThreadStartup, which are the parameters + * that it will receive (System/Start Routines & Context) + * + * - A Trap Frame with the Initial Context *IF AND ONLY IF THE THREAD IS USER* + * + * - The FPU Save Area, theoretically part of the Trap Frame's "ExtendedRegisters" + * + * This Initial Thread Stack Frame starts at Thread->InitialStack and it spans + * a total size of 0x2B8 bytes. */ -{ - if (Context->Eip >= KERNEL_BASE) - { - return(STATUS_UNSUCCESSFUL); - } - if (Context->SegCs == KERNEL_CS) - { - return(STATUS_UNSUCCESSFUL); - } - if (Context->SegDs == KERNEL_DS) - { - return(STATUS_UNSUCCESSFUL); - } - if (Context->SegEs == KERNEL_DS) - { - return(STATUS_UNSUCCESSFUL); - } - if (Context->SegFs == KERNEL_DS) - { - return(STATUS_UNSUCCESSFUL); - } - if (Context->SegGs == KERNEL_DS) - { - return(STATUS_UNSUCCESSFUL); - } - if ((Context->EFlags & X86_EFLAGS_IOPL) != 0 || - (Context->EFlags & X86_EFLAGS_NT) || - (Context->EFlags & X86_EFLAGS_VM) || - (!(Context->EFlags & X86_EFLAGS_IF))) - { - return(STATUS_UNSUCCESSFUL); - } - return(STATUS_SUCCESS); -} +typedef struct _KUINIT_FRAME { + KSHARED_CTXSWITCH_FRAME CtxSwitchFrame; /* -0x2B8 */ + KSTART_FRAME StartFrame; /* -0x2AC */ + KTRAP_FRAME TrapFrame; /* -0x29C */ + FX_SAVE_AREA FxSaveArea; /* -0x210 */ +} KUINIT_FRAME, *PKUINIT_FRAME;
-NTSTATUS -Ke386InitThreadWithContext(PKTHREAD Thread, PCONTEXT Context) -{ - PULONG KernelStack; - ULONG InitSize; - PKTRAP_FRAME TrapFrame; - PFX_SAVE_AREA FxSaveArea; +typedef struct _KKINIT_FRAME { + KSHARED_CTXSWITCH_FRAME CtxSwitchFrame; /* -0x22C */ + KSTART_FRAME StartFrame; /* -0x220 */ + FX_SAVE_AREA FxSaveArea; /* -0x210 */ +} KKINIT_FRAME, *PKKINIT_FRAME;
- /* - * Setup a stack frame for exit from the task switching routine - */ - - InitSize = 6 * sizeof(DWORD) + sizeof(DWORD) + 6 * sizeof(DWORD) + - + sizeof(KTRAP_FRAME) + sizeof (FX_SAVE_AREA); - KernelStack = (PULONG)((char*)Thread->KernelStack - InitSize); +/* FUNCTIONS *****************************************************************/
- /* Set up the initial frame for the return from the dispatcher. */ - KernelStack[0] = (ULONG)Thread->InitialStack - sizeof(FX_SAVE_AREA); /* TSS->Esp0 */ - KernelStack[1] = 0; /* EDI */ - KernelStack[2] = 0; /* ESI */ - KernelStack[3] = 0; /* EBX */ - KernelStack[4] = 0; /* EBP */ - KernelStack[5] = (ULONG)&PsBeginThreadWithContextInternal; /* EIP */ +VOID +STDCALL +Ke386InitThreadWithContext(PKTHREAD Thread, + PKSYSTEM_ROUTINE SystemRoutine, + PKSTART_ROUTINE StartRoutine, + PVOID StartContext, + PCONTEXT Context) +{ + PFX_SAVE_AREA FxSaveArea; + PKSTART_FRAME StartFrame; + PKSHARED_CTXSWITCH_FRAME CtxSwitchFrame; + PKTRAP_FRAME TrapFrame = NULL; + + /* Check if this is a With-Context Thread */ + DPRINT("Ke386InitThreadContext\n"); + if (Context) { + + /* Set up the Initial Frame */ + PKUINIT_FRAME InitFrame; + InitFrame = (PKUINIT_FRAME)((ULONG_PTR)Thread->InitialStack - sizeof(KUINIT_FRAME)); + DPRINT("Setting up a user-mode thread with the Frame at: %x\n", InitFrame); + + /* Setup the Fx Area */ + FxSaveArea = &InitFrame->FxSaveArea; + DPRINT("Fx Save Area: %x\n", FxSaveArea); + + /* Setup the Initial Fx State */ + if (KiContextToFxSaveArea(FxSaveArea, Context)) {
- /* Save the context flags. */ - KernelStack[6] = Context->ContextFlags; - - /* Set up the initial values of the debugging registers. */ - KernelStack[7] = Context->Dr0; - KernelStack[8] = Context->Dr1; - KernelStack[9] = Context->Dr2; - KernelStack[10] = Context->Dr3; - KernelStack[11] = Context->Dr6; - KernelStack[12] = Context->Dr7; - - /* Set up a trap frame from the context. */ - TrapFrame = (PKTRAP_FRAME)(&KernelStack[13]); - TrapFrame->DebugEbp = (PVOID)Context->Ebp; - TrapFrame->DebugEip = (PVOID)Context->Eip; - TrapFrame->DebugArgMark = 0; - TrapFrame->DebugPointer = 0; - TrapFrame->TempCs = 0; - TrapFrame->TempEip = 0; - TrapFrame->Gs = (USHORT)Context->SegGs; - TrapFrame->Es = (USHORT)Context->SegEs; - TrapFrame->Ds = (USHORT)Context->SegDs; - TrapFrame->Edx = Context->Edx; - TrapFrame->Ecx = Context->Ecx; - TrapFrame->Eax = Context->Eax; - TrapFrame->PreviousMode = UserMode; - TrapFrame->ExceptionList = (PVOID)0xFFFFFFFF; - TrapFrame->Fs = TEB_SELECTOR; - TrapFrame->Edi = Context->Edi; - TrapFrame->Esi = Context->Esi; - TrapFrame->Ebx = Context->Ebx; - TrapFrame->Ebp = Context->Ebp; - TrapFrame->ErrorCode = 0; - TrapFrame->Cs = Context->SegCs; - TrapFrame->Eip = Context->Eip; - TrapFrame->Eflags = Context->EFlags | X86_EFLAGS_IF; - TrapFrame->Eflags &= ~(X86_EFLAGS_VM | X86_EFLAGS_NT | X86_EFLAGS_IOPL); - TrapFrame->Esp = Context->Esp; - TrapFrame->Ss = (USHORT)Context->SegSs; - /* FIXME: Should check for a v86 mode context here. */ - - /* Set up the initial floating point state. */ - /* FIXME: Do we have to zero the FxSaveArea or is it already? */ - FxSaveArea = (PFX_SAVE_AREA)((ULONG_PTR)KernelStack + InitSize - sizeof(FX_SAVE_AREA)); - if (KiContextToFxSaveArea(FxSaveArea, Context)) - { - Thread->NpxState = NPX_STATE_VALID; + Thread->NpxState = NPX_STATE_VALID; + + } else { [truncated at 1000 lines; 2134 more skipped]