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 --*/ 00025 00026 #include "ki.h" 00027 00028 // 00029 // The following assert macros are used to check that an input object is 00030 // really the proper type. 00031 // 00032 00033 #define ASSERT_PROCESS(E) { \ 00034 ASSERT((E)->Header.Type == ProcessObject); \ 00035 } 00036 00037 #define ASSERT_THREAD(E) { \ 00038 ASSERT((E)->Header.Type == ThreadObject); \ 00039 } 00040 00041 VOID 00042 KiInitializeContextThread ( 00043 IN PKTHREAD Thread, 00044 IN PKSYSTEM_ROUTINE SystemRoutine, 00045 IN PKSTART_ROUTINE StartRoutine OPTIONAL, 00046 IN PVOID StartContext OPTIONAL, 00047 IN PCONTEXT ContextRecord OPTIONAL 00048 ) 00049 00050 /*++ 00051 00052 Routine Description: 00053 00054 This function initializes the machine dependent context of a thread object. 00055 00056 N.B. This function does not check the accessibility of the context record. 00057 It is assumed the the caller of this routine is either prepared to 00058 handle access violations or has probed and copied the context record 00059 as appropriate. 00060 00061 Arguments: 00062 00063 Thread - Supplies a pointer to a dispatcher object of type thread. 00064 00065 SystemRoutine - Supplies a pointer to the system function that is to be 00066 called when the thread is first scheduled for execution. 00067 00068 StartRoutine - Supplies an optional pointer to a function that is to be 00069 called after the system has finished initializing the thread. This 00070 parameter is specified if the thread is a system thread and will 00071 execute totally in kernel mode. 00072 00073 StartContext - Supplies an optional pointer to an arbitrary data structure 00074 which will be passed to the StartRoutine as a parameter. This 00075 parameter is specified if the thread is a system thread and will 00076 execute totally in kernel mode. 00077 00078 ContextRecord - Supplies an optional pointer a context frame which contains 00079 the initial user mode state of the thread. This parameter is specified 00080 if the thread is a user thread and will execute in user mode. If this 00081 parameter is not specified, then the Teb parameter is ignored. 00082 00083 Return Value: 00084 00085 None. 00086 00087 --*/ 00088 00089 { 00090 00091 PKEXCEPTION_FRAME CxFrame; 00092 PKEXCEPTION_FRAME ExFrame; 00093 ULONG InitialStack; 00094 PKTRAP_FRAME TrFrame; 00095 00096 // 00097 // If a context frame is specified, then initialize a trap frame and 00098 // and an exception frame with the specified user mode context. 00099 // 00100 00101 InitialStack = (LONG)Thread->InitialStack; 00102 if (ARGUMENT_PRESENT(ContextRecord)) { 00103 TrFrame = (PKTRAP_FRAME)(InitialStack - sizeof(KTRAP_FRAME)); 00104 ExFrame = (PKEXCEPTION_FRAME)((ULONG)TrFrame - sizeof(KEXCEPTION_FRAME)); 00105 CxFrame = (PKEXCEPTION_FRAME)((ULONG)ExFrame - sizeof(KEXCEPTION_FRAME)); 00106 00107 // 00108 // Zero the exception and trap frames and copy information from the 00109 // specified context frame to the trap and exception frames. 00110 // 00111 00112 RtlZeroMemory((PVOID)ExFrame, sizeof(KEXCEPTION_FRAME)); 00113 RtlZeroMemory((PVOID)TrFrame, sizeof(KTRAP_FRAME)); 00114 KeContextToKframes(TrFrame, 00115 ExFrame, 00116 ContextRecord, 00117 ContextRecord->ContextFlags | CONTEXT_CONTROL, 00118 UserMode); 00119 00120 // 00121 // Set the saved previous processor mode in the trap frame and the 00122 // previous processor mode in the thread object to user mode. 00123 // 00124 00125 TrFrame->PreviousMode = UserMode; 00126 Thread->PreviousMode = UserMode; 00127 00128 // 00129 // Initialize the return address in the exception frame. 00130 // 00131 00132 ExFrame->IntRa = 0; 00133 00134 } else { 00135 ExFrame = NULL; 00136 CxFrame = (PKEXCEPTION_FRAME)(InitialStack - sizeof(KEXCEPTION_FRAME)); 00137 00138 // 00139 // Set the previous mode in thread object to kernel. 00140 // 00141 00142 Thread->PreviousMode = KernelMode; 00143 } 00144 00145 // 00146 // Initialize context switch frame and set thread start up parameters. 00147 // 00148 00149 CxFrame->SwapReturn = (ULONG)KiThreadStartup; 00150 if (ExFrame == NULL) { 00151 CxFrame->IntS8 = (ULONG)ExFrame; 00152 00153 } else { 00154 CxFrame->IntS8 = (ULONG)TrFrame; 00155 } 00156 00157 CxFrame->IntS0 = (ULONG)ContextRecord; 00158 CxFrame->IntS1 = (ULONG)StartContext; 00159 CxFrame->IntS2 = (ULONG)StartRoutine; 00160 CxFrame->IntS3 = (ULONG)SystemRoutine; 00161 Thread->KernelStack = (PVOID)CxFrame; 00162 return; 00163 } 00164 00165 BOOLEAN 00166 KeSetAutoAlignmentProcess ( 00167 IN PRKPROCESS Process, 00168 IN BOOLEAN Enable 00169 ) 00170 00171 /*++ 00172 00173 Routine Description: 00174 00175 This function sets the data alignment handling mode for the specified 00176 process and returns the previous data alignment handling mode. 00177 00178 Arguments: 00179 00180 Process - Supplies a pointer to a dispatcher object of type process. 00181 00182 Enable - Supplies a boolean value that determines the handling of data 00183 alignment exceptions for the process. A value of TRUE causes all 00184 data alignment exceptions to be automatically handled by the kernel. 00185 A value of FALSE causes all data alignment exceptions to be actually 00186 raised as exceptions. 00187 00188 Return Value: 00189 00190 A value of TRUE is returned if data alignment exceptions were 00191 previously automatically handled by the kernel. Otherwise, a value 00192 of FALSE is returned. 00193 00194 --*/ 00195 00196 { 00197 00198 KIRQL OldIrql; 00199 BOOLEAN Previous; 00200 00201 ASSERT_PROCESS(Process); 00202 00203 // 00204 // Raise IRQL to dispatcher level and lock dispatcher database. 00205 // 00206 00207 KiLockDispatcherDatabase(&OldIrql); 00208 00209 // 00210 // Capture the previous data alignment handling mode and set the 00211 // specified data alignment mode. 00212 // 00213 00214 Previous = Process->AutoAlignment; 00215 Process->AutoAlignment = Enable; 00216 00217 // 00218 // Unlock dispatcher database, lower IRQL to its previous value, and 00219 // return the previous data alignment mode. 00220 // 00221 00222 KiUnlockDispatcherDatabase(OldIrql); 00223 return Previous; 00224 } 00225 00226 BOOLEAN 00227 KeSetAutoAlignmentThread ( 00228 IN PKTHREAD Thread, 00229 IN BOOLEAN Enable 00230 ) 00231 00232 /*++ 00233 00234 Routine Description: 00235 00236 This function sets the data alignment handling mode for the specified 00237 thread and returns the previous data alignment handling mode. 00238 00239 Arguments: 00240 00241 Thread - Supplies a pointer to a dispatcher object of type thread. 00242 00243 Enable - Supplies a boolean value that determines the handling of data 00244 alignment exceptions for the thread. A value of TRUE causes all 00245 data alignment exceptions to be automatically handled by the kernel. 00246 A value of FALSE causes all data alignment exceptions to be actually 00247 raised as exceptions. 00248 00249 Return Value: 00250 00251 A value of TRUE is returned if data alignment exceptions were 00252 previously automatically handled by the kernel. Otherwise, a value 00253 of FALSE is returned. 00254 00255 --*/ 00256 00257 { 00258 00259 KIRQL OldIrql; 00260 BOOLEAN Previous; 00261 00262 ASSERT_THREAD(Thread); 00263 00264 // 00265 // Raise IRQL to dispatcher level and lock dispatcher database. 00266 // 00267 00268 KiLockDispatcherDatabase(&OldIrql); 00269 00270 // 00271 // Capture the previous data alignment handling mode and set the 00272 // specified data alignment mode. 00273 // 00274 00275 Previous = Thread->AutoAlignment; 00276 Thread->AutoAlignment = Enable; 00277 00278 // 00279 // Unlock dispatcher database, lower IRQL to its previous value, and 00280 // return the previous data alignment mode. 00281 // 00282 00283 KiUnlockDispatcherDatabase(OldIrql); 00284 return Previous; 00285 }