Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenkiinit.c
Go to the documentation of this file.
00001 /* 00002 * PROJECT: ReactOS Kernel 00003 * LICENSE: GPL - See COPYING in the top level directory 00004 * FILE: ntoskrnl/ke/i386/kiinit.c 00005 * PURPOSE: Kernel Initialization for x86 CPUs 00006 * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org) 00007 */ 00008 00009 /* INCLUDES *****************************************************************/ 00010 00011 #include <ntoskrnl.h> 00012 #define NDEBUG 00013 #include <debug.h> 00014 #include "internal/i386/trap_x.h" 00015 00016 /* GLOBALS *******************************************************************/ 00017 00018 /* Boot and double-fault/NMI/DPC stack */ 00019 UCHAR DECLSPEC_ALIGN(16) P0BootStackData[KERNEL_STACK_SIZE] = {0}; 00020 UCHAR DECLSPEC_ALIGN(16) KiDoubleFaultStackData[KERNEL_STACK_SIZE] = {0}; 00021 ULONG_PTR P0BootStack = (ULONG_PTR)&P0BootStackData[KERNEL_STACK_SIZE]; 00022 ULONG_PTR KiDoubleFaultStack = (ULONG_PTR)&KiDoubleFaultStackData[KERNEL_STACK_SIZE]; 00023 00024 /* Spinlocks used only on X86 */ 00025 KSPIN_LOCK KiFreezeExecutionLock; 00026 KSPIN_LOCK Ki486CompatibilityLock; 00027 00028 /* Perf */ 00029 ULONG ProcessCount; 00030 ULONGLONG BootCycles, BootCyclesEnd; 00031 00032 /* FUNCTIONS *****************************************************************/ 00033 00034 VOID 00035 NTAPI 00036 INIT_FUNCTION 00037 KiInitMachineDependent(VOID) 00038 { 00039 ULONG CpuCount; 00040 BOOLEAN FbCaching = FALSE; 00041 NTSTATUS Status; 00042 ULONG ReturnLength; 00043 ULONG i, Affinity, Sample = 0; 00044 PFX_SAVE_AREA FxSaveArea; 00045 ULONG MXCsrMask = 0xFFBF; 00046 ULONG Dummy; 00047 KI_SAMPLE_MAP Samples[4]; 00048 PKI_SAMPLE_MAP CurrentSample = Samples; 00049 00050 /* Check for large page support */ 00051 if (KeFeatureBits & KF_LARGE_PAGE) 00052 { 00053 /* FIXME: Support this */ 00054 DPRINT("Large Page support detected but not yet taken advantage of\n"); 00055 } 00056 00057 /* Check for global page support */ 00058 if (KeFeatureBits & KF_GLOBAL_PAGE) 00059 { 00060 /* Do an IPI to enable it on all CPUs */ 00061 CpuCount = KeNumberProcessors; 00062 KeIpiGenericCall(Ki386EnableGlobalPage, (ULONG_PTR)&CpuCount); 00063 } 00064 00065 /* Check for PAT and/or MTRR support */ 00066 if (KeFeatureBits & (KF_PAT | KF_MTRR)) 00067 { 00068 /* Query the HAL to make sure we can use it */ 00069 Status = HalQuerySystemInformation(HalFrameBufferCachingInformation, 00070 sizeof(BOOLEAN), 00071 &FbCaching, 00072 &ReturnLength); 00073 if ((NT_SUCCESS(Status)) && (FbCaching)) 00074 { 00075 /* We can't, disable it */ 00076 KeFeatureBits &= ~(KF_PAT | KF_MTRR); 00077 } 00078 } 00079 00080 /* Check for PAT support and enable it */ 00081 if (KeFeatureBits & KF_PAT) KiInitializePAT(); 00082 00083 /* Assume no errata for now */ 00084 SharedUserData->ProcessorFeatures[PF_FLOATING_POINT_PRECISION_ERRATA] = 0; 00085 00086 /* Check if we have an NPX */ 00087 if (KeI386NpxPresent) 00088 { 00089 /* Loop every CPU */ 00090 i = KeActiveProcessors; 00091 for (Affinity = 1; i; Affinity <<= 1) 00092 { 00093 /* Check if this is part of the set */ 00094 if (i & Affinity) 00095 { 00096 /* Run on this CPU */ 00097 i &= ~Affinity; 00098 KeSetSystemAffinityThread(Affinity); 00099 00100 /* Detect FPU errata */ 00101 if (KiIsNpxErrataPresent()) 00102 { 00103 /* Disable NPX support */ 00104 KeI386NpxPresent = FALSE; 00105 SharedUserData-> 00106 ProcessorFeatures[PF_FLOATING_POINT_PRECISION_ERRATA] = 00107 TRUE; 00108 break; 00109 } 00110 } 00111 } 00112 } 00113 00114 /* If there's no NPX, then we're emulating the FPU */ 00115 SharedUserData->ProcessorFeatures[PF_FLOATING_POINT_EMULATED] = 00116 !KeI386NpxPresent; 00117 00118 /* Check if there's no NPX, so that we can disable associated features */ 00119 if (!KeI386NpxPresent) 00120 { 00121 /* Remove NPX-related bits */ 00122 KeFeatureBits &= ~(KF_XMMI64 | KF_XMMI | KF_FXSR | KF_MMX); 00123 00124 /* Disable kernel flags */ 00125 KeI386FxsrPresent = KeI386XMMIPresent = FALSE; 00126 00127 /* Disable processor features that might've been set until now */ 00128 SharedUserData->ProcessorFeatures[PF_FLOATING_POINT_PRECISION_ERRATA] = 00129 SharedUserData->ProcessorFeatures[PF_XMMI64_INSTRUCTIONS_AVAILABLE] = 00130 SharedUserData->ProcessorFeatures[PF_XMMI_INSTRUCTIONS_AVAILABLE] = 00131 SharedUserData->ProcessorFeatures[PF_3DNOW_INSTRUCTIONS_AVAILABLE] = 00132 SharedUserData->ProcessorFeatures[PF_MMX_INSTRUCTIONS_AVAILABLE] = 0; 00133 } 00134 00135 /* Check for CR4 support */ 00136 if (KeFeatureBits & KF_CR4) 00137 { 00138 /* Do an IPI call to enable the Debug Exceptions */ 00139 CpuCount = KeNumberProcessors; 00140 KeIpiGenericCall(Ki386EnableDE, (ULONG_PTR)&CpuCount); 00141 } 00142 00143 /* Check if FXSR was found */ 00144 if (KeFeatureBits & KF_FXSR) 00145 { 00146 /* Do an IPI call to enable the FXSR */ 00147 CpuCount = KeNumberProcessors; 00148 KeIpiGenericCall(Ki386EnableFxsr, (ULONG_PTR)&CpuCount); 00149 00150 /* Check if XMM was found too */ 00151 if (KeFeatureBits & KF_XMMI) 00152 { 00153 /* Do an IPI call to enable XMMI exceptions */ 00154 CpuCount = KeNumberProcessors; 00155 KeIpiGenericCall(Ki386EnableXMMIExceptions, (ULONG_PTR)&CpuCount); 00156 00157 /* FIXME: Implement and enable XMM Page Zeroing for Mm */ 00158 00159 /* Patch the RtlPrefetchMemoryNonTemporal routine to enable it */ 00160 *(PCHAR)RtlPrefetchMemoryNonTemporal = 0x90; 00161 } 00162 } 00163 00164 /* Check for, and enable SYSENTER support */ 00165 KiRestoreFastSyscallReturnState(); 00166 00167 /* Loop every CPU */ 00168 i = KeActiveProcessors; 00169 for (Affinity = 1; i; Affinity <<= 1) 00170 { 00171 /* Check if this is part of the set */ 00172 if (i & Affinity) 00173 { 00174 /* Run on this CPU */ 00175 i &= ~Affinity; 00176 KeSetSystemAffinityThread(Affinity); 00177 00178 /* Reset MHz to 0 for this CPU */ 00179 KeGetCurrentPrcb()->MHz = 0; 00180 00181 /* Check if we can use RDTSC */ 00182 if (KeFeatureBits & KF_RDTSC) 00183 { 00184 /* Start sampling loop */ 00185 for (;;) 00186 { 00187 /* Do a dummy CPUID to start the sample */ 00188 CPUID(0, &Dummy, &Dummy, &Dummy, &Dummy); 00189 00190 /* Fill out the starting data */ 00191 CurrentSample->PerfStart = KeQueryPerformanceCounter(NULL); 00192 CurrentSample->TSCStart = __rdtsc(); 00193 CurrentSample->PerfFreq.QuadPart = -50000; 00194 00195 /* Sleep for this sample */ 00196 KeDelayExecutionThread(KernelMode, 00197 FALSE, 00198 &CurrentSample->PerfFreq); 00199 00200 /* Do another dummy CPUID */ 00201 CPUID(0, &Dummy, &Dummy, &Dummy, &Dummy); 00202 00203 /* Fill out the ending data */ 00204 CurrentSample->PerfEnd = 00205 KeQueryPerformanceCounter(&CurrentSample->PerfFreq); 00206 CurrentSample->TSCEnd = __rdtsc(); 00207 00208 /* Calculate the differences */ 00209 CurrentSample->PerfDelta = CurrentSample->PerfEnd.QuadPart - 00210 CurrentSample->PerfStart.QuadPart; 00211 CurrentSample->TSCDelta = CurrentSample->TSCEnd - 00212 CurrentSample->TSCStart; 00213 00214 /* Compute CPU Speed */ 00215 CurrentSample->MHz = (ULONG)((CurrentSample->TSCDelta * 00216 CurrentSample-> 00217 PerfFreq.QuadPart + 500000) / 00218 (CurrentSample->PerfDelta * 00219 1000000)); 00220 00221 /* Check if this isn't the first sample */ 00222 if (Sample) 00223 { 00224 /* Check if we got a good precision within 1MHz */ 00225 if ((CurrentSample->MHz == CurrentSample[-1].MHz) || 00226 (CurrentSample->MHz == CurrentSample[-1].MHz + 1) || 00227 (CurrentSample->MHz == CurrentSample[-1].MHz - 1)) 00228 { 00229 /* We did, stop sampling */ 00230 break; 00231 } 00232 } 00233 00234 /* Move on */ 00235 CurrentSample++; 00236 Sample++; 00237 00238 if (Sample == sizeof(Samples) / sizeof(Samples[0])) 00239 { 00240 /* Restart */ 00241 CurrentSample = Samples; 00242 Sample = 0; 00243 } 00244 } 00245 00246 /* Save the CPU Speed */ 00247 KeGetCurrentPrcb()->MHz = CurrentSample[-1].MHz; 00248 } 00249 00250 /* Check if we have MTRR */ 00251 if (KeFeatureBits & KF_MTRR) 00252 { 00253 /* Then manually initialize MTRR for the CPU */ 00254 KiInitializeMTRR(i ? FALSE : TRUE); 00255 } 00256 00257 /* Check if we have AMD MTRR and initialize it for the CPU */ 00258 if (KeFeatureBits & KF_AMDK6MTRR) KiAmdK6InitializeMTRR(); 00259 00260 /* Check if this is a buggy Pentium and apply the fixup if so */ 00261 if (KiI386PentiumLockErrataPresent) KiI386PentiumLockErrataFixup(); 00262 00263 /* Check if the CPU supports FXSR */ 00264 if (KeFeatureBits & KF_FXSR) 00265 { 00266 /* Get the current thread NPX state */ 00267 FxSaveArea = KiGetThreadNpxArea(KeGetCurrentThread()); 00268 00269 /* Clear initial MXCsr mask */ 00270 FxSaveArea->U.FxArea.MXCsrMask = 0; 00271 00272 /* Save the current NPX State */ 00273 Ke386SaveFpuState(FxSaveArea); 00274 00275 /* Check if the current mask doesn't match the reserved bits */ 00276 if (FxSaveArea->U.FxArea.MXCsrMask != 0) 00277 { 00278 /* Then use whatever it's holding */ 00279 MXCsrMask = FxSaveArea->U.FxArea.MXCsrMask; 00280 } 00281 00282 /* Check if nobody set the kernel-wide mask */ 00283 if (!KiMXCsrMask) 00284 { 00285 /* Then use the one we calculated above */ 00286 KiMXCsrMask = MXCsrMask; 00287 } 00288 else 00289 { 00290 /* Was it set to the same value we found now? */ 00291 if (KiMXCsrMask != MXCsrMask) 00292 { 00293 /* No, something is definitely wrong */ 00294 KeBugCheckEx(MULTIPROCESSOR_CONFIGURATION_NOT_SUPPORTED, 00295 KF_FXSR, 00296 KiMXCsrMask, 00297 MXCsrMask, 00298 0); 00299 } 00300 } 00301 00302 /* Now set the kernel mask */ 00303 KiMXCsrMask &= MXCsrMask; 00304 } 00305 } 00306 } 00307 00308 /* Return affinity back to where it was */ 00309 KeRevertToUserAffinityThread(); 00310 00311 /* NT allows limiting the duration of an ISR with a registry key */ 00312 if (KiTimeLimitIsrMicroseconds) 00313 { 00314 /* FIXME: TODO */ 00315 DPRINT1("ISR Time Limit not yet supported\n"); 00316 } 00317 00318 /* Set CR0 features based on detected CPU */ 00319 KiSetCR0Bits(); 00320 } 00321 00322 VOID 00323 NTAPI 00324 INIT_FUNCTION 00325 KiInitializePcr(IN ULONG ProcessorNumber, 00326 IN PKIPCR Pcr, 00327 IN PKIDTENTRY Idt, 00328 IN PKGDTENTRY Gdt, 00329 IN PKTSS Tss, 00330 IN PKTHREAD IdleThread, 00331 IN PVOID DpcStack) 00332 { 00333 /* Setup the TIB */ 00334 Pcr->NtTib.ExceptionList = EXCEPTION_CHAIN_END; 00335 Pcr->NtTib.StackBase = 0; 00336 Pcr->NtTib.StackLimit = 0; 00337 Pcr->NtTib.Self = NULL; 00338 00339 /* Set the Current Thread */ 00340 Pcr->PrcbData.CurrentThread = IdleThread; 00341 00342 /* Set pointers to ourselves */ 00343 Pcr->Self = (PKPCR)Pcr; 00344 Pcr->Prcb = &Pcr->PrcbData; 00345 00346 /* Set the PCR Version */ 00347 Pcr->MajorVersion = PCR_MAJOR_VERSION; 00348 Pcr->MinorVersion = PCR_MINOR_VERSION; 00349 00350 /* Set the PCRB Version */ 00351 Pcr->PrcbData.MajorVersion = 1; 00352 Pcr->PrcbData.MinorVersion = 1; 00353 00354 /* Set the Build Type */ 00355 Pcr->PrcbData.BuildType = 0; 00356 #ifndef CONFIG_SMP 00357 Pcr->PrcbData.BuildType |= PRCB_BUILD_UNIPROCESSOR; 00358 #endif 00359 #if DBG 00360 Pcr->PrcbData.BuildType |= PRCB_BUILD_DEBUG; 00361 #endif 00362 00363 /* Set the Processor Number and current Processor Mask */ 00364 Pcr->PrcbData.Number = (UCHAR)ProcessorNumber; 00365 Pcr->PrcbData.SetMember = 1 << ProcessorNumber; 00366 00367 /* Set the PRCB for this Processor */ 00368 KiProcessorBlock[ProcessorNumber] = Pcr->Prcb; 00369 00370 /* Start us out at PASSIVE_LEVEL */ 00371 Pcr->Irql = PASSIVE_LEVEL; 00372 00373 /* Set the GDI, IDT, TSS and DPC Stack */ 00374 Pcr->GDT = (PVOID)Gdt; 00375 Pcr->IDT = Idt; 00376 Pcr->TSS = Tss; 00377 Pcr->TssCopy = Tss; 00378 Pcr->PrcbData.DpcStack = DpcStack; 00379 00380 /* Setup the processor set */ 00381 Pcr->PrcbData.MultiThreadProcessorSet = Pcr->PrcbData.SetMember; 00382 } 00383 00384 VOID 00385 NTAPI 00386 INIT_FUNCTION 00387 KiInitializeKernel(IN PKPROCESS InitProcess, 00388 IN PKTHREAD InitThread, 00389 IN PVOID IdleStack, 00390 IN PKPRCB Prcb, 00391 IN CCHAR Number, 00392 IN PLOADER_PARAMETER_BLOCK LoaderBlock) 00393 { 00394 BOOLEAN NpxPresent; 00395 ULONG FeatureBits; 00396 ULONG PageDirectory[2]; 00397 PVOID DpcStack; 00398 ULONG Vendor[3]; 00399 00400 /* Detect and set the CPU Type */ 00401 KiSetProcessorType(); 00402 00403 /* Check if an FPU is present */ 00404 NpxPresent = KiIsNpxPresent(); 00405 00406 /* Initialize the Power Management Support for this PRCB */ 00407 PoInitializePrcb(Prcb); 00408 00409 /* Bugcheck if this is a 386 CPU */ 00410 if (Prcb->CpuType == 3) KeBugCheckEx(UNSUPPORTED_PROCESSOR, 0x386, 0, 0, 0); 00411 00412 /* Get the processor features for the CPU */ 00413 FeatureBits = KiGetFeatureBits(); 00414 00415 /* Set the default NX policy (opt-in) */ 00416 SharedUserData->NXSupportPolicy = NX_SUPPORT_POLICY_OPTIN; 00417 00418 /* Check if NPX is always on */ 00419 if (strstr(KeLoaderBlock->LoadOptions, "NOEXECUTE=ALWAYSON")) 00420 { 00421 /* Set it always on */ 00422 SharedUserData->NXSupportPolicy = NX_SUPPORT_POLICY_ALWAYSON; 00423 FeatureBits |= KF_NX_ENABLED; 00424 } 00425 else if (strstr(KeLoaderBlock->LoadOptions, "NOEXECUTE=OPTOUT")) 00426 { 00427 /* Set it in opt-out mode */ 00428 SharedUserData->NXSupportPolicy = NX_SUPPORT_POLICY_OPTOUT; 00429 FeatureBits |= KF_NX_ENABLED; 00430 } 00431 else if ((strstr(KeLoaderBlock->LoadOptions, "NOEXECUTE=OPTIN")) || 00432 (strstr(KeLoaderBlock->LoadOptions, "NOEXECUTE"))) 00433 { 00434 /* Set the feature bits */ 00435 FeatureBits |= KF_NX_ENABLED; 00436 } 00437 else if ((strstr(KeLoaderBlock->LoadOptions, "NOEXECUTE=ALWAYSOFF")) || 00438 (strstr(KeLoaderBlock->LoadOptions, "EXECUTE"))) 00439 { 00440 /* Set disabled mode */ 00441 SharedUserData->NXSupportPolicy = NX_SUPPORT_POLICY_ALWAYSOFF; 00442 FeatureBits |= KF_NX_DISABLED; 00443 } 00444 00445 /* Save feature bits */ 00446 Prcb->FeatureBits = FeatureBits; 00447 00448 /* Save CPU state */ 00449 KiSaveProcessorControlState(&Prcb->ProcessorState); 00450 00451 /* Get cache line information for this CPU */ 00452 KiGetCacheInformation(); 00453 00454 /* Initialize spinlocks and DPC data */ 00455 KiInitSpinLocks(Prcb, Number); 00456 00457 /* Check if this is the Boot CPU */ 00458 if (!Number) 00459 { 00460 /* Set Node Data */ 00461 KeNodeBlock[0] = &KiNode0; 00462 Prcb->ParentNode = KeNodeBlock[0]; 00463 KeNodeBlock[0]->ProcessorMask = Prcb->SetMember; 00464 00465 /* Set boot-level flags */ 00466 KeI386NpxPresent = NpxPresent; 00467 KeI386CpuType = Prcb->CpuType; 00468 KeI386CpuStep = Prcb->CpuStep; 00469 KeProcessorArchitecture = PROCESSOR_ARCHITECTURE_INTEL; 00470 KeProcessorLevel = (USHORT)Prcb->CpuType; 00471 if (Prcb->CpuID) KeProcessorRevision = Prcb->CpuStep; 00472 KeFeatureBits = FeatureBits; 00473 KeI386FxsrPresent = (KeFeatureBits & KF_FXSR) ? TRUE : FALSE; 00474 KeI386XMMIPresent = (KeFeatureBits & KF_XMMI) ? TRUE : FALSE; 00475 00476 /* Detect 8-byte compare exchange support */ 00477 if (!(KeFeatureBits & KF_CMPXCHG8B)) 00478 { 00479 /* Copy the vendor string */ 00480 RtlCopyMemory(Vendor, Prcb->VendorString, sizeof(Vendor)); 00481 00482 /* Bugcheck the system. Windows *requires* this */ 00483 KeBugCheckEx(UNSUPPORTED_PROCESSOR, 00484 (1 << 24 ) | (Prcb->CpuType << 16) | Prcb->CpuStep, 00485 Vendor[0], 00486 Vendor[1], 00487 Vendor[2]); 00488 } 00489 00490 /* Set the current MP Master KPRCB to the Boot PRCB */ 00491 Prcb->MultiThreadSetMaster = Prcb; 00492 00493 /* Lower to APC_LEVEL */ 00494 KeLowerIrql(APC_LEVEL); 00495 00496 /* Initialize some spinlocks */ 00497 KeInitializeSpinLock(&KiFreezeExecutionLock); 00498 KeInitializeSpinLock(&Ki486CompatibilityLock); 00499 00500 /* Initialize portable parts of the OS */ 00501 KiInitSystem(); 00502 00503 /* Initialize the Idle Process and the Process Listhead */ 00504 InitializeListHead(&KiProcessListHead); 00505 PageDirectory[0] = 0; 00506 PageDirectory[1] = 0; 00507 KeInitializeProcess(InitProcess, 00508 0, 00509 0xFFFFFFFF, 00510 PageDirectory, 00511 FALSE); 00512 InitProcess->QuantumReset = MAXCHAR; 00513 } 00514 else 00515 { 00516 /* FIXME */ 00517 DPRINT1("SMP Boot support not yet present\n"); 00518 } 00519 00520 /* Setup the Idle Thread */ 00521 KeInitializeThread(InitProcess, 00522 InitThread, 00523 NULL, 00524 NULL, 00525 NULL, 00526 NULL, 00527 NULL, 00528 IdleStack); 00529 InitThread->NextProcessor = Number; 00530 InitThread->Priority = HIGH_PRIORITY; 00531 InitThread->State = Running; 00532 InitThread->Affinity = 1 << Number; 00533 InitThread->WaitIrql = DISPATCH_LEVEL; 00534 InitProcess->ActiveProcessors = 1 << Number; 00535 00536 /* HACK for MmUpdatePageDir */ 00537 ((PETHREAD)InitThread)->ThreadsProcess = (PEPROCESS)InitProcess; 00538 00539 /* Set basic CPU Features that user mode can read */ 00540 SharedUserData->ProcessorFeatures[PF_MMX_INSTRUCTIONS_AVAILABLE] = 00541 (KeFeatureBits & KF_MMX) ? TRUE: FALSE; 00542 SharedUserData->ProcessorFeatures[PF_COMPARE_EXCHANGE_DOUBLE] = 00543 (KeFeatureBits & KF_CMPXCHG8B) ? TRUE: FALSE; 00544 SharedUserData->ProcessorFeatures[PF_XMMI_INSTRUCTIONS_AVAILABLE] = 00545 ((KeFeatureBits & KF_FXSR) && (KeFeatureBits & KF_XMMI)) ? TRUE: FALSE; 00546 SharedUserData->ProcessorFeatures[PF_XMMI64_INSTRUCTIONS_AVAILABLE] = 00547 ((KeFeatureBits & KF_FXSR) && (KeFeatureBits & KF_XMMI64)) ? TRUE: FALSE; 00548 SharedUserData->ProcessorFeatures[PF_3DNOW_INSTRUCTIONS_AVAILABLE] = 00549 (KeFeatureBits & KF_3DNOW) ? TRUE: FALSE; 00550 SharedUserData->ProcessorFeatures[PF_RDTSC_INSTRUCTION_AVAILABLE] = 00551 (KeFeatureBits & KF_RDTSC) ? TRUE: FALSE; 00552 00553 /* Set up the thread-related fields in the PRCB */ 00554 Prcb->CurrentThread = InitThread; 00555 Prcb->NextThread = NULL; 00556 Prcb->IdleThread = InitThread; 00557 00558 /* Initialize the Kernel Executive */ 00559 ExpInitializeExecutive(Number, LoaderBlock); 00560 00561 /* Only do this on the boot CPU */ 00562 if (!Number) 00563 { 00564 /* Calculate the time reciprocal */ 00565 KiTimeIncrementReciprocal = 00566 KiComputeReciprocal(KeMaximumIncrement, 00567 &KiTimeIncrementShiftCount); 00568 00569 /* Update DPC Values in case they got updated by the executive */ 00570 Prcb->MaximumDpcQueueDepth = KiMaximumDpcQueueDepth; 00571 Prcb->MinimumDpcRate = KiMinimumDpcRate; 00572 Prcb->AdjustDpcThreshold = KiAdjustDpcThreshold; 00573 00574 /* Allocate the DPC Stack */ 00575 DpcStack = MmCreateKernelStack(FALSE, 0); 00576 if (!DpcStack) KeBugCheckEx(NO_PAGES_AVAILABLE, 1, 0, 0, 0); 00577 Prcb->DpcStack = DpcStack; 00578 00579 /* Allocate the IOPM save area. */ 00580 Ki386IopmSaveArea = ExAllocatePoolWithTag(PagedPool, 00581 PAGE_SIZE * 2, 00582 ' eK'); 00583 if (!Ki386IopmSaveArea) 00584 { 00585 /* Bugcheck. We need this for V86/VDM support. */ 00586 KeBugCheckEx(NO_PAGES_AVAILABLE, 2, PAGE_SIZE * 2, 0, 0); 00587 } 00588 } 00589 00590 /* Raise to Dispatch */ 00591 KfRaiseIrql(DISPATCH_LEVEL); 00592 00593 /* Set the Idle Priority to 0. This will jump into Phase 1 */ 00594 KeSetPriorityThread(InitThread, 0); 00595 00596 /* If there's no thread scheduled, put this CPU in the Idle summary */ 00597 KiAcquirePrcbLock(Prcb); 00598 if (!Prcb->NextThread) KiIdleSummary |= 1 << Number; 00599 KiReleasePrcbLock(Prcb); 00600 00601 /* Raise back to HIGH_LEVEL and clear the PRCB for the loader block */ 00602 KfRaiseIrql(HIGH_LEVEL); 00603 LoaderBlock->Prcb = 0; 00604 } 00605 00606 VOID 00607 FASTCALL 00608 INIT_FUNCTION 00609 KiGetMachineBootPointers(IN PKGDTENTRY *Gdt, 00610 IN PKIDTENTRY *Idt, 00611 IN PKIPCR *Pcr, 00612 IN PKTSS *Tss) 00613 { 00614 KDESCRIPTOR GdtDescriptor, IdtDescriptor; 00615 KGDTENTRY TssSelector, PcrSelector; 00616 USHORT Tr, Fs; 00617 00618 /* Get GDT and IDT descriptors */ 00619 Ke386GetGlobalDescriptorTable(&GdtDescriptor.Limit); 00620 __sidt(&IdtDescriptor.Limit); 00621 00622 /* Save IDT and GDT */ 00623 *Gdt = (PKGDTENTRY)GdtDescriptor.Base; 00624 *Idt = (PKIDTENTRY)IdtDescriptor.Base; 00625 00626 /* Get TSS and FS Selectors */ 00627 Tr = Ke386GetTr(); 00628 Fs = Ke386GetFs(); 00629 00630 /* Get PCR Selector, mask it and get its GDT Entry */ 00631 PcrSelector = *(PKGDTENTRY)((ULONG_PTR)*Gdt + (Fs & ~RPL_MASK)); 00632 00633 /* Get the KPCR itself */ 00634 *Pcr = (PKIPCR)(ULONG_PTR)(PcrSelector.BaseLow | 00635 PcrSelector.HighWord.Bytes.BaseMid << 16 | 00636 PcrSelector.HighWord.Bytes.BaseHi << 24); 00637 00638 /* Get TSS Selector, mask it and get its GDT Entry */ 00639 TssSelector = *(PKGDTENTRY)((ULONG_PTR)*Gdt + (Tr & ~RPL_MASK)); 00640 00641 /* Get the KTSS itself */ 00642 *Tss = (PKTSS)(ULONG_PTR)(TssSelector.BaseLow | 00643 TssSelector.HighWord.Bytes.BaseMid << 16 | 00644 TssSelector.HighWord.Bytes.BaseHi << 24); 00645 } 00646 00647 VOID 00648 NTAPI 00649 INIT_FUNCTION 00650 KiSystemStartupBootStack(VOID) 00651 { 00652 PKTHREAD Thread; 00653 00654 /* Initialize the kernel for the current CPU */ 00655 KiInitializeKernel(&KiInitialProcess.Pcb, 00656 (PKTHREAD)KeLoaderBlock->Thread, 00657 (PVOID)(KeLoaderBlock->KernelStack & ~3), 00658 (PKPRCB)__readfsdword(KPCR_PRCB), 00659 KeNumberProcessors - 1, 00660 KeLoaderBlock); 00661 00662 /* Set the priority of this thread to 0 */ 00663 Thread = KeGetCurrentThread(); 00664 Thread->Priority = 0; 00665 00666 /* Force interrupts enabled and lower IRQL back to DISPATCH_LEVEL */ 00667 _enable(); 00668 KfLowerIrql(DISPATCH_LEVEL); 00669 00670 /* Set the right wait IRQL */ 00671 Thread->WaitIrql = DISPATCH_LEVEL; 00672 00673 /* Jump into the idle loop */ 00674 KiIdleLoop(); 00675 } 00676 00677 VOID 00678 NTAPI 00679 INIT_FUNCTION 00680 KiSystemStartup(IN PLOADER_PARAMETER_BLOCK LoaderBlock) 00681 { 00682 ULONG Cpu; 00683 PKTHREAD InitialThread; 00684 ULONG InitialStack; 00685 PKGDTENTRY Gdt; 00686 PKIDTENTRY Idt; 00687 KIDTENTRY NmiEntry, DoubleFaultEntry; 00688 PKTSS Tss; 00689 PKIPCR Pcr; 00690 00691 /* Boot cycles timestamp */ 00692 BootCycles = __rdtsc(); 00693 00694 /* Save the loader block and get the current CPU */ 00695 KeLoaderBlock = LoaderBlock; 00696 Cpu = KeNumberProcessors; 00697 if (!Cpu) 00698 { 00699 /* If this is the boot CPU, set FS and the CPU Number*/ 00700 Ke386SetFs(KGDT_R0_PCR); 00701 __writefsdword(KPCR_PROCESSOR_NUMBER, Cpu); 00702 00703 /* Set the initial stack and idle thread as well */ 00704 LoaderBlock->KernelStack = (ULONG_PTR)P0BootStack; 00705 LoaderBlock->Thread = (ULONG_PTR)&KiInitialThread; 00706 } 00707 00708 /* Save the initial thread and stack */ 00709 InitialStack = LoaderBlock->KernelStack; 00710 InitialThread = (PKTHREAD)LoaderBlock->Thread; 00711 00712 /* Clean the APC List Head */ 00713 InitializeListHead(&InitialThread->ApcState.ApcListHead[KernelMode]); 00714 00715 /* Initialize the machine type */ 00716 KiInitializeMachineType(); 00717 00718 /* Skip initial setup if this isn't the Boot CPU */ 00719 if (Cpu) goto AppCpuInit; 00720 00721 /* Get GDT, IDT, PCR and TSS pointers */ 00722 KiGetMachineBootPointers(&Gdt, &Idt, &Pcr, &Tss); 00723 00724 /* Setup the TSS descriptors and entries */ 00725 Ki386InitializeTss(Tss, Idt, Gdt); 00726 00727 /* Initialize the PCR */ 00728 RtlZeroMemory(Pcr, PAGE_SIZE); 00729 KiInitializePcr(Cpu, 00730 Pcr, 00731 Idt, 00732 Gdt, 00733 Tss, 00734 InitialThread, 00735 (PVOID)KiDoubleFaultStack); 00736 00737 /* Set us as the current process */ 00738 InitialThread->ApcState.Process = &KiInitialProcess.Pcb; 00739 00740 /* Clear DR6/7 to cleanup bootloader debugging */ 00741 __writefsdword(KPCR_TEB, 0); 00742 __writefsdword(KPCR_DR6, 0); 00743 __writefsdword(KPCR_DR7, 0); 00744 00745 /* Setup the IDT */ 00746 KeInitExceptions(); 00747 00748 /* Load Ring 3 selectors for DS/ES */ 00749 Ke386SetDs(KGDT_R3_DATA | RPL_MASK); 00750 Ke386SetEs(KGDT_R3_DATA | RPL_MASK); 00751 00752 /* Save NMI and double fault traps */ 00753 RtlCopyMemory(&NmiEntry, &Idt[2], sizeof(KIDTENTRY)); 00754 RtlCopyMemory(&DoubleFaultEntry, &Idt[8], sizeof(KIDTENTRY)); 00755 00756 /* Copy kernel's trap handlers */ 00757 RtlCopyMemory(Idt, 00758 (PVOID)KiIdtDescriptor.Base, 00759 KiIdtDescriptor.Limit + 1); 00760 00761 /* Restore NMI and double fault */ 00762 RtlCopyMemory(&Idt[2], &NmiEntry, sizeof(KIDTENTRY)); 00763 RtlCopyMemory(&Idt[8], &DoubleFaultEntry, sizeof(KIDTENTRY)); 00764 00765 AppCpuInit: 00766 /* Loop until we can release the freeze lock */ 00767 do 00768 { 00769 /* Loop until execution can continue */ 00770 while (*(volatile PKSPIN_LOCK*)&KiFreezeExecutionLock == (PVOID)1); 00771 } while(InterlockedBitTestAndSet((PLONG)&KiFreezeExecutionLock, 0)); 00772 00773 /* Setup CPU-related fields */ 00774 __writefsdword(KPCR_NUMBER, Cpu); 00775 __writefsdword(KPCR_SET_MEMBER, 1 << Cpu); 00776 __writefsdword(KPCR_SET_MEMBER_COPY, 1 << Cpu); 00777 __writefsdword(KPCR_PRCB_SET_MEMBER, 1 << Cpu); 00778 00779 /* Initialize the Processor with HAL */ 00780 HalInitializeProcessor(Cpu, KeLoaderBlock); 00781 00782 /* Set active processors */ 00783 KeActiveProcessors |= __readfsdword(KPCR_SET_MEMBER); 00784 KeNumberProcessors++; 00785 00786 /* Check if this is the boot CPU */ 00787 if (!Cpu) 00788 { 00789 /* Initialize debugging system */ 00790 KdInitSystem(0, KeLoaderBlock); 00791 00792 /* Check for break-in */ 00793 if (KdPollBreakIn()) DbgBreakPointWithStatus(DBG_STATUS_CONTROL_C); 00794 } 00795 00796 /* Raise to HIGH_LEVEL */ 00797 KfRaiseIrql(HIGH_LEVEL); 00798 00799 /* Switch to new kernel stack and start kernel bootstrapping */ 00800 KiSwitchToBootStack(InitialStack & ~3); 00801 } Generated on Sun May 27 2012 04:37:30 for ReactOS by
1.7.6.1
|