d22fe7e2fd8b490da3d1cafcfac9f8e63671bca6
[reactos.git] / ntoskrnl / ke / krnlinit.c
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 /* System call count */
19 ULONG KiServiceLimit = NUMBER_OF_SYSCALLS;
20
21 /* ARC Loader Block */
22 PLOADER_PARAMETER_BLOCK KeLoaderBlock;
23
24 /* PRCB Array */
25 PKPRCB KiProcessorBlock[MAXIMUM_PROCESSORS];
26
27 /* NUMA Node Support */
28 KNODE KiNode0;
29 PKNODE KeNodeBlock[1];
30 UCHAR KeNumberNodes = 1;
31 UCHAR KeProcessNodeSeed;
32
33 /* Initial Process and Thread */
34 ETHREAD KiInitialThread;
35 EPROCESS KiInitialProcess;
36
37 /* System-defined Spinlocks */
38 KSPIN_LOCK KiDispatcherLock;
39 KSPIN_LOCK MmPfnLock;
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;
55
56 /* FUNCTIONS *****************************************************************/
57
58 VOID
59 NTAPI
60 INIT_FUNCTION
61 KiInitSystem(VOID)
62 {
63 ULONG i;
64
65 /* Initialize Bugcheck Callback data */
66 InitializeListHead(&KeBugcheckCallbackListHead);
67 InitializeListHead(&KeBugcheckReasonCallbackListHead);
68 KeInitializeSpinLock(&BugCheckCallbackLock);
69
70 /* Initialize the Timer Expiration DPC */
71 KeInitializeDpc(&KiTimerExpireDpc, KiTimerExpiration, NULL);
72 KeSetTargetProcessorDpc(&KiTimerExpireDpc, 0);
73
74 /* Initialize Profiling data */
75 KeInitializeSpinLock(&KiProfileLock);
76 InitializeListHead(&KiProfileListHead);
77 InitializeListHead(&KiProfileSourceListHead);
78
79 /* Loop the timer table */
80 for (i = 0; i < TIMER_TABLE_SIZE; i++)
81 {
82 /* Initialize the list and entries */
83 InitializeListHead(&KiTimerTableListHead[i].Entry);
84 KiTimerTableListHead[i].Time.HighPart = 0xFFFFFFFF;
85 KiTimerTableListHead[i].Time.LowPart = 0;
86 }
87
88 /* Initialize the Swap event and all swap lists */
89 KeInitializeEvent(&KiSwapEvent, SynchronizationEvent, FALSE);
90 InitializeListHead(&KiProcessInSwapListHead);
91 InitializeListHead(&KiProcessOutSwapListHead);
92 InitializeListHead(&KiStackInSwapListHead);
93
94 /* Initialize the mutex for generic DPC calls */
95 ExInitializeFastMutex(&KiGenericCallDpcMutex);
96
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;
103
104 /* Copy the the current table into the shadow table for win32k */
105 RtlCopyMemory(KeServiceDescriptorTableShadow,
106 KeServiceDescriptorTable,
107 sizeof(KeServiceDescriptorTable));
108 }
109
110 LARGE_INTEGER
111 NTAPI
112 INIT_FUNCTION
113 KiComputeReciprocal(IN LONG Divisor,
114 OUT PUCHAR Shift)
115 {
116 LARGE_INTEGER Reciprocal = {{0, 0}};
117 LONG BitCount = 0, Remainder = 1;
118
119 /* Start by calculating the remainder */
120 while (Reciprocal.HighPart >= 0)
121 {
122 /* Increase the loop (bit) count */
123 BitCount++;
124
125 /* Calculate the current fraction */
126 Reciprocal.HighPart = (Reciprocal.HighPart << 1) |
127 (Reciprocal.LowPart >> 31);
128 Reciprocal.LowPart <<= 1;
129
130 /* Double the remainder and see if we went past the divisor */
131 Remainder <<= 1;
132 if (Remainder >= Divisor)
133 {
134 /* Set the low-bit and calculate the new remainder */
135 Remainder -= Divisor;
136 Reciprocal.LowPart |= 1;
137 }
138 }
139
140 /* Check if we have a remainder */
141 if (Remainder)
142 {
143 /* Check if the current fraction value is too large */
144 if ((Reciprocal.LowPart == 0xFFFFFFFF) &&
145 (Reciprocal.HighPart == (LONG)0xFFFFFFFF))
146 {
147 /* Set the high bit and reduce the bit count */
148 Reciprocal.LowPart = 0;
149 Reciprocal.HighPart = 0x80000000;
150 BitCount--;
151 }
152 else
153 {
154 /* Check if only the lowest bits got too large */
155 if (Reciprocal.LowPart == 0xFFFFFFFF)
156 {
157 /* Reset them and increase the high bits instead */
158 Reciprocal.LowPart = 0;
159 Reciprocal.HighPart++;
160 }
161 else
162 {
163 /* All is well, increase the low bits */
164 Reciprocal.LowPart++;
165 }
166 }
167 }
168
169 /* Now calculate the actual shift and return the reciprocal */
170 *Shift = (UCHAR)BitCount - 64;
171 return Reciprocal;
172 }
173
174 VOID
175 NTAPI
176 INIT_FUNCTION
177 KiInitSpinLocks(IN PKPRCB Prcb,
178 IN CCHAR Number)
179 {
180 ULONG i;
181
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++)
187 {
188 /* Initialize the ready list */
189 InitializeListHead(&Prcb->DispatcherReadyListHead[i]);
190 }
191
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);
204
205 /* Initialize the Wait List Head */
206 InitializeListHead(&Prcb->WaitListHead);
207
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;
243
244 /* Loop timer locks */
245 for (i = 0; i < LOCK_QUEUE_TIMER_TABLE_LOCKS; i++)
246 {
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];
252 }
253
254 /* Initialize the PRCB lock */
255 KeInitializeSpinLock(&Prcb->PrcbLock);
256
257 /* Check if this is the boot CPU */
258 if (!Number)
259 {
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);
277 }
278 }
279
280 BOOLEAN
281 NTAPI
282 INIT_FUNCTION
283 KeInitSystem(VOID)
284 {
285 /* Check if Threaded DPCs are enabled */
286 if (KeThreadDpcEnable)
287 {
288 /* FIXME: TODO */
289 DPRINT1("Threaded DPCs not yet supported\n");
290 }
291
292 /* Initialize non-portable parts of the kernel */
293 KiInitMachineDependent();
294 return TRUE;
295 }