- KPROCSES Flags are LONG, not ULONG.
[reactos.git] / reactos / ntoskrnl / ke / i386 / kiinit.c
1 /*
2 * PROJECT: ReactOS Kernel
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: ntoskrnl/ke/i386/kiinit.c
5 * PURPOSE: Kernel Initialization for x86 CPUs
6 * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
7 */
8
9 /* INCLUDES *****************************************************************/
10
11 #include <ntoskrnl.h>
12 #define NDEBUG
13 #include <debug.h>
14
15 /* GLOBALS *******************************************************************/
16
17 /* Spinlocks used only on X86 */
18 KSPIN_LOCK KiFreezeExecutionLock;
19 KSPIN_LOCK Ki486CompatibilityLock;
20
21 /* FUNCTIONS *****************************************************************/
22
23 VOID
24 NTAPI
25 KiInitializePcr(IN ULONG ProcessorNumber,
26 IN PKIPCR Pcr,
27 IN PKIDTENTRY Idt,
28 IN PKGDTENTRY Gdt,
29 IN PKTSS Tss,
30 IN PKTHREAD IdleThread,
31 IN PVOID DpcStack)
32 {
33 /* Setup the TIB */
34 Pcr->NtTib.ExceptionList = EXCEPTION_CHAIN_END;
35 Pcr->NtTib.StackBase = 0;
36 Pcr->NtTib.StackLimit = 0;
37 Pcr->NtTib.Self = 0;
38
39 /* Set the Current Thread */
40 //Pcr->PrcbData.CurrentThread = IdleThread;
41
42 /* Set pointers to ourselves */
43 Pcr->Self = (PKPCR)Pcr;
44 Pcr->Prcb = &Pcr->PrcbData;
45
46 /* Set the PCR Version */
47 Pcr->MajorVersion = PCR_MAJOR_VERSION;
48 Pcr->MinorVersion = PCR_MINOR_VERSION;
49
50 /* Set the PCRB Version */
51 Pcr->PrcbData.MajorVersion = 1;
52 Pcr->PrcbData.MinorVersion = 1;
53
54 /* Set the Build Type */
55 Pcr->PrcbData.BuildType = 0;
56
57 /* Set the Processor Number and current Processor Mask */
58 Pcr->PrcbData.Number = (UCHAR)ProcessorNumber;
59 Pcr->PrcbData.SetMember = 1 << ProcessorNumber;
60
61 /* Set the PRCB for this Processor */
62 KiProcessorBlock[ProcessorNumber] = Pcr->Prcb;
63
64 /* Start us out at PASSIVE_LEVEL */
65 Pcr->Irql = PASSIVE_LEVEL;
66
67 /* Set the GDI, IDT, TSS and DPC Stack */
68 Pcr->GDT = (PVOID)Gdt;
69 Pcr->IDT = Idt;
70 Pcr->TSS = Tss;
71 Pcr->PrcbData.DpcStack = DpcStack;
72 }
73
74 VOID
75 NTAPI
76 KiInitializeKernel(IN PKPROCESS InitProcess,
77 IN PKTHREAD InitThread,
78 IN PVOID IdleStack,
79 IN PKPRCB Prcb,
80 IN CCHAR Number,
81 IN PROS_LOADER_PARAMETER_BLOCK LoaderBlock)
82 {
83 BOOLEAN NpxPresent;
84 ULONG FeatureBits;
85 LARGE_INTEGER PageDirectory;
86 PVOID DpcStack;
87
88 /* Detect and set the CPU Type */
89 KiSetProcessorType();
90
91 /* Set CR0 features based on detected CPU */
92 KiSetCR0Bits();
93
94 /* Check if an FPU is present */
95 NpxPresent = KiIsNpxPresent();
96
97 /* Initialize the Power Management Support for this PRCB */
98 PoInitializePrcb(Prcb);
99
100 /* Bugcheck if this is a 386 CPU */
101 if (Prcb->CpuType == 3) KeBugCheckEx(0x5D, 0x386, 0, 0, 0);
102
103 /* Get the processor features for the CPU */
104 FeatureBits = KiGetFeatureBits();
105
106 /* Save feature bits */
107 Prcb->FeatureBits = FeatureBits;
108
109 /* Get cache line information for this CPU */
110 KiGetCacheInformation();
111
112 /* Initialize spinlocks and DPC data */
113 KiInitSpinLocks(Prcb, Number);
114
115 /* Check if this is the Boot CPU */
116 if (!Number)
117 {
118 /* Set Node Data */
119 KeNodeBlock[0] = &KiNode0;
120 Prcb->ParentNode = KeNodeBlock[0];
121 KeNodeBlock[0]->ProcessorMask = Prcb->SetMember;
122
123 /* Set boot-level flags */
124 KeI386NpxPresent = NpxPresent;
125 KeI386CpuType = Prcb->CpuType;
126 KeI386CpuStep = Prcb->CpuStep;
127 KeProcessorArchitecture = 0;
128 KeProcessorLevel = (USHORT)Prcb->CpuType;
129 if (Prcb->CpuID) KeProcessorRevision = Prcb->CpuStep;
130 KeFeatureBits = FeatureBits;
131 KeI386FxsrPresent = (KeFeatureBits & KF_FXSR) ? TRUE : FALSE;
132 KeI386XMMIPresent = (KeFeatureBits & KF_XMMI) ? TRUE : FALSE;
133
134 /* Set the current MP Master KPRCB to the Boot PRCB */
135 Prcb->MultiThreadSetMaster = Prcb;
136
137 /* Initialize some spinlocks */
138 KeInitializeSpinLock(&KiFreezeExecutionLock);
139 KeInitializeSpinLock(&Ki486CompatibilityLock);
140
141 /* Initialize portable parts of the OS */
142 KiInitSystem();
143
144 /* Initialize the Idle Process and the Process Listhead */
145 InitializeListHead(&KiProcessListHead);
146 PageDirectory.QuadPart = 0;
147 KeInitializeProcess(InitProcess,
148 0,
149 0xFFFFFFFF,
150 &PageDirectory,
151 FALSE);
152 InitProcess->QuantumReset = MAXCHAR;
153 }
154 else
155 {
156 /* FIXME */
157 DPRINT1("SMP Boot support not yet present\n");
158 }
159
160 #if 0
161 /* Setup the Idle Thread */
162 KeInitializeThread(InitProcess,
163 InitThread,
164 NULL,
165 NULL,
166 NULL,
167 NULL,
168 NULL,
169 IdleStack);
170 #endif
171 InitThread->NextProcessor = Number;
172 InitThread->Priority = HIGH_PRIORITY;
173 InitThread->State = Running;
174 InitThread->Affinity = 1 << Number;
175 InitThread->WaitIrql = DISPATCH_LEVEL;
176 InitProcess->ActiveProcessors = 1 << Number;
177
178 /* Set up the thread-related fields in the PRCB */
179 //Prcb->CurrentThread = InitThread;
180 Prcb->NextThread = NULL;
181 //Prcb->IdleThread = InitThread;
182
183 /* Initialize the Kernel Executive */
184 ExpInitializeExecutive();
185
186 /* Only do this on the boot CPU */
187 if (!Number)
188 {
189 /* Calculate the time reciprocal */
190 KiTimeIncrementReciprocal =
191 KiComputeReciprocal(KeMaximumIncrement,
192 &KiTimeIncrementShiftCount);
193
194 /* Update DPC Values in case they got updated by the executive */
195 Prcb->MaximumDpcQueueDepth = KiMaximumDpcQueueDepth;
196 Prcb->MinimumDpcRate = KiMinimumDpcRate;
197 Prcb->AdjustDpcThreshold = KiAdjustDpcThreshold;
198
199 /* Allocate the DPC Stack */
200 DpcStack = MmCreateKernelStack(FALSE);
201 if (!DpcStack) KeBugCheckEx(NO_PAGES_AVAILABLE, 1, 0, 0, 0);
202 Prcb->DpcStack = DpcStack;
203
204 /* Allocate the IOPM save area. */
205 Ki386IopmSaveArea = ExAllocatePoolWithTag(PagedPool,
206 PAGE_SIZE * 2,
207 TAG('K', 'e', ' ', ' '));
208 if (!Ki386IopmSaveArea)
209 {
210 /* Bugcheck. We need this for V86/VDM support. */
211 KeBugCheckEx(NO_PAGES_AVAILABLE, 2, PAGE_SIZE * 2, 0, 0);
212 }
213 }
214
215 /* Free Initial Memory */
216 MiFreeInitMemory();
217
218 while (1)
219 {
220 LARGE_INTEGER Timeout;
221 Timeout.QuadPart = 0x7fffffffffffffffLL;
222 KeDelayExecutionThread(KernelMode, FALSE, &Timeout);
223 }
224
225 /* Bug Check and loop forever if anything failed */
226 KEBUGCHECK(0);
227 for(;;);
228 }
229
230 VOID
231 NTAPI
232 KiSystemStartup(IN PROS_LOADER_PARAMETER_BLOCK LoaderBlock)
233 {
234 ULONG Cpu;
235 PKIPCR Pcr = (PKIPCR)KPCR_BASE;
236 PKPRCB Prcb;
237
238 /* Save the loader block and get the current CPU */
239 //KeLoaderBlock = LoaderBlock;
240 Cpu = KeNumberProcessors;
241 if (!Cpu)
242 {
243 /* If this is the boot CPU, set FS and the CPU Number*/
244 Ke386SetFs(KGDT_R0_PCR);
245 KeGetPcr()->Number = Cpu;
246 }
247
248 /* Skip initial setup if this isn't the Boot CPU */
249 if (Cpu) goto AppCpuInit;
250
251 /* Setup the boot (Freeldr should've done), double fault and NMI TSS */
252 Ki386InitializeTss();
253
254 /* Initialize the PCR */
255 RtlZeroMemory(Pcr, PAGE_SIZE);
256 KiInitializePcr(Cpu,
257 Pcr,
258 KiIdt,
259 KiBootGdt,
260 &KiBootTss,
261 &KiInitialThread.Tcb,
262 KiDoubleFaultStack);
263
264 /* Set us as the current process */
265 KiInitialThread.Tcb.ApcState.Process = &KiInitialProcess.Pcb;
266
267 /* Clear DR6/7 to cleanup bootloader debugging */
268 Pcr->PrcbData.ProcessorState.SpecialRegisters.KernelDr6 = 0;
269 Pcr->PrcbData.ProcessorState.SpecialRegisters.KernelDr7 = 0;
270
271 /* Load Ring 3 selectors for DS/ES */
272 Ke386SetDs(KGDT_R3_DATA | RPL_MASK);
273 Ke386SetEs(KGDT_R3_DATA | RPL_MASK);
274
275 /* Setup CPU-related fields */
276 AppCpuInit:
277 Prcb = Pcr->Prcb;
278 Pcr->Number = Cpu;
279 Pcr->SetMember = 1 << Cpu;
280 Pcr->SetMemberCopy = 1 << Cpu;
281 Prcb->SetMember = 1 << Cpu;
282
283 /* Initialize the Processor with HAL */
284 HalInitializeProcessor(Cpu, (PLOADER_PARAMETER_BLOCK)&KeLoaderBlock);
285
286 /* Set active processors */
287 KeActiveProcessors |= Pcr->SetMember;
288 KeNumberProcessors++;
289
290 /* Initialize the Debugger for the Boot CPU */
291 if (!Cpu) KdInitSystem (0, &KeLoaderBlock);
292
293 /* Check for break-in */
294 if (KdPollBreakIn()) DbgBreakPointWithStatus(1);
295
296 /* Raise to HIGH_LEVEL */
297 KfRaiseIrql(HIGH_LEVEL);
298
299 /* Call main kernel intialization */
300 KiInitializeKernel(&KiInitialProcess.Pcb,
301 &KiInitialThread.Tcb,
302 P0BootStack,
303 Prcb,
304 Cpu,
305 LoaderBlock);
306 }
307