1999-11-12 12:01:17 +00:00
|
|
|
/*
|
2001-03-26 00:56:53 +00:00
|
|
|
* ReactOS kernel
|
|
|
|
* Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team
|
|
|
|
*
|
|
|
|
* 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.
|
|
|
|
*/
|
|
|
|
/*
|
1999-11-12 12:01:17 +00:00
|
|
|
* PROJECT: ReactOS kernel
|
2001-03-14 16:30:08 +00:00
|
|
|
* FILE: ntoskrnl/ke/i386/thread.c
|
|
|
|
* PURPOSE: Architecture multitasking functions
|
1999-11-12 12:01:17 +00:00
|
|
|
* PROGRAMMER: David Welch (welch@cwcom.net)
|
|
|
|
* REVISION HISTORY:
|
|
|
|
* 27/06/98: Created
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* INCLUDES ****************************************************************/
|
|
|
|
|
2004-08-15 16:39:12 +00:00
|
|
|
#include <ntoskrnl.h>
|
1999-11-12 12:01:17 +00:00
|
|
|
#define NDEBUG
|
|
|
|
#include <internal/debug.h>
|
|
|
|
|
2002-08-14 20:58:39 +00:00
|
|
|
/* FUNCTIONS *****************************************************************/
|
|
|
|
|
2000-12-23 02:37:41 +00:00
|
|
|
NTSTATUS
|
2002-08-14 20:58:39 +00:00
|
|
|
Ki386ValidateUserContext(PCONTEXT Context)
|
1999-11-12 12:01:17 +00:00
|
|
|
/*
|
|
|
|
* 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
|
|
|
|
*/
|
|
|
|
{
|
|
|
|
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);
|
|
|
|
}
|
2004-11-20 23:46:37 +00:00
|
|
|
if ((Context->EFlags & X86_EFLAGS_IOPL) != 0 ||
|
|
|
|
(Context->EFlags & X86_EFLAGS_NT) ||
|
|
|
|
(Context->EFlags & X86_EFLAGS_VM) ||
|
|
|
|
(!(Context->EFlags & X86_EFLAGS_IF)))
|
1999-11-12 12:01:17 +00:00
|
|
|
{
|
|
|
|
return(STATUS_UNSUCCESSFUL);
|
|
|
|
}
|
|
|
|
return(STATUS_SUCCESS);
|
|
|
|
}
|
|
|
|
|
2000-12-23 02:37:41 +00:00
|
|
|
NTSTATUS
|
|
|
|
Ke386InitThreadWithContext(PKTHREAD Thread, PCONTEXT Context)
|
1999-11-12 12:01:17 +00:00
|
|
|
{
|
2002-08-08 17:54:16 +00:00
|
|
|
PULONG KernelStack;
|
|
|
|
ULONG InitSize;
|
|
|
|
PKTRAP_FRAME TrapFrame;
|
2004-11-20 23:46:37 +00:00
|
|
|
PFX_SAVE_AREA FxSaveArea;
|
1999-11-12 12:01:17 +00:00
|
|
|
|
2000-12-23 02:37:41 +00:00
|
|
|
/*
|
|
|
|
* Setup a stack frame for exit from the task switching routine
|
|
|
|
*/
|
2002-09-17 23:41:44 +00:00
|
|
|
|
2004-11-20 23:46:37 +00:00
|
|
|
InitSize = 6 * sizeof(DWORD) + sizeof(DWORD) + 6 * sizeof(DWORD) +
|
|
|
|
+ sizeof(KTRAP_FRAME) + sizeof (FX_SAVE_AREA);
|
2003-12-30 18:52:06 +00:00
|
|
|
KernelStack = (PULONG)((char*)Thread->KernelStack - InitSize);
|
2002-08-08 17:54:16 +00:00
|
|
|
|
|
|
|
/* Set up the initial frame for the return from the dispatcher. */
|
2004-11-20 23:46:37 +00:00
|
|
|
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 */
|
2002-08-08 17:54:16 +00:00
|
|
|
|
2002-09-17 23:41:44 +00:00
|
|
|
/* Save the context flags. */
|
2004-11-20 23:46:37 +00:00
|
|
|
KernelStack[6] = Context->ContextFlags;
|
2002-09-17 23:41:44 +00:00
|
|
|
|
2002-08-08 17:54:16 +00:00
|
|
|
/* Set up the initial values of the debugging registers. */
|
2004-11-20 23:46:37 +00:00
|
|
|
KernelStack[7] = Context->Dr0;
|
|
|
|
KernelStack[8] = Context->Dr1;
|
|
|
|
KernelStack[9] = Context->Dr2;
|
|
|
|
KernelStack[10] = Context->Dr3;
|
|
|
|
KernelStack[11] = Context->Dr6;
|
|
|
|
KernelStack[12] = Context->Dr7;
|
2002-08-08 17:54:16 +00:00
|
|
|
|
|
|
|
/* Set up a trap frame from the context. */
|
2004-11-20 23:46:37 +00:00
|
|
|
TrapFrame = (PKTRAP_FRAME)(&KernelStack[13]);
|
2002-08-08 17:54:16 +00:00
|
|
|
TrapFrame->DebugEbp = (PVOID)Context->Ebp;
|
|
|
|
TrapFrame->DebugEip = (PVOID)Context->Eip;
|
|
|
|
TrapFrame->DebugArgMark = 0;
|
|
|
|
TrapFrame->DebugPointer = 0;
|
|
|
|
TrapFrame->TempCs = 0;
|
|
|
|
TrapFrame->TempEip = 0;
|
2003-12-30 18:52:06 +00:00
|
|
|
TrapFrame->Gs = (USHORT)Context->SegGs;
|
|
|
|
TrapFrame->Es = (USHORT)Context->SegEs;
|
|
|
|
TrapFrame->Ds = (USHORT)Context->SegDs;
|
2002-09-17 16:41:22 +00:00
|
|
|
TrapFrame->Edx = Context->Edx;
|
2002-08-08 17:54:16 +00:00
|
|
|
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;
|
2004-11-20 23:46:37 +00:00
|
|
|
TrapFrame->Eflags = Context->EFlags | X86_EFLAGS_IF;
|
|
|
|
TrapFrame->Eflags &= ~(X86_EFLAGS_VM | X86_EFLAGS_NT | X86_EFLAGS_IOPL);
|
2002-08-08 17:54:16 +00:00
|
|
|
TrapFrame->Esp = Context->Esp;
|
2003-12-30 18:52:06 +00:00
|
|
|
TrapFrame->Ss = (USHORT)Context->SegSs;
|
2002-08-08 17:54:16 +00:00
|
|
|
/* FIXME: Should check for a v86 mode context here. */
|
|
|
|
|
2004-11-20 23:46:37 +00:00
|
|
|
/* 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;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
Thread->NpxState = NPX_STATE_INVALID;
|
|
|
|
}
|
|
|
|
|
2002-08-08 17:54:16 +00:00
|
|
|
/* Save back the new value of the kernel stack. */
|
2001-03-14 16:30:08 +00:00
|
|
|
Thread->KernelStack = (PVOID)KernelStack;
|
2000-12-23 02:37:41 +00:00
|
|
|
|
|
|
|
return(STATUS_SUCCESS);
|
2000-05-13 13:51:08 +00:00
|
|
|
}
|
|
|
|
|
2000-12-23 02:37:41 +00:00
|
|
|
NTSTATUS
|
2002-09-17 23:41:44 +00:00
|
|
|
Ke386InitThread(PKTHREAD Thread,
|
|
|
|
PKSTART_ROUTINE StartRoutine,
|
2000-12-23 02:37:41 +00:00
|
|
|
PVOID StartContext)
|
|
|
|
/*
|
|
|
|
* Initialize a thread
|
|
|
|
*/
|
1999-11-12 12:01:17 +00:00
|
|
|
{
|
2000-12-23 02:37:41 +00:00
|
|
|
PULONG KernelStack;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Setup a stack frame for exit from the task switching routine
|
|
|
|
*/
|
2004-01-05 14:28:21 +00:00
|
|
|
|
2004-11-20 23:46:37 +00:00
|
|
|
KernelStack = (PULONG)((char*)Thread->KernelStack - (9 * sizeof(DWORD)) - sizeof(FX_SAVE_AREA));
|
|
|
|
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)&PsBeginThread; /* EIP */
|
|
|
|
KernelStack[6] = 0; /* Return EIP */
|
|
|
|
KernelStack[7] = (ULONG)StartRoutine; /* First argument to PsBeginThread */
|
|
|
|
KernelStack[8] = (ULONG)StartContext; /* Second argument to PsBeginThread */
|
2000-12-23 02:37:41 +00:00
|
|
|
Thread->KernelStack = (VOID*)KernelStack;
|
|
|
|
|
2004-11-20 23:46:37 +00:00
|
|
|
/*
|
|
|
|
* Setup FPU state
|
|
|
|
*/
|
|
|
|
Thread->NpxState = NPX_STATE_INVALID;
|
|
|
|
|
2000-12-23 02:37:41 +00:00
|
|
|
return(STATUS_SUCCESS);
|
1999-11-12 12:01:17 +00:00
|
|
|
}
|
|
|
|
|
2002-02-15 14:47:55 +00:00
|
|
|
/* EOF */
|
2004-11-20 23:46:37 +00:00
|
|
|
|