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: BSD - See COPYING.ARM in the top level directory 00004 * FILE: ntoskrnl/ke/arm/kiinit.c 00005 * PURPOSE: Implements the kernel entry point for ARM machines 00006 * PROGRAMMERS: ReactOS Portable Systems Group 00007 */ 00008 00009 /* INCLUDES *******************************************************************/ 00010 00011 #include <ntoskrnl.h> 00012 #define NDEBUG 00013 #include <debug.h> 00014 00015 /* GLOBALS ********************************************************************/ 00016 00017 KINTERRUPT KxUnexpectedInterrupt; 00018 BOOLEAN KeIsArmV6; 00019 ULONG KeNumberProcessIds; 00020 ULONG KeNumberTbEntries; 00021 ULONG ProcessCount; // PERF 00022 extern PVOID KiArmVectorTable; 00023 #define __ARMV6__ KeIsArmV6 00024 00025 /* FUNCTIONS ******************************************************************/ 00026 00027 VOID 00028 NTAPI 00029 KiInitMachineDependent(VOID) 00030 { 00031 /* There is nothing to do on ARM */ 00032 return; 00033 } 00034 00035 VOID 00036 NTAPI 00037 KiInitializeKernel(IN PKPROCESS InitProcess, 00038 IN PKTHREAD InitThread, 00039 IN PVOID IdleStack, 00040 IN PKPRCB Prcb, 00041 IN CCHAR Number, 00042 IN PLOADER_PARAMETER_BLOCK LoaderBlock) 00043 { 00044 PKIPCR Pcr = (PKIPCR)KeGetPcr(); 00045 ULONG PageDirectory[2]; 00046 ULONG i; 00047 00048 /* Set the default NX policy (opt-in) */ 00049 SharedUserData->NXSupportPolicy = NX_SUPPORT_POLICY_OPTIN; 00050 00051 /* Initialize spinlocks and DPC data */ 00052 KiInitSpinLocks(Prcb, Number); 00053 00054 /* Set stack pointers */ 00055 Pcr->InitialStack = IdleStack; 00056 00057 /* Check if this is the Boot CPU */ 00058 if (!Number) 00059 { 00060 /* Setup the unexpected interrupt */ 00061 KxUnexpectedInterrupt.DispatchAddress = KiUnexpectedInterrupt; 00062 for (i = 0; i < 4; i++) 00063 { 00064 /* Copy the template code */ 00065 KxUnexpectedInterrupt.DispatchCode[i] = ((PULONG)KiInterruptTemplate)[i]; 00066 } 00067 00068 /* Set DMA coherency */ 00069 KiDmaIoCoherency = 0; 00070 00071 /* Sweep D-Cache */ 00072 HalSweepDcache(); 00073 00074 /* Set boot-level flags */ 00075 KeProcessorArchitecture = PROCESSOR_ARCHITECTURE_ARM; 00076 KeFeatureBits = 0; 00077 KeProcessorLevel = (USHORT)(Pcr->ProcessorId >> 8); 00078 KeProcessorRevision = (USHORT)(Pcr->ProcessorId & 0xFF); 00079 00080 /* Set the current MP Master KPRCB to the Boot PRCB */ 00081 Prcb->MultiThreadSetMaster = Prcb; 00082 00083 /* Lower to APC_LEVEL */ 00084 KeLowerIrql(APC_LEVEL); 00085 00086 /* Initialize portable parts of the OS */ 00087 KiInitSystem(); 00088 00089 /* Initialize the Idle Process and the Process Listhead */ 00090 InitializeListHead(&KiProcessListHead); 00091 PageDirectory[0] = 0; 00092 PageDirectory[1] = 0; 00093 KeInitializeProcess(InitProcess, 00094 0, 00095 0xFFFFFFFF, 00096 PageDirectory, 00097 FALSE); 00098 InitProcess->QuantumReset = MAXCHAR; 00099 } 00100 else 00101 { 00102 /* FIXME-V6: See if we want to support MP */ 00103 DPRINT1("ARM MPCore not supported\n"); 00104 } 00105 00106 /* Setup the Idle Thread */ 00107 KeInitializeThread(InitProcess, 00108 InitThread, 00109 NULL, 00110 NULL, 00111 NULL, 00112 NULL, 00113 NULL, 00114 IdleStack); 00115 InitThread->NextProcessor = Number; 00116 InitThread->Priority = HIGH_PRIORITY; 00117 InitThread->State = Running; 00118 InitThread->Affinity = 1 << Number; 00119 InitThread->WaitIrql = DISPATCH_LEVEL; 00120 InitProcess->ActiveProcessors = 1 << Number; 00121 00122 /* HACK for MmUpdatePageDir */ 00123 ((PETHREAD)InitThread)->ThreadsProcess = (PEPROCESS)InitProcess; 00124 00125 /* Set up the thread-related fields in the PRCB */ 00126 Prcb->CurrentThread = InitThread; 00127 Prcb->NextThread = NULL; 00128 Prcb->IdleThread = InitThread; 00129 00130 /* Initialize the Kernel Executive */ 00131 ExpInitializeExecutive(Number, LoaderBlock); 00132 00133 /* Only do this on the boot CPU */ 00134 if (!Number) 00135 { 00136 /* Calculate the time reciprocal */ 00137 KiTimeIncrementReciprocal = 00138 KiComputeReciprocal(KeMaximumIncrement, 00139 &KiTimeIncrementShiftCount); 00140 00141 /* Update DPC Values in case they got updated by the executive */ 00142 Prcb->MaximumDpcQueueDepth = KiMaximumDpcQueueDepth; 00143 Prcb->MinimumDpcRate = KiMinimumDpcRate; 00144 Prcb->AdjustDpcThreshold = KiAdjustDpcThreshold; 00145 } 00146 00147 /* Raise to Dispatch */ 00148 KfRaiseIrql(DISPATCH_LEVEL); 00149 00150 /* Set the Idle Priority to 0. This will jump into Phase 1 */ 00151 KeSetPriorityThread(InitThread, 0); 00152 00153 /* If there's no thread scheduled, put this CPU in the Idle summary */ 00154 KiAcquirePrcbLock(Prcb); 00155 if (!Prcb->NextThread) KiIdleSummary |= 1 << Number; 00156 KiReleasePrcbLock(Prcb); 00157 00158 /* Raise back to HIGH_LEVEL and clear the PRCB for the loader block */ 00159 KfRaiseIrql(HIGH_LEVEL); 00160 LoaderBlock->Prcb = 0; 00161 } 00162 00163 C_ASSERT((PKIPCR)KeGetPcr() == (PKIPCR)0xFFDFF000); 00164 C_ASSERT((FIELD_OFFSET(KIPCR, FirstLevelDcacheSize) & 4) == 0); 00165 C_ASSERT(sizeof(KIPCR) <= PAGE_SIZE); 00166 00167 VOID 00168 NTAPI 00169 KiInitializePcr(IN ULONG ProcessorNumber, 00170 IN PKIPCR Pcr, 00171 IN PKTHREAD IdleThread, 00172 IN PVOID PanicStack, 00173 IN PVOID InterruptStack) 00174 { 00175 ULONG i; 00176 00177 /* Set the Current Thread */ 00178 Pcr->PrcbData.CurrentThread = IdleThread; 00179 00180 /* Set pointers to ourselves */ 00181 Pcr->Self = (PKPCR)Pcr; 00182 Pcr->Prcb = &Pcr->PrcbData; 00183 00184 /* Set the PCR Version */ 00185 Pcr->MajorVersion = PCR_MAJOR_VERSION; 00186 Pcr->MinorVersion = PCR_MINOR_VERSION; 00187 00188 /* Set the PCRB Version */ 00189 Pcr->PrcbData.MajorVersion = 1; 00190 Pcr->PrcbData.MinorVersion = 1; 00191 00192 /* Set the Build Type */ 00193 Pcr->PrcbData.BuildType = 0; 00194 #ifndef CONFIG_SMP 00195 Pcr->PrcbData.BuildType |= PRCB_BUILD_UNIPROCESSOR; 00196 #endif 00197 #if DBG 00198 Pcr->PrcbData.BuildType |= PRCB_BUILD_DEBUG; 00199 #endif 00200 00201 /* Set the Processor Number and current Processor Mask */ 00202 Pcr->PrcbData.Number = (UCHAR)ProcessorNumber; 00203 Pcr->PrcbData.SetMember = 1 << ProcessorNumber; 00204 00205 /* Set the PRCB for this Processor */ 00206 KiProcessorBlock[ProcessorNumber] = Pcr->Prcb; 00207 00208 /* Start us out at PASSIVE_LEVEL */ 00209 Pcr->Irql = PASSIVE_LEVEL; 00210 00211 /* Set the stacks */ 00212 Pcr->PanicStack = PanicStack; 00213 Pcr->InterruptStack = InterruptStack; 00214 00215 /* Setup the processor set */ 00216 Pcr->PrcbData.MultiThreadProcessorSet = Pcr->PrcbData.SetMember; 00217 00218 /* Copy cache information from the loader block */ 00219 Pcr->FirstLevelDcacheSize = KeLoaderBlock->u.Arm.FirstLevelDcacheSize; 00220 Pcr->SecondLevelDcacheSize = KeLoaderBlock->u.Arm.SecondLevelDcacheSize; 00221 Pcr->FirstLevelIcacheSize = KeLoaderBlock->u.Arm.FirstLevelIcacheSize; 00222 Pcr->SecondLevelIcacheSize = KeLoaderBlock->u.Arm.SecondLevelIcacheSize; 00223 Pcr->FirstLevelDcacheFillSize = KeLoaderBlock->u.Arm.FirstLevelDcacheFillSize; 00224 Pcr->SecondLevelDcacheFillSize = KeLoaderBlock->u.Arm.SecondLevelDcacheFillSize; 00225 Pcr->FirstLevelIcacheFillSize = KeLoaderBlock->u.Arm.FirstLevelIcacheFillSize; 00226 Pcr->SecondLevelIcacheFillSize = KeLoaderBlock->u.Arm.SecondLevelIcacheFillSize; 00227 00228 /* Set global d-cache fill and alignment values */ 00229 if (!Pcr->SecondLevelDcacheSize) 00230 { 00231 /* Use the first level */ 00232 Pcr->DcacheFillSize = Pcr->FirstLevelDcacheSize; 00233 } 00234 else 00235 { 00236 /* Use the second level */ 00237 Pcr->DcacheFillSize = Pcr->SecondLevelDcacheSize; 00238 } 00239 00240 /* Set the alignment */ 00241 Pcr->DcacheAlignment = Pcr->DcacheFillSize - 1; 00242 00243 /* Set global i-cache fill and alignment values */ 00244 if (!Pcr->SecondLevelIcacheSize) 00245 { 00246 /* Use the first level */ 00247 Pcr->IcacheFillSize = Pcr->FirstLevelIcacheSize; 00248 } 00249 else 00250 { 00251 /* Use the second level */ 00252 Pcr->IcacheFillSize = Pcr->SecondLevelIcacheSize; 00253 } 00254 00255 /* Set the alignment */ 00256 Pcr->IcacheAlignment = Pcr->IcacheFillSize - 1; 00257 00258 /* Set processor information */ 00259 Pcr->ProcessorId = KeArmIdCodeRegisterGet().AsUlong; 00260 00261 /* Set all interrupt routines to unexpected interrupts as well */ 00262 for (i = 0; i < MAXIMUM_VECTOR; i++) 00263 { 00264 /* Point to the same template */ 00265 Pcr->InterruptRoutine[i] = (PVOID)&KxUnexpectedInterrupt.DispatchCode; 00266 } 00267 00268 /* Set default stall factor */ 00269 Pcr->StallScaleFactor = 50; 00270 00271 /* Setup software interrupts */ 00272 Pcr->InterruptRoutine[PASSIVE_LEVEL] = KiPassiveRelease; 00273 Pcr->InterruptRoutine[APC_LEVEL] = KiApcInterrupt; 00274 Pcr->InterruptRoutine[DISPATCH_LEVEL] = KiDispatchInterrupt; 00275 Pcr->ReservedVectors = (1 << PASSIVE_LEVEL) | 00276 (1 << APC_LEVEL) | 00277 (1 << DISPATCH_LEVEL) | 00278 (1 << IPI_LEVEL); 00279 } 00280 00281 VOID 00282 KiInitializeMachineType(VOID) 00283 { 00284 /* Detect ARM version */ 00285 KeIsArmV6 = KeArmIdCodeRegisterGet().Architecture >= 7; 00286 00287 /* Set the number of TLB entries and ASIDs */ 00288 KeNumberTbEntries = 64; 00289 if (__ARMV6__) 00290 { 00291 /* 256 ASIDs on v6/v7 */ 00292 KeNumberProcessIds = 256; 00293 } 00294 else 00295 { 00296 /* The TLB is VIVT on v4/v5 */ 00297 KeNumberProcessIds = 0; 00298 } 00299 } 00300 00301 VOID 00302 KiInitializeSystem(IN PLOADER_PARAMETER_BLOCK LoaderBlock) 00303 { 00304 ULONG Cpu; 00305 PKTHREAD InitialThread; 00306 PKPROCESS InitialProcess; 00307 ARM_CONTROL_REGISTER ControlRegister; 00308 PKIPCR Pcr = (PKIPCR)KeGetPcr(); 00309 PKTHREAD Thread; 00310 00311 /* Flush the TLB */ 00312 KeFlushTb(); 00313 00314 /* Save the loader block and get the current CPU */ 00315 KeLoaderBlock = LoaderBlock; 00316 Cpu = KeNumberProcessors; 00317 00318 /* Save the initial thread and process */ 00319 InitialThread = (PKTHREAD)LoaderBlock->Thread; 00320 InitialProcess = (PKPROCESS)LoaderBlock->Process; 00321 00322 /* Clean the APC List Head */ 00323 InitializeListHead(&InitialThread->ApcState.ApcListHead[KernelMode]); 00324 00325 /* Initialize the machine type */ 00326 KiInitializeMachineType(); 00327 00328 /* Skip initial setup if this isn't the Boot CPU */ 00329 if (Cpu) goto AppCpuInit; 00330 00331 /* Initialize the PCR */ 00332 RtlZeroMemory(Pcr, PAGE_SIZE); 00333 KiInitializePcr(Cpu, 00334 Pcr, 00335 InitialThread, 00336 (PVOID)LoaderBlock->u.Arm.PanicStack, 00337 (PVOID)LoaderBlock->u.Arm.InterruptStack); 00338 00339 /* Now sweep caches */ 00340 HalSweepIcache(); 00341 HalSweepDcache(); 00342 00343 /* Set us as the current process */ 00344 InitialThread->ApcState.Process = InitialProcess; 00345 00346 AppCpuInit: 00347 /* Setup CPU-related fields */ 00348 Pcr->Number = Cpu; 00349 Pcr->SetMember = 1 << Cpu; 00350 Pcr->SetMemberCopy = 1 << Cpu; 00351 Pcr->PrcbData.SetMember = 1 << Cpu; 00352 00353 /* Initialize the Processor with HAL */ 00354 HalInitializeProcessor(Cpu, KeLoaderBlock); 00355 00356 /* Set active processors */ 00357 KeActiveProcessors |= Pcr->SetMember; 00358 KeNumberProcessors++; 00359 00360 /* Check if this is the boot CPU */ 00361 if (!Cpu) 00362 { 00363 /* Initialize debugging system */ 00364 KdInitSystem(0, KeLoaderBlock); 00365 00366 /* Check for break-in */ 00367 if (KdPollBreakIn()) DbgBreakPointWithStatus(DBG_STATUS_CONTROL_C); 00368 } 00369 00370 /* Raise to HIGH_LEVEL */ 00371 KfRaiseIrql(HIGH_LEVEL); 00372 00373 /* Set the exception address to high */ 00374 ControlRegister = KeArmControlRegisterGet(); 00375 ControlRegister.HighVectors = TRUE; 00376 KeArmControlRegisterSet(ControlRegister); 00377 00378 /* Setup the exception vector table */ 00379 RtlCopyMemory((PVOID)0xFFFF0000, &KiArmVectorTable, 14 * sizeof(PVOID)); 00380 00381 /* Initialize the rest of the kernel now */ 00382 KiInitializeKernel((PKPROCESS)LoaderBlock->Process, 00383 (PKTHREAD)LoaderBlock->Thread, 00384 (PVOID)LoaderBlock->KernelStack, 00385 Pcr->Prcb, 00386 Pcr->Prcb->Number, 00387 KeLoaderBlock); 00388 00389 /* Set the priority of this thread to 0 */ 00390 Thread = KeGetCurrentThread(); 00391 Thread->Priority = 0; 00392 00393 /* Force interrupts enabled and lower IRQL back to DISPATCH_LEVEL */ 00394 _enable(); 00395 KfLowerIrql(DISPATCH_LEVEL); 00396 00397 /* Set the right wait IRQL */ 00398 Thread->WaitIrql = DISPATCH_LEVEL; 00399 00400 /* Jump into the idle loop */ 00401 KiIdleLoop(); 00402 } 00403 00404 ULONG 00405 DbgPrintEarly(const char *fmt, ...) 00406 { 00407 va_list args; 00408 unsigned int i; 00409 char Buffer[1024]; 00410 PCHAR String = Buffer; 00411 00412 va_start(args, fmt); 00413 i = vsprintf(Buffer, fmt, args); 00414 va_end(args); 00415 00416 /* Output the message */ 00417 while (*String != 0) 00418 { 00419 if (*String == '\n') 00420 { 00421 KdPortPutByteEx(NULL, '\r'); 00422 } 00423 KdPortPutByteEx(NULL, *String); 00424 String++; 00425 } 00426 00427 return STATUS_SUCCESS; 00428 } Generated on Fri May 25 2012 04:35:54 for ReactOS by
1.7.6.1
|