ReactOS Fundraising Campaign 2012
 
€ 4,060 / € 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  *                  Timo Kreuzer (timo.kreuzer@reactos.org)
00008  */
00009 
00010 /* INCLUDES *****************************************************************/
00011 
00012 #include <ntoskrnl.h>
00013 #define NDEBUG
00014 #include <debug.h>
00015 
00016 #define REQUIRED_FEATURE_BITS (KF_RDTSC|KF_CR4|KF_CMPXCHG8B|KF_XMMI|KF_XMMI64| \
00017                                KF_NX_BIT)
00018 
00019 /* GLOBALS *******************************************************************/
00020 
00021 /* Function pointer for early debug prints */
00022 ULONG (*FrLdrDbgPrint)(const char *Format, ...);
00023 
00024 /* Spinlocks used only on X86 */
00025 KSPIN_LOCK KiFreezeExecutionLock;
00026 
00027 
00028 KIPCR KiInitialPcr;
00029 
00030 /* Boot and double-fault/NMI/DPC stack */
00031 UCHAR DECLSPEC_ALIGN(16) P0BootStackData[KERNEL_STACK_SIZE] = {0};
00032 UCHAR DECLSPEC_ALIGN(16) KiDoubleFaultStackData[KERNEL_STACK_SIZE] = {0};
00033 ULONG_PTR P0BootStack = (ULONG_PTR)&P0BootStackData[KERNEL_STACK_SIZE];
00034 ULONG_PTR KiDoubleFaultStack = (ULONG_PTR)&KiDoubleFaultStackData[KERNEL_STACK_SIZE];
00035 
00036 void KiInitializeSegments();
00037 void KiSystemCallEntry64();
00038 void KiSystemCallEntry32();
00039 
00040 /* FUNCTIONS *****************************************************************/
00041 
00042 VOID
00043 NTAPI
00044 KiInitMachineDependent(VOID)
00045 {
00046     /* Check for large page support */
00047     if (KeFeatureBits & KF_LARGE_PAGE)
00048     {
00049         /* FIXME: Support this */
00050         DPRINT("Large Page support detected but not yet taken advantage of!\n");
00051     }
00052 
00053     /* Check for global page support */
00054     if (KeFeatureBits & KF_GLOBAL_PAGE)
00055     {
00056         /* FIXME: Support this */
00057         DPRINT("Global Page support detected but not yet taken advantage of!\n");
00058     }
00059 
00060     /* Check if we have MTRR */
00061     if (KeFeatureBits & KF_MTRR)
00062     {
00063         /* FIXME: Support this */
00064         DPRINT("MTRR support detected but not yet taken advantage of!\n");
00065     }
00066 
00067     /* Check for PAT and/or MTRR support */
00068     if (KeFeatureBits & KF_PAT)
00069     {
00070         /* FIXME: Support this */
00071         DPRINT("PAT support detected but not yet taken advantage of!\n");
00072     }
00073 
00074         /* Allocate the IOPM save area. */
00075 //        Ki386IopmSaveArea = ExAllocatePoolWithTag(PagedPool,
00076 //                                                  PAGE_SIZE * 2,
00077 //                                                  TAG('K', 'e', ' ', ' '));
00078 //        if (!Ki386IopmSaveArea)
00079 //        {
00080 //            /* Bugcheck. We need this for V86/VDM support. */
00081 //            KeBugCheckEx(NO_PAGES_AVAILABLE, 2, PAGE_SIZE * 2, 0, 0);
00082 //        }
00083 
00084 }
00085 
00086 VOID
00087 NTAPI
00088 KiInitializePcr(IN PKIPCR Pcr,
00089                 IN ULONG ProcessorNumber,
00090                 IN PKTHREAD IdleThread,
00091                 IN PVOID DpcStack)
00092 {
00093     KDESCRIPTOR GdtDescriptor = {{0},0,0}, IdtDescriptor = {{0},0,0};
00094     PKGDTENTRY64 TssEntry;
00095     USHORT Tr = 0;
00096 
00097     /* Zero out the PCR */
00098     RtlZeroMemory(Pcr, sizeof(KIPCR));
00099 
00100     /* Set pointers to ourselves */
00101     Pcr->Self = (PKPCR)Pcr;
00102     Pcr->CurrentPrcb = &Pcr->Prcb;
00103 
00104     /* Set the PCR Version */
00105     Pcr->MajorVersion = PCR_MAJOR_VERSION;
00106     Pcr->MinorVersion = PCR_MINOR_VERSION;
00107 
00108     /* Set the PRCB Version */
00109     Pcr->Prcb.MajorVersion = 1;
00110     Pcr->Prcb.MinorVersion = 1;
00111 
00112     /* Set the Build Type */
00113     Pcr->Prcb.BuildType = 0;
00114 #ifndef CONFIG_SMP
00115     Pcr->Prcb.BuildType |= PRCB_BUILD_UNIPROCESSOR;
00116 #endif
00117 #if DBG
00118     Pcr->Prcb.BuildType |= PRCB_BUILD_DEBUG;
00119 #endif
00120 
00121     /* Set the Processor Number and current Processor Mask */
00122     Pcr->Prcb.Number = (UCHAR)ProcessorNumber;
00123     Pcr->Prcb.SetMember = 1ULL << ProcessorNumber;
00124 
00125     /* Get GDT and IDT descriptors */
00126     __sgdt(&GdtDescriptor.Limit);
00127     __sidt(&IdtDescriptor.Limit);
00128     Pcr->GdtBase = (PVOID)GdtDescriptor.Base;
00129     Pcr->IdtBase = (PKIDTENTRY)IdtDescriptor.Base;
00130 
00131     /* Get TSS Selector */
00132     __str(&Tr);
00133     ASSERT(Tr == KGDT64_SYS_TSS);
00134 
00135     /* Get TSS Entry */
00136     TssEntry = KiGetGdtEntry(Pcr->GdtBase, Tr);
00137 
00138     /* Get the KTSS itself */
00139     Pcr->TssBase = KiGetGdtDescriptorBase(TssEntry);
00140 
00141     Pcr->Prcb.RspBase = Pcr->TssBase->Rsp0; // FIXME
00142 
00143     /* Set DPC Stack */
00144     Pcr->Prcb.DpcStack = DpcStack;
00145 
00146     /* Setup the processor set */
00147     Pcr->Prcb.MultiThreadProcessorSet = Pcr->Prcb.SetMember;
00148 
00149     /* Clear DR6/7 to cleanup bootloader debugging */
00150     Pcr->Prcb.ProcessorState.SpecialRegisters.KernelDr6 = 0;
00151     Pcr->Prcb.ProcessorState.SpecialRegisters.KernelDr7 = 0;
00152 
00153     /* Set the Current Thread */
00154     Pcr->Prcb.CurrentThread = IdleThread;
00155 
00156     /* Start us out at PASSIVE_LEVEL */
00157     Pcr->Irql = PASSIVE_LEVEL;
00158     KeSetCurrentIrql(PASSIVE_LEVEL);
00159 }
00160 
00161 VOID
00162 NTAPI
00163 KiInitializeCpu(PKIPCR Pcr)
00164 {
00165     ULONG FeatureBits;
00166 
00167     /* Initialize gs */
00168     KiInitializeSegments();
00169 
00170     /* Set GS base */
00171     __writemsr(MSR_GS_BASE, (ULONG64)Pcr);
00172     __writemsr(MSR_GS_SWAP, (ULONG64)Pcr);
00173 
00174     /* Detect and set the CPU Type */
00175     KiSetProcessorType();
00176 
00177     /* Get the processor features for this CPU */
00178     FeatureBits = KiGetFeatureBits();
00179 
00180     /* Check if we support all needed features */
00181     if ((FeatureBits & REQUIRED_FEATURE_BITS) != REQUIRED_FEATURE_BITS)
00182     {
00183         /* If not, bugcheck system */
00184         FrLdrDbgPrint("CPU doesn't have needed features! Has: 0x%x, required: 0x%x\n",
00185                 FeatureBits, REQUIRED_FEATURE_BITS);
00186         KeBugCheck(0);
00187     }
00188 
00189     /* Set DEP to always on */
00190     SharedUserData->NXSupportPolicy = NX_SUPPORT_POLICY_ALWAYSON;
00191     FeatureBits |= KF_NX_ENABLED;
00192 
00193     /* Save feature bits */
00194     Pcr->Prcb.FeatureBits = FeatureBits;
00195 
00196     /* Enable fx save restore support */
00197     __writecr4(__readcr4() | CR4_FXSR);
00198 
00199     /* Enable XMMI exceptions */
00200     __writecr4(__readcr4() | CR4_XMMEXCPT);
00201 
00202     /* Enable Write-Protection */
00203     __writecr0(__readcr0() | CR0_WP);
00204 
00205     /* Disable fpu monitoring */
00206     __writecr0(__readcr0() & ~CR0_MP);
00207 
00208     /* Disable x87 fpu exceptions */
00209     __writecr0(__readcr0() & ~CR0_NE);
00210 
00211     /* LDT is unused */
00212     __lldt(0);
00213 
00214     /* Set the systemcall entry points */
00215     __writemsr(MSR_LSTAR, (ULONG64)KiSystemCallEntry64);
00216     __writemsr(MSR_CSTAR, (ULONG64)KiSystemCallEntry32);
00217 
00218    __writemsr(MSR_STAR, ((ULONG64)KGDT64_R0_CODE << 32) |
00219                         ((ULONG64)(KGDT64_R3_CMCODE|RPL_MASK) << 48));
00220 
00221     /* Set the flags to be cleared when doing a syscall */
00222     __writemsr(MSR_SYSCALL_MASK, EFLAGS_IF_MASK | EFLAGS_TF | EFLAGS_DF);
00223 
00224     /* Enable syscall instruction */
00225     __writemsr(MSR_EFER, __readmsr(MSR_EFER) | MSR_SCE);
00226 }
00227 
00228 VOID
00229 FASTCALL
00230 KiInitializeTss(IN PKTSS64 Tss,
00231                 IN UINT64 Stack)
00232 {
00233     PKGDTENTRY64 TssEntry;
00234 
00235     /* Get pointer to the GDT entry */
00236     TssEntry = KiGetGdtEntry(KeGetPcr()->GdtBase, KGDT64_SYS_TSS);
00237 
00238     /* Initialize the GDT entry */
00239     KiInitGdtEntry(TssEntry, (ULONG64)Tss, sizeof(KTSS64), AMD64_TSS, 0);
00240 
00241     /* Zero out the TSS */
00242     RtlZeroMemory(Tss, sizeof(KTSS64));
00243 
00244     /* FIXME: I/O Map? */
00245     Tss->IoMapBase = 0x68;
00246 
00247     /* Setup ring 0 stack pointer */
00248     Tss->Rsp0 = Stack;
00249 
00250     /* Setup a stack for Double Fault Traps */
00251     Tss->Ist[1] = (ULONG64)KiDoubleFaultStack;
00252 
00253     /* Setup a stack for CheckAbort Traps */
00254     Tss->Ist[2] = (ULONG64)KiDoubleFaultStack;
00255 
00256     /* Setup a stack for NMI Traps */
00257     Tss->Ist[3] = (ULONG64)KiDoubleFaultStack;
00258 
00259     /* Load the task register */
00260     __ltr(KGDT64_SYS_TSS);
00261 }
00262 
00263 VOID
00264 NTAPI
00265 INIT_FUNCTION
00266 KiInitializeKernelMachineDependent(
00267     IN PKPRCB Prcb,
00268     IN PLOADER_PARAMETER_BLOCK LoaderBlock)
00269 {
00270     /* Set boot-level flags */
00271     KeI386CpuType = Prcb->CpuType;
00272     KeI386CpuStep = Prcb->CpuStep;
00273     KeProcessorArchitecture = PROCESSOR_ARCHITECTURE_AMD64;
00274     KeProcessorLevel = (USHORT)Prcb->CpuType;
00275     if (Prcb->CpuID) KeProcessorRevision = Prcb->CpuStep;
00276 
00277     /* Set basic CPU Features that user mode can read */
00278     SharedUserData->ProcessorFeatures[PF_MMX_INSTRUCTIONS_AVAILABLE] =
00279         (Prcb->FeatureBits & KF_MMX) ? TRUE: FALSE;
00280     SharedUserData->ProcessorFeatures[PF_COMPARE_EXCHANGE_DOUBLE] = TRUE;
00281     SharedUserData->ProcessorFeatures[PF_XMMI_INSTRUCTIONS_AVAILABLE] =
00282         ((Prcb->FeatureBits & KF_FXSR) && (Prcb->FeatureBits & KF_XMMI)) ? TRUE: FALSE;
00283     SharedUserData->ProcessorFeatures[PF_XMMI64_INSTRUCTIONS_AVAILABLE] =
00284         ((Prcb->FeatureBits & KF_FXSR) && (Prcb->FeatureBits & KF_XMMI64)) ? TRUE: FALSE;
00285     SharedUserData->ProcessorFeatures[PF_3DNOW_INSTRUCTIONS_AVAILABLE] =
00286         (Prcb->FeatureBits & KF_3DNOW) ? TRUE: FALSE;
00287     SharedUserData->ProcessorFeatures[PF_RDTSC_INSTRUCTION_AVAILABLE] = TRUE;
00288 
00289     /* Set the default NX policy (opt-in) */
00290     SharedUserData->NXSupportPolicy = NX_SUPPORT_POLICY_OPTIN;
00291 
00292     /* Check if NPX is always on */
00293     if (strstr(KeLoaderBlock->LoadOptions, "NOEXECUTE=ALWAYSON"))
00294     {
00295         /* Set it always on */
00296         SharedUserData->NXSupportPolicy = NX_SUPPORT_POLICY_ALWAYSON;
00297         Prcb->FeatureBits |= KF_NX_ENABLED;
00298     }
00299     else if (strstr(KeLoaderBlock->LoadOptions, "NOEXECUTE=OPTOUT"))
00300     {
00301         /* Set it in opt-out mode */
00302         SharedUserData->NXSupportPolicy = NX_SUPPORT_POLICY_OPTOUT;
00303         Prcb->FeatureBits |= KF_NX_ENABLED;
00304     }
00305     else if ((strstr(KeLoaderBlock->LoadOptions, "NOEXECUTE=OPTIN")) ||
00306              (strstr(KeLoaderBlock->LoadOptions, "NOEXECUTE")))
00307     {
00308         /* Set the feature bits */
00309         Prcb->FeatureBits |= KF_NX_ENABLED;
00310     }
00311     else if ((strstr(KeLoaderBlock->LoadOptions, "NOEXECUTE=ALWAYSOFF")) ||
00312              (strstr(KeLoaderBlock->LoadOptions, "EXECUTE")))
00313     {
00314         /* Set disabled mode */
00315         SharedUserData->NXSupportPolicy = NX_SUPPORT_POLICY_ALWAYSOFF;
00316         Prcb->FeatureBits |= KF_NX_DISABLED;
00317     }
00318 
00319 }
00320 
00321 static LDR_DATA_TABLE_ENTRY LdrCoreEntries[3];
00322 
00323 void
00324 KiInitModuleList(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
00325 {
00326     PLDR_DATA_TABLE_ENTRY LdrEntry;
00327     PLIST_ENTRY Entry;
00328     ULONG i;
00329 
00330     /* Initialize the list head */
00331     InitializeListHead(&PsLoadedModuleList);
00332 
00333     /* Loop the first 3 entries */
00334     for (Entry = LoaderBlock->LoadOrderListHead.Flink, i = 0;
00335          Entry != &LoaderBlock->LoadOrderListHead && i < 3;
00336          Entry = Entry->Flink, i++)
00337     {
00338         /* Get the data table entry */
00339         LdrEntry = CONTAINING_RECORD(Entry,
00340                                      LDR_DATA_TABLE_ENTRY,
00341                                      InLoadOrderLinks);
00342 
00343         /* Copy the entry */
00344         LdrCoreEntries[i] = *LdrEntry;
00345 
00346         /* Insert the copy into the list */
00347         InsertTailList(&PsLoadedModuleList, &LdrCoreEntries[i].InLoadOrderLinks);
00348     }
00349 }
00350 
00351 VOID
00352 NTAPI
00353 KiSystemStartup(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
00354 {
00355     CCHAR Cpu;
00356     PKTHREAD InitialThread;
00357     ULONG64 InitialStack;
00358     PKIPCR Pcr;
00359 
00360     /* HACK */
00361     FrLdrDbgPrint = LoaderBlock->u.I386.CommonDataArea;
00362     //FrLdrDbgPrint("Hello from KiSystemStartup!!!\n");
00363 
00364     /* Save the loader block */
00365     KeLoaderBlock = LoaderBlock;
00366 
00367     /* Get the current CPU number */
00368     Cpu = (CCHAR)KeNumberProcessors++; // FIXME
00369 
00370     /* LoaderBlock initialization for Cpu 0 */
00371     if (Cpu == 0)
00372     {
00373         /* Set the initial stack, idle thread and process */
00374         LoaderBlock->KernelStack = (ULONG_PTR)P0BootStack;
00375         LoaderBlock->Thread = (ULONG_PTR)&KiInitialThread;
00376         LoaderBlock->Process = (ULONG_PTR)&KiInitialProcess.Pcb;
00377         LoaderBlock->Prcb = (ULONG_PTR)&KiInitialPcr.Prcb;
00378     }
00379 
00380     /* Get Pcr from loader block */
00381     Pcr = CONTAINING_RECORD(LoaderBlock->Prcb, KIPCR, Prcb);
00382 
00383     /* Set the PRCB for this Processor */
00384     KiProcessorBlock[Cpu] = &Pcr->Prcb;
00385 
00386     /* Align stack to 16 bytes */
00387     LoaderBlock->KernelStack &= ~(16 - 1);
00388 
00389     /* Save the initial thread and stack */
00390     InitialStack = LoaderBlock->KernelStack; // Checkme
00391     InitialThread = (PKTHREAD)LoaderBlock->Thread;
00392 
00393     /* Set us as the current process */
00394     InitialThread->ApcState.Process = (PVOID)LoaderBlock->Process;
00395 
00396     /* Initialize the PCR */
00397     KiInitializePcr(Pcr, Cpu, InitialThread, (PVOID)KiDoubleFaultStack);
00398 
00399     /* Initialize the CPU features */
00400     KiInitializeCpu(Pcr);
00401 
00402     /* Initial setup for the boot CPU */
00403     if (Cpu == 0)
00404     {
00405         /* Initialize the module list (ntos, hal, kdcom) */
00406         KiInitModuleList(LoaderBlock);
00407 
00408         /* Setup the TSS descriptors and entries */
00409         KiInitializeTss(Pcr->TssBase, InitialStack);
00410 
00411         /* Setup the IDT */
00412         KeInitExceptions();
00413 
00414          /* Initialize debugging system */
00415         KdInitSystem(0, KeLoaderBlock);
00416 
00417         /* Check for break-in */
00418         if (KdPollBreakIn()) DbgBreakPointWithStatus(DBG_STATUS_CONTROL_C);
00419     }
00420 
00421     DPRINT1("Pcr = %p, Gdt = %p, Idt = %p, Tss = %p\n",
00422            Pcr, Pcr->GdtBase, Pcr->IdtBase, Pcr->TssBase);
00423 
00424     /* Acquire lock */
00425     while (InterlockedBitTestAndSet64((PLONG64)&KiFreezeExecutionLock, 0))
00426     {
00427         /* Loop until lock is free */
00428         while ((*(volatile KSPIN_LOCK*)&KiFreezeExecutionLock) & 1);
00429     }
00430 
00431     /* Initialize the Processor with HAL */
00432     HalInitializeProcessor(Cpu, KeLoaderBlock);
00433 
00434     /* Set processor as active */
00435     KeActiveProcessors |= 1ULL << Cpu;
00436 
00437     /* Release lock */
00438     InterlockedAnd64((PLONG64)&KiFreezeExecutionLock, 0);
00439 
00440     /* Raise to HIGH_LEVEL */
00441     KfRaiseIrql(HIGH_LEVEL);
00442 
00443     /* Machine specific kernel initialization */
00444     if (Cpu == 0) KiInitializeKernelMachineDependent(&Pcr->Prcb, LoaderBlock);
00445 
00446     /* Switch to new kernel stack and start kernel bootstrapping */
00447     KiSwitchToBootStack(InitialStack & ~3);
00448 }
00449 

Generated on Tue May 22 2012 04:41:27 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.