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 /* System call count */
19 ULONG KiServiceLimit
= NUMBER_OF_SYSCALLS
;
21 /* ARC Loader Block */
22 PLOADER_PARAMETER_BLOCK KeLoaderBlock
;
25 PKPRCB KiProcessorBlock
[MAXIMUM_PROCESSORS
];
27 /* NUMA Node Support */
29 PKNODE KeNodeBlock
[1];
30 UCHAR KeNumberNodes
= 1;
31 UCHAR KeProcessNodeSeed
;
33 /* Initial Process and Thread */
34 ETHREAD KiInitialThread
;
35 EPROCESS KiInitialProcess
;
37 /* System-defined Spinlocks */
38 KSPIN_LOCK KiDispatcherLock
;
40 KSPIN_LOCK MmSystemSpaceLock
;
41 KSPIN_LOCK CcBcbSpinLock
;
42 KSPIN_LOCK CcMasterSpinLock
;
43 KSPIN_LOCK CcVacbSpinLock
;
44 KSPIN_LOCK CcWorkQueueSpinLock
;
45 KSPIN_LOCK NonPagedPoolLock
;
46 KSPIN_LOCK MmNonPagedPoolLock
;
47 KSPIN_LOCK IopCancelSpinLock
;
48 KSPIN_LOCK IopVpbSpinLock
;
49 KSPIN_LOCK IopDatabaseLock
;
50 KSPIN_LOCK IopCompletionLock
;
51 KSPIN_LOCK NtfsStructLock
;
52 KSPIN_LOCK AfdWorkQueueSpinLock
;
53 KSPIN_LOCK KiTimerTableLock
[16];
54 KSPIN_LOCK KiReverseStallIpiLock
;
56 /* FUNCTIONS *****************************************************************/
64 /* Initialize Bugcheck Callback data */
65 InitializeListHead(&BugcheckCallbackListHead
);
66 InitializeListHead(&BugcheckReasonCallbackListHead
);
67 KeInitializeSpinLock(&BugCheckCallbackLock
);
69 /* Initialize the Timer Expiration DPC */
70 KeInitializeDpc(&KiTimerExpireDpc
, KiTimerExpiration
, NULL
);
71 KeSetTargetProcessorDpc(&KiTimerExpireDpc
, 0);
73 /* Initialize Profiling data */
74 KeInitializeSpinLock(&KiProfileLock
);
75 InitializeListHead(&KiProfileListHead
);
76 InitializeListHead(&KiProfileSourceListHead
);
78 /* Loop the timer table */
79 for (i
= 0; i
< TIMER_TABLE_SIZE
; i
++)
81 /* Initialize the list and entries */
82 InitializeListHead(&KiTimerTableListHead
[i
].Entry
);
83 KiTimerTableListHead
[i
].Time
.HighPart
= 0xFFFFFFFF;
84 KiTimerTableListHead
[i
].Time
.LowPart
= 0;
87 /* Initialize the Swap event and all swap lists */
88 KeInitializeEvent(&KiSwapEvent
, SynchronizationEvent
, FALSE
);
89 InitializeListHead(&KiProcessInSwapListHead
);
90 InitializeListHead(&KiProcessOutSwapListHead
);
91 InitializeListHead(&KiStackInSwapListHead
);
93 /* Initialize the mutex for generic DPC calls */
94 ExInitializeFastMutex(&KiGenericCallDpcMutex
);
96 /* Initialize the syscall table */
97 KeServiceDescriptorTable
[0].Base
= MainSSDT
;
98 KeServiceDescriptorTable
[0].Count
= NULL
;
99 KeServiceDescriptorTable
[0].Limit
= KiServiceLimit
;
100 KeServiceDescriptorTable
[1].Limit
= 0;
101 KeServiceDescriptorTable
[0].Number
= MainSSPT
;
103 /* Copy the the current table into the shadow table for win32k */
104 RtlCopyMemory(KeServiceDescriptorTableShadow
,
105 KeServiceDescriptorTable
,
106 sizeof(KeServiceDescriptorTable
));
111 KiComputeReciprocal(IN LONG Divisor
,
114 LARGE_INTEGER Reciprocal
= {{0}};
115 LONG BitCount
= 0, Remainder
= 1;
117 /* Start by calculating the remainder */
118 while (Reciprocal
.HighPart
>= 0)
120 /* Increase the loop (bit) count */
123 /* Calculate the current fraction */
124 Reciprocal
.HighPart
= (Reciprocal
.HighPart
<< 1) |
125 (Reciprocal
.LowPart
>> 31);
126 Reciprocal
.LowPart
<<= 1;
128 /* Double the remainder and see if we went past the divisor */
130 if (Remainder
>= Divisor
)
132 /* Set the low-bit and calculate the new remainder */
133 Remainder
-= Divisor
;
134 Reciprocal
.LowPart
|= 1;
138 /* Check if we have a remainder */
141 /* Check if the current fraction value is too large */
142 if ((Reciprocal
.LowPart
== 0xFFFFFFFF) &&
143 (Reciprocal
.HighPart
== 0xFFFFFFFF))
145 /* Set the high bit and reduce the bit count */
146 Reciprocal
.LowPart
= 0;
147 Reciprocal
.HighPart
= 0x80000000;
152 /* Check if only the lowest bits got too large */
153 if (Reciprocal
.LowPart
== 0xFFFFFFFF)
155 /* Reset them and increase the high bits instead */
156 Reciprocal
.LowPart
= 0;
157 Reciprocal
.HighPart
++;
161 /* All is well, increase the low bits */
162 Reciprocal
.LowPart
++;
167 /* Now calculate the actual shift and return the reciprocal */
168 *Shift
= (UCHAR
)BitCount
- 64;
174 KiInitSpinLocks(IN PKPRCB Prcb
,
179 /* Initialize Dispatcher Fields */
180 Prcb
->QueueIndex
= 1;
181 Prcb
->ReadySummary
= 0;
182 Prcb
->DeferredReadyListHead
.Next
= NULL
;
183 for (i
= 0; i
< MAXIMUM_PRIORITY
; i
++)
185 /* Initialize the ready list */
186 InitializeListHead(&Prcb
->DispatcherReadyListHead
[i
]);
189 /* Initialize DPC Fields */
190 InitializeListHead(&Prcb
->DpcData
[DPC_NORMAL
].DpcListHead
);
191 KeInitializeSpinLock(&Prcb
->DpcData
[DPC_NORMAL
].DpcLock
);
192 Prcb
->DpcData
[DPC_NORMAL
].DpcQueueDepth
= 0;
193 Prcb
->DpcData
[DPC_NORMAL
].DpcCount
= 0;
194 Prcb
->DpcRoutineActive
= FALSE
;
195 Prcb
->MaximumDpcQueueDepth
= KiMaximumDpcQueueDepth
;
196 Prcb
->MinimumDpcRate
= KiMinimumDpcRate
;
197 Prcb
->AdjustDpcThreshold
= KiAdjustDpcThreshold
;
198 KeInitializeDpc(&Prcb
->CallDpc
, NULL
, NULL
);
199 KeSetTargetProcessorDpc(&Prcb
->CallDpc
, Number
);
200 KeSetImportanceDpc(&Prcb
->CallDpc
, HighImportance
);
202 /* Initialize the Wait List Head */
203 InitializeListHead(&Prcb
->WaitListHead
);
205 /* Initialize Queued Spinlocks */
206 Prcb
->LockQueue
[LockQueueDispatcherLock
].Next
= NULL
;
207 Prcb
->LockQueue
[LockQueueDispatcherLock
].Lock
= &KiDispatcherLock
;
208 Prcb
->LockQueue
[LockQueueExpansionLock
].Next
= NULL
;
209 Prcb
->LockQueue
[LockQueueExpansionLock
].Lock
= NULL
;
210 Prcb
->LockQueue
[LockQueuePfnLock
].Next
= NULL
;
211 Prcb
->LockQueue
[LockQueuePfnLock
].Lock
= &MmPfnLock
;
212 Prcb
->LockQueue
[LockQueueSystemSpaceLock
].Next
= NULL
;
213 Prcb
->LockQueue
[LockQueueSystemSpaceLock
].Lock
= &MmSystemSpaceLock
;
214 Prcb
->LockQueue
[LockQueueBcbLock
].Next
= NULL
;
215 Prcb
->LockQueue
[LockQueueBcbLock
].Lock
= &CcBcbSpinLock
;
216 Prcb
->LockQueue
[LockQueueMasterLock
].Next
= NULL
;
217 Prcb
->LockQueue
[LockQueueMasterLock
].Lock
= &CcMasterSpinLock
;
218 Prcb
->LockQueue
[LockQueueVacbLock
].Next
= NULL
;
219 Prcb
->LockQueue
[LockQueueVacbLock
].Lock
= &CcVacbSpinLock
;
220 Prcb
->LockQueue
[LockQueueWorkQueueLock
].Next
= NULL
;
221 Prcb
->LockQueue
[LockQueueWorkQueueLock
].Lock
= &CcWorkQueueSpinLock
;
222 Prcb
->LockQueue
[LockQueueNonPagedPoolLock
].Next
= NULL
;
223 Prcb
->LockQueue
[LockQueueNonPagedPoolLock
].Lock
= &NonPagedPoolLock
;
224 Prcb
->LockQueue
[LockQueueMmNonPagedPoolLock
].Next
= NULL
;
225 Prcb
->LockQueue
[LockQueueMmNonPagedPoolLock
].Lock
= &MmNonPagedPoolLock
;
226 Prcb
->LockQueue
[LockQueueIoCancelLock
].Next
= NULL
;
227 Prcb
->LockQueue
[LockQueueIoCancelLock
].Lock
= &IopCancelSpinLock
;
228 Prcb
->LockQueue
[LockQueueIoVpbLock
].Next
= NULL
;
229 Prcb
->LockQueue
[LockQueueIoVpbLock
].Lock
= &IopVpbSpinLock
;
230 Prcb
->LockQueue
[LockQueueIoDatabaseLock
].Next
= NULL
;
231 Prcb
->LockQueue
[LockQueueIoDatabaseLock
].Lock
= &IopDatabaseLock
;
232 Prcb
->LockQueue
[LockQueueIoCompletionLock
].Next
= NULL
;
233 Prcb
->LockQueue
[LockQueueIoCompletionLock
].Lock
= &IopCompletionLock
;
234 Prcb
->LockQueue
[LockQueueNtfsStructLock
].Next
= NULL
;
235 Prcb
->LockQueue
[LockQueueNtfsStructLock
].Lock
= &NtfsStructLock
;
236 Prcb
->LockQueue
[LockQueueAfdWorkQueueLock
].Next
= NULL
;
237 Prcb
->LockQueue
[LockQueueAfdWorkQueueLock
].Lock
= &AfdWorkQueueSpinLock
;
238 Prcb
->LockQueue
[LockQueueUnusedSpare16
].Next
= NULL
;
239 Prcb
->LockQueue
[LockQueueUnusedSpare16
].Lock
= NULL
;
241 /* Loop timer locks */
242 for (i
= 0; i
< LOCK_QUEUE_TIMER_TABLE_LOCKS
; i
++)
244 /* Initialize the lock and setup the Queued Spinlock */
245 KeInitializeSpinLock(&KiTimerTableLock
[i
]);
246 Prcb
->LockQueue
[LockQueueTimerTableLock
+ i
].Next
= NULL
;
247 Prcb
->LockQueue
[LockQueueTimerTableLock
+ i
].Lock
=
248 &KiTimerTableLock
[i
];
251 /* Initialize the PRCB lock */
252 KeInitializeSpinLock(&Prcb
->PrcbLock
);
254 /* Check if this is the boot CPU */
257 /* Initialize the lock themselves */
258 KeInitializeSpinLock(&KiDispatcherLock
);
259 KeInitializeSpinLock(&KiReverseStallIpiLock
);
260 KeInitializeSpinLock(&MmPfnLock
);
261 KeInitializeSpinLock(&MmSystemSpaceLock
);
262 KeInitializeSpinLock(&CcBcbSpinLock
);
263 KeInitializeSpinLock(&CcMasterSpinLock
);
264 KeInitializeSpinLock(&CcVacbSpinLock
);
265 KeInitializeSpinLock(&CcWorkQueueSpinLock
);
266 KeInitializeSpinLock(&IopCancelSpinLock
);
267 KeInitializeSpinLock(&IopCompletionLock
);
268 KeInitializeSpinLock(&IopDatabaseLock
);
269 KeInitializeSpinLock(&IopVpbSpinLock
);
270 KeInitializeSpinLock(&NonPagedPoolLock
);
271 KeInitializeSpinLock(&MmNonPagedPoolLock
);
272 KeInitializeSpinLock(&NtfsStructLock
);
273 KeInitializeSpinLock(&AfdWorkQueueSpinLock
);
281 /* Check if Threaded DPCs are enabled */
282 if (KeThreadDpcEnable
)
285 DPRINT1("Threaded DPCs not yet supported\n");
288 /* Initialize non-portable parts of the kernel */
289 KiInitMachineDependent();