ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

kiinit.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 doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.