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