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

initkr.c

Go to the documentation of this file.
00001 /*++ 00002 00003 Copyright (c) 1990 Microsoft Corporation 00004 00005 Module Name: 00006 00007 initkr.c 00008 00009 Abstract: 00010 00011 This module contains the code to initialize the kernel data structures 00012 and to initialize the idle thread, its process, and the processor control 00013 block. 00014 00015 Author: 00016 00017 David N. Cutler (davec) 11-Apr-1990 00018 00019 Environment: 00020 00021 Kernel mode only. 00022 00023 Revision History: 00024 00025 Joe Notarangelo 21-April-1992 00026 very minor changes for ALPHA 00027 - system time to 64bit integer 00028 - some data moved out of pcr 00029 --*/ 00030 00031 #include "ki.h" 00032 00033 // 00034 // External data. 00035 // 00036 00037 extern KSPIN_LOCK CcMasterSpinLock; 00038 extern KSPIN_LOCK CcVacbSpinLock; 00039 extern KSPIN_LOCK MmPfnLock; 00040 extern KSPIN_LOCK MmSystemSpaceLock; 00041 00042 // 00043 // Define forward referenced prototypes. 00044 // 00045 00046 ULONG 00047 KiGetFeatureBits ( 00048 VOID 00049 ); 00050 00051 __inline 00052 ULONG 00053 amask( 00054 IN ULONG Feature 00055 ) 00056 00057 { 00058 return(__asm("amask %0, v0",Feature)); 00059 } 00060 #ifdef ALLOC_PRAGMA 00061 #pragma alloc_text(INIT, KiInitializeKernel) 00062 #endif 00063 00064 VOID 00065 KiInitializeKernel ( 00066 IN PKPROCESS Process, 00067 IN PKTHREAD Thread, 00068 IN PVOID IdleStack, 00069 IN PKPRCB Prcb, 00070 IN CCHAR Number, 00071 IN PLOADER_PARAMETER_BLOCK LoaderBlock 00072 ) 00073 00074 /*++ 00075 00076 Routine Description: 00077 00078 This function gains control after the system has been bootstrapped and 00079 before the system has been initialized. Its function is to initialize 00080 the kernel data structures, initialize the idle thread and process objects, 00081 initialize the processor control block, call the executive initialization 00082 routine, and then return to the system startup routine. This routine is 00083 also called to initialize the processor specific structures when a new 00084 processor is brought on line. 00085 00086 Arguments: 00087 00088 Process - Supplies a pointer to a control object of type process for 00089 the specified processor. 00090 00091 Thread - Supplies a pointer to a dispatcher object of type thread for 00092 the specified processor. 00093 00094 IdleStack - Supplies a pointer the base of the real kernel stack for 00095 idle thread on the specified processor. 00096 00097 Prcb - Supplies a pointer to a processor control block for the specified 00098 processor. 00099 00100 Number - Supplies the number of the processor that is being 00101 initialized. 00102 00103 LoaderBlock - Supplies a pointer to the loader parameter block. 00104 00105 Return Value: 00106 00107 None. 00108 00109 --*/ 00110 00111 { 00112 00113 UCHAR DataByte; 00114 ULONG DataLong; 00115 LONG Index; 00116 KIRQL OldIrql; 00117 PKPCR Pcr = PCR; 00118 struct _RESTART_BLOCK *RestartBlock; 00119 00120 // 00121 // Save the address of the loader parameter block. 00122 // 00123 00124 KeLoaderBlock = LoaderBlock; 00125 00126 // 00127 // Set the appropriate member in the active processors set. 00128 // 00129 00130 SetMember(Number, KeActiveProcessors); 00131 00132 // 00133 // Set the number of processors based on the maximum of the current 00134 // number of processors and the current processor number. 00135 // 00136 00137 if ((Number + 1) > KeNumberProcessors) { 00138 KeNumberProcessors = Number + 1; 00139 } 00140 00141 // 00142 // Set the maximum address space number to the minimum of all maximum 00143 // address space numbers passed via the loader block. 00144 // 00145 00146 if (Number == 0) { 00147 KiMaximumAsn = LoaderBlock->u.Alpha.MaximumAddressSpaceNumber; 00148 00149 } else if (KiMaximumAsn > LoaderBlock->u.Alpha.MaximumAddressSpaceNumber) { 00150 KiMaximumAsn = LoaderBlock->u.Alpha.MaximumAddressSpaceNumber; 00151 } 00152 00153 // 00154 // Initialize the passive release, APC, and DPC interrupt vectors. 00155 // 00156 00157 Pcr->InterruptRoutine[0] = KiPassiveRelease; 00158 Pcr->InterruptRoutine[APC_LEVEL] = KiApcInterrupt; 00159 Pcr->InterruptRoutine[DISPATCH_LEVEL] = KiDispatchInterrupt; 00160 Pcr->ReservedVectors = 00161 (1 << PASSIVE_LEVEL) | (1 << APC_LEVEL) | (1 << DISPATCH_LEVEL); 00162 00163 // 00164 // Initialize the processor id fields in the PCR. 00165 // 00166 00167 Pcr->Number = Number; 00168 Pcr->SetMember = 1 << Number; 00169 Pcr->NotMember = ~Pcr->SetMember; 00170 00171 // 00172 // Initialize the processor block. 00173 // 00174 00175 Prcb->MinorVersion = PRCB_MINOR_VERSION; 00176 Prcb->MajorVersion = PRCB_MAJOR_VERSION; 00177 Prcb->BuildType = 0; 00178 00179 #if DBG 00180 00181 Prcb->BuildType |= PRCB_BUILD_DEBUG; 00182 00183 #endif 00184 00185 #ifdef NT_UP 00186 00187 Prcb->BuildType |= PRCB_BUILD_UNIPROCESSOR; 00188 00189 #endif 00190 00191 Prcb->CurrentThread = Thread; 00192 Prcb->NextThread = (PKTHREAD)NULL; 00193 Prcb->IdleThread = Thread; 00194 Prcb->Number = Number; 00195 Prcb->SetMember = 1 << Number; 00196 00197 KeInitializeDpc(&Prcb->QuantumEndDpc, 00198 (PKDEFERRED_ROUTINE)KiQuantumEnd, 00199 NIL); 00200 00201 // 00202 // initialize the per processor lock queue entry for implemented locks. 00203 // 00204 00205 #if !defined(NT_UP) 00206 00207 Prcb->LockQueue[LockQueueDispatcherLock].Next = NULL; 00208 Prcb->LockQueue[LockQueueDispatcherLock].Lock = &KiDispatcherLock; 00209 Prcb->LockQueue[LockQueueContextSwapLock].Next = NULL; 00210 Prcb->LockQueue[LockQueueContextSwapLock].Lock = &KiContextSwapLock; 00211 Prcb->LockQueue[LockQueuePfnLock].Next = NULL; 00212 Prcb->LockQueue[LockQueuePfnLock].Lock = &MmPfnLock; 00213 Prcb->LockQueue[LockQueueSystemSpaceLock].Next = NULL; 00214 Prcb->LockQueue[LockQueueSystemSpaceLock].Lock = &MmSystemSpaceLock; 00215 Prcb->LockQueue[LockQueueMasterLock].Next = NULL; 00216 Prcb->LockQueue[LockQueueMasterLock].Lock = &CcMasterSpinLock; 00217 Prcb->LockQueue[LockQueueVacbLock].Next = NULL; 00218 Prcb->LockQueue[LockQueueVacbLock].Lock = &CcVacbSpinLock; 00219 00220 #endif 00221 00222 // 00223 // Set address of PCR in PRCB. 00224 // 00225 00226 Prcb->Pcr = Pcr; 00227 00228 // 00229 // Initialize the interprocessor communication packet. 00230 // 00231 00232 #if !defined(NT_UP) 00233 00234 Prcb->TargetSet = 0; 00235 Prcb->WorkerRoutine = NULL; 00236 Prcb->RequestSummary = 0; 00237 Prcb->IpiFrozen = 0; 00238 00239 #if NT_INST 00240 00241 Prcb->IpiCounts = &KiIpiCounts[Number]; 00242 00243 #endif //NT_INST 00244 00245 #endif //NT_UP 00246 00247 Prcb->MaximumDpcQueueDepth = KiMaximumDpcQueueDepth; 00248 Prcb->MinimumDpcRate = KiMinimumDpcRate; 00249 Prcb->AdjustDpcThreshold = KiAdjustDpcThreshold; 00250 00251 // 00252 // Initialize DPC listhead and lock. 00253 // 00254 00255 InitializeListHead(&Prcb->DpcListHead); 00256 KeInitializeSpinLock(&Prcb->DpcLock); 00257 00258 // 00259 // Set address of processor block. 00260 // 00261 00262 KiProcessorBlock[Number] = Prcb; 00263 00264 // 00265 // Set address of process object in thread object. 00266 // 00267 00268 Thread->ApcState.Process = Process; 00269 00270 // 00271 // Set the appropriate member in the active processors set. 00272 // 00273 00274 SetMember( Number, KeActiveProcessors ); 00275 00276 // 00277 // Set the number of processors based on the maximum of the current 00278 // number of processors and the current processor number. 00279 // 00280 00281 if( (Number+1) > KeNumberProcessors ){ 00282 KeNumberProcessors = Number + 1; 00283 } 00284 00285 // 00286 // Initialize processors PowerState 00287 // 00288 00289 PoInitializePrcb (Prcb); 00290 00291 // 00292 // Set global processor architecture, level and revision. The 00293 // latter two are the least common denominator on an MP system. 00294 // 00295 00296 #ifdef _AXP64_ 00297 KeProcessorArchitecture = PROCESSOR_ARCHITECTURE_ALPHA64; 00298 #else 00299 KeProcessorArchitecture = PROCESSOR_ARCHITECTURE_ALPHA; 00300 #endif 00301 00302 if ((KeProcessorLevel == 0) || 00303 (KeProcessorLevel > (USHORT)Pcr->ProcessorType)) { 00304 KeProcessorLevel = (USHORT)Pcr->ProcessorType; 00305 } 00306 00307 if ((KeProcessorRevision == 0) || 00308 (KeProcessorRevision > (USHORT)Pcr->ProcessorRevision)) { 00309 KeProcessorRevision = (USHORT)Pcr->ProcessorRevision; 00310 } 00311 00312 // 00313 // Initialize all interrupt vectors to transfer control to the unexpected 00314 // interrupt routine. 00315 // 00316 // N.B. This interrupt object is never actually "connected" to an interrupt 00317 // vector via KeConnectInterrupt. It is initialized and then connected 00318 // by simply storing the address of the dispatch code in the interrupt 00319 // vector. 00320 // 00321 00322 if (Number == 0) { 00323 00324 KeFeatureBits = KiGetFeatureBits(); 00325 00326 // 00327 // Initial the address of the interrupt dispatch routine. 00328 // 00329 00330 KxUnexpectedInterrupt.DispatchAddress = KiUnexpectedInterrupt; 00331 00332 // 00333 // Initialize the context swap spinlock. 00334 // 00335 00336 KeInitializeSpinLock(&KiContextSwapLock); 00337 00338 // 00339 // Copy the interrupt dispatch code template into the interrupt object 00340 // and flush the dcache on all processors that the current thread can 00341 // run on to ensure that the code is actually in memory. 00342 // 00343 00344 for (Index = 0; Index < DISPATCH_LENGTH; Index += 1) { 00345 KxUnexpectedInterrupt.DispatchCode[Index] = KiInterruptTemplate[Index]; 00346 } 00347 00348 // 00349 // Sweep the instruction cache on the current processor. 00350 // 00351 00352 KiImb(); 00353 00354 } else { 00355 00356 // 00357 // Mask off feature bits that are not supported on all processors. 00358 // 00359 00360 KeFeatureBits &= KiGetFeatureBits(); 00361 } 00362 00363 // 00364 // Update processor features 00365 // 00366 00367 SharedUserData->ProcessorFeatures[PF_ALPHA_BYTE_INSTRUCTIONS] = 00368 (KeFeatureBits & KF_BYTE) ? TRUE : FALSE; 00369 00370 for (Index = DISPATCH_LEVEL+1; Index < MAXIMUM_VECTOR; Index += 1) { 00371 Pcr->InterruptRoutine[Index] = (PKINTERRUPT_ROUTINE)(&KxUnexpectedInterrupt.DispatchCode); 00372 } 00373 00374 // 00375 // Raise IRQL to APC level. 00376 // 00377 00378 KeRaiseIrql(APC_LEVEL, &OldIrql); 00379 00380 // 00381 // If the initial processor is being initialized, then initialize the 00382 // per system data structures. 00383 // 00384 00385 if (Number == 0) { 00386 00387 // 00388 // Initialize the address of the restart block for the boot master. 00389 // 00390 00391 Prcb->RestartBlock = SYSTEM_BLOCK->RestartBlock; 00392 00393 // 00394 // Initialize the kernel debugger if enabled by the load options. 00395 // 00396 00397 if (KdInitSystem(LoaderBlock, FALSE) == FALSE) { 00398 KeBugCheck(PHASE0_INITIALIZATION_FAILED); 00399 } 00400 00401 #if DBG 00402 00403 // 00404 // Allow a breakin to the kernel debugger if one is pending. 00405 // 00406 00407 if (KdPollBreakIn() != FALSE){ 00408 DbgBreakPointWithStatus(DBG_STATUS_CONTROL_C); 00409 } 00410 00411 #endif //DBG 00412 00413 // 00414 // Initialize processor block array. 00415 // 00416 00417 for (Index = 1; Index < MAXIMUM_PROCESSORS; Index += 1) { 00418 KiProcessorBlock[Index] = (PKPRCB)NULL; 00419 } 00420 00421 // 00422 // Initialize default DMA coherency value for Alpha. 00423 // 00424 00425 KiDmaIoCoherency = DMA_READ_DCACHE_INVALIDATE | DMA_WRITE_DCACHE_SNOOP; 00426 00427 // 00428 // Perform architecture independent initialization. 00429 // 00430 00431 KiInitSystem(); 00432 00433 // 00434 // Initialize idle thread process object and then set: 00435 // 00436 // 1. all the quantum values to the maximum possible. 00437 // 2. the process in the balance set. 00438 // 3. the active processor mask to the specified processor. 00439 // 00440 00441 KeInitializeProcess(Process, 00442 (KPRIORITY)0, 00443 (KAFFINITY)(0xffffffff), 00444 (PULONG_PTR)PDE_SELFMAP, 00445 FALSE); 00446 00447 Process->ThreadQuantum = MAXCHAR; 00448 } 00449 00450 // 00451 // Initialize idle thread object and then set: 00452 // 00453 // 1. the initial kernel stack to the specified idle stack. 00454 // 2. the next processor number to the specified processor. 00455 // 3. the thread priority to the highest possible value. 00456 // 4. the state of the thread to running. 00457 // 5. the thread affinity to the specified processor. 00458 // 6. the specified processor member in the process active processors 00459 // set. 00460 // 00461 00462 KeInitializeThread(Thread, 00463 (PVOID)((ULONG_PTR)IdleStack - PAGE_SIZE), 00464 (PKSYSTEM_ROUTINE)NULL, 00465 (PKSTART_ROUTINE)NULL, 00466 (PVOID)NULL, 00467 (PCONTEXT)NULL, 00468 (PVOID)NULL, 00469 Process); 00470 00471 Thread->InitialStack = IdleStack; 00472 Thread->StackBase = IdleStack; 00473 Thread->StackLimit = (PVOID)((ULONG_PTR)IdleStack - KERNEL_STACK_SIZE); 00474 Thread->NextProcessor = Number; 00475 Thread->Priority = HIGH_PRIORITY; 00476 Thread->State = Running; 00477 Thread->Affinity = (KAFFINITY)(1 << Number); 00478 Thread->WaitIrql = DISPATCH_LEVEL; 00479 00480 // 00481 // If the current processor is the boot master then set the appropriate 00482 // bit in the active summary of the idle process. 00483 // 00484 00485 if (Number == 0) { 00486 SetMember(Number, Process->ActiveProcessors); 00487 } 00488 00489 // 00490 // call the executive initialization routine. 00491 // 00492 00493 try { 00494 ExpInitializeExecutive(Number, LoaderBlock); 00495 00496 } except(KeBugCheckEx(PHASE0_EXCEPTION, 00497 (ULONG)GetExceptionCode(), 00498 (ULONG_PTR)GetExceptionInformation(), 00499 0,0), EXCEPTION_EXECUTE_HANDLER) { 00500 ; // should never get here 00501 } 00502 00503 // 00504 // If the initial processor is being initialized, then compute the 00505 // timer table reciprocal value and reset the PRCB values for 00506 // the controllable DPC behavior in order to reflect any registry 00507 // overrides. 00508 // 00509 00510 if (Number == 0) { 00511 KiTimeIncrementReciprocal = KiComputeReciprocal((LONG)KeMaximumIncrement, 00512 &KiTimeIncrementShiftCount); 00513 00514 Prcb->MaximumDpcQueueDepth = KiMaximumDpcQueueDepth; 00515 Prcb->MinimumDpcRate = KiMinimumDpcRate; 00516 Prcb->AdjustDpcThreshold = KiAdjustDpcThreshold; 00517 } 00518 00519 // 00520 // Try to enable automatic PAL code fixups on this processor. 00521 // This must be done after the configuration values are read 00522 // out of the registry in ExpInitializeExecutive. 00523 // 00524 00525 KiDisableAlignmentExceptions(); 00526 00527 // 00528 // 00529 // Raise IRQL to dispatch level and set the priority of the idle thread 00530 // to zero. This will have the effect of immediately causing the phase 00531 // one initialization thread to get scheduled for execution. The idle 00532 // thread priority is then set to the lowest realtime priority. 00533 // 00534 00535 KeRaiseIrql(DISPATCH_LEVEL, &OldIrql); 00536 KeSetPriorityThread(Thread, (KPRIORITY)0); 00537 Thread->Priority = LOW_REALTIME_PRIORITY; 00538 00539 // 00540 // Raise IRQL to the highest level. 00541 // 00542 00543 KeRaiseIrql(HIGH_LEVEL, &OldIrql); 00544 00545 // 00546 // If a restart block exists for the current processor then set boot 00547 // completed. 00548 // 00549 00550 #if !defined(NT_UP) 00551 00552 RestartBlock = Prcb->RestartBlock; 00553 if (RestartBlock != NULL) { 00554 RestartBlock->BootStatus.BootFinished = 1; 00555 } 00556 00557 // 00558 // If the current processor is a secondary processor and a thread has 00559 // not been selected for execution, then set the appropriate bit in the 00560 // idle summary. 00561 // 00562 00563 if ((Number != 0) && (Prcb->NextThread == NULL)) { 00564 SetMember(Number, KiIdleSummary); 00565 } 00566 00567 #endif //NT_UP 00568 00569 return; 00570 } 00571 00572 ULONG 00573 KiGetFeatureBits( 00574 VOID 00575 ) 00576 00577 /*++ 00578 00579 Return the NT feature bits supported by this processors 00580 00581 --*/ 00582 00583 { 00584 00585 ULONG Features = 0; 00586 00587 // 00588 // Check for byte instructions. 00589 // 00590 00591 if (amask(1) == 0) { 00592 Features |= KF_BYTE; 00593 } 00594 00595 return Features; 00596 } 00597 00598 #if defined(_AXP64_) 00599 00600 00601 VOID 00602 KiStartHalThread ( 00603 IN PKTHREAD Thread, 00604 IN PVOID Stack, 00605 IN PKSTART_ROUTINE StartRoutine, 00606 IN ULONG_PTR Process 00607 ) 00608 00609 /*++ 00610 00611 Routine Description: 00612 00613 This function is called to initialize and start a thread from the 00614 HAL to emulate BIOS calls. 00615 00616 Arguments: 00617 00618 Thread - Supplies a pointer to a dispatcher object of type thread. 00619 00620 Stack - Supplies a pointer the base of the real kernel stack for 00621 thread. 00622 00623 StartRoutine - Supplies the address of the start routine. 00624 00625 Return Value: 00626 00627 None. 00628 00629 --*/ 00630 00631 { 00632 00633 // 00634 // Initialize the specified thread object. 00635 // 00636 00637 KeInitializeThread(Thread, 00638 Stack, 00639 (PKSYSTEM_ROUTINE)StartRoutine, 00640 NULL, 00641 NULL, 00642 NULL, 00643 NULL, 00644 (PKPROCESS)Process); 00645 00646 // 00647 // Set thread priority. 00648 // 00649 00650 Thread->Priority = (KPRIORITY) NORMAL_BASE_PRIORITY - 1; 00651 KeReadyThread(Thread); 00652 return; 00653 } 00654 00655 #endif

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