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 *****************************************************************/
15 /* GLOBALS *******************************************************************/
17 /* Spinlocks used only on X86 */
18 KSPIN_LOCK KiFreezeExecutionLock
;
19 KSPIN_LOCK Ki486CompatibilityLock
;
21 /* BIOS Memory Map. Not NTLDR-compliant yet */
22 extern ULONG KeMemoryMapRangeCount
;
23 extern ADDRESS_RANGE KeMemoryMap
[64];
25 /* FUNCTIONS *****************************************************************/
29 KiInitMachineDependent(VOID
)
33 BOOLEAN FbCaching
= FALSE
;
36 ULONG i
, Affinity
, Sample
= 0;
37 PFX_SAVE_AREA FxSaveArea
;
38 ULONG MXCsrMask
= 0xFFBF;
40 KI_SAMPLE_MAP Samples
[4];
41 PKI_SAMPLE_MAP CurrentSample
= Samples
;
43 /* Check for large page support */
44 if (KeFeatureBits
& KF_LARGE_PAGE
)
46 /* FIXME: Support this */
47 DPRINT1("Large Page support detected but not yet taken advantage of!\n");
50 /* Check for global page support */
51 if (KeFeatureBits
& KF_GLOBAL_PAGE
)
53 /* Do an IPI to enable it on all CPUs */
54 CpuCount
= KeNumberProcessors
;
55 KeIpiGenericCall(Ki386EnableGlobalPage
, (ULONG_PTR
)&CpuCount
);
58 /* Check for PAT and/or MTRR support */
59 if (KeFeatureBits
& (KF_PAT
| KF_MTRR
))
61 /* Query the HAL to make sure we can use it */
62 Status
= HalQuerySystemInformation(HalFrameBufferCachingInformation
,
66 if ((NT_SUCCESS(Status
)) && (FbCaching
))
68 /* We can't, disable it */
69 KeFeatureBits
&= ~(KF_PAT
| KF_MTRR
);
73 /* Check for PAT support and enable it */
74 if (KeFeatureBits
& KF_PAT
) KiInitializePAT();
76 /* Assume no errata for now */
77 SharedUserData
->ProcessorFeatures
[PF_FLOATING_POINT_PRECISION_ERRATA
] = 0;
79 /* Check if we have an NPX */
83 i
= KeActiveProcessors
;
84 for (Affinity
= 1; i
; Affinity
<<= 1)
86 /* Check if this is part of the set */
91 KeSetSystemAffinityThread(Affinity
);
93 /* Detect FPU errata */
94 if (KiIsNpxErrataPresent())
96 /* Disable NPX support */
97 KeI386NpxPresent
= FALSE
;
99 ProcessorFeatures
[PF_FLOATING_POINT_PRECISION_ERRATA
] =
107 /* If there's no NPX, then we're emulating the FPU */
108 SharedUserData
->ProcessorFeatures
[PF_FLOATING_POINT_EMULATED
] =
111 /* Check if there's no NPX, so that we can disable associated features */
112 if (!KeI386NpxPresent
)
114 /* Remove NPX-related bits */
115 KeFeatureBits
&= ~(KF_XMMI64
| KF_XMMI
| KF_FXSR
| KF_MMX
);
117 /* Disable kernel flags */
118 KeI386FxsrPresent
= KeI386XMMIPresent
= FALSE
;
120 /* Disable processor features that might've been set until now */
121 SharedUserData
->ProcessorFeatures
[PF_FLOATING_POINT_PRECISION_ERRATA
] =
122 SharedUserData
->ProcessorFeatures
[PF_XMMI64_INSTRUCTIONS_AVAILABLE
] =
123 SharedUserData
->ProcessorFeatures
[PF_XMMI_INSTRUCTIONS_AVAILABLE
] =
124 SharedUserData
->ProcessorFeatures
[PF_3DNOW_INSTRUCTIONS_AVAILABLE
] =
125 SharedUserData
->ProcessorFeatures
[PF_MMX_INSTRUCTIONS_AVAILABLE
] = 0;
128 /* Check for CR4 support */
129 if (KeFeatureBits
& KF_CR4
)
131 /* Do an IPI call to enable the Debug Exceptions */
132 CpuCount
= KeNumberProcessors
;
133 KeIpiGenericCall(Ki386EnableDE
, (ULONG_PTR
)&CpuCount
);
136 /* Check if FXSR was found */
137 if (KeFeatureBits
& KF_FXSR
)
139 /* Do an IPI call to enable the FXSR */
140 CpuCount
= KeNumberProcessors
;
141 KeIpiGenericCall(Ki386EnableFxsr
, (ULONG_PTR
)&CpuCount
);
143 /* Check if XMM was found too */
144 if (KeFeatureBits
& KF_XMMI
)
146 /* Do an IPI call to enable XMMI exceptions */
147 CpuCount
= KeNumberProcessors
;
148 KeIpiGenericCall(Ki386EnableXMMIExceptions
, (ULONG_PTR
)&CpuCount
);
150 /* FIXME: Implement and enable XMM Page Zeroing for Mm */
152 /* Patch the RtlPrefetchMemoryNonTemporal routine to enable it */
153 Protect
= MmGetPageProtect(NULL
, RtlPrefetchMemoryNonTemporal
);
154 MmSetPageProtect(NULL
,
155 RtlPrefetchMemoryNonTemporal
,
156 Protect
| PAGE_IS_WRITABLE
);
157 *(PCHAR
)RtlPrefetchMemoryNonTemporal
= 0x90;
158 MmSetPageProtect(NULL
, RtlPrefetchMemoryNonTemporal
, Protect
);
162 /* Check for, and enable SYSENTER support */
163 KiRestoreFastSyscallReturnState();
166 i
= KeActiveProcessors
;
167 for (Affinity
= 1; i
; Affinity
<<= 1)
169 /* Check if this is part of the set */
172 /* Run on this CPU */
174 KeSetSystemAffinityThread(Affinity
);
176 /* Reset MHz to 0 for this CPU */
177 KeGetCurrentPrcb()->MHz
= 0;
179 /* Check if we can use RDTSC */
180 if (KeFeatureBits
& KF_RDTSC
)
182 /* Start sampling loop */
185 /* Do a dummy CPUID to start the sample */
188 /* Fill out the starting data */
189 CurrentSample
->PerfStart
= KeQueryPerformanceCounter(NULL
);
190 CurrentSample
->TSCStart
= __rdtsc();
191 CurrentSample
->PerfFreq
.QuadPart
= -50000;
193 /* Sleep for this sample */
194 KeDelayExecutionThread(KernelMode
,
196 &CurrentSample
->PerfFreq
);
198 /* Do another dummy CPUID */
201 /* Fill out the ending data */
202 CurrentSample
->PerfEnd
=
203 KeQueryPerformanceCounter(&CurrentSample
->PerfFreq
);
204 CurrentSample
->TSCEnd
= __rdtsc();
206 /* Calculate the differences */
207 CurrentSample
->PerfDelta
= CurrentSample
->PerfEnd
.QuadPart
-
208 CurrentSample
->PerfStart
.QuadPart
;
209 CurrentSample
->TSCDelta
= CurrentSample
->TSCEnd
-
210 CurrentSample
->TSCStart
;
212 /* Compute CPU Speed */
213 CurrentSample
->MHz
= (ULONG
)((CurrentSample
->TSCDelta
*
215 PerfFreq
.QuadPart
+ 500000) /
216 (CurrentSample
->PerfDelta
*
219 /* Check if this isn't the first sample */
222 /* Check if we got a good precision within 1MHz */
223 if ((CurrentSample
->MHz
== CurrentSample
[-1].MHz
) ||
224 (CurrentSample
->MHz
== CurrentSample
[-1].MHz
+ 1) ||
225 (CurrentSample
->MHz
== CurrentSample
[-1].MHz
- 1))
227 /* We did, stop sampling */
236 if (Sample
== sizeof(Samples
) / sizeof(Samples
[0]))
239 CurrentSample
= Samples
;
244 /* Save the CPU Speed */
245 KeGetCurrentPrcb()->MHz
= CurrentSample
[-1].MHz
;
248 /* Check if we have MTRR */
249 if (KeFeatureBits
& KF_MTRR
)
251 /* Then manually initialize MTRR for the CPU */
252 KiInitializeMTRR(i
? FALSE
: TRUE
);
255 /* Check if we have AMD MTRR and initialize it for the CPU */
256 if (KeFeatureBits
& KF_AMDK6MTRR
) KiAmdK6InitializeMTRR();
258 /* Check if this is a buggy Pentium and apply the fixup if so */
259 if (KiI386PentiumLockErrataPresent
) KiI386PentiumLockErrataFixup();
261 /* Check if the CPU supports FXSR */
262 if (KeFeatureBits
& KF_FXSR
)
264 /* Get the current thread NPX state */
266 ((ULONG_PTR
)KeGetCurrentThread()->InitialStack
-
269 /* Clear initial MXCsr mask */
270 FxSaveArea
->U
.FxArea
.MXCsrMask
= 0;
272 /* Save the current NPX State */
274 asm volatile("fxsave %0\n\t" : "=m" (*FxSaveArea
));
276 __asm fxsave
[FxSaveArea
]
278 /* Check if the current mask doesn't match the reserved bits */
279 if (FxSaveArea
->U
.FxArea
.MXCsrMask
!= 0)
281 /* Then use whatever it's holding */
282 MXCsrMask
= FxSaveArea
->U
.FxArea
.MXCsrMask
;
285 /* Check if nobody set the kernel-wide mask */
288 /* Then use the one we calculated above */
289 KiMXCsrMask
= MXCsrMask
;
293 /* Was it set to the same value we found now? */
294 if (KiMXCsrMask
!= MXCsrMask
)
296 /* No, something is definitely wrong */
297 KEBUGCHECKEX(MULTIPROCESSOR_CONFIGURATION_NOT_SUPPORTED
,
305 /* Now set the kernel mask */
306 KiMXCsrMask
&= MXCsrMask
;
311 /* Return affinity back to where it was */
312 KeRevertToUserAffinityThread();
314 /* NT allows limiting the duration of an ISR with a registry key */
315 if (KiTimeLimitIsrMicroseconds
)
318 DPRINT1("ISR Time Limit not yet supported\n");
324 KiInitializePcr(IN ULONG ProcessorNumber
,
329 IN PKTHREAD IdleThread
,
333 Pcr
->NtTib
.ExceptionList
= EXCEPTION_CHAIN_END
;
334 Pcr
->NtTib
.StackBase
= 0;
335 Pcr
->NtTib
.StackLimit
= 0;
336 Pcr
->NtTib
.Self
= NULL
;
338 /* Set the Current Thread */
339 Pcr
->PrcbData
.CurrentThread
= IdleThread
;
341 /* Set pointers to ourselves */
342 Pcr
->Self
= (PKPCR
)Pcr
;
343 Pcr
->Prcb
= &Pcr
->PrcbData
;
345 /* Set the PCR Version */
346 Pcr
->MajorVersion
= PCR_MAJOR_VERSION
;
347 Pcr
->MinorVersion
= PCR_MINOR_VERSION
;
349 /* Set the PCRB Version */
350 Pcr
->PrcbData
.MajorVersion
= 1;
351 Pcr
->PrcbData
.MinorVersion
= 1;
353 /* Set the Build Type */
354 Pcr
->PrcbData
.BuildType
= 0;
356 Pcr
->PrcbData
.BuildType
|= PRCB_BUILD_UNIPROCESSOR
;
359 Pcr
->PrcbData
.BuildType
|= PRCB_BUILD_DEBUG
;
362 /* Set the Processor Number and current Processor Mask */
363 Pcr
->PrcbData
.Number
= (UCHAR
)ProcessorNumber
;
364 Pcr
->PrcbData
.SetMember
= 1 << ProcessorNumber
;
366 /* Set the PRCB for this Processor */
367 KiProcessorBlock
[ProcessorNumber
] = Pcr
->Prcb
;
369 /* Start us out at PASSIVE_LEVEL */
370 Pcr
->Irql
= PASSIVE_LEVEL
;
372 /* Set the GDI, IDT, TSS and DPC Stack */
373 Pcr
->GDT
= (PVOID
)Gdt
;
377 Pcr
->PrcbData
.DpcStack
= DpcStack
;
379 /* Setup the processor set */
380 Pcr
->PrcbData
.MultiThreadProcessorSet
= Pcr
->PrcbData
.SetMember
;
385 KiInitializeKernel(IN PKPROCESS InitProcess
,
386 IN PKTHREAD InitThread
,
390 IN PLOADER_PARAMETER_BLOCK LoaderBlock
)
394 LARGE_INTEGER PageDirectory
;
398 /* Detect and set the CPU Type */
399 KiSetProcessorType();
401 /* Set CR0 features based on detected CPU */
404 /* Check if an FPU is present */
405 NpxPresent
= KiIsNpxPresent();
407 /* Initialize the Power Management Support for this PRCB */
408 PoInitializePrcb(Prcb
);
410 /* Bugcheck if this is a 386 CPU */
411 if (Prcb
->CpuType
== 3) KeBugCheckEx(0x5D, 0x386, 0, 0, 0);
413 /* Get the processor features for the CPU */
414 FeatureBits
= KiGetFeatureBits();
416 /* Set the default NX policy (opt-in) */
417 SharedUserData
->NXSupportPolicy
= NX_SUPPORT_POLICY_OPTIN
;
419 /* Check if NPX is always on */
420 if (strstr(KeLoaderBlock
->LoadOptions
, "NOEXECUTE=ALWAYSON"))
422 /* Set it always on */
423 SharedUserData
->NXSupportPolicy
= NX_SUPPORT_POLICY_ALWAYSON
;
424 FeatureBits
|= KF_NX_ENABLED
;
426 else if (strstr(KeLoaderBlock
->LoadOptions
, "NOEXECUTE=OPTOUT"))
428 /* Set it in opt-out mode */
429 SharedUserData
->NXSupportPolicy
= NX_SUPPORT_POLICY_OPTOUT
;
430 FeatureBits
|= KF_NX_ENABLED
;
432 else if ((strstr(KeLoaderBlock
->LoadOptions
, "NOEXECUTE=OPTIN")) ||
433 (strstr(KeLoaderBlock
->LoadOptions
, "NOEXECUTE")))
435 /* Set the feature bits */
436 FeatureBits
|= KF_NX_ENABLED
;
438 else if ((strstr(KeLoaderBlock
->LoadOptions
, "NOEXECUTE=ALWAYSOFF")) ||
439 (strstr(KeLoaderBlock
->LoadOptions
, "EXECUTE")))
441 /* Set disabled mode */
442 SharedUserData
->NXSupportPolicy
= NX_SUPPORT_POLICY_ALWAYSOFF
;
443 FeatureBits
|= KF_NX_DISABLED
;
446 /* Save feature bits */
447 Prcb
->FeatureBits
= FeatureBits
;
450 KiSaveProcessorControlState(&Prcb
->ProcessorState
);
452 /* Get cache line information for this CPU */
453 KiGetCacheInformation();
455 /* Initialize spinlocks and DPC data */
456 KiInitSpinLocks(Prcb
, Number
);
458 /* Check if this is the Boot CPU */
462 KeNodeBlock
[0] = &KiNode0
;
463 Prcb
->ParentNode
= KeNodeBlock
[0];
464 KeNodeBlock
[0]->ProcessorMask
= Prcb
->SetMember
;
466 /* Set boot-level flags */
467 KeI386NpxPresent
= NpxPresent
;
468 KeI386CpuType
= Prcb
->CpuType
;
469 KeI386CpuStep
= Prcb
->CpuStep
;
470 KeProcessorArchitecture
= PROCESSOR_ARCHITECTURE_INTEL
;
471 KeProcessorLevel
= (USHORT
)Prcb
->CpuType
;
472 if (Prcb
->CpuID
) KeProcessorRevision
= Prcb
->CpuStep
;
473 KeFeatureBits
= FeatureBits
;
474 KeI386FxsrPresent
= (KeFeatureBits
& KF_FXSR
) ? TRUE
: FALSE
;
475 KeI386XMMIPresent
= (KeFeatureBits
& KF_XMMI
) ? TRUE
: FALSE
;
477 /* Detect 8-byte compare exchange support */
478 if (!(KeFeatureBits
& KF_CMPXCHG8B
))
480 /* Copy the vendor string */
481 RtlCopyMemory(Vendor
, Prcb
->VendorString
, sizeof(Vendor
));
483 /* Bugcheck the system. Windows *requires* this */
485 (1 << 24 ) | (Prcb
->CpuType
<< 16) | Prcb
->CpuStep
,
491 /* Set the current MP Master KPRCB to the Boot PRCB */
492 Prcb
->MultiThreadSetMaster
= Prcb
;
494 /* Lower to APC_LEVEL */
495 KeLowerIrql(APC_LEVEL
);
497 /* Initialize some spinlocks */
498 KeInitializeSpinLock(&KiFreezeExecutionLock
);
499 KeInitializeSpinLock(&Ki486CompatibilityLock
);
501 /* Initialize portable parts of the OS */
504 /* Initialize the Idle Process and the Process Listhead */
505 InitializeListHead(&KiProcessListHead
);
506 PageDirectory
.QuadPart
= 0;
507 KeInitializeProcess(InitProcess
,
512 InitProcess
->QuantumReset
= MAXCHAR
;
517 DPRINT1("SMP Boot support not yet present\n");
520 /* Setup the Idle Thread */
521 KeInitializeThread(InitProcess
,
529 InitThread
->NextProcessor
= Number
;
530 InitThread
->Priority
= HIGH_PRIORITY
;
531 InitThread
->State
= Running
;
532 InitThread
->Affinity
= 1 << Number
;
533 InitThread
->WaitIrql
= DISPATCH_LEVEL
;
534 InitProcess
->ActiveProcessors
= 1 << Number
;
536 /* HACK for MmUpdatePageDir */
537 ((PETHREAD
)InitThread
)->ThreadsProcess
= (PEPROCESS
)InitProcess
;
539 /* Set basic CPU Features that user mode can read */
540 SharedUserData
->ProcessorFeatures
[PF_MMX_INSTRUCTIONS_AVAILABLE
] =
541 (KeFeatureBits
& KF_MMX
) ? TRUE
: FALSE
;
542 SharedUserData
->ProcessorFeatures
[PF_COMPARE_EXCHANGE_DOUBLE
] =
543 (KeFeatureBits
& KF_CMPXCHG8B
) ? TRUE
: FALSE
;
544 SharedUserData
->ProcessorFeatures
[PF_XMMI_INSTRUCTIONS_AVAILABLE
] =
545 ((KeFeatureBits
& KF_FXSR
) && (KeFeatureBits
& KF_XMMI
)) ? TRUE
: FALSE
;
546 SharedUserData
->ProcessorFeatures
[PF_XMMI64_INSTRUCTIONS_AVAILABLE
] =
547 ((KeFeatureBits
& KF_FXSR
) && (KeFeatureBits
& KF_XMMI64
)) ? TRUE
: FALSE
;
548 SharedUserData
->ProcessorFeatures
[PF_3DNOW_INSTRUCTIONS_AVAILABLE
] =
549 (KeFeatureBits
& KF_3DNOW
) ? TRUE
: FALSE
;
550 SharedUserData
->ProcessorFeatures
[PF_RDTSC_INSTRUCTION_AVAILABLE
] =
551 (KeFeatureBits
& KF_RDTSC
) ? TRUE
: FALSE
;
553 /* Set up the thread-related fields in the PRCB */
554 Prcb
->CurrentThread
= InitThread
;
555 Prcb
->NextThread
= NULL
;
556 Prcb
->IdleThread
= InitThread
;
558 /* Initialize the Kernel Executive */
559 ExpInitializeExecutive(Number
, LoaderBlock
);
561 /* Only do this on the boot CPU */
564 /* Calculate the time reciprocal */
565 KiTimeIncrementReciprocal
=
566 KiComputeReciprocal(KeMaximumIncrement
,
567 &KiTimeIncrementShiftCount
);
569 /* Update DPC Values in case they got updated by the executive */
570 Prcb
->MaximumDpcQueueDepth
= KiMaximumDpcQueueDepth
;
571 Prcb
->MinimumDpcRate
= KiMinimumDpcRate
;
572 Prcb
->AdjustDpcThreshold
= KiAdjustDpcThreshold
;
574 /* Allocate the DPC Stack */
575 DpcStack
= MmCreateKernelStack(FALSE
, 0);
576 if (!DpcStack
) KeBugCheckEx(NO_PAGES_AVAILABLE
, 1, 0, 0, 0);
577 Prcb
->DpcStack
= DpcStack
;
579 /* Allocate the IOPM save area. */
580 Ki386IopmSaveArea
= ExAllocatePoolWithTag(PagedPool
,
582 TAG('K', 'e', ' ', ' '));
583 if (!Ki386IopmSaveArea
)
585 /* Bugcheck. We need this for V86/VDM support. */
586 KeBugCheckEx(NO_PAGES_AVAILABLE
, 2, PAGE_SIZE
* 2, 0, 0);
590 /* Raise to Dispatch */
591 KfRaiseIrql(DISPATCH_LEVEL
);
593 /* Set the Idle Priority to 0. This will jump into Phase 1 */
594 KeSetPriorityThread(InitThread
, 0);
596 /* If there's no thread scheduled, put this CPU in the Idle summary */
597 KiAcquirePrcbLock(Prcb
);
598 if (!Prcb
->NextThread
) KiIdleSummary
|= 1 << Number
;
599 KiReleasePrcbLock(Prcb
);
601 /* Raise back to HIGH_LEVEL and clear the PRCB for the loader block */
602 KfRaiseIrql(HIGH_LEVEL
);
603 LoaderBlock
->Prcb
= 0;
608 KiGetMachineBootPointers(IN PKGDTENTRY
*Gdt
,
613 KDESCRIPTOR GdtDescriptor
= {0}, IdtDescriptor
= {0};
614 KGDTENTRY TssSelector
, PcrSelector
;
617 /* Get GDT and IDT descriptors */
618 Ke386GetGlobalDescriptorTable(*(PKDESCRIPTOR
)&GdtDescriptor
.Limit
);
619 Ke386GetInterruptDescriptorTable(*(PKDESCRIPTOR
)&IdtDescriptor
.Limit
);
621 /* Save IDT and GDT */
622 *Gdt
= (PKGDTENTRY
)GdtDescriptor
.Base
;
623 *Idt
= (PKIDTENTRY
)IdtDescriptor
.Base
;
625 /* Get TSS and FS Selectors */
627 if (Tr
!= KGDT_TSS
) Tr
= KGDT_TSS
; // FIXME: HACKHACK
630 /* Get PCR Selector, mask it and get its GDT Entry */
631 PcrSelector
= *(PKGDTENTRY
)((ULONG_PTR
)*Gdt
+ (Fs
& ~RPL_MASK
));
633 /* Get the KPCR itself */
634 *Pcr
= (PKIPCR
)(ULONG_PTR
)(PcrSelector
.BaseLow
|
635 PcrSelector
.HighWord
.Bytes
.BaseMid
<< 16 |
636 PcrSelector
.HighWord
.Bytes
.BaseHi
<< 24);
638 /* Get TSS Selector, mask it and get its GDT Entry */
639 TssSelector
= *(PKGDTENTRY
)((ULONG_PTR
)*Gdt
+ (Tr
& ~RPL_MASK
));
641 /* Get the KTSS itself */
642 *Tss
= (PKTSS
)(ULONG_PTR
)(TssSelector
.BaseLow
|
643 TssSelector
.HighWord
.Bytes
.BaseMid
<< 16 |
644 TssSelector
.HighWord
.Bytes
.BaseHi
<< 24);
649 KiSystemStartupReal(IN PLOADER_PARAMETER_BLOCK LoaderBlock
)
652 PKTHREAD InitialThread
;
656 KIDTENTRY NmiEntry
, DoubleFaultEntry
;
660 /* Save the loader block and get the current CPU */
661 KeLoaderBlock
= LoaderBlock
;
662 Cpu
= KeNumberProcessors
;
665 /* If this is the boot CPU, set FS and the CPU Number*/
666 Ke386SetFs(KGDT_R0_PCR
);
667 __writefsdword(KPCR_PROCESSOR_NUMBER
, Cpu
);
669 /* Set the initial stack and idle thread as well */
670 LoaderBlock
->KernelStack
= (ULONG_PTR
)P0BootStack
;
671 LoaderBlock
->Thread
= (ULONG_PTR
)&KiInitialThread
;
674 /* Save the initial thread and stack */
675 InitialStack
= LoaderBlock
->KernelStack
;
676 InitialThread
= (PKTHREAD
)LoaderBlock
->Thread
;
678 /* Clean the APC List Head */
679 InitializeListHead(&InitialThread
->ApcState
.ApcListHead
[KernelMode
]);
681 /* Initialize the machine type */
682 KiInitializeMachineType();
684 /* Skip initial setup if this isn't the Boot CPU */
685 if (Cpu
) goto AppCpuInit
;
687 /* Get GDT, IDT, PCR and TSS pointers */
688 KiGetMachineBootPointers(&Gdt
, &Idt
, &Pcr
, &Tss
);
690 /* Setup the TSS descriptors and entries */
691 Ki386InitializeTss(Tss
, Idt
, Gdt
);
693 /* Initialize the PCR */
694 RtlZeroMemory(Pcr
, PAGE_SIZE
);
703 /* Set us as the current process */
704 InitialThread
->ApcState
.Process
= &KiInitialProcess
.Pcb
;
706 /* Clear DR6/7 to cleanup bootloader debugging */
707 __writefsdword(KPCR_TEB
, 0);
708 __writefsdword(KPCR_DR6
, 0);
709 __writefsdword(KPCR_DR7
, 0);
714 /* Load Ring 3 selectors for DS/ES */
715 Ke386SetDs(KGDT_R3_DATA
| RPL_MASK
);
716 Ke386SetEs(KGDT_R3_DATA
| RPL_MASK
);
718 /* Save NMI and double fault traps */
719 RtlCopyMemory(&NmiEntry
, &Idt
[2], sizeof(KIDTENTRY
));
720 RtlCopyMemory(&DoubleFaultEntry
, &Idt
[8], sizeof(KIDTENTRY
));
722 /* Copy kernel's trap handlers */
724 (PVOID
)KiIdtDescriptor
.Base
,
725 KiIdtDescriptor
.Limit
+ 1);
727 /* Restore NMI and double fault */
728 RtlCopyMemory(&Idt
[2], &NmiEntry
, sizeof(KIDTENTRY
));
729 RtlCopyMemory(&Idt
[8], &DoubleFaultEntry
, sizeof(KIDTENTRY
));
732 /* Loop until we can release the freeze lock */
735 /* Loop until execution can continue */
736 while (*(volatile PKSPIN_LOCK
*)&KiFreezeExecutionLock
== (PVOID
)1);
737 } while(InterlockedBitTestAndSet((PLONG
)&KiFreezeExecutionLock
, 0));
739 /* Setup CPU-related fields */
740 __writefsdword(KPCR_NUMBER
, Cpu
);
741 __writefsdword(KPCR_SET_MEMBER
, 1 << Cpu
);
742 __writefsdword(KPCR_SET_MEMBER_COPY
, 1 << Cpu
);
743 __writefsdword(KPCR_PRCB_SET_MEMBER
, 1 << Cpu
);
745 /* Initialize the Processor with HAL */
746 HalInitializeProcessor(Cpu
, KeLoaderBlock
);
748 /* Set active processors */
749 KeActiveProcessors
|= __readfsdword(KPCR_SET_MEMBER
);
750 KeNumberProcessors
++;
752 /* Check if this is the boot CPU */
755 /* Initialize debugging system */
756 KdInitSystem(0, KeLoaderBlock
);
758 /* Check for break-in */
759 if (KdPollBreakIn()) DbgBreakPointWithStatus(1);
762 /* Raise to HIGH_LEVEL */
763 KfRaiseIrql(HIGH_LEVEL
);
765 /* Align stack and make space for the trap frame and NPX frame */
766 InitialStack
&= ~(KTRAP_FRAME_ALIGN
- 1);
768 /* Switch to new kernel stack and start kernel bootstrapping */
769 KiSetupStackAndInitializeKernel(&KiInitialProcess
.Pcb
,
772 (PKPRCB
)__readfsdword(KPCR_PRCB
),