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)
10 /* INCLUDES ******************************************************************/
16 extern ULONG_PTR MainSSDT
[];
17 extern UCHAR MainSSPT
[];
19 extern BOOLEAN RtlpUse16ByteSLists
;
21 /* FUNCTIONS *****************************************************************/
26 KiInitializeKernel(IN PKPROCESS InitProcess
,
27 IN PKTHREAD InitThread
,
30 IN PLOADER_PARAMETER_BLOCK LoaderBlock
);
35 KiCalculateCpuFrequency(
38 if (Prcb
->FeatureBits
& KF_RDTSC
)
42 KI_SAMPLE_MAP Samples
[10];
43 PKI_SAMPLE_MAP CurrentSample
= Samples
;
45 /* Start sampling loop */
48 /* Do a dummy CPUID to start the sample */
51 /* Fill out the starting data */
52 CurrentSample
->PerfStart
= KeQueryPerformanceCounter(NULL
);
53 CurrentSample
->TSCStart
= __rdtsc();
54 CurrentSample
->PerfFreq
.QuadPart
= -50000;
56 /* Sleep for this sample */
57 KeStallExecutionProcessor(CurrentSample
->PerfFreq
.QuadPart
* -1 / 10);
59 /* Do another dummy CPUID */
62 /* Fill out the ending data */
63 CurrentSample
->PerfEnd
=
64 KeQueryPerformanceCounter(&CurrentSample
->PerfFreq
);
65 CurrentSample
->TSCEnd
= __rdtsc();
67 /* Calculate the differences */
68 CurrentSample
->PerfDelta
= CurrentSample
->PerfEnd
.QuadPart
-
69 CurrentSample
->PerfStart
.QuadPart
;
70 CurrentSample
->TSCDelta
= CurrentSample
->TSCEnd
-
71 CurrentSample
->TSCStart
;
73 /* Compute CPU Speed */
74 CurrentSample
->MHz
= (ULONG
)((CurrentSample
->TSCDelta
*
76 PerfFreq
.QuadPart
+ 500000) /
77 (CurrentSample
->PerfDelta
*
80 /* Check if this isn't the first sample */
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))
88 /* We did, stop sampling */
97 if (Sample
== RTL_NUMBER_OF(Samples
))
99 /* No luck. Average the samples and be done */
103 TotalMHz
+= Samples
[Sample
].MHz
;
105 CurrentSample
[-1].MHz
= TotalMHz
/ RTL_NUMBER_OF(Samples
);
106 DPRINT1("Sampling CPU frequency failed. Using average of %lu MHz\n", CurrentSample
[-1].MHz
);
111 /* Save the CPU Speed */
112 Prcb
->MHz
= CurrentSample
[-1].MHz
;
118 KiInitializeHandBuiltThread(
120 IN PKPROCESS Process
,
123 PKPRCB Prcb
= KeGetCurrentPrcb();
125 /* Setup the Thread */
126 KeInitializeThread(Process
, Thread
, NULL
, NULL
, NULL
, NULL
, NULL
, Stack
);
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
;
142 KiSystemStartupBootStack(VOID
)
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
;
151 Prcb
->ParentNode
= KeNodeBlock
[0];
152 Prcb
->ParentNode
->ProcessorMask
|= Prcb
->SetMember
;
154 /* Initialize the Power Management Support for this PRCB */
155 PoInitializePrcb(Prcb
);
158 KiSaveProcessorControlState(&Prcb
->ProcessorState
);
160 /* Get cache line information for this CPU */
161 KiGetCacheInformation();
163 /* Initialize spinlocks and DPC data */
164 KiInitSpinLocks(Prcb
, Prcb
->Number
);
166 /* Set up the thread-related fields in the PRCB */
167 Prcb
->CurrentThread
= Thread
;
168 Prcb
->NextThread
= NULL
;
169 Prcb
->IdleThread
= Thread
;
171 /* Initialize PRCB pool lookaside pointers */
172 ExInitPoolLookasidePointers();
174 /* Lower to APC_LEVEL */
175 KeLowerIrql(APC_LEVEL
);
177 /* Check if this is the boot cpu */
178 if (Prcb
->Number
== 0)
180 /* Initialize the kernel */
181 KiInitializeKernel(Process
, Thread
, KernelStack
, Prcb
, LoaderBlock
);
185 /* Initialize the startup thread */
186 KiInitializeHandBuiltThread(Thread
, Process
, KernelStack
);
189 /* Calculate the CPU frequency */
190 KiCalculateCpuFrequency(Prcb
);
192 /* Raise to Dispatch */
193 KfRaiseIrql(DISPATCH_LEVEL
);
195 /* Set the Idle Priority to 0. This will jump into Phase 1 */
196 KeSetPriorityThread(Thread
, 0);
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
);
203 /* Raise back to HIGH_LEVEL and clear the PRCB for the loader block */
204 KfRaiseIrql(HIGH_LEVEL
);
205 LoaderBlock
->Prcb
= 0;
207 /* Set the priority of this thread to 0 */
208 Thread
= KeGetCurrentThread();
209 Thread
->Priority
= 0;
211 /* Force interrupts enabled and lower IRQL back to DISPATCH_LEVEL */
213 KeLowerIrql(DISPATCH_LEVEL
);
215 /* Set the right wait IRQL */
216 Thread
->WaitIrql
= DISPATCH_LEVEL
;
218 /* Jump into the idle loop */
225 KiInitializeKernel(IN PKPROCESS InitProcess
,
226 IN PKTHREAD InitThread
,
229 IN PLOADER_PARAMETER_BLOCK LoaderBlock
)
231 ULONG_PTR PageDirectory
[2];
235 /* Set boot-level flags */
236 KeFeatureBits
= Prcb
->FeatureBits
;
238 /* Initialize 8/16 bit SList support */
239 RtlpUse16ByteSLists
= (KeFeatureBits
& KF_CMPXCHG16B
) ? TRUE
: FALSE
;
241 /* Set the current MP Master KPRCB to the Boot PRCB */
242 Prcb
->MultiThreadSetMaster
= Prcb
;
244 /* Initialize Bugcheck Callback data */
245 InitializeListHead(&KeBugcheckCallbackListHead
);
246 InitializeListHead(&KeBugcheckReasonCallbackListHead
);
247 KeInitializeSpinLock(&BugCheckCallbackLock
);
249 /* Initialize the Timer Expiration DPC */
250 KeInitializeDpc(&KiTimerExpireDpc
, KiTimerExpiration
, NULL
);
251 KeSetTargetProcessorDpc(&KiTimerExpireDpc
, 0);
253 /* Initialize Profiling data */
254 KeInitializeSpinLock(&KiProfileLock
);
255 InitializeListHead(&KiProfileListHead
);
256 InitializeListHead(&KiProfileSourceListHead
);
258 /* Loop the timer table */
259 for (i
= 0; i
< TIMER_TABLE_SIZE
; i
++)
261 /* Initialize the list and entries */
262 InitializeListHead(&KiTimerTableListHead
[i
].Entry
);
263 KiTimerTableListHead
[i
].Time
.HighPart
= 0xFFFFFFFF;
264 KiTimerTableListHead
[i
].Time
.LowPart
= 0;
267 /* Initialize the Swap event and all swap lists */
268 KeInitializeEvent(&KiSwapEvent
, SynchronizationEvent
, FALSE
);
269 InitializeListHead(&KiProcessInSwapListHead
);
270 InitializeListHead(&KiProcessOutSwapListHead
);
271 InitializeListHead(&KiStackInSwapListHead
);
273 /* Initialize the mutex for generic DPC calls */
274 ExInitializeFastMutex(&KiGenericCallDpcMutex
);
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
;
283 /* Copy the the current table into the shadow table for win32k */
284 RtlCopyMemory(KeServiceDescriptorTableShadow
,
285 KeServiceDescriptorTable
,
286 sizeof(KeServiceDescriptorTable
));
288 /* Initialize the Idle Process and the Process Listhead */
289 InitializeListHead(&KiProcessListHead
);
290 PageDirectory
[0] = 0;
291 PageDirectory
[1] = 0;
292 KeInitializeProcess(InitProcess
,
297 InitProcess
->QuantumReset
= MAXCHAR
;
299 /* Initialize the startup thread */
300 KiInitializeHandBuiltThread(InitThread
, InitProcess
, IdleStack
);
302 /* Initialize the Kernel Executive */
303 ExpInitializeExecutive(0, LoaderBlock
);
305 /* Calculate the time reciprocal */
306 KiTimeIncrementReciprocal
=
307 KiComputeReciprocal(KeMaximumIncrement
,
308 &KiTimeIncrementShiftCount
);
310 /* Update DPC Values in case they got updated by the executive */
311 Prcb
->MaximumDpcQueueDepth
= KiMaximumDpcQueueDepth
;
312 Prcb
->MinimumDpcRate
= KiMinimumDpcRate
;
313 Prcb
->AdjustDpcThreshold
= KiAdjustDpcThreshold
;
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
;