286 lines
7.3 KiB
C
286 lines
7.3 KiB
C
/*++
|
||
|
||
Copyright (c) 1990 Microsoft Corporation
|
||
|
||
Module Name:
|
||
|
||
thredini.c
|
||
|
||
Abstract:
|
||
|
||
This module implements the machine dependent functions to set the initial
|
||
context and data alignment handling mode for a process or thread object.
|
||
|
||
Author:
|
||
|
||
David N. Cutler (davec) 1-Apr-1990
|
||
|
||
Environment:
|
||
|
||
Kernel mode only.
|
||
|
||
Revision History:
|
||
|
||
--*/
|
||
|
||
#include "ki.h"
|
||
|
||
//
|
||
// The following assert macros are used to check that an input object is
|
||
// really the proper type.
|
||
//
|
||
|
||
#define ASSERT_PROCESS(E) { \
|
||
ASSERT((E)->Header.Type == ProcessObject); \
|
||
}
|
||
|
||
#define ASSERT_THREAD(E) { \
|
||
ASSERT((E)->Header.Type == ThreadObject); \
|
||
}
|
||
|
||
VOID
|
||
KiInitializeContextThread (
|
||
IN PKTHREAD Thread,
|
||
IN PKSYSTEM_ROUTINE SystemRoutine,
|
||
IN PKSTART_ROUTINE StartRoutine OPTIONAL,
|
||
IN PVOID StartContext OPTIONAL,
|
||
IN PCONTEXT ContextRecord OPTIONAL
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This function initializes the machine dependent context of a thread object.
|
||
|
||
N.B. This function does not check the accessibility of the context record.
|
||
It is assumed the the caller of this routine is either prepared to
|
||
handle access violations or has probed and copied the context record
|
||
as appropriate.
|
||
|
||
Arguments:
|
||
|
||
Thread - Supplies a pointer to a dispatcher object of type thread.
|
||
|
||
SystemRoutine - Supplies a pointer to the system function that is to be
|
||
called when the thread is first scheduled for execution.
|
||
|
||
StartRoutine - Supplies an optional pointer to a function that is to be
|
||
called after the system has finished initializing the thread. This
|
||
parameter is specified if the thread is a system thread and will
|
||
execute totally in kernel mode.
|
||
|
||
StartContext - Supplies an optional pointer to an arbitrary data structure
|
||
which will be passed to the StartRoutine as a parameter. This
|
||
parameter is specified if the thread is a system thread and will
|
||
execute totally in kernel mode.
|
||
|
||
ContextRecord - Supplies an optional pointer a context frame which contains
|
||
the initial user mode state of the thread. This parameter is specified
|
||
if the thread is a user thread and will execute in user mode. If this
|
||
parameter is not specified, then the Teb parameter is ignored.
|
||
|
||
Return Value:
|
||
|
||
None.
|
||
|
||
--*/
|
||
|
||
{
|
||
|
||
PKEXCEPTION_FRAME CxFrame;
|
||
PKEXCEPTION_FRAME ExFrame;
|
||
ULONG InitialStack;
|
||
PKTRAP_FRAME TrFrame;
|
||
|
||
//
|
||
// If a context frame is specified, then initialize a trap frame and
|
||
// and an exception frame with the specified user mode context.
|
||
//
|
||
|
||
InitialStack = (LONG)Thread->InitialStack;
|
||
if (ARGUMENT_PRESENT(ContextRecord)) {
|
||
TrFrame = (PKTRAP_FRAME)(InitialStack - sizeof(KTRAP_FRAME));
|
||
ExFrame = (PKEXCEPTION_FRAME)((ULONG)TrFrame - sizeof(KEXCEPTION_FRAME));
|
||
CxFrame = (PKEXCEPTION_FRAME)((ULONG)ExFrame - sizeof(KEXCEPTION_FRAME));
|
||
|
||
//
|
||
// Zero the exception and trap frames and copy information from the
|
||
// specified context frame to the trap and exception frames.
|
||
//
|
||
|
||
RtlZeroMemory((PVOID)ExFrame, sizeof(KEXCEPTION_FRAME));
|
||
RtlZeroMemory((PVOID)TrFrame, sizeof(KTRAP_FRAME));
|
||
KeContextToKframes(TrFrame,
|
||
ExFrame,
|
||
ContextRecord,
|
||
ContextRecord->ContextFlags | CONTEXT_CONTROL,
|
||
UserMode);
|
||
|
||
//
|
||
// Set the saved previous processor mode in the trap frame and the
|
||
// previous processor mode in the thread object to user mode.
|
||
//
|
||
|
||
TrFrame->PreviousMode = UserMode;
|
||
Thread->PreviousMode = UserMode;
|
||
|
||
//
|
||
// Initialize the return address in the exception frame.
|
||
//
|
||
|
||
ExFrame->IntRa = 0;
|
||
|
||
} else {
|
||
ExFrame = NULL;
|
||
CxFrame = (PKEXCEPTION_FRAME)(InitialStack - sizeof(KEXCEPTION_FRAME));
|
||
|
||
//
|
||
// Set the previous mode in thread object to kernel.
|
||
//
|
||
|
||
Thread->PreviousMode = KernelMode;
|
||
}
|
||
|
||
//
|
||
// Initialize context switch frame and set thread start up parameters.
|
||
//
|
||
|
||
CxFrame->SwapReturn = (ULONG)KiThreadStartup;
|
||
if (ExFrame == NULL) {
|
||
CxFrame->IntS8 = (ULONG)ExFrame;
|
||
|
||
} else {
|
||
CxFrame->IntS8 = (ULONG)TrFrame;
|
||
}
|
||
|
||
CxFrame->IntS0 = (ULONG)ContextRecord;
|
||
CxFrame->IntS1 = (ULONG)StartContext;
|
||
CxFrame->IntS2 = (ULONG)StartRoutine;
|
||
CxFrame->IntS3 = (ULONG)SystemRoutine;
|
||
Thread->KernelStack = (PVOID)CxFrame;
|
||
return;
|
||
}
|
||
|
||
BOOLEAN
|
||
KeSetAutoAlignmentProcess (
|
||
IN PRKPROCESS Process,
|
||
IN BOOLEAN Enable
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This function sets the data alignment handling mode for the specified
|
||
process and returns the previous data alignment handling mode.
|
||
|
||
Arguments:
|
||
|
||
Process - Supplies a pointer to a dispatcher object of type process.
|
||
|
||
Enable - Supplies a boolean value that determines the handling of data
|
||
alignment exceptions for the process. A value of TRUE causes all
|
||
data alignment exceptions to be automatically handled by the kernel.
|
||
A value of FALSE causes all data alignment exceptions to be actually
|
||
raised as exceptions.
|
||
|
||
Return Value:
|
||
|
||
A value of TRUE is returned if data alignment exceptions were
|
||
previously automatically handled by the kernel. Otherwise, a value
|
||
of FALSE is returned.
|
||
|
||
--*/
|
||
|
||
{
|
||
|
||
KIRQL OldIrql;
|
||
BOOLEAN Previous;
|
||
|
||
ASSERT_PROCESS(Process);
|
||
|
||
//
|
||
// Raise IRQL to dispatcher level and lock dispatcher database.
|
||
//
|
||
|
||
KiLockDispatcherDatabase(&OldIrql);
|
||
|
||
//
|
||
// Capture the previous data alignment handling mode and set the
|
||
// specified data alignment mode.
|
||
//
|
||
|
||
Previous = Process->AutoAlignment;
|
||
Process->AutoAlignment = Enable;
|
||
|
||
//
|
||
// Unlock dispatcher database, lower IRQL to its previous value, and
|
||
// return the previous data alignment mode.
|
||
//
|
||
|
||
KiUnlockDispatcherDatabase(OldIrql);
|
||
return Previous;
|
||
}
|
||
|
||
BOOLEAN
|
||
KeSetAutoAlignmentThread (
|
||
IN PKTHREAD Thread,
|
||
IN BOOLEAN Enable
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This function sets the data alignment handling mode for the specified
|
||
thread and returns the previous data alignment handling mode.
|
||
|
||
Arguments:
|
||
|
||
Thread - Supplies a pointer to a dispatcher object of type thread.
|
||
|
||
Enable - Supplies a boolean value that determines the handling of data
|
||
alignment exceptions for the thread. A value of TRUE causes all
|
||
data alignment exceptions to be automatically handled by the kernel.
|
||
A value of FALSE causes all data alignment exceptions to be actually
|
||
raised as exceptions.
|
||
|
||
Return Value:
|
||
|
||
A value of TRUE is returned if data alignment exceptions were
|
||
previously automatically handled by the kernel. Otherwise, a value
|
||
of FALSE is returned.
|
||
|
||
--*/
|
||
|
||
{
|
||
|
||
KIRQL OldIrql;
|
||
BOOLEAN Previous;
|
||
|
||
ASSERT_THREAD(Thread);
|
||
|
||
//
|
||
// Raise IRQL to dispatcher level and lock dispatcher database.
|
||
//
|
||
|
||
KiLockDispatcherDatabase(&OldIrql);
|
||
|
||
//
|
||
// Capture the previous data alignment handling mode and set the
|
||
// specified data alignment mode.
|
||
//
|
||
|
||
Previous = Thread->AutoAlignment;
|
||
Thread->AutoAlignment = Enable;
|
||
|
||
//
|
||
// Unlock dispatcher database, lower IRQL to its previous value, and
|
||
// return the previous data alignment mode.
|
||
//
|
||
|
||
KiUnlockDispatcherDatabase(OldIrql);
|
||
return Previous;
|
||
}
|