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: 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 /* FUNCTIONS *****************************************************************/
24 KiInitializeKernel(IN PKPROCESS InitProcess
,
25 IN PKTHREAD InitThread
,
28 IN PLOADER_PARAMETER_BLOCK LoaderBlock
);
33 KiInitializeHandBuiltThread(
38 PKPRCB Prcb
= KeGetCurrentPrcb();
40 /* Setup the Thread */
41 KeInitializeThread(Process
, Thread
, NULL
, NULL
, NULL
, NULL
, NULL
, Stack
);
43 Thread
->NextProcessor
= Prcb
->Number
;
44 Thread
->Priority
= HIGH_PRIORITY
;
45 Thread
->State
= Running
;
46 Thread
->Affinity
= (ULONG_PTR
)1 << Prcb
->Number
;
47 Thread
->WaitIrql
= DISPATCH_LEVEL
;
48 Process
->ActiveProcessors
|= (ULONG_PTR
)1 << Prcb
->Number
;
55 KiSystemStartupBootStack(VOID
)
57 PLOADER_PARAMETER_BLOCK LoaderBlock
= KeLoaderBlock
; // hack
58 PKPRCB Prcb
= KeGetCurrentPrcb();
59 PKTHREAD Thread
= (PKTHREAD
)KeLoaderBlock
->Thread
;
60 PKPROCESS Process
= Thread
->ApcState
.Process
;
61 PVOID KernelStack
= (PVOID
)KeLoaderBlock
->KernelStack
;
63 /* Initialize the Power Management Support for this PRCB */
64 PoInitializePrcb(Prcb
);
67 KiSaveProcessorControlState(&Prcb
->ProcessorState
);
69 /* Get cache line information for this CPU */
70 KiGetCacheInformation();
72 /* Initialize spinlocks and DPC data */
73 KiInitSpinLocks(Prcb
, Prcb
->Number
);
75 /* Set up the thread-related fields in the PRCB */
76 Prcb
->CurrentThread
= Thread
;
77 Prcb
->NextThread
= NULL
;
78 Prcb
->IdleThread
= Thread
;
80 /* Initialize PRCB pool lookaside pointers */
81 ExInitPoolLookasidePointers();
83 /* Lower to APC_LEVEL */
84 KeLowerIrql(APC_LEVEL
);
86 /* Check if this is the boot cpu */
87 if (Prcb
->Number
== 0)
89 /* Initialize the kernel */
90 KiInitializeKernel(Process
, Thread
, KernelStack
, Prcb
, LoaderBlock
);
94 /* Initialize the startup thread */
95 KiInitializeHandBuiltThread(Thread
, Process
, KernelStack
);
97 /* Initialize cpu with HAL */
98 if (!HalInitSystem(0, LoaderBlock
))
100 /* Initialization failed */
101 KeBugCheck(HAL_INITIALIZATION_FAILED
);
105 /* Raise to Dispatch */
106 KfRaiseIrql(DISPATCH_LEVEL
);
108 /* Set the Idle Priority to 0. This will jump into Phase 1 */
109 KeSetPriorityThread(Thread
, 0);
111 /* If there's no thread scheduled, put this CPU in the Idle summary */
112 KiAcquirePrcbLock(Prcb
);
113 if (!Prcb
->NextThread
) KiIdleSummary
|= (ULONG_PTR
)1 << Prcb
->Number
;
114 KiReleasePrcbLock(Prcb
);
116 /* Raise back to HIGH_LEVEL and clear the PRCB for the loader block */
117 KfRaiseIrql(HIGH_LEVEL
);
118 LoaderBlock
->Prcb
= 0;
120 /* Set the priority of this thread to 0 */
121 Thread
= KeGetCurrentThread();
122 Thread
->Priority
= 0;
124 /* Force interrupts enabled and lower IRQL back to DISPATCH_LEVEL */
126 KeLowerIrql(DISPATCH_LEVEL
);
128 /* Set the right wait IRQL */
129 Thread
->WaitIrql
= DISPATCH_LEVEL
;
131 /* Jump into the idle loop */
138 KiInitializeKernel(IN PKPROCESS InitProcess
,
139 IN PKTHREAD InitThread
,
142 IN PLOADER_PARAMETER_BLOCK LoaderBlock
)
144 ULONG_PTR PageDirectory
[2];
149 KeNodeBlock
[0] = &KiNode0
;
150 Prcb
->ParentNode
= KeNodeBlock
[0];
151 KeNodeBlock
[0]->ProcessorMask
= Prcb
->SetMember
;
153 /* Set boot-level flags */
154 KeFeatureBits
= Prcb
->FeatureBits
;
156 /* Set the current MP Master KPRCB to the Boot PRCB */
157 Prcb
->MultiThreadSetMaster
= Prcb
;
159 /* Initialize Bugcheck Callback data */
160 InitializeListHead(&KeBugcheckCallbackListHead
);
161 InitializeListHead(&KeBugcheckReasonCallbackListHead
);
162 KeInitializeSpinLock(&BugCheckCallbackLock
);
164 /* Initialize the Timer Expiration DPC */
165 KeInitializeDpc(&KiTimerExpireDpc
, KiTimerExpiration
, NULL
);
166 KeSetTargetProcessorDpc(&KiTimerExpireDpc
, 0);
168 /* Initialize Profiling data */
169 KeInitializeSpinLock(&KiProfileLock
);
170 InitializeListHead(&KiProfileListHead
);
171 InitializeListHead(&KiProfileSourceListHead
);
173 /* Loop the timer table */
174 for (i
= 0; i
< TIMER_TABLE_SIZE
; i
++)
176 /* Initialize the list and entries */
177 InitializeListHead(&KiTimerTableListHead
[i
].Entry
);
178 KiTimerTableListHead
[i
].Time
.HighPart
= 0xFFFFFFFF;
179 KiTimerTableListHead
[i
].Time
.LowPart
= 0;
182 /* Initialize the Swap event and all swap lists */
183 KeInitializeEvent(&KiSwapEvent
, SynchronizationEvent
, FALSE
);
184 InitializeListHead(&KiProcessInSwapListHead
);
185 InitializeListHead(&KiProcessOutSwapListHead
);
186 InitializeListHead(&KiStackInSwapListHead
);
188 /* Initialize the mutex for generic DPC calls */
189 ExInitializeFastMutex(&KiGenericCallDpcMutex
);
191 /* Initialize the syscall table */
192 KeServiceDescriptorTable
[0].Base
= MainSSDT
;
193 KeServiceDescriptorTable
[0].Count
= NULL
;
194 KeServiceDescriptorTable
[0].Limit
= KiServiceLimit
;
195 KeServiceDescriptorTable
[1].Limit
= 0;
196 KeServiceDescriptorTable
[0].Number
= MainSSPT
;
198 /* Copy the the current table into the shadow table for win32k */
199 RtlCopyMemory(KeServiceDescriptorTableShadow
,
200 KeServiceDescriptorTable
,
201 sizeof(KeServiceDescriptorTable
));
203 /* Initialize the Idle Process and the Process Listhead */
204 InitializeListHead(&KiProcessListHead
);
205 PageDirectory
[0] = 0;
206 PageDirectory
[1] = 0;
207 KeInitializeProcess(InitProcess
,
212 InitProcess
->QuantumReset
= MAXCHAR
;
214 /* Initialize the startup thread */
215 KiInitializeHandBuiltThread(InitThread
, InitProcess
, IdleStack
);
217 /* Initialize the Kernel Executive */
218 ExpInitializeExecutive(0, LoaderBlock
);
220 /* Calculate the time reciprocal */
221 KiTimeIncrementReciprocal
=
222 KiComputeReciprocal(KeMaximumIncrement
,
223 &KiTimeIncrementShiftCount
);
225 /* Update DPC Values in case they got updated by the executive */
226 Prcb
->MaximumDpcQueueDepth
= KiMaximumDpcQueueDepth
;
227 Prcb
->MinimumDpcRate
= KiMinimumDpcRate
;
228 Prcb
->AdjustDpcThreshold
= KiAdjustDpcThreshold
;
230 /* Allocate the DPC Stack */
231 DpcStack
= MmCreateKernelStack(FALSE
, 0);
232 if (!DpcStack
) KeBugCheckEx(NO_PAGES_AVAILABLE
, 1, 0, 0, 0);
233 Prcb
->DpcStack
= DpcStack
;