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 *****************************************************************/
65 /* Initialize Bugcheck Callback data */
66 InitializeListHead(&KeBugcheckCallbackListHead
);
67 InitializeListHead(&KeBugcheckReasonCallbackListHead
);
68 KeInitializeSpinLock(&BugCheckCallbackLock
);
70 /* Initialize the Timer Expiration DPC */
71 KeInitializeDpc(&KiTimerExpireDpc
, KiTimerExpiration
, NULL
);
72 KeSetTargetProcessorDpc(&KiTimerExpireDpc
, 0);
74 /* Initialize Profiling data */
75 KeInitializeSpinLock(&KiProfileLock
);
76 InitializeListHead(&KiProfileListHead
);
77 InitializeListHead(&KiProfileSourceListHead
);
79 /* Loop the timer table */
80 for (i
= 0; i
< TIMER_TABLE_SIZE
; i
++)
82 /* Initialize the list and entries */
83 InitializeListHead(&KiTimerTableListHead
[i
].Entry
);
84 KiTimerTableListHead
[i
].Time
.HighPart
= 0xFFFFFFFF;
85 KiTimerTableListHead
[i
].Time
.LowPart
= 0;
88 /* Initialize the Swap event and all swap lists */
89 KeInitializeEvent(&KiSwapEvent
, SynchronizationEvent
, FALSE
);
90 InitializeListHead(&KiProcessInSwapListHead
);
91 InitializeListHead(&KiProcessOutSwapListHead
);
92 InitializeListHead(&KiStackInSwapListHead
);
94 /* Initialize the mutex for generic DPC calls */
95 ExInitializeFastMutex(&KiGenericCallDpcMutex
);
97 /* Initialize the syscall table */
98 KeServiceDescriptorTable
[0].Base
= MainSSDT
;
99 KeServiceDescriptorTable
[0].Count
= NULL
;
100 KeServiceDescriptorTable
[0].Limit
= KiServiceLimit
;
101 KeServiceDescriptorTable
[1].Limit
= 0;
102 KeServiceDescriptorTable
[0].Number
= MainSSPT
;
104 /* Copy the the current table into the shadow table for win32k */
105 RtlCopyMemory(KeServiceDescriptorTableShadow
,
106 KeServiceDescriptorTable
,
107 sizeof(KeServiceDescriptorTable
));
113 KiComputeReciprocal(IN LONG Divisor
,
116 LARGE_INTEGER Reciprocal
= {{0, 0}};
117 LONG BitCount
= 0, Remainder
= 1;
119 /* Start by calculating the remainder */
120 while (Reciprocal
.HighPart
>= 0)
122 /* Increase the loop (bit) count */
125 /* Calculate the current fraction */
126 Reciprocal
.HighPart
= (Reciprocal
.HighPart
<< 1) |
127 (Reciprocal
.LowPart
>> 31);
128 Reciprocal
.LowPart
<<= 1;
130 /* Double the remainder and see if we went past the divisor */
132 if (Remainder
>= Divisor
)
134 /* Set the low-bit and calculate the new remainder */
135 Remainder
-= Divisor
;
136 Reciprocal
.LowPart
|= 1;
140 /* Check if we have a remainder */
143 /* Check if the current fraction value is too large */
144 if ((Reciprocal
.LowPart
== 0xFFFFFFFF) &&
145 (Reciprocal
.HighPart
== (LONG
)0xFFFFFFFF))
147 /* Set the high bit and reduce the bit count */
148 Reciprocal
.LowPart
= 0;
149 Reciprocal
.HighPart
= 0x80000000;
154 /* Check if only the lowest bits got too large */
155 if (Reciprocal
.LowPart
== 0xFFFFFFFF)
157 /* Reset them and increase the high bits instead */
158 Reciprocal
.LowPart
= 0;
159 Reciprocal
.HighPart
++;
163 /* All is well, increase the low bits */
164 Reciprocal
.LowPart
++;
169 /* Now calculate the actual shift and return the reciprocal */
170 *Shift
= (UCHAR
)BitCount
- 64;
177 KiInitSpinLocks(IN PKPRCB Prcb
,
182 /* Initialize Dispatcher Fields */
183 Prcb
->QueueIndex
= 1;
184 Prcb
->ReadySummary
= 0;
185 Prcb
->DeferredReadyListHead
.Next
= NULL
;
186 for (i
= 0; i
< MAXIMUM_PRIORITY
; i
++)
188 /* Initialize the ready list */
189 InitializeListHead(&Prcb
->DispatcherReadyListHead
[i
]);
192 /* Initialize DPC Fields */
193 InitializeListHead(&Prcb
->DpcData
[DPC_NORMAL
].DpcListHead
);
194 KeInitializeSpinLock(&Prcb
->DpcData
[DPC_NORMAL
].DpcLock
);
195 Prcb
->DpcData
[DPC_NORMAL
].DpcQueueDepth
= 0;
196 Prcb
->DpcData
[DPC_NORMAL
].DpcCount
= 0;
197 Prcb
->DpcRoutineActive
= FALSE
;
198 Prcb
->MaximumDpcQueueDepth
= KiMaximumDpcQueueDepth
;
199 Prcb
->MinimumDpcRate
= KiMinimumDpcRate
;
200 Prcb
->AdjustDpcThreshold
= KiAdjustDpcThreshold
;
201 KeInitializeDpc(&Prcb
->CallDpc
, NULL
, NULL
);
202 KeSetTargetProcessorDpc(&Prcb
->CallDpc
, Number
);
203 KeSetImportanceDpc(&Prcb
->CallDpc
, HighImportance
);
205 /* Initialize the Wait List Head */
206 InitializeListHead(&Prcb
->WaitListHead
);
208 /* Initialize Queued Spinlocks */
209 Prcb
->LockQueue
[LockQueueDispatcherLock
].Next
= NULL
;
210 Prcb
->LockQueue
[LockQueueDispatcherLock
].Lock
= &KiDispatcherLock
;
211 Prcb
->LockQueue
[LockQueueExpansionLock
].Next
= NULL
;
212 Prcb
->LockQueue
[LockQueueExpansionLock
].Lock
= NULL
;
213 Prcb
->LockQueue
[LockQueuePfnLock
].Next
= NULL
;
214 Prcb
->LockQueue
[LockQueuePfnLock
].Lock
= &MmPfnLock
;
215 Prcb
->LockQueue
[LockQueueSystemSpaceLock
].Next
= NULL
;
216 Prcb
->LockQueue
[LockQueueSystemSpaceLock
].Lock
= &MmSystemSpaceLock
;
217 Prcb
->LockQueue
[LockQueueBcbLock
].Next
= NULL
;
218 Prcb
->LockQueue
[LockQueueBcbLock
].Lock
= &CcBcbSpinLock
;
219 Prcb
->LockQueue
[LockQueueMasterLock
].Next
= NULL
;
220 Prcb
->LockQueue
[LockQueueMasterLock
].Lock
= &CcMasterSpinLock
;
221 Prcb
->LockQueue
[LockQueueVacbLock
].Next
= NULL
;
222 Prcb
->LockQueue
[LockQueueVacbLock
].Lock
= &CcVacbSpinLock
;
223 Prcb
->LockQueue
[LockQueueWorkQueueLock
].Next
= NULL
;
224 Prcb
->LockQueue
[LockQueueWorkQueueLock
].Lock
= &CcWorkQueueSpinLock
;
225 Prcb
->LockQueue
[LockQueueNonPagedPoolLock
].Next
= NULL
;
226 Prcb
->LockQueue
[LockQueueNonPagedPoolLock
].Lock
= &NonPagedPoolLock
;
227 Prcb
->LockQueue
[LockQueueMmNonPagedPoolLock
].Next
= NULL
;
228 Prcb
->LockQueue
[LockQueueMmNonPagedPoolLock
].Lock
= &MmNonPagedPoolLock
;
229 Prcb
->LockQueue
[LockQueueIoCancelLock
].Next
= NULL
;
230 Prcb
->LockQueue
[LockQueueIoCancelLock
].Lock
= &IopCancelSpinLock
;
231 Prcb
->LockQueue
[LockQueueIoVpbLock
].Next
= NULL
;
232 Prcb
->LockQueue
[LockQueueIoVpbLock
].Lock
= &IopVpbSpinLock
;
233 Prcb
->LockQueue
[LockQueueIoDatabaseLock
].Next
= NULL
;
234 Prcb
->LockQueue
[LockQueueIoDatabaseLock
].Lock
= &IopDatabaseLock
;
235 Prcb
->LockQueue
[LockQueueIoCompletionLock
].Next
= NULL
;
236 Prcb
->LockQueue
[LockQueueIoCompletionLock
].Lock
= &IopCompletionLock
;
237 Prcb
->LockQueue
[LockQueueNtfsStructLock
].Next
= NULL
;
238 Prcb
->LockQueue
[LockQueueNtfsStructLock
].Lock
= &NtfsStructLock
;
239 Prcb
->LockQueue
[LockQueueAfdWorkQueueLock
].Next
= NULL
;
240 Prcb
->LockQueue
[LockQueueAfdWorkQueueLock
].Lock
= &AfdWorkQueueSpinLock
;
241 Prcb
->LockQueue
[LockQueueUnusedSpare16
].Next
= NULL
;
242 Prcb
->LockQueue
[LockQueueUnusedSpare16
].Lock
= NULL
;
244 /* Loop timer locks */
245 for (i
= 0; i
< LOCK_QUEUE_TIMER_TABLE_LOCKS
; i
++)
247 /* Initialize the lock and setup the Queued Spinlock */
248 KeInitializeSpinLock(&KiTimerTableLock
[i
]);
249 Prcb
->LockQueue
[LockQueueTimerTableLock
+ i
].Next
= NULL
;
250 Prcb
->LockQueue
[LockQueueTimerTableLock
+ i
].Lock
=
251 &KiTimerTableLock
[i
];
254 /* Initialize the PRCB lock */
255 KeInitializeSpinLock(&Prcb
->PrcbLock
);
257 /* Check if this is the boot CPU */
260 /* Initialize the lock themselves */
261 KeInitializeSpinLock(&KiDispatcherLock
);
262 KeInitializeSpinLock(&KiReverseStallIpiLock
);
263 KeInitializeSpinLock(&MmPfnLock
);
264 KeInitializeSpinLock(&MmSystemSpaceLock
);
265 KeInitializeSpinLock(&CcBcbSpinLock
);
266 KeInitializeSpinLock(&CcMasterSpinLock
);
267 KeInitializeSpinLock(&CcVacbSpinLock
);
268 KeInitializeSpinLock(&CcWorkQueueSpinLock
);
269 KeInitializeSpinLock(&IopCancelSpinLock
);
270 KeInitializeSpinLock(&IopCompletionLock
);
271 KeInitializeSpinLock(&IopDatabaseLock
);
272 KeInitializeSpinLock(&IopVpbSpinLock
);
273 KeInitializeSpinLock(&NonPagedPoolLock
);
274 KeInitializeSpinLock(&MmNonPagedPoolLock
);
275 KeInitializeSpinLock(&NtfsStructLock
);
276 KeInitializeSpinLock(&AfdWorkQueueSpinLock
);
285 /* Check if Threaded DPCs are enabled */
286 if (KeThreadDpcEnable
)
289 DPRINT1("Threaded DPCs not yet supported\n");
292 /* Initialize non-portable parts of the kernel */
293 KiInitMachineDependent();