1 /* 2 * PROJECT: ReactOS Kernel 3 * LICENSE: GPL - See COPYING in the top level directory 4 * FILE: ntoskrnl/ke/amd64/krnlinit.c 5 * PURPOSE: Portable part of kernel initialization 6 * PROGRAMMERS: Timo Kreuzer (timo.kreuzer@reactos.org) 7 * Alex Ionescu (alex.ionescu@reactos.org) 8 */ 9 10 /* INCLUDES ******************************************************************/ 11 12 #include <ntoskrnl.h> 13 #define NDEBUG 14 #include <debug.h> 15 16 extern ULONG_PTR MainSSDT[]; 17 extern UCHAR MainSSPT[]; 18 19 extern BOOLEAN RtlpUse16ByteSLists; 20 21 /* FUNCTIONS *****************************************************************/ 22 23 VOID 24 NTAPI 25 INIT_FUNCTION 26 KiInitializeKernel(IN PKPROCESS InitProcess, 27 IN PKTHREAD InitThread, 28 IN PVOID IdleStack, 29 IN PKPRCB Prcb, 30 IN PLOADER_PARAMETER_BLOCK LoaderBlock); 31 32 33 VOID 34 NTAPI 35 KiInitializeHandBuiltThread( 36 IN PKTHREAD Thread, 37 IN PKPROCESS Process, 38 IN PVOID Stack) 39 { 40 PKPRCB Prcb = KeGetCurrentPrcb(); 41 42 /* Setup the Thread */ 43 KeInitializeThread(Process, Thread, NULL, NULL, NULL, NULL, NULL, Stack); 44 45 Thread->NextProcessor = Prcb->Number; 46 Thread->Priority = HIGH_PRIORITY; 47 Thread->State = Running; 48 Thread->Affinity = (ULONG_PTR)1 << Prcb->Number; 49 Thread->WaitIrql = DISPATCH_LEVEL; 50 Process->ActiveProcessors |= (ULONG_PTR)1 << Prcb->Number; 51 52 } 53 54 VOID 55 NTAPI 56 INIT_FUNCTION 57 KiSystemStartupBootStack(VOID) 58 { 59 PLOADER_PARAMETER_BLOCK LoaderBlock = KeLoaderBlock; // hack 60 PKPRCB Prcb = KeGetCurrentPrcb(); 61 PKTHREAD Thread = (PKTHREAD)KeLoaderBlock->Thread; 62 PKPROCESS Process = Thread->ApcState.Process; 63 PVOID KernelStack = (PVOID)KeLoaderBlock->KernelStack; 64 65 /* Initialize the Power Management Support for this PRCB */ 66 PoInitializePrcb(Prcb); 67 68 /* Save CPU state */ 69 KiSaveProcessorControlState(&Prcb->ProcessorState); 70 71 /* Get cache line information for this CPU */ 72 KiGetCacheInformation(); 73 74 /* Initialize spinlocks and DPC data */ 75 KiInitSpinLocks(Prcb, Prcb->Number); 76 77 /* Set up the thread-related fields in the PRCB */ 78 Prcb->CurrentThread = Thread; 79 Prcb->NextThread = NULL; 80 Prcb->IdleThread = Thread; 81 82 /* Initialize PRCB pool lookaside pointers */ 83 ExInitPoolLookasidePointers(); 84 85 /* Lower to APC_LEVEL */ 86 KeLowerIrql(APC_LEVEL); 87 88 /* Check if this is the boot cpu */ 89 if (Prcb->Number == 0) 90 { 91 /* Initialize the kernel */ 92 KiInitializeKernel(Process, Thread, KernelStack, Prcb, LoaderBlock); 93 } 94 else 95 { 96 /* Initialize the startup thread */ 97 KiInitializeHandBuiltThread(Thread, Process, KernelStack); 98 99 /* Initialize cpu with HAL */ 100 if (!HalInitSystem(0, LoaderBlock)) 101 { 102 /* Initialization failed */ 103 KeBugCheck(HAL_INITIALIZATION_FAILED); 104 } 105 } 106 107 /* Raise to Dispatch */ 108 KfRaiseIrql(DISPATCH_LEVEL); 109 110 /* Set the Idle Priority to 0. This will jump into Phase 1 */ 111 KeSetPriorityThread(Thread, 0); 112 113 /* If there's no thread scheduled, put this CPU in the Idle summary */ 114 KiAcquirePrcbLock(Prcb); 115 if (!Prcb->NextThread) KiIdleSummary |= (ULONG_PTR)1 << Prcb->Number; 116 KiReleasePrcbLock(Prcb); 117 118 /* Raise back to HIGH_LEVEL and clear the PRCB for the loader block */ 119 KfRaiseIrql(HIGH_LEVEL); 120 LoaderBlock->Prcb = 0; 121 122 /* Set the priority of this thread to 0 */ 123 Thread = KeGetCurrentThread(); 124 Thread->Priority = 0; 125 126 /* Force interrupts enabled and lower IRQL back to DISPATCH_LEVEL */ 127 _enable(); 128 KeLowerIrql(DISPATCH_LEVEL); 129 130 /* Set the right wait IRQL */ 131 Thread->WaitIrql = DISPATCH_LEVEL; 132 133 /* Jump into the idle loop */ 134 KiIdleLoop(); 135 } 136 137 VOID 138 NTAPI 139 INIT_FUNCTION 140 KiInitializeKernel(IN PKPROCESS InitProcess, 141 IN PKTHREAD InitThread, 142 IN PVOID IdleStack, 143 IN PKPRCB Prcb, 144 IN PLOADER_PARAMETER_BLOCK LoaderBlock) 145 { 146 ULONG_PTR PageDirectory[2]; 147 PVOID DpcStack; 148 ULONG i; 149 150 /* Set Node Data */ 151 KeNodeBlock[0] = &KiNode0; 152 Prcb->ParentNode = KeNodeBlock[0]; 153 KeNodeBlock[0]->ProcessorMask = Prcb->SetMember; 154 155 /* Set boot-level flags */ 156 KeFeatureBits = Prcb->FeatureBits; 157 158 /* Initialize 8/16 bit SList support */ 159 RtlpUse16ByteSLists = (KeFeatureBits & KF_CMPXCHG16B) ? TRUE : FALSE; 160 161 /* Set the current MP Master KPRCB to the Boot PRCB */ 162 Prcb->MultiThreadSetMaster = Prcb; 163 164 /* Initialize Bugcheck Callback data */ 165 InitializeListHead(&KeBugcheckCallbackListHead); 166 InitializeListHead(&KeBugcheckReasonCallbackListHead); 167 KeInitializeSpinLock(&BugCheckCallbackLock); 168 169 /* Initialize the Timer Expiration DPC */ 170 KeInitializeDpc(&KiTimerExpireDpc, KiTimerExpiration, NULL); 171 KeSetTargetProcessorDpc(&KiTimerExpireDpc, 0); 172 173 /* Initialize Profiling data */ 174 KeInitializeSpinLock(&KiProfileLock); 175 InitializeListHead(&KiProfileListHead); 176 InitializeListHead(&KiProfileSourceListHead); 177 178 /* Loop the timer table */ 179 for (i = 0; i < TIMER_TABLE_SIZE; i++) 180 { 181 /* Initialize the list and entries */ 182 InitializeListHead(&KiTimerTableListHead[i].Entry); 183 KiTimerTableListHead[i].Time.HighPart = 0xFFFFFFFF; 184 KiTimerTableListHead[i].Time.LowPart = 0; 185 } 186 187 /* Initialize the Swap event and all swap lists */ 188 KeInitializeEvent(&KiSwapEvent, SynchronizationEvent, FALSE); 189 InitializeListHead(&KiProcessInSwapListHead); 190 InitializeListHead(&KiProcessOutSwapListHead); 191 InitializeListHead(&KiStackInSwapListHead); 192 193 /* Initialize the mutex for generic DPC calls */ 194 ExInitializeFastMutex(&KiGenericCallDpcMutex); 195 196 /* Initialize the syscall table */ 197 KeServiceDescriptorTable[0].Base = MainSSDT; 198 KeServiceDescriptorTable[0].Count = NULL; 199 KeServiceDescriptorTable[0].Limit = KiServiceLimit; 200 KeServiceDescriptorTable[1].Limit = 0; 201 KeServiceDescriptorTable[0].Number = MainSSPT; 202 203 /* Copy the the current table into the shadow table for win32k */ 204 RtlCopyMemory(KeServiceDescriptorTableShadow, 205 KeServiceDescriptorTable, 206 sizeof(KeServiceDescriptorTable)); 207 208 /* Initialize the Idle Process and the Process Listhead */ 209 InitializeListHead(&KiProcessListHead); 210 PageDirectory[0] = 0; 211 PageDirectory[1] = 0; 212 KeInitializeProcess(InitProcess, 213 0, 214 0xFFFFFFFF, 215 PageDirectory, 216 FALSE); 217 InitProcess->QuantumReset = MAXCHAR; 218 219 /* Initialize the startup thread */ 220 KiInitializeHandBuiltThread(InitThread, InitProcess, IdleStack); 221 222 /* Initialize the Kernel Executive */ 223 ExpInitializeExecutive(0, LoaderBlock); 224 225 /* Calculate the time reciprocal */ 226 KiTimeIncrementReciprocal = 227 KiComputeReciprocal(KeMaximumIncrement, 228 &KiTimeIncrementShiftCount); 229 230 /* Update DPC Values in case they got updated by the executive */ 231 Prcb->MaximumDpcQueueDepth = KiMaximumDpcQueueDepth; 232 Prcb->MinimumDpcRate = KiMinimumDpcRate; 233 Prcb->AdjustDpcThreshold = KiAdjustDpcThreshold; 234 235 /* Allocate the DPC Stack */ 236 DpcStack = MmCreateKernelStack(FALSE, 0); 237 if (!DpcStack) KeBugCheckEx(NO_PAGES_AVAILABLE, 1, 0, 0, 0); 238 Prcb->DpcStack = DpcStack; 239 } 240 241