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

thredini.c File Reference

#include "ki.h"

Go to the source code of this file.

Defines

#define ASSERT_PROCESS(E)
#define ASSERT_THREAD(E)
#define ALIGN_DOWN(address, amt)   ((ULONG)(address) & ~(( amt ) - 1))
#define ALIGN_UP(address, amt)   (ALIGN_DOWN( (address + (amt) - 1), (amt) ))

Functions

VOID KepSetAlignmentSpecialApc (IN PKAPC Apc, IN PKNORMAL_ROUTINE *NormalRoutine, IN PVOID *NormalContext, IN PVOID *SystemArgument1, IN PVOID *SystemArgument2)
VOID KiInitializeContextThread (IN PKTHREAD Thread, IN PKSYSTEM_ROUTINE SystemRoutine, IN PKSTART_ROUTINE StartRoutine OPTIONAL, IN PVOID StartContext OPTIONAL, IN PCONTEXT ContextFrame OPTIONAL)
BOOLEAN KeSetAutoAlignmentProcess (IN PKPROCESS Process, IN BOOLEAN Enable)
BOOLEAN KeSetAutoAlignmentThread (IN PKTHREAD Thread, IN BOOLEAN Enable)

Variables

BOOLEAN KeI386XMMIPresent


Define Documentation

#define ALIGN_DOWN address,
amt   )     ((ULONG)(address) & ~(( amt ) - 1))
 

Definition at line 50 of file i386/thredini.c.

#define ALIGN_UP address,
amt   )     (ALIGN_DOWN( (address + (amt) - 1), (amt) ))
 

Definition at line 51 of file i386/thredini.c.

#define ASSERT_PROCESS  ) 
 

Value:

{ \ ASSERT((E)->Header.Type == ProcessObject); \ }

Definition at line 37 of file i386/thredini.c.

#define ASSERT_THREAD  ) 
 

Value:

{ \ ASSERT((E)->Header.Type == ThreadObject); \ }

Definition at line 41 of file i386/thredini.c.


Function Documentation

VOID KepSetAlignmentSpecialApc IN PKAPC  Apc,
IN PKNORMAL_ROUTINE NormalRoutine,
IN PVOID *  NormalContext,
IN PVOID *  SystemArgument1,
IN PVOID *  SystemArgument2
 

Referenced by KeSetAutoAlignmentThread().

BOOLEAN KeSetAutoAlignmentProcess IN PKPROCESS  Process,
IN BOOLEAN  Enable
 

Definition at line 393 of file i386/thredini.c.

References ASSERT_PROCESS, KiLockDispatcherDatabase, and KiUnlockDispatcherDatabase().

00400 : 00401 00402 This function sets the data alignment handling mode for the specified 00403 process and returns the previous data alignment handling mode. 00404 00405 Arguments: 00406 00407 Process - Supplies a pointer to a dispatcher object of type process. 00408 00409 Enable - Supplies a boolean value that determines the handling of data 00410 alignment exceptions for the process. A value of TRUE causes all 00411 data alignment exceptions to be automatically handled by the kernel. 00412 A value of FALSE causes all data alignment exceptions to be actually 00413 raised as exceptions. 00414 00415 Return Value: 00416 00417 A value of TRUE is returned if data alignment exceptions were 00418 previously automatically handled by the kernel. Otherwise, a value 00419 of FALSE is returned. 00420 00421 --*/ 00422 00423 { 00424 00425 KIRQL OldIrql; 00426 BOOLEAN Previous; 00427 00428 ASSERT_PROCESS(Process); 00429 00430 // 00431 // Raise IRQL to dispatcher level and lock dispatcher database. 00432 // 00433 00434 KiLockDispatcherDatabase(&OldIrql); 00435 00436 // 00437 // Capture the previous data alignment handling mode and set the 00438 // specified data alignment mode. 00439 // 00440 00441 Previous = Process->AutoAlignment; 00442 Process->AutoAlignment = Enable; 00443 00444 // 00445 // Unlock dispatcher database, lower IRQL to its previous value, and 00446 // return the previous data alignment mode. 00447 // 00448 00449 KiUnlockDispatcherDatabase(OldIrql); 00450 return Previous; 00451 }

BOOLEAN KeSetAutoAlignmentThread IN PKTHREAD  Thread,
IN BOOLEAN  Enable
 

Definition at line 454 of file i386/thredini.c.

References APC_LEVEL, ASSERT_THREAD, CurrentApcEnvironment, DbgPrint, Event(), ExAllocatePool, Executive, ExFreePool(), FALSE, KeGetCurrentThread, KeInitializeApc(), KeInitializeEvent, KeInsertQueueApc(), KeLowerIrql(), KepSetAlignmentSpecialApc(), KeRaiseIrql(), KernelMode, KeWaitForSingleObject(), KiLockDispatcherDatabase, KiUnlockDispatcherDatabase(), NonPagedPoolMustSucceed, NULL, _KAPC::SystemArgument1, and _KAPC::SystemArgument2.

00461 : 00462 00463 This function sets the data alignment handling mode for the specified 00464 thread and returns the previous data alignment handling mode. 00465 00466 Arguments: 00467 00468 Thread - Supplies a pointer to a dispatcher object of type thread. 00469 00470 Enable - Supplies a boolean value that determines the handling of data 00471 alignment exceptions for the specified thread. A value of TRUE causes 00472 all data alignment exceptions to be automatically handled by the kernel. 00473 A value of FALSE causes all data alignment exceptions to be actually 00474 raised as exceptions. 00475 00476 Return Value: 00477 00478 A value of TRUE is returned if data alignment exceptions were 00479 previously automatically handled by the kernel. Otherwise, a value 00480 of FALSE is returned. 00481 00482 --*/ 00483 00484 { 00485 00486 BOOLEAN Previous; 00487 PKAPC Apc; 00488 PKEVENT Event; 00489 KIRQL OldIrql; 00490 00491 ASSERT_THREAD(Thread); 00492 00493 // 00494 // Raise IRQL to dispatcher level and lock dispatcher database. 00495 // 00496 00497 KiLockDispatcherDatabase(&OldIrql); 00498 00499 // 00500 // Capture the previous data alignment handling mode and set the 00501 // specified data alignment mode. 00502 // 00503 00504 Previous = Thread->AutoAlignment; 00505 Thread->AutoAlignment = Enable; 00506 00507 // 00508 // Unlock dispatcher database and lower IRQL to its previous value. 00509 // 00510 00511 KiUnlockDispatcherDatabase(OldIrql); 00512 00513 #if 0 00514 Apc = ExAllocatePool(NonPagedPoolMustSucceed, sizeof(KAPC)); 00515 Event = ExAllocatePool(NonPagedPoolMustSucceed, sizeof(KEVENT)); 00516 00517 KeInitializeEvent(Event, NotificationEvent, FALSE); 00518 00519 if ( Thread == KeGetCurrentThread() ) { 00520 00521 Apc->SystemArgument1 = Thread; 00522 Apc->SystemArgument2 = Event; 00523 00524 KeRaiseIrql(APC_LEVEL, &Irql); 00525 KepSetAlignmentSpecialApc( Apc, NULL, NULL, 00526 &Apc->SystemArgument1, 00527 &Apc->SystemArgument2 ); 00528 KeLowerIrql(Irql); 00529 } else { 00530 KeInitializeApc( Apc, 00531 Thread, 00532 CurrentApcEnvironment, 00533 KepSetAlignmentSpecialApc, 00534 NULL, 00535 NULL, 00536 KernelMode, 00537 NULL ); 00538 00539 if (!KeInsertQueueApc( Apc, 00540 Thread, 00541 Event, 00542 2 ) ) { 00543 // 00544 // We couldn't queue the APC, so we will not be able to change 00545 // the AutoAlignment. Update the thread object so that it 00546 // stays in sync with the hardware state. 00547 // 00548 #if DBG 00549 DbgPrint("KeSetAutoAlignmentThread: unable to change thread's context\n"); 00550 #endif 00551 Thread->AutoAlignment = Previous; 00552 } 00553 00554 KeWaitForSingleObject( Event, 00555 Executive, 00556 KernelMode, 00557 FALSE, 00558 NULL ); 00559 } 00560 00561 ExFreePool(Apc); 00562 ExFreePool(Event); 00563 #endif 00564 00565 return(Previous); 00566 }

VOID KiInitializeContextThread IN PKTHREAD  Thread,
IN PKSYSTEM_ROUTINE  SystemRoutine,
IN PKSTART_ROUTINE StartRoutine  OPTIONAL,
IN PVOID StartContext  OPTIONAL,
IN PCONTEXT ContextFrame  OPTIONAL
 

Definition at line 71 of file i386/thredini.c.

00081 : 00082 00083 This function initializes the machine dependent context of a thread object. 00084 00085 N.B. This function does not check the accessibility of the context record. 00086 It is assumed the the caller of this routine is either prepared to 00087 handle access violations or has probed and copied the context record 00088 as appropriate. 00089 00090 Arguments: 00091 00092 Thread - Supplies a pointer to a dispatcher object of type thread. 00093 00094 SystemRoutine - Supplies a pointer to the system function that is to be 00095 called when the thread is first scheduled for execution. 00096 00097 StartRoutine - Supplies an optional pointer to a function that is to be 00098 called after the system has finished initializing the thread. This 00099 parameter is specified if the thread is a system thread and will 00100 execute totally in kernel mode. 00101 00102 StartContext - Supplies an optional pointer to an arbitrary data structure 00103 which will be passed to the StartRoutine as a parameter. This 00104 parameter is specified if the thread is a system thread and will 00105 execute totally in kernel mode. 00106 00107 ContextFrame - Supplies an optional pointer a context frame which contains 00108 the initial user mode state of the thread. This parameter is specified 00109 if the thread is a user thread and will execute in user mode. If this 00110 parameter is not specified, then the Teb parameter is ignored. 00111 00112 Return Value: 00113 00114 None. 00115 00116 --*/ 00117 00118 { 00119 PFX_SAVE_AREA NpxFrame; 00120 PKSWITCHFRAME SwitchFrame; 00121 PKTRAP_FRAME TrFrame; 00122 PULONG PSystemRoutine; 00123 PULONG PStartRoutine; 00124 PULONG PStartContext; 00125 PULONG PUserContextFlag; 00126 ULONG ContextFlags; 00127 CONTEXT Context2; 00128 PCONTEXT ContextFrame2 = NULL; 00129 PFXSAVE_FORMAT PFxSaveArea; 00130 00131 // 00132 // If a context frame is specified, then initialize a trap frame and 00133 // and an exception frame with the specified user mode context. 00134 // 00135 00136 if (ARGUMENT_PRESENT(ContextFrame)) { 00137 00138 RtlMoveMemory(&Context2, ContextFrame, sizeof(CONTEXT)); 00139 ContextFrame2 = &Context2; 00140 ContextFlags = CONTEXT_CONTROL; 00141 00142 // 00143 // The 80387 save area is at the very base of the kernel stack. 00144 // 00145 00146 NpxFrame = (PFX_SAVE_AREA)(((ULONG)(Thread->InitialStack) - 00147 sizeof(FX_SAVE_AREA))); 00148 00149 // 00150 // Load up an initial NPX state. 00151 // 00152 00153 if (KeI386XMMIPresent == TRUE) { 00154 PFxSaveArea = (PFXSAVE_FORMAT)ContextFrame2->ExtendedRegisters; 00155 00156 PFxSaveArea->ControlWord = 0x27f; // like fpinit but 64bit mode 00157 PFxSaveArea->StatusWord = 0; 00158 PFxSaveArea->TagWord = 0; 00159 PFxSaveArea->ErrorOffset = 0; 00160 PFxSaveArea->ErrorSelector = 0; 00161 PFxSaveArea->DataOffset = 0; 00162 PFxSaveArea->DataSelector = 0; 00163 PFxSaveArea->MXCsr = 0x1f80; // mask all the exceptions 00164 } else { 00165 ContextFrame2->FloatSave.ControlWord = 0x27f; // like fpinit but 64bit mode 00166 ContextFrame2->FloatSave.StatusWord = 0; 00167 ContextFrame2->FloatSave.TagWord = 0xffff; 00168 ContextFrame2->FloatSave.ErrorOffset = 0; 00169 ContextFrame2->FloatSave.ErrorSelector = 0; 00170 ContextFrame2->FloatSave.DataOffset = 0; 00171 ContextFrame2->FloatSave.DataSelector = 0; 00172 } 00173 00174 00175 if (KeI386NpxPresent) { 00176 ContextFrame2->FloatSave.Cr0NpxState = 0; 00177 NpxFrame->Cr0NpxState = 0; 00178 NpxFrame->NpxSavedCpu = 0; 00179 if (KeI386XMMIPresent == TRUE) { 00180 ContextFlags |= CONTEXT_EXTENDED_REGISTERS; 00181 } else { 00182 ContextFlags |= CONTEXT_FLOATING_POINT; 00183 } 00184 00185 // 00186 // Threads NPX state is not in the coprocessor. 00187 // 00188 00189 Thread->NpxState = NPX_STATE_NOT_LOADED; 00190 Thread->NpxIrql = PASSIVE_LEVEL; 00191 00192 } else { 00193 NpxFrame->Cr0NpxState = CR0_EM; 00194 00195 // 00196 // Threads NPX state is not in the coprocessor. 00197 // In the emulator case, do not set the CR0_EM bit as their 00198 // emulators may not want exceptions on FWAIT instructions. 00199 // 00200 00201 Thread->NpxState = NPX_STATE_NOT_LOADED & ~CR0_MP; 00202 } 00203 00204 // 00205 // Force debug registers off. They won't work anyway from an 00206 // initial frame, debuggers must set a hard breakpoint in the target 00207 // 00208 00209 ContextFrame2->Dr0 = 0; 00210 ContextFrame2->Dr1 = 0; 00211 ContextFrame2->Dr2 = 0; 00212 ContextFrame2->Dr3 = 0; 00213 ContextFrame2->Dr6 = 0; 00214 ContextFrame2->Dr7 = 0; 00215 ContextFrame2->ContextFlags &= ~(CONTEXT_DEBUG_REGISTERS); 00216 #if 0 00217 // 00218 // If AutoAlignment is FALSE, we want to set the Alignment Check bit 00219 // in Eflags, so we will get alignment faults. 00220 // 00221 00222 if (Thread->AutoAlignment == FALSE) { 00223 ContextFrame2->EFlags |= EFLAGS_ALIGN_CHECK; 00224 } 00225 #endif 00226 // 00227 // If the thread is set 00228 00229 TrFrame = (PKTRAP_FRAME)(((ULONG)NpxFrame - KTRAP_FRAME_LENGTH)); 00230 00231 // Space for arguments to KiThreadStartup. Order is important, 00232 // Since args are passed on stack through KiThreadStartup to 00233 // PStartRoutine with PStartContext as an argument. 00234 00235 PUserContextFlag = (PULONG)TrFrame - 1; 00236 PStartContext = PUserContextFlag - 1; 00237 PStartRoutine = PStartContext - 1; 00238 PSystemRoutine = PStartRoutine - 1; 00239 00240 SwitchFrame = (PKSWITCHFRAME)((PUCHAR)PSystemRoutine - 00241 sizeof(KSWITCHFRAME)); 00242 00243 // 00244 // Copy information from the specified context frame to the trap and 00245 // exception frames. 00246 // 00247 00248 KeContextToKframes(TrFrame, NULL, ContextFrame2, 00249 ContextFrame2->ContextFlags | ContextFlags, 00250 UserMode); 00251 00252 TrFrame->HardwareSegSs |= RPL_MASK; 00253 TrFrame->SegDs |= RPL_MASK; 00254 TrFrame->SegEs |= RPL_MASK; 00255 00256 #if DBG 00257 TrFrame->DbgArgMark = 0xBADB0D00; 00258 #endif 00259 00260 // 00261 // Tell KiThreadStartup that a user context is present. 00262 // 00263 00264 *PUserContextFlag = 1; 00265 00266 00267 // 00268 // Initialize the kernel mode ExceptionList pointer 00269 // 00270 00271 TrFrame->ExceptionList = EXCEPTION_CHAIN_END; 00272 00273 // 00274 // Initialize the saved previous processor mode. 00275 // 00276 00277 TrFrame->PreviousPreviousMode = UserMode; 00278 00279 // 00280 // Set the previous mode in thread object to user. 00281 // 00282 00283 Thread->PreviousMode = UserMode; 00284 00285 00286 } else { 00287 00288 // 00289 // Dummy floating save area. Kernel threads don't have or use 00290 // the floating point - the dummy save area is make the stacks 00291 // consistent. 00292 // 00293 00294 NpxFrame = (PFX_SAVE_AREA)(((ULONG)(Thread->InitialStack) - 00295 sizeof(FX_SAVE_AREA))); 00296 00297 // 00298 // Load up an initial NPX state. 00299 // 00300 RtlZeroMemory((PVOID)NpxFrame, sizeof(FX_SAVE_AREA)); 00301 00302 if (KeI386FxsrPresent == TRUE) { 00303 NpxFrame->U.FxArea.ControlWord = 0x27f;//like fpinit but 64bit mode 00304 NpxFrame->U.FxArea.MXCsr = 0x1f80;// mask all the exceptions 00305 } else { 00306 NpxFrame->U.FnArea.ControlWord = 0x27f;//like fpinit but 64bit mode 00307 NpxFrame->U.FnArea.TagWord = 0xffff; 00308 } 00309 00310 // 00311 // Threads NPX state is not in the coprocessor. 00312 // 00313 00314 Thread->NpxState = NPX_STATE_NOT_LOADED; 00315 00316 // 00317 // Space for arguments to KiThreadStartup. 00318 // Order of fields in the switchframe is important, 00319 // Since args are passed on stack through KiThreadStartup to 00320 // PStartRoutine with PStartContext as an argument. 00321 // 00322 00323 PUserContextFlag = (PULONG)((ULONG)NpxFrame) - 1; 00324 00325 PStartContext = PUserContextFlag - 1; 00326 PStartRoutine = PStartContext - 1; 00327 PSystemRoutine = PStartRoutine - 1; 00328 00329 SwitchFrame = (PKSWITCHFRAME)((PUCHAR)PSystemRoutine - 00330 sizeof(KSWITCHFRAME)); 00331 00332 00333 // 00334 // Tell KiThreadStartup that a user context is NOT present. 00335 // 00336 00337 *PUserContextFlag = 0; 00338 00339 00340 // 00341 // Set the previous mode in thread object to kernel. 00342 // 00343 00344 Thread->PreviousMode = KernelMode; 00345 } 00346 00347 // 00348 // Set up thread start parameters. 00349 // (UserContextFlag set above) 00350 // 00351 00352 *PStartContext = (ULONG)StartContext; 00353 *PStartRoutine = (ULONG)StartRoutine; 00354 *PSystemRoutine = (ULONG)SystemRoutine; 00355 00356 00357 // 00358 // Set up switch frame. Assume the thread doesn't use the 80387; 00359 // if it ever does (and there is one), these flags will get reset. 00360 // Each thread starts with these same flags set, regardless of 00361 // whether the hardware exists or not. 00362 // 00363 00364 SwitchFrame->RetAddr = (ULONG)KiThreadStartup; 00365 00366 SwitchFrame->Eflags = EFLAGS_INTERRUPT_MASK; 00367 00368 #if 0 00369 // 00370 // If AutoAlignment is FALSE, we want to set the Alignment Check bit 00371 // in Eflags, so we will get alignment faults. 00372 // 00373 00374 if (Thread->AutoAlignment == FALSE) { 00375 SwitchFrame->Eflags |= EFLAGS_ALIGN_CHECK; 00376 } 00377 #endif 00378 00379 SwitchFrame->ExceptionList = (ULONG)(EXCEPTION_CHAIN_END); 00380 00381 // 00382 // Set the initial kernel stack pointer. 00383 // 00384 00385 //DbgPrint("KiInitializeContextThread Thread %08x SwitchFrame %08x\n", Thread, SwitchFrame); 00386 //DbgPrint("PSystemRoutine %08x PStartRoutine %08x PStartContext %08x\n", *PSystemRoutine, *PStartRoutine, *PStartContext); 00387 00388 Thread->KernelStack = (PVOID)SwitchFrame; 00389 return; 00390 }


Variable Documentation

BOOLEAN KeI386XMMIPresent
 

Definition at line 67 of file i386/thredini.c.


Generated on Sat May 15 19:45:45 2004 for test by doxygen 1.3.7