test: thredini.c Source File

Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

# thredini.c

Go to the documentation of this file.

    00001 /*++
    00002
    00003 Copyright (c) 1990  Microsoft Corporation
    00004
    00005 Module Name:
    00006
    00007     thredini.c
    00008
    00009 Abstract:
    00010
    00011     This module implements the machine dependent functions to set the initial
    00012     context and data alignment handling mode for a process or thread object.
    00013
    00014 Author:
    00015
    00016     David N. Cutler (davec) 1-Apr-1990
    00017
    00018 Environment:
    00019
    00020     Kernel mode only.
    00021
    00022 Revision History:
    00023
    00024     Joe Notarangelo  21-Apr-1992
    00025         very minor changes for ALPHA
    00026              1. psr definition
    00027              2. pte and mask (from 3ffffc to 1ffffc), mips page size is 4k
    00028                     our first alpha page size is 8k
    00029                     mips code shifts right 10 (12-2) and then turns off the
    00030                     upper 10 bits, alpha shifts right 11 (13-2) and so must
    00031                     turn off upper 11 bits
    00032              3. Insert register values into context structure as quadwords
    00033                     to insure that the written values are in canonical form
    00034
    00035     Thomas Van Baak (tvb) 9-Oct-1992
    00036
    00037         Adapted for Alpha AXP.
    00038
    00039 --*/
    00040
    00041 #include "ki.h"
    00042
    00043 //
    00044 // The following assert macros are used to check that an input object is
    00045 // really the proper type.
    00046 //
    00047
    00048 #define ASSERT_PROCESS(E) {                    \
    00049     ASSERT((E)->Header.Type == ProcessObject); \
    00050 }
    00051
    00052 #define ASSERT_THREAD(E) {                    \
    00053     ASSERT((E)->Header.Type == ThreadObject); \
    00054 }
    00055
    00056 VOID
    00057 KiInitializeContextThread (
    00058     IN PKTHREAD Thread,
    00059     IN PKSYSTEM_ROUTINE SystemRoutine,
    00060     IN PKSTART_ROUTINE StartRoutine OPTIONAL,
    00061     IN PVOID StartContext OPTIONAL,
    00062     IN PCONTEXT ContextRecord OPTIONAL
    00063     )
    00064
    00065 /*++
    00066
    00067 Routine Description:
    00068
    00069     This function initializes the machine dependent context of a thread object.
    00070
    00071     N.B. This function does not check the accessibility of the context record.
    00072          It is assumed the the caller of this routine is either prepared to
    00073          handle access violations or has probed and copied the context record
    00074          as appropriate.
    00075
    00076 Arguments:
    00077
    00078     Thread - Supplies a pointer to a dispatcher object of type thread.
    00079
    00080     SystemRoutine - Supplies a pointer to the system function that is to be
    00081         called when the thread is first scheduled for execution.
    00082
    00083     StartRoutine - Supplies an optional pointer to a function that is to be
    00084         called after the system has finished initializing the thread. This
    00085         parameter is specified if the thread is a system thread and will
    00086         execute totally in kernel mode.
    00087
    00088     StartContext - Supplies an optional pointer to an arbitrary data structure
    00089         which will be passed to the StartRoutine as a parameter. This
    00090         parameter is specified if the thread is a system thread and will
    00091         execute totally in kernel mode.
    00092
    00093     ContextRecord - Supplies an optional pointer a context frame which contains
    00094         the initial user mode state of the thread. This parameter is specified
    00095         if the thread is a user thread and will execute in user mode. If this
    00096         parameter is not specified, then the Teb parameter is ignored.
    00097
    00098 Return Value:
    00099
    00100     None.
    00101
    00102 --*/
    00103
    00104 {
    00105
    00106     PKEXCEPTION_FRAME CxFrame;
    00107     PKEXCEPTION_FRAME ExFrame;
    00108     ULONG_PTR InitialStack;
    00109     PKTRAP_FRAME TrFrame;
    00110
    00111     //
    00112     // If a context frame is specified, then initialize a trap frame and
    00113     // and an exception frame with the specified user mode context.
    00114     //
    00115
    00116     InitialStack = (ULONG_PTR)Thread->InitialStack;
    00117     if (ARGUMENT_PRESENT(ContextRecord)) {
    00118         TrFrame = (PKTRAP_FRAME)(((InitialStack) -
    00119                   sizeof(KTRAP_FRAME)) & ~((ULONG_PTR)15));
    00120         ExFrame = (PKEXCEPTION_FRAME)(((ULONG_PTR)TrFrame -
    00121                   sizeof(KEXCEPTION_FRAME)) & ~((ULONG_PTR)15));
    00122         CxFrame = (PKEXCEPTION_FRAME)(((ULONG_PTR)ExFrame -
    00123                   sizeof(KEXCEPTION_FRAME)) & ~((ULONG_PTR)15));
    00124
    00125         //
    00126         // Zero the exception and trap frames and copy information from the
    00127         // specified context frame to the trap and exception frames.
    00128         //
    00129
    00130         RtlZeroMemory((PVOID)ExFrame, sizeof(KEXCEPTION_FRAME));
    00131         RtlZeroMemory((PVOID)TrFrame, sizeof(KTRAP_FRAME));
    00132         KeContextToKframes(TrFrame, ExFrame,
    00133                            ContextRecord,
    00134                            ContextRecord->ContextFlags | CONTEXT_CONTROL,
    00135                            UserMode);
    00136
    00137         //
    00138         // If the FPCR quadword in the specified context record is zero,
    00139         // then assume it is a default value and force floating point round
    00140         // to nearest mode (the hardware default mode is chopped rounding
    00141         // which is not desirable for NT). It would be nice to initialize
    00142         // the SoftFpcr here also but not all threads have a Teb.
    00143         //
    00144
    00145         if (TrFrame->Fpcr == 0) {
    00146             ((PFPCR)(&TrFrame->Fpcr))->DynamicRoundingMode = ROUND_TO_NEAREST;
    00147         }
    00148
    00149         //
    00150         // Set the saved previous processor mode in the trap frame and the
    00151         // previous processor mode in the thread object to user mode.
    00152         //
    00153
    00154         TrFrame->PreviousMode = UserMode;
    00155         Thread->PreviousMode = UserMode;
    00156
    00157         //
    00158         // Initialize the return address in the exception frame.
    00159         //
    00160
    00161         ExFrame->IntRa = 0;
    00162
    00163     } else {
    00164         ExFrame = NULL;
    00165         CxFrame = (PKEXCEPTION_FRAME)(((InitialStack) -
    00166                   sizeof(KEXCEPTION_FRAME)) & ~((ULONG_PTR)15));
    00167
    00168         //
    00169         // Set the previous mode in thread object to kernel.
    00170         //
    00171
    00172         Thread->PreviousMode = KernelMode;
    00173     }
    00174
    00175     //
    00176     // Initialize context switch frame and set thread start up parameters.
    00177     //
    00178     // N.B. ULONG becomes canonical longword with (ULONGLONG)(LONG) cast.
    00179     //
    00180
    00181     CxFrame->SwapReturn = (ULONGLONG)(LONG_PTR)KiThreadStartup;
    00182     if (ExFrame == NULL) {
    00183         CxFrame->IntFp = (ULONGLONG)(LONG_PTR)ExFrame;
    00184
    00185     } else {
    00186         CxFrame->IntFp = (ULONGLONG)(LONG_PTR)TrFrame;
    00187     }
    00188
    00189     CxFrame->IntS0 = (ULONGLONG)(LONG_PTR)ContextRecord;
    00190     CxFrame->IntS1 = (ULONGLONG)(LONG_PTR)StartContext;
    00191     CxFrame->IntS2 = (ULONGLONG)(LONG_PTR)StartRoutine;
    00192     CxFrame->IntS3 = (ULONGLONG)(LONG_PTR)SystemRoutine;
    00193
    00194     CxFrame->Psr = 0;                   // clear everything
    00195     ((PSR *)(&CxFrame->Psr))->INTERRUPT_ENABLE = 1;
    00196     ((PSR *)(&CxFrame->Psr))->IRQL = DISPATCH_LEVEL;
    00197     ((PSR *)(&CxFrame->Psr))->MODE = 0;
    00198
    00199     //
    00200     // Set the initial kernel stack pointer.
    00201     //
    00202
    00203     Thread->KernelStack = (PVOID)(ULONGLONG)(LONG_PTR)CxFrame;
    00204     return;
    00205 }
    00206
    00207 BOOLEAN
    00208 KeSetAutoAlignmentProcess (
    00209     IN PKPROCESS Process,
    00210     IN BOOLEAN Enable
    00211     )
    00212
    00213 /*++
    00214
    00215 Routine Description:
    00216
    00217     This function sets the data alignment handling mode for the specified
    00218     process and returns the previous data alignment handling mode.
    00219
    00220 Arguments:
    00221
    00222     Process  - Supplies a pointer to a dispatcher object of type process.
    00223
    00224     Enable - Supplies a boolean value that determines the handling of data
    00225         alignment exceptions for the process. A value of TRUE causes all
    00226         data alignment exceptions to be automatically handled by the kernel.
    00227         A value of FALSE causes all data alignment exceptions to be actually
    00228         raised as exceptions.
    00229
    00230 Return Value:
    00231
    00232     A value of TRUE is returned if data alignment exceptions were
    00233     previously automatically handled by the kernel. Otherwise, a value
    00234     of FALSE is returned.
    00235
    00236 --*/
    00237
    00238 {
    00239
    00240     KIRQL OldIrql;
    00241     BOOLEAN Previous;
    00242
    00243     ASSERT_PROCESS(Process);
    00244
    00245     //
    00246     // Raise IRQL to dispatcher level and lock dispatcher database.
    00247     //
    00248
    00249     KiLockDispatcherDatabase(&OldIrql);
    00250
    00251     //
    00252     // Capture the previous data alignment handling mode and set the
    00253     // specified data alignment mode.
    00254     //
    00255
    00256     Previous = Process->AutoAlignment;
    00257     Process->AutoAlignment = Enable;
    00258
    00259     //
    00260     // Unlock dispatcher database, lower IRQL to its previous value, and
    00261     // return the previous data alignment mode.
    00262     //
    00263
    00264     KiUnlockDispatcherDatabase(OldIrql);
    00265     return Previous;
    00266 }
    00267
    00268 BOOLEAN
    00269 KeSetAutoAlignmentThread (
    00270     IN PKTHREAD Thread,
    00271     IN BOOLEAN Enable
    00272     )
    00273
    00274 /*++
    00275
    00276 Routine Description:
    00277
    00278     This function sets the data alignment handling mode for the specified
    00279     thread and returns the previous data alignment handling mode.
    00280
    00281 Arguments:
    00282
    00283     Thread  - Supplies a pointer to a dispatcher object of type thread.
    00284
    00285     Enable - Supplies a boolean value that determines the handling of data
    00286         alignment exceptions for the thread. A value of TRUE causes all
    00287         data alignment exceptions to be automatically handled by the kernel.
    00288         A value of FALSE causes all data alignment exceptions to be actually
    00289         raised as exceptions.
    00290
    00291 Return Value:
    00292
    00293     A value of TRUE is returned if data alignment exceptions were
    00294     previously automatically handled by the kernel. Otherwise, a value
    00295     of FALSE is returned.
    00296
    00297 --*/
    00298
    00299 {
    00300
    00301     KIRQL OldIrql;
    00302     BOOLEAN Previous;
    00303
    00304     ASSERT_THREAD(Thread);
    00305
    00306     //
    00307     // Raise IRQL to dispatcher level and lock dispatcher database.
    00308     //
    00309
    00310     KiLockDispatcherDatabase(&OldIrql);
    00311
    00312     //
    00313     // Capture the previous data alignment handling mode and set the
    00314     // specified data alignment mode.
    00315     //
    00316
    00317     Previous = Thread->AutoAlignment;
    00318     Thread->AutoAlignment = Enable;
    00319
    00320     //
    00321     // Unlock dispatcher database, lower IRQL to its previous value, and
    00322     // return the previous data alignment mode.
    00323     //
    00324
    00325     KiUnlockDispatcherDatabase(OldIrql);
    00326     return Previous;
    00327 }