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)
9 /* INCLUDES ******************************************************************/
14 #include <internal/napi.h>
16 /* GLOBALS *******************************************************************/
18 /* Portable CPU Features and Flags */
19 USHORT KeProcessorArchitecture
;
20 USHORT KeProcessorLevel
;
21 USHORT KeProcessorRevision
;
23 KAFFINITY KeActiveProcessors
= 1;
25 /* System call count */
26 ULONG KiServiceLimit
= NUMBER_OF_SYSCALLS
;
28 /* ARC Loader Block */
29 PLOADER_PARAMETER_BLOCK KeLoaderBlock
;
32 PKPRCB KiProcessorBlock
[MAXIMUM_PROCESSORS
];
34 /* Number of processors */
35 UCHAR KeNumberProcessors
= 0;
37 /* NUMA Node Support */
39 PKNODE KeNodeBlock
[1];
40 UCHAR KeNumberNodes
= 1;
41 UCHAR KeProcessNodeSeed
;
43 /* Initial Process and Thread */
44 ETHREAD KiInitialThread
;
45 EPROCESS KiInitialProcess
;
47 /* System-defined Spinlocks */
48 KSPIN_LOCK KiDispatcherLock
;
50 KSPIN_LOCK MmSystemSpaceLock
;
51 KSPIN_LOCK CcBcbSpinLock
;
52 KSPIN_LOCK CcMasterSpinLock
;
53 KSPIN_LOCK CcVacbSpinLock
;
54 KSPIN_LOCK CcWorkQueueSpinLock
;
55 KSPIN_LOCK NonPagedPoolLock
;
56 KSPIN_LOCK MmNonPagedPoolLock
;
57 KSPIN_LOCK IopCancelSpinLock
;
58 KSPIN_LOCK IopVpbSpinLock
;
59 KSPIN_LOCK IopDatabaseLock
;
60 KSPIN_LOCK IopCompletionLock
;
61 KSPIN_LOCK NtfsStructLock
;
62 KSPIN_LOCK AfdWorkQueueSpinLock
;
63 KSPIN_LOCK KiTimerTableLock
[16];
64 KSPIN_LOCK KiReverseStallIpiLock
;
66 /* FUNCTIONS *****************************************************************/
75 /* Initialize Bugcheck Callback data */
76 InitializeListHead(&KeBugcheckCallbackListHead
);
77 InitializeListHead(&KeBugcheckReasonCallbackListHead
);
78 KeInitializeSpinLock(&BugCheckCallbackLock
);
80 /* Initialize the Timer Expiration DPC */
81 KeInitializeDpc(&KiTimerExpireDpc
, KiTimerExpiration
, NULL
);
82 KeSetTargetProcessorDpc(&KiTimerExpireDpc
, 0);
84 /* Initialize Profiling data */
85 KeInitializeSpinLock(&KiProfileLock
);
86 InitializeListHead(&KiProfileListHead
);
87 InitializeListHead(&KiProfileSourceListHead
);
89 /* Loop the timer table */
90 for (i
= 0; i
< TIMER_TABLE_SIZE
; i
++)
92 /* Initialize the list and entries */
93 InitializeListHead(&KiTimerTableListHead
[i
].Entry
);
94 KiTimerTableListHead
[i
].Time
.HighPart
= 0xFFFFFFFF;
95 KiTimerTableListHead
[i
].Time
.LowPart
= 0;
98 /* Initialize the Swap event and all swap lists */
99 KeInitializeEvent(&KiSwapEvent
, SynchronizationEvent
, FALSE
);
100 InitializeListHead(&KiProcessInSwapListHead
);
101 InitializeListHead(&KiProcessOutSwapListHead
);
102 InitializeListHead(&KiStackInSwapListHead
);
104 /* Initialize the mutex for generic DPC calls */
105 ExInitializeFastMutex(&KiGenericCallDpcMutex
);
107 /* Initialize the syscall table */
108 KeServiceDescriptorTable
[0].Base
= MainSSDT
;
109 KeServiceDescriptorTable
[0].Count
= NULL
;
110 KeServiceDescriptorTable
[0].Limit
= KiServiceLimit
;
111 KeServiceDescriptorTable
[1].Limit
= 0;
112 KeServiceDescriptorTable
[0].Number
= MainSSPT
;
114 /* Copy the the current table into the shadow table for win32k */
115 RtlCopyMemory(KeServiceDescriptorTableShadow
,
116 KeServiceDescriptorTable
,
117 sizeof(KeServiceDescriptorTable
));
123 KiComputeReciprocal(IN LONG Divisor
,
126 LARGE_INTEGER Reciprocal
= {{0, 0}};
127 LONG BitCount
= 0, Remainder
= 1;
129 /* Start by calculating the remainder */
130 while (Reciprocal
.HighPart
>= 0)
132 /* Increase the loop (bit) count */
135 /* Calculate the current fraction */
136 Reciprocal
.HighPart
= (Reciprocal
.HighPart
<< 1) |
137 (Reciprocal
.LowPart
>> 31);
138 Reciprocal
.LowPart
<<= 1;
140 /* Double the remainder and see if we went past the divisor */
142 if (Remainder
>= Divisor
)
144 /* Set the low-bit and calculate the new remainder */
145 Remainder
-= Divisor
;
146 Reciprocal
.LowPart
|= 1;
150 /* Check if we have a remainder */
153 /* Check if the current fraction value is too large */
154 if ((Reciprocal
.LowPart
== 0xFFFFFFFF) &&
155 (Reciprocal
.HighPart
== (LONG
)0xFFFFFFFF))
157 /* Set the high bit and reduce the bit count */
158 Reciprocal
.LowPart
= 0;
159 Reciprocal
.HighPart
= 0x80000000;
164 /* Check if only the lowest bits got too large */
165 if (Reciprocal
.LowPart
== 0xFFFFFFFF)
167 /* Reset them and increase the high bits instead */
168 Reciprocal
.LowPart
= 0;
169 Reciprocal
.HighPart
++;
173 /* All is well, increase the low bits */
174 Reciprocal
.LowPart
++;
179 /* Now calculate the actual shift and return the reciprocal */
180 *Shift
= (UCHAR
)BitCount
- 64;
187 KiInitSpinLocks(IN PKPRCB Prcb
,
192 /* Initialize Dispatcher Fields */
193 Prcb
->QueueIndex
= 1;
194 Prcb
->ReadySummary
= 0;
195 Prcb
->DeferredReadyListHead
.Next
= NULL
;
196 for (i
= 0; i
< MAXIMUM_PRIORITY
; i
++)
198 /* Initialize the ready list */
199 InitializeListHead(&Prcb
->DispatcherReadyListHead
[i
]);
202 /* Initialize DPC Fields */
203 InitializeListHead(&Prcb
->DpcData
[DPC_NORMAL
].DpcListHead
);
204 KeInitializeSpinLock(&Prcb
->DpcData
[DPC_NORMAL
].DpcLock
);
205 Prcb
->DpcData
[DPC_NORMAL
].DpcQueueDepth
= 0;
206 Prcb
->DpcData
[DPC_NORMAL
].DpcCount
= 0;
207 Prcb
->DpcRoutineActive
= FALSE
;
208 Prcb
->MaximumDpcQueueDepth
= KiMaximumDpcQueueDepth
;
209 Prcb
->MinimumDpcRate
= KiMinimumDpcRate
;
210 Prcb
->AdjustDpcThreshold
= KiAdjustDpcThreshold
;
211 KeInitializeDpc(&Prcb
->CallDpc
, NULL
, NULL
);
212 KeSetTargetProcessorDpc(&Prcb
->CallDpc
, Number
);
213 KeSetImportanceDpc(&Prcb
->CallDpc
, HighImportance
);
215 /* Initialize the Wait List Head */
216 InitializeListHead(&Prcb
->WaitListHead
);
218 /* Initialize Queued Spinlocks */
219 Prcb
->LockQueue
[LockQueueDispatcherLock
].Next
= NULL
;
220 Prcb
->LockQueue
[LockQueueDispatcherLock
].Lock
= &KiDispatcherLock
;
221 Prcb
->LockQueue
[LockQueueExpansionLock
].Next
= NULL
;
222 Prcb
->LockQueue
[LockQueueExpansionLock
].Lock
= NULL
;
223 Prcb
->LockQueue
[LockQueuePfnLock
].Next
= NULL
;
224 Prcb
->LockQueue
[LockQueuePfnLock
].Lock
= &MmPfnLock
;
225 Prcb
->LockQueue
[LockQueueSystemSpaceLock
].Next
= NULL
;
226 Prcb
->LockQueue
[LockQueueSystemSpaceLock
].Lock
= &MmSystemSpaceLock
;
227 Prcb
->LockQueue
[LockQueueBcbLock
].Next
= NULL
;
228 Prcb
->LockQueue
[LockQueueBcbLock
].Lock
= &CcBcbSpinLock
;
229 Prcb
->LockQueue
[LockQueueMasterLock
].Next
= NULL
;
230 Prcb
->LockQueue
[LockQueueMasterLock
].Lock
= &CcMasterSpinLock
;
231 Prcb
->LockQueue
[LockQueueVacbLock
].Next
= NULL
;
232 Prcb
->LockQueue
[LockQueueVacbLock
].Lock
= &CcVacbSpinLock
;
233 Prcb
->LockQueue
[LockQueueWorkQueueLock
].Next
= NULL
;
234 Prcb
->LockQueue
[LockQueueWorkQueueLock
].Lock
= &CcWorkQueueSpinLock
;
235 Prcb
->LockQueue
[LockQueueNonPagedPoolLock
].Next
= NULL
;
236 Prcb
->LockQueue
[LockQueueNonPagedPoolLock
].Lock
= &NonPagedPoolLock
;
237 Prcb
->LockQueue
[LockQueueMmNonPagedPoolLock
].Next
= NULL
;
238 Prcb
->LockQueue
[LockQueueMmNonPagedPoolLock
].Lock
= &MmNonPagedPoolLock
;
239 Prcb
->LockQueue
[LockQueueIoCancelLock
].Next
= NULL
;
240 Prcb
->LockQueue
[LockQueueIoCancelLock
].Lock
= &IopCancelSpinLock
;
241 Prcb
->LockQueue
[LockQueueIoVpbLock
].Next
= NULL
;
242 Prcb
->LockQueue
[LockQueueIoVpbLock
].Lock
= &IopVpbSpinLock
;
243 Prcb
->LockQueue
[LockQueueIoDatabaseLock
].Next
= NULL
;
244 Prcb
->LockQueue
[LockQueueIoDatabaseLock
].Lock
= &IopDatabaseLock
;
245 Prcb
->LockQueue
[LockQueueIoCompletionLock
].Next
= NULL
;
246 Prcb
->LockQueue
[LockQueueIoCompletionLock
].Lock
= &IopCompletionLock
;
247 Prcb
->LockQueue
[LockQueueNtfsStructLock
].Next
= NULL
;
248 Prcb
->LockQueue
[LockQueueNtfsStructLock
].Lock
= &NtfsStructLock
;
249 Prcb
->LockQueue
[LockQueueAfdWorkQueueLock
].Next
= NULL
;
250 Prcb
->LockQueue
[LockQueueAfdWorkQueueLock
].Lock
= &AfdWorkQueueSpinLock
;
251 Prcb
->LockQueue
[LockQueueUnusedSpare16
].Next
= NULL
;
252 Prcb
->LockQueue
[LockQueueUnusedSpare16
].Lock
= NULL
;
254 /* Loop timer locks */
255 for (i
= 0; i
< LOCK_QUEUE_TIMER_TABLE_LOCKS
; i
++)
257 /* Initialize the lock and setup the Queued Spinlock */
258 KeInitializeSpinLock(&KiTimerTableLock
[i
]);
259 Prcb
->LockQueue
[LockQueueTimerTableLock
+ i
].Next
= NULL
;
260 Prcb
->LockQueue
[LockQueueTimerTableLock
+ i
].Lock
=
261 &KiTimerTableLock
[i
];
264 /* Initialize the PRCB lock */
265 KeInitializeSpinLock(&Prcb
->PrcbLock
);
267 /* Check if this is the boot CPU */
270 /* Initialize the lock themselves */
271 KeInitializeSpinLock(&KiDispatcherLock
);
272 KeInitializeSpinLock(&KiReverseStallIpiLock
);
273 KeInitializeSpinLock(&MmPfnLock
);
274 KeInitializeSpinLock(&MmSystemSpaceLock
);
275 KeInitializeSpinLock(&CcBcbSpinLock
);
276 KeInitializeSpinLock(&CcMasterSpinLock
);
277 KeInitializeSpinLock(&CcVacbSpinLock
);
278 KeInitializeSpinLock(&CcWorkQueueSpinLock
);
279 KeInitializeSpinLock(&IopCancelSpinLock
);
280 KeInitializeSpinLock(&IopCompletionLock
);
281 KeInitializeSpinLock(&IopDatabaseLock
);
282 KeInitializeSpinLock(&IopVpbSpinLock
);
283 KeInitializeSpinLock(&NonPagedPoolLock
);
284 KeInitializeSpinLock(&MmNonPagedPoolLock
);
285 KeInitializeSpinLock(&NtfsStructLock
);
286 KeInitializeSpinLock(&AfdWorkQueueSpinLock
);
295 /* Check if Threaded DPCs are enabled */
296 if (KeThreadDpcEnable
)
299 DPRINT1("Threaded DPCs not yet supported\n");
302 /* Initialize non-portable parts of the kernel */
303 KiInitMachineDependent();