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 * 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
1.7.6.1
|