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)
9 /* INCLUDES *****************************************************************/
11 #define NTDDI_VERSION NTDDI_WS03SP1
16 /* GLOBALS *******************************************************************/
18 /* Spinlocks used only on X86 */
19 KSPIN_LOCK KiFreezeExecutionLock
;
20 KSPIN_LOCK Ki486CompatibilityLock
;
22 /* FUNCTIONS *****************************************************************/
26 KiInitMachineDependent(VOID
)
30 BOOLEAN FbCaching
= FALSE
;
33 ULONG i
, Affinity
, Sample
= 0;
34 PFX_SAVE_AREA FxSaveArea
;
35 ULONG MXCsrMask
= 0xFFBF;
37 KI_SAMPLE_MAP Samples
[4];
38 PKI_SAMPLE_MAP CurrentSample
= Samples
;
40 /* Check for large page support */
41 if (KeFeatureBits
& KF_LARGE_PAGE
)
43 /* FIXME: Support this */
44 DPRINT1("Large Page support detected but not yet taken advantage of!\n");
47 /* Check for global page support */
48 if (KeFeatureBits
& KF_GLOBAL_PAGE
)
50 /* Do an IPI to enable it on all CPUs */
51 CpuCount
= KeNumberProcessors
;
52 KeIpiGenericCall(Ki386EnableGlobalPage
, (ULONG_PTR
)&CpuCount
);
55 /* Check for PAT and/or MTRR support */
56 if (KeFeatureBits
& (KF_PAT
| KF_MTRR
))
58 /* Query the HAL to make sure we can use it */
59 Status
= HalQuerySystemInformation(HalFrameBufferCachingInformation
,
63 if ((NT_SUCCESS(Status
)) && (FbCaching
))
65 /* We can't, disable it */
66 KeFeatureBits
&= ~(KF_PAT
| KF_MTRR
);
70 /* Check for PAT support and enable it */
71 if (KeFeatureBits
& KF_PAT
) KiInitializePAT();
73 /* Assume no errata for now */
74 SharedUserData
->ProcessorFeatures
[PF_FLOATING_POINT_PRECISION_ERRATA
] = 0;
76 /* Check if we have an NPX */
80 i
= KeActiveProcessors
;
81 for (Affinity
= 1; i
; Affinity
<<= 1)
83 /* Check if this is part of the set */
88 KeSetSystemAffinityThread(Affinity
);
90 /* Detect FPU errata */
91 if (KiIsNpxErrataPresent())
93 /* Disable NPX support */
94 KeI386NpxPresent
= FALSE
;
96 ProcessorFeatures
[PF_FLOATING_POINT_PRECISION_ERRATA
] =
104 /* If there's no NPX, then we're emulating the FPU */
105 SharedUserData
->ProcessorFeatures
[PF_FLOATING_POINT_EMULATED
] =
108 /* Check if there's no NPX, so that we can disable associated features */
109 if (!KeI386NpxPresent
)
111 /* Remove NPX-related bits */
112 KeFeatureBits
&= ~(KF_XMMI64
| KF_XMMI
| KF_FXSR
| KF_MMX
);
114 /* Disable kernel flags */
115 KeI386FxsrPresent
= KeI386XMMIPresent
= FALSE
;
117 /* Disable processor features that might've been set until now */
118 SharedUserData
->ProcessorFeatures
[PF_FLOATING_POINT_PRECISION_ERRATA
] =
119 SharedUserData
->ProcessorFeatures
[PF_XMMI64_INSTRUCTIONS_AVAILABLE
] =
120 SharedUserData
->ProcessorFeatures
[PF_XMMI_INSTRUCTIONS_AVAILABLE
] =
121 SharedUserData
->ProcessorFeatures
[PF_3DNOW_INSTRUCTIONS_AVAILABLE
] =
122 SharedUserData
->ProcessorFeatures
[PF_MMX_INSTRUCTIONS_AVAILABLE
] = 0;
125 /* Check for CR4 support */
126 if (KeFeatureBits
& KF_CR4
)
128 /* Do an IPI call to enable the Debug Exceptions */
129 CpuCount
= KeNumberProcessors
;
130 KeIpiGenericCall(Ki386EnableDE
, (ULONG_PTR
)&CpuCount
);
133 /* Check if FXSR was found */
134 if (KeFeatureBits
& KF_FXSR
)
136 /* Do an IPI call to enable the FXSR */
137 CpuCount
= KeNumberProcessors
;
138 KeIpiGenericCall(Ki386EnableFxsr
, (ULONG_PTR
)&CpuCount
);
140 /* Check if XMM was found too */
141 if (KeFeatureBits
& KF_XMMI
)
143 /* Do an IPI call to enable XMMI exceptions */
144 CpuCount
= KeNumberProcessors
;
145 KeIpiGenericCall(Ki386EnableXMMIExceptions
, (ULONG_PTR
)&CpuCount
);
147 /* FIXME: Implement and enable XMM Page Zeroing for Mm */
149 /* Patch the RtlPrefetchMemoryNonTemporal routine to enable it */
150 Protect
= MmGetPageProtect(NULL
, RtlPrefetchMemoryNonTemporal
);
151 MmSetPageProtect(NULL
,
152 RtlPrefetchMemoryNonTemporal
,
153 Protect
| PAGE_IS_WRITABLE
);
154 *(PCHAR
)RtlPrefetchMemoryNonTemporal
= 0x90;
155 MmSetPageProtect(NULL
, RtlPrefetchMemoryNonTemporal
, Protect
);
159 /* Check for, and enable SYSENTER support */
160 KiRestoreFastSyscallReturnState();
163 i
= KeActiveProcessors
;
164 for (Affinity
= 1; i
; Affinity
<<= 1)
166 /* Check if this is part of the set */
169 /* Run on this CPU */
171 KeSetSystemAffinityThread(Affinity
);
173 /* Reset MHz to 0 for this CPU */
174 KeGetCurrentPrcb()->MHz
= 0;
176 /* Check if we can use RDTSC */
177 if (KeFeatureBits
& KF_RDTSC
)
179 /* Start sampling loop */
182 /* Do a dummy CPUID to start the sample */
185 /* Fill out the starting data */
186 CurrentSample
->PerfStart
= KeQueryPerformanceCounter(NULL
);
187 CurrentSample
->TSCStart
= __rdtsc();
188 CurrentSample
->PerfFreq
.QuadPart
= -50000;
190 /* Sleep for this sample */
191 KeDelayExecutionThread(KernelMode
,
193 &CurrentSample
->PerfFreq
);
195 /* Do another dummy CPUID */
198 /* Fill out the ending data */
199 CurrentSample
->PerfEnd
=
200 KeQueryPerformanceCounter(&CurrentSample
->PerfFreq
);
201 CurrentSample
->TSCEnd
= __rdtsc();
203 /* Calculate the differences */
204 CurrentSample
->PerfDelta
= CurrentSample
->PerfEnd
.QuadPart
-
205 CurrentSample
->PerfStart
.QuadPart
;
206 CurrentSample
->TSCDelta
= CurrentSample
->TSCEnd
-
207 CurrentSample
->TSCStart
;
209 /* Compute CPU Speed */
210 CurrentSample
->MHz
= ((CurrentSample
->TSCDelta
*
211 CurrentSample
->PerfFreq
.QuadPart
+
213 (CurrentSample
->PerfDelta
* 1000000));
215 /* Check if this isn't the first sample */
218 /* Check if we got a good precision within 1MHz */
219 if ((CurrentSample
->MHz
== CurrentSample
[-1].MHz
) ||
220 (CurrentSample
->MHz
== CurrentSample
[-1].MHz
+ 1) ||
221 (CurrentSample
->MHz
== CurrentSample
[-1].MHz
- 1))
223 /* We did, stop sampling */
233 /* Save the CPU Speed */
234 KeGetCurrentPrcb()->MHz
= CurrentSample
[-1].MHz
;
237 /* Check if we have MTRR */
238 if (KeFeatureBits
& KF_MTRR
)
240 /* Then manually initialize MTRR for the CPU */
241 KiInitializeMTRR((BOOLEAN
)i
? FALSE
: TRUE
);
244 /* Check if we have AMD MTRR and initialize it for the CPU */
245 if (KeFeatureBits
& KF_AMDK6MTRR
) KiAmdK6InitializeMTRR();
247 /* Check if this is a buggy Pentium and apply the fixup if so */
248 if (KiI386PentiumLockErrataPresent
) KiI386PentiumLockErrataFixup();
250 /* Check if the CPU supports FXSR */
251 if (KeFeatureBits
& KF_FXSR
)
253 /* Get the current thread NPX state */
255 ((ULONG_PTR
)KeGetCurrentThread()->InitialStack
-
258 /* Clear initial MXCsr mask */
259 FxSaveArea
->U
.FxArea
.MXCsrMask
= 0;
261 /* Save the current NPX State */
263 asm volatile("fxsave %0\n\t" : "=m" (*FxSaveArea
));
265 __asm fxsave
[FxSaveArea
]
267 /* Check if the current mask doesn't match the reserved bits */
268 if (FxSaveArea
->U
.FxArea
.MXCsrMask
!= 0)
270 /* Then use whatever it's holding */
271 MXCsrMask
= FxSaveArea
->U
.FxArea
.MXCsrMask
;
274 /* Check if nobody set the kernel-wide mask */
277 /* Then use the one we calculated above */
278 KiMXCsrMask
= MXCsrMask
;
282 /* Was it set to the same value we found now? */
283 if (KiMXCsrMask
!= MXCsrMask
)
285 /* No, something is definitely wrong */
286 KEBUGCHECKEX(MULTIPROCESSOR_CONFIGURATION_NOT_SUPPORTED
,
294 /* Now set the kernel mask */
295 KiMXCsrMask
&= MXCsrMask
;
300 /* Return affinity back to where it was */
301 KeRevertToUserAffinityThread();
303 /* NT allows limiting the duration of an ISR with a registry key */
304 if (KiTimeLimitIsrMicroseconds
)
307 DPRINT1("ISR Time Limit not yet supported\n");
313 KiInitializePcr(IN ULONG ProcessorNumber
,
318 IN PKTHREAD IdleThread
,
322 Pcr
->NtTib
.ExceptionList
= EXCEPTION_CHAIN_END
;
323 Pcr
->NtTib
.StackBase
= 0;
324 Pcr
->NtTib
.StackLimit
= 0;
325 Pcr
->NtTib
.Self
= NULL
;
327 /* Set the Current Thread */
328 Pcr
->PrcbData
.CurrentThread
= IdleThread
;
330 /* Set pointers to ourselves */
331 Pcr
->Self
= (PKPCR
)Pcr
;
332 Pcr
->Prcb
= &Pcr
->PrcbData
;
334 /* Set the PCR Version */
335 Pcr
->MajorVersion
= PCR_MAJOR_VERSION
;
336 Pcr
->MinorVersion
= PCR_MINOR_VERSION
;
338 /* Set the PCRB Version */
339 Pcr
->PrcbData
.MajorVersion
= 1;
340 Pcr
->PrcbData
.MinorVersion
= 1;
342 /* Set the Build Type */
343 Pcr
->PrcbData
.BuildType
= 0;
345 Pcr
->PrcbData
.BuildType
|= PRCB_BUILD_UNIPROCESSOR
;
348 Pcr
->PrcbData
.BuildType
|= PRCB_BUILD_DEBUG
;
351 /* Set the Processor Number and current Processor Mask */
352 Pcr
->PrcbData
.Number
= (UCHAR
)ProcessorNumber
;
353 Pcr
->PrcbData
.SetMember
= 1 << ProcessorNumber
;
355 /* Set the PRCB for this Processor */
356 KiProcessorBlock
[ProcessorNumber
] = Pcr
->Prcb
;
358 /* Start us out at PASSIVE_LEVEL */
359 Pcr
->Irql
= PASSIVE_LEVEL
;
361 /* Set the GDI, IDT, TSS and DPC Stack */
362 Pcr
->GDT
= (PVOID
)Gdt
;
366 Pcr
->PrcbData
.DpcStack
= DpcStack
;
368 /* Setup the processor set */
369 Pcr
->PrcbData
.MultiThreadProcessorSet
= Pcr
->PrcbData
.SetMember
;
374 KiInitializeKernel(IN PKPROCESS InitProcess
,
375 IN PKTHREAD InitThread
,
379 IN PLOADER_PARAMETER_BLOCK LoaderBlock
)
383 LARGE_INTEGER PageDirectory
;
385 ULONG NXSupportPolicy
;
388 /* Detect and set the CPU Type */
389 KiSetProcessorType();
391 /* Set CR0 features based on detected CPU */
394 /* Check if an FPU is present */
395 NpxPresent
= KiIsNpxPresent();
397 /* Initialize the Power Management Support for this PRCB */
398 PoInitializePrcb(Prcb
);
400 /* Bugcheck if this is a 386 CPU */
401 if (Prcb
->CpuType
== 3) KeBugCheckEx(0x5D, 0x386, 0, 0, 0);
403 /* Get the processor features for the CPU */
404 FeatureBits
= KiGetFeatureBits();
406 /* Set the default NX policy (opt-in) */
407 NXSupportPolicy
= NX_SUPPORT_POLICY_OPTIN
;
409 /* Check if NPX is always on */
410 if (strstr(KeLoaderBlock
->LoadOptions
, "NOEXECUTE=ALWAYSON"))
412 /* Set it always on */
413 NXSupportPolicy
= NX_SUPPORT_POLICY_ALWAYSON
;
414 FeatureBits
|= KF_NX_ENABLED
;
416 else if (strstr(KeLoaderBlock
->LoadOptions
, "NOEXECUTE=OPTOUT"))
418 /* Set it in opt-out mode */
419 NXSupportPolicy
= NX_SUPPORT_POLICY_OPTOUT
;
420 FeatureBits
|= KF_NX_ENABLED
;
422 else if ((strstr(KeLoaderBlock
->LoadOptions
, "NOEXECUTE=OPTIN")) ||
423 (strstr(KeLoaderBlock
->LoadOptions
, "NOEXECUTE")))
425 /* Set the feature bits */
426 FeatureBits
|= KF_NX_ENABLED
;
428 else if ((strstr(KeLoaderBlock
->LoadOptions
, "NOEXECUTE=ALWAYSOFF")) ||
429 (strstr(KeLoaderBlock
->LoadOptions
, "EXECUTE")))
431 /* Set disabled mode */
432 NXSupportPolicy
= NX_SUPPORT_POLICY_ALWAYSOFF
;
433 FeatureBits
|= KF_NX_DISABLED
;
436 /* Save feature bits */
437 Prcb
->FeatureBits
= FeatureBits
;
440 KiSaveProcessorControlState(&Prcb
->ProcessorState
);
442 /* Get cache line information for this CPU */
443 KiGetCacheInformation();
445 /* Initialize spinlocks and DPC data */
446 KiInitSpinLocks(Prcb
, Number
);
448 /* Check if this is the Boot CPU */
452 KeNodeBlock
[0] = &KiNode0
;
453 Prcb
->ParentNode
= KeNodeBlock
[0];
454 KeNodeBlock
[0]->ProcessorMask
= Prcb
->SetMember
;
456 /* Set boot-level flags */
457 KeI386NpxPresent
= NpxPresent
;
458 KeI386CpuType
= Prcb
->CpuType
;
459 KeI386CpuStep
= Prcb
->CpuStep
;
460 KeProcessorArchitecture
= PROCESSOR_ARCHITECTURE_INTEL
;
461 KeProcessorLevel
= (USHORT
)Prcb
->CpuType
;
462 if (Prcb
->CpuID
) KeProcessorRevision
= Prcb
->CpuStep
;
463 KeFeatureBits
= FeatureBits
;
464 KeI386FxsrPresent
= (KeFeatureBits
& KF_FXSR
) ? TRUE
: FALSE
;
465 KeI386XMMIPresent
= (KeFeatureBits
& KF_XMMI
) ? TRUE
: FALSE
;
467 /* Detect 8-byte compare exchange support */
468 if (!(KeFeatureBits
& KF_CMPXCHG8B
))
470 /* Copy the vendor string */
471 RtlCopyMemory(Vendor
, Prcb
->VendorString
, sizeof(Vendor
));
473 /* Bugcheck the system. Windows *requires* this */
475 (1 << 24 ) | (Prcb
->CpuType
<< 16) | Prcb
->CpuStep
,
481 /* Set the current MP Master KPRCB to the Boot PRCB */
482 Prcb
->MultiThreadSetMaster
= Prcb
;
484 /* Lower to APC_LEVEL */
485 KeLowerIrql(APC_LEVEL
);
487 /* Initialize some spinlocks */
488 KeInitializeSpinLock(&KiFreezeExecutionLock
);
489 KeInitializeSpinLock(&Ki486CompatibilityLock
);
491 /* Initialize portable parts of the OS */
494 /* Initialize the Idle Process and the Process Listhead */
495 InitializeListHead(&KiProcessListHead
);
496 PageDirectory
.QuadPart
= 0;
497 KeInitializeProcess(InitProcess
,
502 InitProcess
->QuantumReset
= MAXCHAR
;
507 DPRINT1("SMP Boot support not yet present\n");
510 /* Setup the Idle Thread */
511 KeInitializeThread(InitProcess
,
519 InitThread
->NextProcessor
= Number
;
520 InitThread
->Priority
= HIGH_PRIORITY
;
521 InitThread
->State
= Running
;
522 InitThread
->Affinity
= 1 << Number
;
523 InitThread
->WaitIrql
= DISPATCH_LEVEL
;
524 InitProcess
->ActiveProcessors
= 1 << Number
;
526 /* HACK for MmUpdatePageDir */
527 ((PETHREAD
)InitThread
)->ThreadsProcess
= (PEPROCESS
)InitProcess
;
529 /* Initialize Kernel Memory Address Space */
530 MmInit1(MmFreeLdrFirstKrnlPhysAddr
,
531 MmFreeLdrLastKrnlPhysAddr
,
532 MmFreeLdrLastKernelAddress
,
537 /* Sets up the Text Sections of the Kernel and HAL for debugging */
540 /* Set the NX Support policy */
541 SharedUserData
->NXSupportPolicy
= (UCHAR
)NXSupportPolicy
;
543 /* Set basic CPU Features that user mode can read */
544 SharedUserData
->ProcessorFeatures
[PF_MMX_INSTRUCTIONS_AVAILABLE
] =
545 (KeFeatureBits
& KF_MMX
) ? TRUE
: FALSE
;
546 SharedUserData
->ProcessorFeatures
[PF_COMPARE_EXCHANGE_DOUBLE
] =
547 (KeFeatureBits
& KF_CMPXCHG8B
) ? TRUE
: FALSE
;
548 SharedUserData
->ProcessorFeatures
[PF_XMMI_INSTRUCTIONS_AVAILABLE
] =
549 ((KeFeatureBits
& KF_FXSR
) && (KeFeatureBits
& KF_XMMI
)) ? TRUE
: FALSE
;
550 SharedUserData
->ProcessorFeatures
[PF_XMMI64_INSTRUCTIONS_AVAILABLE
] =
551 ((KeFeatureBits
& KF_FXSR
) && (KeFeatureBits
& KF_XMMI64
)) ? TRUE
: FALSE
;
552 SharedUserData
->ProcessorFeatures
[PF_3DNOW_INSTRUCTIONS_AVAILABLE
] =
553 (KeFeatureBits
& KF_3DNOW
) ? TRUE
: FALSE
;
554 SharedUserData
->ProcessorFeatures
[PF_RDTSC_INSTRUCTION_AVAILABLE
] =
555 (KeFeatureBits
& KF_RDTSC
) ? TRUE
: FALSE
;
557 /* Set up the thread-related fields in the PRCB */
558 Prcb
->CurrentThread
= InitThread
;
559 Prcb
->NextThread
= NULL
;
560 Prcb
->IdleThread
= InitThread
;
562 /* Initialize the Kernel Executive */
563 ExpInitializeExecutive(Number
, LoaderBlock
);
565 /* Only do this on the boot CPU */
568 /* Calculate the time reciprocal */
569 KiTimeIncrementReciprocal
=
570 KiComputeReciprocal(KeMaximumIncrement
,
571 &KiTimeIncrementShiftCount
);
573 /* Update DPC Values in case they got updated by the executive */
574 Prcb
->MaximumDpcQueueDepth
= KiMaximumDpcQueueDepth
;
575 Prcb
->MinimumDpcRate
= KiMinimumDpcRate
;
576 Prcb
->AdjustDpcThreshold
= KiAdjustDpcThreshold
;
578 /* Allocate the DPC Stack */
579 DpcStack
= MmCreateKernelStack(FALSE
);
580 if (!DpcStack
) KeBugCheckEx(NO_PAGES_AVAILABLE
, 1, 0, 0, 0);
581 Prcb
->DpcStack
= DpcStack
;
583 /* Allocate the IOPM save area. */
584 Ki386IopmSaveArea
= ExAllocatePoolWithTag(PagedPool
,
586 TAG('K', 'e', ' ', ' '));
587 if (!Ki386IopmSaveArea
)
589 /* Bugcheck. We need this for V86/VDM support. */
590 KeBugCheckEx(NO_PAGES_AVAILABLE
, 2, PAGE_SIZE
* 2, 0, 0);
594 /* Raise to Dispatch */
595 KfRaiseIrql(DISPATCH_LEVEL
);
597 /* Set the Idle Priority to 0. This will jump into Phase 1 */
598 KeSetPriorityThread(InitThread
, 0);
600 /* If there's no thread scheduled, put this CPU in the Idle summary */
601 KiAcquirePrcbLock(Prcb
);
602 if (!Prcb
->NextThread
) KiIdleSummary
|= 1 << Number
;
603 KiReleasePrcbLock(Prcb
);
605 /* Raise back to HIGH_LEVEL and clear the PRCB for the loader block */
606 KfRaiseIrql(HIGH_LEVEL
);
607 LoaderBlock
->Prcb
= 0;
612 KiGetMachineBootPointers(IN PKGDTENTRY
*Gdt
,
617 KDESCRIPTOR GdtDescriptor
, IdtDescriptor
;
618 KGDTENTRY TssSelector
, PcrSelector
;
621 /* Get GDT and IDT descriptors */
622 Ke386GetGlobalDescriptorTable(GdtDescriptor
);
623 Ke386GetInterruptDescriptorTable(IdtDescriptor
);
625 /* Save IDT and GDT */
626 *Gdt
= (PKGDTENTRY
)GdtDescriptor
.Base
;
627 *Idt
= (PKIDTENTRY
)IdtDescriptor
.Base
;
629 /* Get TSS and FS Selectors */
631 if (Tr
!= KGDT_TSS
) Tr
= KGDT_TSS
; // FIXME: HACKHACK
634 /* Get PCR Selector, mask it and get its GDT Entry */
635 PcrSelector
= *(PKGDTENTRY
)((ULONG_PTR
)*Gdt
+ (Fs
& ~RPL_MASK
));
637 /* Get the KPCR itself */
638 *Pcr
= (PKIPCR
)(ULONG_PTR
)(PcrSelector
.BaseLow
|
639 PcrSelector
.HighWord
.Bytes
.BaseMid
<< 16 |
640 PcrSelector
.HighWord
.Bytes
.BaseHi
<< 24);
642 /* Get TSS Selector, mask it and get its GDT Entry */
643 TssSelector
= *(PKGDTENTRY
)((ULONG_PTR
)*Gdt
+ (Tr
& ~RPL_MASK
));
645 /* Get the KTSS itself */
646 *Tss
= (PKTSS
)(ULONG_PTR
)(TssSelector
.BaseLow
|
647 TssSelector
.HighWord
.Bytes
.BaseMid
<< 16 |
648 TssSelector
.HighWord
.Bytes
.BaseHi
<< 24);
653 KiSystemStartup(IN PLOADER_PARAMETER_BLOCK LoaderBlock
)
656 PKTHREAD InitialThread
;
663 /* Save the loader block and get the current CPU */
664 KeLoaderBlock
= LoaderBlock
;
665 Cpu
= KeNumberProcessors
;
668 /* If this is the boot CPU, set FS and the CPU Number*/
669 Ke386SetFs(KGDT_R0_PCR
);
670 __writefsdword(KPCR_PROCESSOR_NUMBER
, Cpu
);
672 /* Set the initial stack and idle thread as well */
673 LoaderBlock
->KernelStack
= (ULONG_PTR
)P0BootStack
;
674 LoaderBlock
->Thread
= (ULONG_PTR
)&KiInitialThread
;
677 /* Save the initial thread and stack */
678 InitialStack
= LoaderBlock
->KernelStack
;
679 InitialThread
= (PKTHREAD
)LoaderBlock
->Thread
;
681 /* Clean the APC List Head */
682 InitializeListHead(&InitialThread
->ApcState
.ApcListHead
[KernelMode
]);
684 /* Initialize the machine type */
685 KiInitializeMachineType();
687 /* Skip initial setup if this isn't the Boot CPU */
688 if (Cpu
) goto AppCpuInit
;
690 /* Get GDT, IDT, PCR and TSS pointers */
691 KiGetMachineBootPointers(&Gdt
, &Idt
, &Pcr
, &Tss
);
693 /* Setup the TSS descriptors and entries */
694 Ki386InitializeTss(Tss
, Idt
, Gdt
);
696 /* Initialize the PCR */
697 RtlZeroMemory(Pcr
, PAGE_SIZE
);
706 /* Set us as the current process */
707 InitialThread
->ApcState
.Process
= &KiInitialProcess
.Pcb
;
709 /* Clear DR6/7 to cleanup bootloader debugging */
710 __writefsdword(KPCR_TEB
, 0);
711 __writefsdword(KPCR_DR6
, 0);
712 __writefsdword(KPCR_DR7
, 0);
717 /* Load Ring 3 selectors for DS/ES */
718 Ke386SetDs(KGDT_R3_DATA
| RPL_MASK
);
719 Ke386SetEs(KGDT_R3_DATA
| RPL_MASK
);
722 /* Loop until we can release the freeze lock */
725 /* Loop until execution can continue */
726 while ((volatile KSPIN_LOCK
)KiFreezeExecutionLock
== 1);
727 } while(InterlockedBitTestAndSet((PLONG
)&KiFreezeExecutionLock
, 0));
729 /* Setup CPU-related fields */
730 __writefsdword(KPCR_NUMBER
, Cpu
);
731 __writefsdword(KPCR_SET_MEMBER
, 1 << Cpu
);
732 __writefsdword(KPCR_SET_MEMBER_COPY
, 1 << Cpu
);
733 __writefsdword(KPCR_PRCB_SET_MEMBER
, 1 << Cpu
);
735 /* Initialize the Processor with HAL */
736 HalInitializeProcessor(Cpu
, KeLoaderBlock
);
738 /* Set active processors */
739 KeActiveProcessors
|= __readfsdword(KPCR_SET_MEMBER
);
740 KeNumberProcessors
++;
742 /* Check if this is the boot CPU */
745 /* Initialize debugging system */
746 KdInitSystem(0, KeLoaderBlock
);
748 /* Check for break-in */
749 if (KdPollBreakIn()) DbgBreakPointWithStatus(1);
752 /* Raise to HIGH_LEVEL */
753 KfRaiseIrql(HIGH_LEVEL
);
755 /* Align stack and make space for the trap frame and NPX frame */
756 InitialStack
&= ~KTRAP_FRAME_ALIGN
;
758 __asm__
__volatile__("movl %0,%%esp" : :"r" (InitialStack
));
759 __asm__
__volatile__("subl %0,%%esp" : :"r" (NPX_FRAME_LENGTH
+
762 __asm__
__volatile__("push %0" : :"r" (CR0_EM
+ CR0_TS
+ CR0_MP
));
764 __asm mov esp
, InitialStack
;
765 __asm sub esp
, NPX_FRAME_LENGTH
+ KTRAP_FRAME_ALIGN
+ KTRAP_FRAME_LENGTH
;
766 __asm push CR0_EM
+ CR0_TS
+ CR0_MP
769 /* Call main kernel initialization */
770 KiInitializeKernel(&KiInitialProcess
.Pcb
,
773 (PKPRCB
)__readfsdword(KPCR_PRCB
),
777 /* Set the priority of this thread to 0 */
778 KeGetCurrentThread()->Priority
= 0;
780 /* Force interrupts enabled and lower IRQL back to DISPATCH_LEVEL */
782 KfLowerIrql(DISPATCH_LEVEL
);
784 /* Set the right wait IRQL */
785 KeGetCurrentThread()->WaitIrql
= DISPATCH_LEVEL
;
787 /* Jump into the idle loop */