1 /* 2 * PROJECT: ReactOS Kernel 3 * LICENSE: GPL - See COPYING in the top level directory 4 * FILE: ntoskrnl/ke/krnlinit.c 5 * PURPOSE: Portable part of kernel initialization 6 * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org) 7 */ 8 9 /* INCLUDES ******************************************************************/ 10 11 #include <ntoskrnl.h> 12 #define NDEBUG 13 #include <debug.h> 14 #include <internal/napi.h> 15 16 /* GLOBALS *******************************************************************/ 17 18 /* Portable CPU Features and Flags */ 19 USHORT KeProcessorArchitecture; 20 USHORT KeProcessorLevel; 21 USHORT KeProcessorRevision; 22 ULONG KeFeatureBits; 23 24 /* System call count */ 25 ULONG KiServiceLimit = NUMBER_OF_SYSCALLS; 26 27 /* ARC Loader Block */ 28 PLOADER_PARAMETER_BLOCK KeLoaderBlock; 29 30 /* PRCB Array */ 31 PKPRCB KiProcessorBlock[MAXIMUM_PROCESSORS]; 32 33 /* NUMA Node Support */ 34 KNODE KiNode0; 35 PKNODE KeNodeBlock[1] = { &KiNode0 }; 36 UCHAR KeNumberNodes = 1; 37 UCHAR KeProcessNodeSeed; 38 39 /* Initial Process and Thread */ 40 ETHREAD KiInitialThread; 41 EPROCESS KiInitialProcess; 42 43 /* System-defined Spinlocks */ 44 KSPIN_LOCK KiDispatcherLock; 45 KSPIN_LOCK MmPfnLock; 46 KSPIN_LOCK MmSystemSpaceLock; 47 KSPIN_LOCK CcBcbSpinLock; 48 KSPIN_LOCK CcMasterSpinLock; 49 KSPIN_LOCK CcVacbSpinLock; 50 KSPIN_LOCK CcWorkQueueSpinLock; 51 KSPIN_LOCK NonPagedPoolLock; 52 KSPIN_LOCK MmNonPagedPoolLock; 53 KSPIN_LOCK IopCancelSpinLock; 54 KSPIN_LOCK IopVpbSpinLock; 55 KSPIN_LOCK IopDatabaseLock; 56 KSPIN_LOCK IopCompletionLock; 57 KSPIN_LOCK NtfsStructLock; 58 KSPIN_LOCK AfdWorkQueueSpinLock; 59 KSPIN_LOCK KiTimerTableLock[LOCK_QUEUE_TIMER_TABLE_LOCKS]; 60 KSPIN_LOCK KiReverseStallIpiLock; 61 62 /* FUNCTIONS *****************************************************************/ 63 64 CODE_SEG("INIT") 65 VOID 66 NTAPI 67 KiInitSystem(VOID) 68 { 69 ULONG i; 70 71 /* Initialize Bugcheck Callback data */ 72 InitializeListHead(&KeBugcheckCallbackListHead); 73 InitializeListHead(&KeBugcheckReasonCallbackListHead); 74 KeInitializeSpinLock(&BugCheckCallbackLock); 75 76 /* Initialize the Timer Expiration DPC */ 77 KeInitializeDpc(&KiTimerExpireDpc, KiTimerExpiration, NULL); 78 KeSetTargetProcessorDpc(&KiTimerExpireDpc, 0); 79 80 /* Initialize Profiling data */ 81 KeInitializeSpinLock(&KiProfileLock); 82 InitializeListHead(&KiProfileListHead); 83 InitializeListHead(&KiProfileSourceListHead); 84 85 /* Loop the timer table */ 86 for (i = 0; i < TIMER_TABLE_SIZE; i++) 87 { 88 /* Initialize the list and entries */ 89 InitializeListHead(&KiTimerTableListHead[i].Entry); 90 KiTimerTableListHead[i].Time.HighPart = 0xFFFFFFFF; 91 KiTimerTableListHead[i].Time.LowPart = 0; 92 } 93 94 /* Initialize the Swap event and all swap lists */ 95 KeInitializeEvent(&KiSwapEvent, SynchronizationEvent, FALSE); 96 InitializeListHead(&KiProcessInSwapListHead); 97 InitializeListHead(&KiProcessOutSwapListHead); 98 InitializeListHead(&KiStackInSwapListHead); 99 100 /* Initialize the mutex for generic DPC calls */ 101 ExInitializeFastMutex(&KiGenericCallDpcMutex); 102 103 /* Initialize the syscall table */ 104 KeServiceDescriptorTable[0].Base = MainSSDT; 105 KeServiceDescriptorTable[0].Count = NULL; 106 KeServiceDescriptorTable[0].Limit = KiServiceLimit; 107 KeServiceDescriptorTable[1].Limit = 0; 108 KeServiceDescriptorTable[0].Number = MainSSPT; 109 110 /* Copy the the current table into the shadow table for win32k */ 111 RtlCopyMemory(KeServiceDescriptorTableShadow, 112 KeServiceDescriptorTable, 113 sizeof(KeServiceDescriptorTable)); 114 } 115 116 CODE_SEG("INIT") 117 LARGE_INTEGER 118 NTAPI 119 KiComputeReciprocal(IN LONG Divisor, 120 OUT PUCHAR Shift) 121 { 122 LARGE_INTEGER Reciprocal = {{0, 0}}; 123 LONG BitCount = 0, Remainder = 1; 124 125 /* Start by calculating the remainder */ 126 while (Reciprocal.HighPart >= 0) 127 { 128 /* Increase the loop (bit) count */ 129 BitCount++; 130 131 /* Calculate the current fraction */ 132 Reciprocal.HighPart = (Reciprocal.HighPart << 1) | 133 (Reciprocal.LowPart >> 31); 134 Reciprocal.LowPart <<= 1; 135 136 /* Double the remainder and see if we went past the divisor */ 137 Remainder <<= 1; 138 if (Remainder >= Divisor) 139 { 140 /* Set the low-bit and calculate the new remainder */ 141 Remainder -= Divisor; 142 Reciprocal.LowPart |= 1; 143 } 144 } 145 146 /* Check if we have a remainder */ 147 if (Remainder) 148 { 149 /* Check if the current fraction value is too large */ 150 if ((Reciprocal.LowPart == 0xFFFFFFFF) && 151 (Reciprocal.HighPart == (LONG)0xFFFFFFFF)) 152 { 153 /* Set the high bit and reduce the bit count */ 154 Reciprocal.LowPart = 0; 155 Reciprocal.HighPart = 0x80000000; 156 BitCount--; 157 } 158 else 159 { 160 /* Check if only the lowest bits got too large */ 161 if (Reciprocal.LowPart == 0xFFFFFFFF) 162 { 163 /* Reset them and increase the high bits instead */ 164 Reciprocal.LowPart = 0; 165 Reciprocal.HighPart++; 166 } 167 else 168 { 169 /* All is well, increase the low bits */ 170 Reciprocal.LowPart++; 171 } 172 } 173 } 174 175 /* Now calculate the actual shift and return the reciprocal */ 176 *Shift = (UCHAR)BitCount - 64; 177 return Reciprocal; 178 } 179 180 CODE_SEG("INIT") 181 VOID 182 NTAPI 183 KiInitSpinLocks(IN PKPRCB Prcb, 184 IN CCHAR Number) 185 { 186 ULONG i; 187 188 /* Initialize Dispatcher Fields */ 189 Prcb->QueueIndex = 1; 190 Prcb->ReadySummary = 0; 191 Prcb->DeferredReadyListHead.Next = NULL; 192 for (i = 0; i < MAXIMUM_PRIORITY; i++) 193 { 194 /* Initialize the ready list */ 195 InitializeListHead(&Prcb->DispatcherReadyListHead[i]); 196 } 197 198 /* Initialize DPC Fields */ 199 InitializeListHead(&Prcb->DpcData[DPC_NORMAL].DpcListHead); 200 KeInitializeSpinLock(&Prcb->DpcData[DPC_NORMAL].DpcLock); 201 Prcb->DpcData[DPC_NORMAL].DpcQueueDepth = 0; 202 Prcb->DpcData[DPC_NORMAL].DpcCount = 0; 203 Prcb->DpcRoutineActive = FALSE; 204 Prcb->MaximumDpcQueueDepth = KiMaximumDpcQueueDepth; 205 Prcb->MinimumDpcRate = KiMinimumDpcRate; 206 Prcb->AdjustDpcThreshold = KiAdjustDpcThreshold; 207 KeInitializeDpc(&Prcb->CallDpc, NULL, NULL); 208 KeSetTargetProcessorDpc(&Prcb->CallDpc, Number); 209 KeSetImportanceDpc(&Prcb->CallDpc, HighImportance); 210 211 /* Initialize the Wait List Head */ 212 InitializeListHead(&Prcb->WaitListHead); 213 214 /* Initialize Queued Spinlocks */ 215 Prcb->LockQueue[LockQueueDispatcherLock].Next = NULL; 216 Prcb->LockQueue[LockQueueDispatcherLock].Lock = &KiDispatcherLock; 217 Prcb->LockQueue[LockQueueExpansionLock].Next = NULL; 218 Prcb->LockQueue[LockQueueExpansionLock].Lock = NULL; 219 Prcb->LockQueue[LockQueuePfnLock].Next = NULL; 220 Prcb->LockQueue[LockQueuePfnLock].Lock = &MmPfnLock; 221 Prcb->LockQueue[LockQueueSystemSpaceLock].Next = NULL; 222 Prcb->LockQueue[LockQueueSystemSpaceLock].Lock = &MmSystemSpaceLock; 223 Prcb->LockQueue[LockQueueBcbLock].Next = NULL; 224 Prcb->LockQueue[LockQueueBcbLock].Lock = &CcBcbSpinLock; 225 Prcb->LockQueue[LockQueueMasterLock].Next = NULL; 226 Prcb->LockQueue[LockQueueMasterLock].Lock = &CcMasterSpinLock; 227 Prcb->LockQueue[LockQueueVacbLock].Next = NULL; 228 Prcb->LockQueue[LockQueueVacbLock].Lock = &CcVacbSpinLock; 229 Prcb->LockQueue[LockQueueWorkQueueLock].Next = NULL; 230 Prcb->LockQueue[LockQueueWorkQueueLock].Lock = &CcWorkQueueSpinLock; 231 Prcb->LockQueue[LockQueueNonPagedPoolLock].Next = NULL; 232 Prcb->LockQueue[LockQueueNonPagedPoolLock].Lock = &NonPagedPoolLock; 233 Prcb->LockQueue[LockQueueMmNonPagedPoolLock].Next = NULL; 234 Prcb->LockQueue[LockQueueMmNonPagedPoolLock].Lock = &MmNonPagedPoolLock; 235 Prcb->LockQueue[LockQueueIoCancelLock].Next = NULL; 236 Prcb->LockQueue[LockQueueIoCancelLock].Lock = &IopCancelSpinLock; 237 Prcb->LockQueue[LockQueueIoVpbLock].Next = NULL; 238 Prcb->LockQueue[LockQueueIoVpbLock].Lock = &IopVpbSpinLock; 239 Prcb->LockQueue[LockQueueIoDatabaseLock].Next = NULL; 240 Prcb->LockQueue[LockQueueIoDatabaseLock].Lock = &IopDatabaseLock; 241 Prcb->LockQueue[LockQueueIoCompletionLock].Next = NULL; 242 Prcb->LockQueue[LockQueueIoCompletionLock].Lock = &IopCompletionLock; 243 Prcb->LockQueue[LockQueueNtfsStructLock].Next = NULL; 244 Prcb->LockQueue[LockQueueNtfsStructLock].Lock = &NtfsStructLock; 245 Prcb->LockQueue[LockQueueAfdWorkQueueLock].Next = NULL; 246 Prcb->LockQueue[LockQueueAfdWorkQueueLock].Lock = &AfdWorkQueueSpinLock; 247 Prcb->LockQueue[LockQueueUnusedSpare16].Next = NULL; 248 Prcb->LockQueue[LockQueueUnusedSpare16].Lock = NULL; 249 250 /* Loop timer locks (shared amongst all CPUs) */ 251 for (i = 0; i < LOCK_QUEUE_TIMER_TABLE_LOCKS; i++) 252 { 253 /* Setup the Queued Spinlock (done only once by the boot CPU) */ 254 if (!Number) 255 KeInitializeSpinLock(&KiTimerTableLock[i]); 256 257 /* Initialize the lock */ 258 Prcb->LockQueue[LockQueueTimerTableLock + i].Next = NULL; 259 Prcb->LockQueue[LockQueueTimerTableLock + i].Lock = 260 &KiTimerTableLock[i]; 261 } 262 263 /* Initialize the PRCB lock */ 264 KeInitializeSpinLock(&Prcb->PrcbLock); 265 266 /* Check if this is the boot CPU */ 267 if (!Number) 268 { 269 /* Initialize the lock themselves */ 270 KeInitializeSpinLock(&KiDispatcherLock); 271 KeInitializeSpinLock(&KiReverseStallIpiLock); 272 KeInitializeSpinLock(&MmPfnLock); 273 KeInitializeSpinLock(&MmSystemSpaceLock); 274 KeInitializeSpinLock(&CcBcbSpinLock); 275 KeInitializeSpinLock(&CcMasterSpinLock); 276 KeInitializeSpinLock(&CcVacbSpinLock); 277 KeInitializeSpinLock(&CcWorkQueueSpinLock); 278 KeInitializeSpinLock(&IopCancelSpinLock); 279 KeInitializeSpinLock(&IopCompletionLock); 280 KeInitializeSpinLock(&IopDatabaseLock); 281 KeInitializeSpinLock(&IopVpbSpinLock); 282 KeInitializeSpinLock(&NonPagedPoolLock); 283 KeInitializeSpinLock(&MmNonPagedPoolLock); 284 KeInitializeSpinLock(&NtfsStructLock); 285 KeInitializeSpinLock(&AfdWorkQueueSpinLock); 286 } 287 } 288 289 CODE_SEG("INIT") 290 BOOLEAN 291 NTAPI 292 KeInitSystem(VOID) 293 { 294 /* Check if Threaded DPCs are enabled */ 295 if (KeThreadDpcEnable) 296 { 297 /* FIXME: TODO */ 298 DPRINT1("Threaded DPCs not yet supported\n"); 299 } 300 301 /* Initialize non-portable parts of the kernel */ 302 KiInitMachineDependent(); 303 return TRUE; 304 } 305