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