merge trunk rev : 25663 and 25664 to 0.3.1 branch - update freetype, take care of...
[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 #define NTDDI_VERSION NTDDI_WS03SP1
12 #include <ntoskrnl.h>
13 #define NDEBUG
14 #include <debug.h>
15
16 /* GLOBALS *******************************************************************/
17
18 /* Spinlocks used only on X86 */
19 KSPIN_LOCK KiFreezeExecutionLock;
20 KSPIN_LOCK Ki486CompatibilityLock;
21
22 /* FUNCTIONS *****************************************************************/
23
24 VOID
25 NTAPI
26 KiInitMachineDependent(VOID)
27 {
28 ULONG Protect;
29 ULONG CpuCount;
30 BOOLEAN FbCaching = FALSE;
31 NTSTATUS Status;
32 ULONG ReturnLength;
33 ULONG i, Affinity;
34 PFX_SAVE_AREA FxSaveArea;
35 ULONG MXCsrMask = 0xFFBF, NewMask;
36
37 /* Check for large page support */
38 if (KeFeatureBits & KF_LARGE_PAGE)
39 {
40 /* FIXME: Support this */
41 DPRINT1("Your machine supports PGE but ReactOS doesn't yet.\n");
42 }
43
44 /* Check for global page support */
45 if (KeFeatureBits & KF_GLOBAL_PAGE)
46 {
47 /* Do an IPI to enable it on all CPUs */
48 CpuCount = KeNumberProcessors;
49 KeIpiGenericCall(Ki386EnableGlobalPage, (ULONG_PTR)&CpuCount);
50 }
51
52 /* Check for PAT and/or MTRR support */
53 if (KeFeatureBits & (KF_PAT | KF_MTRR))
54 {
55 /* Query the HAL to make sure we can use it */
56 Status = HalQuerySystemInformation(HalFrameBufferCachingInformation,
57 sizeof(BOOLEAN),
58 &FbCaching,
59 &ReturnLength);
60 if ((NT_SUCCESS(Status)) && (FbCaching))
61 {
62 /* We can't, disable it */
63 KeFeatureBits &= ~(KF_PAT | KF_MTRR);
64 }
65 }
66
67 /* Check for PAT support and enable it */
68 if (KeFeatureBits & KF_PAT) KiInitializePAT();
69
70 /* Assume no errata for now */
71 SharedUserData->ProcessorFeatures[PF_FLOATING_POINT_PRECISION_ERRATA] = 0;
72
73 /* If there's no NPX, then we're emulating the FPU */
74 SharedUserData->ProcessorFeatures[PF_FLOATING_POINT_EMULATED] =
75 !KeI386NpxPresent;
76
77 /* Check if there's no NPX, so that we can disable associated features */
78 if (!KeI386NpxPresent)
79 {
80 /* Remove NPX-related bits */
81 KeFeatureBits &= ~(KF_XMMI64 | KF_XMMI | KF_FXSR | KF_MMX);
82
83 /* Disable kernel flags */
84 KeI386FxsrPresent = KeI386XMMIPresent = FALSE;
85
86 /* Disable processor features that might've been set until now */
87 SharedUserData->ProcessorFeatures[PF_FLOATING_POINT_PRECISION_ERRATA] =
88 SharedUserData->ProcessorFeatures[PF_XMMI64_INSTRUCTIONS_AVAILABLE] =
89 SharedUserData->ProcessorFeatures[PF_XMMI_INSTRUCTIONS_AVAILABLE] =
90 SharedUserData->ProcessorFeatures[PF_3DNOW_INSTRUCTIONS_AVAILABLE] =
91 SharedUserData->ProcessorFeatures[PF_MMX_INSTRUCTIONS_AVAILABLE] = 0;
92 }
93
94 /* Check for CR4 support */
95 if (KeFeatureBits & KF_CR4)
96 {
97 /* Do an IPI call to enable the Debug Exceptions */
98 CpuCount = KeNumberProcessors;
99 KeIpiGenericCall(Ki386EnableDE, (ULONG_PTR)&CpuCount);
100 }
101
102 /* Check if FXSR was found */
103 if (KeFeatureBits & KF_FXSR)
104 {
105 /* Do an IPI call to enable the FXSR */
106 CpuCount = KeNumberProcessors;
107 KeIpiGenericCall(Ki386EnableFxsr, (ULONG_PTR)&CpuCount);
108
109 /* Check if XMM was found too */
110 if (KeFeatureBits & KF_XMMI)
111 {
112 /* Do an IPI call to enable XMMI exceptions */
113 CpuCount = KeNumberProcessors;
114 KeIpiGenericCall(Ki386EnableXMMIExceptions, (ULONG_PTR)&CpuCount);
115
116 /* FIXME: Implement and enable XMM Page Zeroing for Mm */
117
118 /* Patch the RtlPrefetchMemoryNonTemporal routine to enable it */
119 Protect = MmGetPageProtect(NULL, RtlPrefetchMemoryNonTemporal);
120 MmSetPageProtect(NULL,
121 RtlPrefetchMemoryNonTemporal,
122 Protect | PAGE_IS_WRITABLE);
123 *(PCHAR)RtlPrefetchMemoryNonTemporal = 0x90;
124 MmSetPageProtect(NULL, RtlPrefetchMemoryNonTemporal, Protect);
125 }
126 }
127
128 /* Check for, and enable SYSENTER support */
129 KiRestoreFastSyscallReturnState();
130
131 /* Loop every CPU */
132 i = KeActiveProcessors;
133 for (Affinity = 1; i; Affinity <<= 1)
134 {
135 /* Check if this is part of the set */
136 if (i & Affinity)
137 {
138 /* Run on this CPU */
139 i &= ~Affinity;
140 KeSetSystemAffinityThread(Affinity);
141
142 /* Reset MHz to 0 for this CPU */
143 KeGetCurrentPrcb()->MHz = 0;
144
145 /* Check if we can use RDTSC */
146 if (KeFeatureBits & KF_RDTSC)
147 {
148 /* Start sampling loop */
149 for (;;)
150 {
151 //
152 // FIXME: TODO
153 //
154 break;
155 }
156 }
157
158 /* Check if we have MTRR without PAT */
159 if (!(KeFeatureBits & KF_PAT) && (KeFeatureBits & KF_MTRR))
160 {
161 /* Then manually initialize MTRR for the CPU */
162 KiInitializeMTRR((BOOLEAN)i);
163 }
164
165 /* Check if we have AMD MTRR and initialize it for the CPU */
166 if (KeFeatureBits & KF_AMDK6MTRR) KiAmdK6InitializeMTRR();
167
168 /* Check if this is a buggy Pentium and apply the fixup if so */
169 if (KiI386PentiumLockErrataPresent) KiI386PentiumLockErrataFixup();
170
171 /* Get the current thread NPX state */
172 FxSaveArea = (PVOID)
173 ((ULONG_PTR)KeGetCurrentThread()->InitialStack -
174 NPX_FRAME_LENGTH);
175
176 /* Clear initial MXCsr mask */
177 FxSaveArea->U.FxArea.MXCsrMask = 0;
178
179 /* Save the current NPX State */
180 #ifdef __GNUC__
181 asm volatile("fxsave %0\n\t" : "=m" (*FxSaveArea));
182 #else
183 __asm fxsave [FxSaveArea]
184 #endif
185 /* Check if the current mask doesn't match the reserved bits */
186 if (FxSaveArea->U.FxArea.MXCsrMask != MXCsrMask)
187 {
188 /* Then use whatever it's holding */
189 MXCsrMask = FxSaveArea->U.FxArea.MXCsrMask;
190 }
191
192 /* Check if nobody set the kernel-wide mask */
193 if (!KiMXCsrMask)
194 {
195 /* Then use the one we calculated above */
196 NewMask = MXCsrMask;
197 }
198 else
199 {
200 /* Use the existing mask */
201 NewMask = KiMXCsrMask;
202
203 /* Was it set to the same value we found now? */
204 if (NewMask != MXCsrMask)
205 {
206 /* No, something is definitely wrong */
207 KEBUGCHECKEX(MULTIPROCESSOR_CONFIGURATION_NOT_SUPPORTED,
208 KF_FXSR,
209 NewMask,
210 MXCsrMask,
211 0);
212 }
213 }
214
215 /* Now set the kernel mask */
216 KiMXCsrMask = NewMask & MXCsrMask;
217 }
218 }
219
220 /* Return affinity back to where it was */
221 KeRevertToUserAffinityThread();
222
223 /* NT allows limiting the duration of an ISR with a registry key */
224 if (KiTimeLimitIsrMicroseconds)
225 {
226 /* FIXME: TODO */
227 DPRINT1("ISR Time Limit not yet supported\n");
228 }
229 }
230
231 VOID
232 NTAPI
233 KiInitializePcr(IN ULONG ProcessorNumber,
234 IN PKIPCR Pcr,
235 IN PKIDTENTRY Idt,
236 IN PKGDTENTRY Gdt,
237 IN PKTSS Tss,
238 IN PKTHREAD IdleThread,
239 IN PVOID DpcStack)
240 {
241 /* Setup the TIB */
242 Pcr->NtTib.ExceptionList = EXCEPTION_CHAIN_END;
243 Pcr->NtTib.StackBase = 0;
244 Pcr->NtTib.StackLimit = 0;
245 Pcr->NtTib.Self = 0;
246
247 /* Set the Current Thread */
248 Pcr->PrcbData.CurrentThread = IdleThread;
249
250 /* Set pointers to ourselves */
251 Pcr->Self = (PKPCR)Pcr;
252 Pcr->Prcb = &Pcr->PrcbData;
253
254 /* Set the PCR Version */
255 Pcr->MajorVersion = PCR_MAJOR_VERSION;
256 Pcr->MinorVersion = PCR_MINOR_VERSION;
257
258 /* Set the PCRB Version */
259 Pcr->PrcbData.MajorVersion = 1;
260 Pcr->PrcbData.MinorVersion = 1;
261
262 /* Set the Build Type */
263 Pcr->PrcbData.BuildType = 0;
264 #ifndef CONFIG_SMP
265 Pcr->PrcbData.BuildType |= PRCB_BUILD_UNIPROCESSOR;
266 #endif
267 #ifdef DBG
268 Pcr->PrcbData.BuildType |= PRCB_BUILD_DEBUG;
269 #endif
270
271 /* Set the Processor Number and current Processor Mask */
272 Pcr->PrcbData.Number = (UCHAR)ProcessorNumber;
273 Pcr->PrcbData.SetMember = 1 << ProcessorNumber;
274
275 /* Set the PRCB for this Processor */
276 KiProcessorBlock[ProcessorNumber] = Pcr->Prcb;
277
278 /* Start us out at PASSIVE_LEVEL */
279 Pcr->Irql = PASSIVE_LEVEL;
280
281 /* Set the GDI, IDT, TSS and DPC Stack */
282 Pcr->GDT = (PVOID)Gdt;
283 Pcr->IDT = Idt;
284 Pcr->TSS = Tss;
285 Pcr->PrcbData.DpcStack = DpcStack;
286 }
287
288 VOID
289 NTAPI
290 KiInitializeKernel(IN PKPROCESS InitProcess,
291 IN PKTHREAD InitThread,
292 IN PVOID IdleStack,
293 IN PKPRCB Prcb,
294 IN CCHAR Number,
295 IN PLOADER_PARAMETER_BLOCK LoaderBlock)
296 {
297 BOOLEAN NpxPresent;
298 ULONG FeatureBits;
299 LARGE_INTEGER PageDirectory;
300 PVOID DpcStack;
301 ULONG NXSupportPolicy;
302
303 /* Detect and set the CPU Type */
304 KiSetProcessorType();
305
306 /* Set CR0 features based on detected CPU */
307 KiSetCR0Bits();
308
309 /* Check if an FPU is present */
310 NpxPresent = KiIsNpxPresent();
311
312 /* Initialize the Power Management Support for this PRCB */
313 PoInitializePrcb(Prcb);
314
315 /* Bugcheck if this is a 386 CPU */
316 if (Prcb->CpuType == 3) KeBugCheckEx(0x5D, 0x386, 0, 0, 0);
317
318 /* Get the processor features for the CPU */
319 FeatureBits = KiGetFeatureBits();
320
321 /* Set the default NX policy (opt-in) */
322 NXSupportPolicy = 2;
323
324 /* Check if NPX is always on */
325 if (strstr(KeLoaderBlock->LoadOptions, "NOEXECUTE=ALWAYSON"))
326 {
327 /* Set it always on */
328 NXSupportPolicy = 1;
329 FeatureBits |= KF_NX_ENABLED;
330 }
331 else if (strstr(KeLoaderBlock->LoadOptions, "NOEXECUTE=OPTOUT"))
332 {
333 /* Set it in opt-out mode */
334 NXSupportPolicy = 3;
335 FeatureBits |= KF_NX_ENABLED;
336 }
337 else if ((strstr(KeLoaderBlock->LoadOptions, "NOEXECUTE=OPTIN")) ||
338 (strstr(KeLoaderBlock->LoadOptions, "NOEXECUTE")))
339 {
340 /* Set the feature bits */
341 FeatureBits |= KF_NX_ENABLED;
342 }
343 else if ((strstr(KeLoaderBlock->LoadOptions, "NOEXECUTE=ALWAYSOFF")) ||
344 (strstr(KeLoaderBlock->LoadOptions, "EXECUTE")))
345 {
346 /* Set disabled mode */
347 NXSupportPolicy = 0;
348 FeatureBits |= KF_NX_DISABLED;
349 }
350
351 /* Save feature bits */
352 Prcb->FeatureBits = FeatureBits;
353
354 /* Save CPU state */
355 KiSaveProcessorControlState(&Prcb->ProcessorState);
356
357 /* Get cache line information for this CPU */
358 KiGetCacheInformation();
359
360 /* Initialize spinlocks and DPC data */
361 KiInitSpinLocks(Prcb, Number);
362
363 /* Check if this is the Boot CPU */
364 if (!Number)
365 {
366 /* Set Node Data */
367 KeNodeBlock[0] = &KiNode0;
368 Prcb->ParentNode = KeNodeBlock[0];
369 KeNodeBlock[0]->ProcessorMask = Prcb->SetMember;
370
371 /* Set boot-level flags */
372 KeI386NpxPresent = NpxPresent;
373 KeI386CpuType = Prcb->CpuType;
374 KeI386CpuStep = Prcb->CpuStep;
375 KeProcessorArchitecture = 0;
376 KeProcessorLevel = (USHORT)Prcb->CpuType;
377 if (Prcb->CpuID) KeProcessorRevision = Prcb->CpuStep;
378 KeFeatureBits = FeatureBits;
379 KeI386FxsrPresent = (KeFeatureBits & KF_FXSR) ? TRUE : FALSE;
380 KeI386XMMIPresent = (KeFeatureBits & KF_XMMI) ? TRUE : FALSE;
381
382 /* Set the current MP Master KPRCB to the Boot PRCB */
383 Prcb->MultiThreadSetMaster = Prcb;
384
385 /* Lower to APC_LEVEL */
386 KfLowerIrql(APC_LEVEL);
387
388 /* Initialize some spinlocks */
389 KeInitializeSpinLock(&KiFreezeExecutionLock);
390 KeInitializeSpinLock(&Ki486CompatibilityLock);
391
392 /* Initialize portable parts of the OS */
393 KiInitSystem();
394
395 /* Initialize the Idle Process and the Process Listhead */
396 InitializeListHead(&KiProcessListHead);
397 PageDirectory.QuadPart = 0;
398 KeInitializeProcess(InitProcess,
399 0,
400 0xFFFFFFFF,
401 &PageDirectory,
402 FALSE);
403 InitProcess->QuantumReset = MAXCHAR;
404 }
405 else
406 {
407 /* FIXME */
408 DPRINT1("SMP Boot support not yet present\n");
409 }
410
411 /* Setup the Idle Thread */
412 KeInitializeThread(InitProcess,
413 InitThread,
414 NULL,
415 NULL,
416 NULL,
417 NULL,
418 NULL,
419 IdleStack);
420 InitThread->NextProcessor = Number;
421 InitThread->Priority = HIGH_PRIORITY;
422 InitThread->State = Running;
423 InitThread->Affinity = 1 << Number;
424 InitThread->WaitIrql = DISPATCH_LEVEL;
425 InitProcess->ActiveProcessors = 1 << Number;
426
427 /* HACK for MmUpdatePageDir */
428 ((PETHREAD)InitThread)->ThreadsProcess = (PEPROCESS)InitProcess;
429
430 /* Initialize Kernel Memory Address Space */
431 MmInit1(MmFreeLdrFirstKrnlPhysAddr,
432 MmFreeLdrLastKrnlPhysAddr,
433 MmFreeLdrLastKernelAddress,
434 NULL,
435 0,
436 4096);
437
438 /* Sets up the Text Sections of the Kernel and HAL for debugging */
439 LdrInit1();
440
441 /* Set the NX Support policy */
442 SharedUserData->NXSupportPolicy = (UCHAR)NXSupportPolicy;
443
444 /* Set basic CPU Features that user mode can read */
445 SharedUserData->ProcessorFeatures[PF_MMX_INSTRUCTIONS_AVAILABLE] =
446 (KeFeatureBits & KF_MMX) ? TRUE: FALSE;
447 SharedUserData->ProcessorFeatures[PF_COMPARE_EXCHANGE_DOUBLE] =
448 (KeFeatureBits & KF_CMPXCHG8B) ? TRUE: FALSE;
449 SharedUserData->ProcessorFeatures[PF_XMMI_INSTRUCTIONS_AVAILABLE] =
450 ((KeFeatureBits & KF_FXSR) && (KeFeatureBits & KF_XMMI)) ? TRUE: FALSE;
451 SharedUserData->ProcessorFeatures[PF_XMMI64_INSTRUCTIONS_AVAILABLE] =
452 ((KeFeatureBits & KF_FXSR) && (KeFeatureBits & KF_XMMI64)) ? TRUE: FALSE;
453 SharedUserData->ProcessorFeatures[PF_3DNOW_INSTRUCTIONS_AVAILABLE] =
454 (KeFeatureBits & KF_3DNOW) ? TRUE: FALSE;
455 SharedUserData->ProcessorFeatures[PF_RDTSC_INSTRUCTION_AVAILABLE] =
456 (KeFeatureBits & KF_RDTSC) ? TRUE: FALSE;
457
458 /* Set up the thread-related fields in the PRCB */
459 Prcb->CurrentThread = InitThread;
460 Prcb->NextThread = NULL;
461 Prcb->IdleThread = InitThread;
462
463 /* Initialize the Kernel Executive */
464 ExpInitializeExecutive(Number, LoaderBlock);
465
466 /* Only do this on the boot CPU */
467 if (!Number)
468 {
469 /* Calculate the time reciprocal */
470 KiTimeIncrementReciprocal =
471 KiComputeReciprocal(KeMaximumIncrement,
472 &KiTimeIncrementShiftCount);
473
474 /* Update DPC Values in case they got updated by the executive */
475 Prcb->MaximumDpcQueueDepth = KiMaximumDpcQueueDepth;
476 Prcb->MinimumDpcRate = KiMinimumDpcRate;
477 Prcb->AdjustDpcThreshold = KiAdjustDpcThreshold;
478
479 /* Allocate the DPC Stack */
480 DpcStack = MmCreateKernelStack(FALSE);
481 if (!DpcStack) KeBugCheckEx(NO_PAGES_AVAILABLE, 1, 0, 0, 0);
482 Prcb->DpcStack = DpcStack;
483
484 /* Allocate the IOPM save area. */
485 Ki386IopmSaveArea = ExAllocatePoolWithTag(PagedPool,
486 PAGE_SIZE * 2,
487 TAG('K', 'e', ' ', ' '));
488 if (!Ki386IopmSaveArea)
489 {
490 /* Bugcheck. We need this for V86/VDM support. */
491 KeBugCheckEx(NO_PAGES_AVAILABLE, 2, PAGE_SIZE * 2, 0, 0);
492 }
493 }
494
495 /* Raise to Dispatch */
496 KfRaiseIrql(DISPATCH_LEVEL);
497
498 /* Set the Idle Priority to 0. This will jump into Phase 1 */
499 KeSetPriorityThread(InitThread, 0);
500
501 /* If there's no thread scheduled, put this CPU in the Idle summary */
502 if (!Prcb->NextThread) KiIdleSummary |= 1 << Number;
503
504 /* Raise back to HIGH_LEVEL and clear the PRCB for the loader block */
505 KfRaiseIrql(HIGH_LEVEL);
506 LoaderBlock->Prcb = 0;
507 }
508
509 VOID
510 FASTCALL
511 KiGetMachineBootPointers(IN PKGDTENTRY *Gdt,
512 IN PKIDTENTRY *Idt,
513 IN PKIPCR *Pcr,
514 IN PKTSS *Tss)
515 {
516 KDESCRIPTOR GdtDescriptor, IdtDescriptor;
517 KGDTENTRY TssSelector, PcrSelector;
518 USHORT Tr, Fs;
519
520 /* Get GDT and IDT descriptors */
521 Ke386GetGlobalDescriptorTable(GdtDescriptor);
522 Ke386GetInterruptDescriptorTable(IdtDescriptor);
523
524 /* Save IDT and GDT */
525 *Gdt = (PKGDTENTRY)GdtDescriptor.Base;
526 *Idt = (PKIDTENTRY)IdtDescriptor.Base;
527
528 /* Get TSS and FS Selectors */
529 Ke386GetTr(Tr);
530 if (Tr != KGDT_TSS) Tr = KGDT_TSS; // FIXME: HACKHACK
531 Fs = Ke386GetFs();
532
533 /* Get PCR Selector, mask it and get its GDT Entry */
534 PcrSelector = *(PKGDTENTRY)((ULONG_PTR)*Gdt + (Fs & ~RPL_MASK));
535
536 /* Get the KPCR itself */
537 *Pcr = (PKIPCR)(ULONG_PTR)(PcrSelector.BaseLow |
538 PcrSelector.HighWord.Bytes.BaseMid << 16 |
539 PcrSelector.HighWord.Bytes.BaseHi << 24);
540
541 /* Get TSS Selector, mask it and get its GDT Entry */
542 TssSelector = *(PKGDTENTRY)((ULONG_PTR)*Gdt + (Tr & ~RPL_MASK));
543
544 /* Get the KTSS itself */
545 *Tss = (PKTSS)(ULONG_PTR)(TssSelector.BaseLow |
546 TssSelector.HighWord.Bytes.BaseMid << 16 |
547 TssSelector.HighWord.Bytes.BaseHi << 24);
548 }
549
550 VOID
551 NTAPI
552 KiSystemStartup(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
553 {
554 ULONG Cpu;
555 PKTHREAD InitialThread;
556 ULONG InitialStack;
557 PKGDTENTRY Gdt;
558 PKIDTENTRY Idt;
559 PKTSS Tss;
560 PKIPCR Pcr;
561
562 /* Save the loader block and get the current CPU */
563 KeLoaderBlock = LoaderBlock;
564 Cpu = KeNumberProcessors;
565 if (!Cpu)
566 {
567 /* If this is the boot CPU, set FS and the CPU Number*/
568 Ke386SetFs(KGDT_R0_PCR);
569 __writefsdword(KPCR_PROCESSOR_NUMBER, Cpu);
570
571 /* Set the initial stack and idle thread as well */
572 LoaderBlock->KernelStack = (ULONG_PTR)P0BootStack;
573 LoaderBlock->Thread = (ULONG_PTR)&KiInitialThread;
574 }
575
576 /* Save the initial thread and stack */
577 InitialStack = LoaderBlock->KernelStack;
578 InitialThread = (PKTHREAD)LoaderBlock->Thread;
579
580 /* Clean the APC List Head */
581 InitializeListHead(&InitialThread->ApcState.ApcListHead[KernelMode]);
582
583 /* Initialize the machine type */
584 KiInitializeMachineType();
585
586 /* Skip initial setup if this isn't the Boot CPU */
587 if (Cpu) goto AppCpuInit;
588
589 /* Get GDT, IDT, PCR and TSS pointers */
590 KiGetMachineBootPointers(&Gdt, &Idt, &Pcr, &Tss);
591
592 /* Setup the TSS descriptors and entries */
593 Ki386InitializeTss(Tss, Idt, Gdt);
594
595 /* Initialize the PCR */
596 RtlZeroMemory(Pcr, PAGE_SIZE);
597 KiInitializePcr(Cpu,
598 Pcr,
599 Idt,
600 Gdt,
601 Tss,
602 InitialThread,
603 KiDoubleFaultStack);
604
605 /* Set us as the current process */
606 InitialThread->ApcState.Process = &KiInitialProcess.Pcb;
607
608 /* Clear DR6/7 to cleanup bootloader debugging */
609 __writefsdword(KPCR_TEB, 0);
610 __writefsdword(KPCR_DR6, 0);
611 __writefsdword(KPCR_DR7, 0);
612
613 /* Setup the IDT */
614 KeInitExceptions();
615
616 /* Load Ring 3 selectors for DS/ES */
617 Ke386SetDs(KGDT_R3_DATA | RPL_MASK);
618 Ke386SetEs(KGDT_R3_DATA | RPL_MASK);
619
620 AppCpuInit:
621 /* Loop until we can release the freeze lock */
622 do
623 {
624 /* Loop until execution can continue */
625 while ((volatile KSPIN_LOCK)KiFreezeExecutionLock == 1);
626 } while(InterlockedBitTestAndSet((PLONG)&KiFreezeExecutionLock, 0));
627
628 /* Setup CPU-related fields */
629 __writefsdword(KPCR_NUMBER, Cpu);
630 __writefsdword(KPCR_SET_MEMBER, 1 << Cpu);
631 __writefsdword(KPCR_SET_MEMBER_COPY, 1 << Cpu);
632 __writefsdword(KPCR_PRCB_SET_MEMBER, 1 << Cpu);
633
634 /* Initialize the Processor with HAL */
635 HalInitializeProcessor(Cpu, KeLoaderBlock);
636
637 /* Set active processors */
638 KeActiveProcessors |= __readfsdword(KPCR_SET_MEMBER);
639 KeNumberProcessors++;
640
641 /* Check if this is the boot CPU */
642 if (!Cpu)
643 {
644 /* Initialize debugging system */
645 KdInitSystem(0, KeLoaderBlock);
646
647 /* Check for break-in */
648 if (KdPollBreakIn()) DbgBreakPointWithStatus(1);
649 }
650
651 /* Raise to HIGH_LEVEL */
652 KfRaiseIrql(HIGH_LEVEL);
653
654 /* Align stack and make space for the trap frame and NPX frame */
655 InitialStack &= ~KTRAP_FRAME_ALIGN;
656 #ifdef __GNUC__
657 __asm__ __volatile__("movl %0,%%esp" : :"r" (InitialStack));
658 __asm__ __volatile__("subl %0,%%esp" : :"r" (NPX_FRAME_LENGTH +
659 KTRAP_FRAME_LENGTH +
660 KTRAP_FRAME_ALIGN));
661 __asm__ __volatile__("push %0" : :"r" (CR0_EM + CR0_TS + CR0_MP));
662 #else
663 __asm mov esp, InitialStack;
664 __asm sub esp, NPX_FRAME_LENGTH + KTRAP_FRAME_ALIGN + KTRAP_FRAME_LENGTH;
665 __asm push CR0_EM + CR0_TS + CR0_MP
666 #endif
667
668 /* Call main kernel initialization */
669 KiInitializeKernel(&KiInitialProcess.Pcb,
670 InitialThread,
671 (PVOID)InitialStack,
672 (PKPRCB)__readfsdword(KPCR_PRCB),
673 (CCHAR)Cpu,
674 KeLoaderBlock);
675
676 /* Set the priority of this thread to 0 */
677 KeGetCurrentThread()->Priority = 0;
678
679 /* Force interrupts enabled and lower IRQL back to DISPATCH_LEVEL */
680 _enable();
681 KfLowerIrql(DISPATCH_LEVEL);
682
683 /* Set the right wait IRQL */
684 KeGetCurrentThread()->WaitIrql = DISPATCH_LEVEL;
685
686 /* Set idle thread as running on UP builds */
687 #ifndef CONFIG_SMP
688 KeGetCurrentThread()->State = Running;
689 #endif
690
691 /* Jump into the idle loop */
692 KiIdleLoop();
693 }
694