[CRT] Remove useless #undef abort from process.h
[reactos.git] / ntoskrnl / ke / amd64 / krnlinit.c
1 /*
2 * PROJECT: ReactOS Kernel
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: ntoskrnl/ke/amd64/krnlinit.c
5 * PURPOSE: Portable part of kernel initialization
6 * PROGRAMMERS: Timo Kreuzer (timo.kreuzer@reactos.org)
7 * Alex Ionescu (alex.ionescu@reactos.org)
8 */
9
10 /* INCLUDES ******************************************************************/
11
12 #include <ntoskrnl.h>
13 #define NDEBUG
14 #include <debug.h>
15
16 extern ULONG_PTR MainSSDT[];
17 extern UCHAR MainSSPT[];
18
19 extern BOOLEAN RtlpUse16ByteSLists;
20
21 /* FUNCTIONS *****************************************************************/
22
23 CODE_SEG("INIT")
24 VOID
25 NTAPI
26 KiInitializeKernel(IN PKPROCESS InitProcess,
27 IN PKTHREAD InitThread,
28 IN PVOID IdleStack,
29 IN PKPRCB Prcb,
30 IN PLOADER_PARAMETER_BLOCK LoaderBlock);
31
32
33 CODE_SEG("INIT")
34 VOID
35 KiCalculateCpuFrequency(
36 IN PKPRCB Prcb)
37 {
38 if (Prcb->FeatureBits & KF_RDTSC)
39 {
40 ULONG Sample = 0;
41 CPU_INFO CpuInfo;
42 KI_SAMPLE_MAP Samples[10];
43 PKI_SAMPLE_MAP CurrentSample = Samples;
44
45 /* Start sampling loop */
46 for (;;)
47 {
48 /* Do a dummy CPUID to start the sample */
49 KiCpuId(&CpuInfo, 0);
50
51 /* Fill out the starting data */
52 CurrentSample->PerfStart = KeQueryPerformanceCounter(NULL);
53 CurrentSample->TSCStart = __rdtsc();
54 CurrentSample->PerfFreq.QuadPart = -50000;
55
56 /* Sleep for this sample */
57 KeStallExecutionProcessor(CurrentSample->PerfFreq.QuadPart * -1 / 10);
58
59 /* Do another dummy CPUID */
60 KiCpuId(&CpuInfo, 0);
61
62 /* Fill out the ending data */
63 CurrentSample->PerfEnd =
64 KeQueryPerformanceCounter(&CurrentSample->PerfFreq);
65 CurrentSample->TSCEnd = __rdtsc();
66
67 /* Calculate the differences */
68 CurrentSample->PerfDelta = CurrentSample->PerfEnd.QuadPart -
69 CurrentSample->PerfStart.QuadPart;
70 CurrentSample->TSCDelta = CurrentSample->TSCEnd -
71 CurrentSample->TSCStart;
72
73 /* Compute CPU Speed */
74 CurrentSample->MHz = (ULONG)((CurrentSample->TSCDelta *
75 CurrentSample->
76 PerfFreq.QuadPart + 500000) /
77 (CurrentSample->PerfDelta *
78 1000000));
79
80 /* Check if this isn't the first sample */
81 if (Sample)
82 {
83 /* Check if we got a good precision within 1MHz */
84 if ((CurrentSample->MHz == CurrentSample[-1].MHz) ||
85 (CurrentSample->MHz == CurrentSample[-1].MHz + 1) ||
86 (CurrentSample->MHz == CurrentSample[-1].MHz - 1))
87 {
88 /* We did, stop sampling */
89 break;
90 }
91 }
92
93 /* Move on */
94 CurrentSample++;
95 Sample++;
96
97 if (Sample == RTL_NUMBER_OF(Samples))
98 {
99 /* No luck. Average the samples and be done */
100 ULONG TotalMHz = 0;
101 while (Sample--)
102 {
103 TotalMHz += Samples[Sample].MHz;
104 }
105 CurrentSample[-1].MHz = TotalMHz / RTL_NUMBER_OF(Samples);
106 DPRINT1("Sampling CPU frequency failed. Using average of %lu MHz\n", CurrentSample[-1].MHz);
107 break;
108 }
109 }
110
111 /* Save the CPU Speed */
112 Prcb->MHz = CurrentSample[-1].MHz;
113 }
114 }
115
116 VOID
117 NTAPI
118 KiInitializeHandBuiltThread(
119 IN PKTHREAD Thread,
120 IN PKPROCESS Process,
121 IN PVOID Stack)
122 {
123 PKPRCB Prcb = KeGetCurrentPrcb();
124
125 /* Setup the Thread */
126 KeInitializeThread(Process, Thread, NULL, NULL, NULL, NULL, NULL, Stack);
127
128 Thread->NextProcessor = Prcb->Number;
129 Thread->IdealProcessor = Prcb->Number;
130 Thread->Priority = HIGH_PRIORITY;
131 Thread->State = Running;
132 Thread->Affinity = (ULONG_PTR)1 << Prcb->Number;
133 Thread->WaitIrql = DISPATCH_LEVEL;
134 Process->ActiveProcessors |= (ULONG_PTR)1 << Prcb->Number;
135
136 }
137
138 CODE_SEG("INIT")
139 DECLSPEC_NORETURN
140 VOID
141 NTAPI
142 KiSystemStartupBootStack(VOID)
143 {
144 PLOADER_PARAMETER_BLOCK LoaderBlock = KeLoaderBlock; // hack
145 PKPRCB Prcb = KeGetCurrentPrcb();
146 PKTHREAD Thread = (PKTHREAD)KeLoaderBlock->Thread;
147 PKPROCESS Process = Thread->ApcState.Process;
148 PVOID KernelStack = (PVOID)KeLoaderBlock->KernelStack;
149
150 /* Set Node Data */
151 Prcb->ParentNode = KeNodeBlock[0];
152 Prcb->ParentNode->ProcessorMask |= Prcb->SetMember;
153
154 /* Initialize the Power Management Support for this PRCB */
155 PoInitializePrcb(Prcb);
156
157 /* Save CPU state */
158 KiSaveProcessorControlState(&Prcb->ProcessorState);
159
160 /* Get cache line information for this CPU */
161 KiGetCacheInformation();
162
163 /* Initialize spinlocks and DPC data */
164 KiInitSpinLocks(Prcb, Prcb->Number);
165
166 /* Set up the thread-related fields in the PRCB */
167 Prcb->CurrentThread = Thread;
168 Prcb->NextThread = NULL;
169 Prcb->IdleThread = Thread;
170
171 /* Initialize PRCB pool lookaside pointers */
172 ExInitPoolLookasidePointers();
173
174 /* Lower to APC_LEVEL */
175 KeLowerIrql(APC_LEVEL);
176
177 /* Check if this is the boot cpu */
178 if (Prcb->Number == 0)
179 {
180 /* Initialize the kernel */
181 KiInitializeKernel(Process, Thread, KernelStack, Prcb, LoaderBlock);
182 }
183 else
184 {
185 /* Initialize the startup thread */
186 KiInitializeHandBuiltThread(Thread, Process, KernelStack);
187 }
188
189 /* Calculate the CPU frequency */
190 KiCalculateCpuFrequency(Prcb);
191
192 /* Raise to Dispatch */
193 KfRaiseIrql(DISPATCH_LEVEL);
194
195 /* Set the Idle Priority to 0. This will jump into Phase 1 */
196 KeSetPriorityThread(Thread, 0);
197
198 /* If there's no thread scheduled, put this CPU in the Idle summary */
199 KiAcquirePrcbLock(Prcb);
200 if (!Prcb->NextThread) KiIdleSummary |= (ULONG_PTR)1 << Prcb->Number;
201 KiReleasePrcbLock(Prcb);
202
203 /* Raise back to HIGH_LEVEL and clear the PRCB for the loader block */
204 KfRaiseIrql(HIGH_LEVEL);
205 LoaderBlock->Prcb = 0;
206
207 /* Set the priority of this thread to 0 */
208 Thread = KeGetCurrentThread();
209 Thread->Priority = 0;
210
211 /* Force interrupts enabled and lower IRQL back to DISPATCH_LEVEL */
212 _enable();
213 KeLowerIrql(DISPATCH_LEVEL);
214
215 /* Set the right wait IRQL */
216 Thread->WaitIrql = DISPATCH_LEVEL;
217
218 /* Jump into the idle loop */
219 KiIdleLoop();
220 }
221
222 CODE_SEG("INIT")
223 VOID
224 NTAPI
225 KiInitializeKernel(IN PKPROCESS InitProcess,
226 IN PKTHREAD InitThread,
227 IN PVOID IdleStack,
228 IN PKPRCB Prcb,
229 IN PLOADER_PARAMETER_BLOCK LoaderBlock)
230 {
231 ULONG_PTR PageDirectory[2];
232 PVOID DpcStack;
233 ULONG i;
234
235 /* Set boot-level flags */
236 KeFeatureBits = Prcb->FeatureBits;
237
238 /* Initialize 8/16 bit SList support */
239 RtlpUse16ByteSLists = (KeFeatureBits & KF_CMPXCHG16B) ? TRUE : FALSE;
240
241 /* Set the current MP Master KPRCB to the Boot PRCB */
242 Prcb->MultiThreadSetMaster = Prcb;
243
244 /* Initialize Bugcheck Callback data */
245 InitializeListHead(&KeBugcheckCallbackListHead);
246 InitializeListHead(&KeBugcheckReasonCallbackListHead);
247 KeInitializeSpinLock(&BugCheckCallbackLock);
248
249 /* Initialize the Timer Expiration DPC */
250 KeInitializeDpc(&KiTimerExpireDpc, KiTimerExpiration, NULL);
251 KeSetTargetProcessorDpc(&KiTimerExpireDpc, 0);
252
253 /* Initialize Profiling data */
254 KeInitializeSpinLock(&KiProfileLock);
255 InitializeListHead(&KiProfileListHead);
256 InitializeListHead(&KiProfileSourceListHead);
257
258 /* Loop the timer table */
259 for (i = 0; i < TIMER_TABLE_SIZE; i++)
260 {
261 /* Initialize the list and entries */
262 InitializeListHead(&KiTimerTableListHead[i].Entry);
263 KiTimerTableListHead[i].Time.HighPart = 0xFFFFFFFF;
264 KiTimerTableListHead[i].Time.LowPart = 0;
265 }
266
267 /* Initialize the Swap event and all swap lists */
268 KeInitializeEvent(&KiSwapEvent, SynchronizationEvent, FALSE);
269 InitializeListHead(&KiProcessInSwapListHead);
270 InitializeListHead(&KiProcessOutSwapListHead);
271 InitializeListHead(&KiStackInSwapListHead);
272
273 /* Initialize the mutex for generic DPC calls */
274 ExInitializeFastMutex(&KiGenericCallDpcMutex);
275
276 /* Initialize the syscall table */
277 KeServiceDescriptorTable[0].Base = MainSSDT;
278 KeServiceDescriptorTable[0].Count = NULL;
279 KeServiceDescriptorTable[0].Limit = KiServiceLimit;
280 KeServiceDescriptorTable[1].Limit = 0;
281 KeServiceDescriptorTable[0].Number = MainSSPT;
282
283 /* Copy the the current table into the shadow table for win32k */
284 RtlCopyMemory(KeServiceDescriptorTableShadow,
285 KeServiceDescriptorTable,
286 sizeof(KeServiceDescriptorTable));
287
288 /* Initialize the Idle Process and the Process Listhead */
289 InitializeListHead(&KiProcessListHead);
290 PageDirectory[0] = 0;
291 PageDirectory[1] = 0;
292 KeInitializeProcess(InitProcess,
293 0,
294 MAXULONG_PTR,
295 PageDirectory,
296 FALSE);
297 InitProcess->QuantumReset = MAXCHAR;
298
299 /* Initialize the startup thread */
300 KiInitializeHandBuiltThread(InitThread, InitProcess, IdleStack);
301
302 /* Initialize the Kernel Executive */
303 ExpInitializeExecutive(0, LoaderBlock);
304
305 /* Calculate the time reciprocal */
306 KiTimeIncrementReciprocal =
307 KiComputeReciprocal(KeMaximumIncrement,
308 &KiTimeIncrementShiftCount);
309
310 /* Update DPC Values in case they got updated by the executive */
311 Prcb->MaximumDpcQueueDepth = KiMaximumDpcQueueDepth;
312 Prcb->MinimumDpcRate = KiMinimumDpcRate;
313 Prcb->AdjustDpcThreshold = KiAdjustDpcThreshold;
314
315 /* Allocate the DPC Stack */
316 DpcStack = MmCreateKernelStack(FALSE, 0);
317 if (!DpcStack) KeBugCheckEx(NO_PAGES_AVAILABLE, 1, 0, 0, 0);
318 Prcb->DpcStack = DpcStack;
319 }
320