Sync with trunk r63743.
[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/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 /* FUNCTIONS *****************************************************************/
20
21 VOID
22 NTAPI
23 INIT_FUNCTION
24 KiInitializeKernel(IN PKPROCESS InitProcess,
25 IN PKTHREAD InitThread,
26 IN PVOID IdleStack,
27 IN PKPRCB Prcb,
28 IN PLOADER_PARAMETER_BLOCK LoaderBlock);
29
30
31 VOID
32 NTAPI
33 KiInitializeHandBuiltThread(
34 IN PKTHREAD Thread,
35 IN PKPROCESS Process,
36 IN PVOID Stack)
37 {
38 PKPRCB Prcb = KeGetCurrentPrcb();
39
40 /* Setup the Thread */
41 KeInitializeThread(Process, Thread, NULL, NULL, NULL, NULL, NULL, Stack);
42
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;
49
50 }
51
52 VOID
53 NTAPI
54 INIT_FUNCTION
55 KiSystemStartupBootStack(VOID)
56 {
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;
62
63 /* Initialize the Power Management Support for this PRCB */
64 PoInitializePrcb(Prcb);
65
66 /* Save CPU state */
67 KiSaveProcessorControlState(&Prcb->ProcessorState);
68
69 /* Get cache line information for this CPU */
70 KiGetCacheInformation();
71
72 /* Initialize spinlocks and DPC data */
73 KiInitSpinLocks(Prcb, Prcb->Number);
74
75 /* Set up the thread-related fields in the PRCB */
76 Prcb->CurrentThread = Thread;
77 Prcb->NextThread = NULL;
78 Prcb->IdleThread = Thread;
79
80 /* Initialize PRCB pool lookaside pointers */
81 ExInitPoolLookasidePointers();
82
83 /* Lower to APC_LEVEL */
84 KeLowerIrql(APC_LEVEL);
85
86 /* Check if this is the boot cpu */
87 if (Prcb->Number == 0)
88 {
89 /* Initialize the kernel */
90 KiInitializeKernel(Process, Thread, KernelStack, Prcb, LoaderBlock);
91 }
92 else
93 {
94 /* Initialize the startup thread */
95 KiInitializeHandBuiltThread(Thread, Process, KernelStack);
96
97 /* Initialize cpu with HAL */
98 if (!HalInitSystem(0, LoaderBlock))
99 {
100 /* Initialization failed */
101 KeBugCheck(HAL_INITIALIZATION_FAILED);
102 }
103 }
104
105 /* Raise to Dispatch */
106 KfRaiseIrql(DISPATCH_LEVEL);
107
108 /* Set the Idle Priority to 0. This will jump into Phase 1 */
109 KeSetPriorityThread(Thread, 0);
110
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);
115
116 /* Raise back to HIGH_LEVEL and clear the PRCB for the loader block */
117 KfRaiseIrql(HIGH_LEVEL);
118 LoaderBlock->Prcb = 0;
119
120 /* Set the priority of this thread to 0 */
121 Thread = KeGetCurrentThread();
122 Thread->Priority = 0;
123
124 /* Force interrupts enabled and lower IRQL back to DISPATCH_LEVEL */
125 _enable();
126 KeLowerIrql(DISPATCH_LEVEL);
127
128 /* Set the right wait IRQL */
129 Thread->WaitIrql = DISPATCH_LEVEL;
130
131 /* Jump into the idle loop */
132 KiIdleLoop();
133 }
134
135 VOID
136 NTAPI
137 INIT_FUNCTION
138 KiInitializeKernel(IN PKPROCESS InitProcess,
139 IN PKTHREAD InitThread,
140 IN PVOID IdleStack,
141 IN PKPRCB Prcb,
142 IN PLOADER_PARAMETER_BLOCK LoaderBlock)
143 {
144 ULONG_PTR PageDirectory[2];
145 PVOID DpcStack;
146 ULONG i;
147
148 /* Set Node Data */
149 KeNodeBlock[0] = &KiNode0;
150 Prcb->ParentNode = KeNodeBlock[0];
151 KeNodeBlock[0]->ProcessorMask = Prcb->SetMember;
152
153 /* Set boot-level flags */
154 KeFeatureBits = Prcb->FeatureBits;
155
156 /* Set the current MP Master KPRCB to the Boot PRCB */
157 Prcb->MultiThreadSetMaster = Prcb;
158
159 /* Initialize Bugcheck Callback data */
160 InitializeListHead(&KeBugcheckCallbackListHead);
161 InitializeListHead(&KeBugcheckReasonCallbackListHead);
162 KeInitializeSpinLock(&BugCheckCallbackLock);
163
164 /* Initialize the Timer Expiration DPC */
165 KeInitializeDpc(&KiTimerExpireDpc, KiTimerExpiration, NULL);
166 KeSetTargetProcessorDpc(&KiTimerExpireDpc, 0);
167
168 /* Initialize Profiling data */
169 KeInitializeSpinLock(&KiProfileLock);
170 InitializeListHead(&KiProfileListHead);
171 InitializeListHead(&KiProfileSourceListHead);
172
173 /* Loop the timer table */
174 for (i = 0; i < TIMER_TABLE_SIZE; i++)
175 {
176 /* Initialize the list and entries */
177 InitializeListHead(&KiTimerTableListHead[i].Entry);
178 KiTimerTableListHead[i].Time.HighPart = 0xFFFFFFFF;
179 KiTimerTableListHead[i].Time.LowPart = 0;
180 }
181
182 /* Initialize the Swap event and all swap lists */
183 KeInitializeEvent(&KiSwapEvent, SynchronizationEvent, FALSE);
184 InitializeListHead(&KiProcessInSwapListHead);
185 InitializeListHead(&KiProcessOutSwapListHead);
186 InitializeListHead(&KiStackInSwapListHead);
187
188 /* Initialize the mutex for generic DPC calls */
189 ExInitializeFastMutex(&KiGenericCallDpcMutex);
190
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;
197
198 /* Copy the the current table into the shadow table for win32k */
199 RtlCopyMemory(KeServiceDescriptorTableShadow,
200 KeServiceDescriptorTable,
201 sizeof(KeServiceDescriptorTable));
202
203 /* Initialize the Idle Process and the Process Listhead */
204 InitializeListHead(&KiProcessListHead);
205 PageDirectory[0] = 0;
206 PageDirectory[1] = 0;
207 KeInitializeProcess(InitProcess,
208 0,
209 0xFFFFFFFF,
210 PageDirectory,
211 FALSE);
212 InitProcess->QuantumReset = MAXCHAR;
213
214 /* Initialize the startup thread */
215 KiInitializeHandBuiltThread(InitThread, InitProcess, IdleStack);
216
217 /* Initialize the Kernel Executive */
218 ExpInitializeExecutive(0, LoaderBlock);
219
220 /* Calculate the time reciprocal */
221 KiTimeIncrementReciprocal =
222 KiComputeReciprocal(KeMaximumIncrement,
223 &KiTimeIncrementShiftCount);
224
225 /* Update DPC Values in case they got updated by the executive */
226 Prcb->MaximumDpcQueueDepth = KiMaximumDpcQueueDepth;
227 Prcb->MinimumDpcRate = KiMinimumDpcRate;
228 Prcb->AdjustDpcThreshold = KiAdjustDpcThreshold;
229
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;
234 }
235