ReactOS 0.4.17-dev-650-gd0e71de
kiinit.c File Reference
#include <ntoskrnl.h>
#include <debug.h>
#include "internal/i386/trap_x.h"
Include dependency graph for kiinit.c:

Go to the source code of this file.

Macros

#define NDEBUG
 

Functions

UCHAR DECLSPEC_ALIGN (PAGE_SIZE)
 
VOID NTAPI KiInitMachineDependent (VOID)
 
VOID NTAPI KiInitializePcr (IN ULONG ProcessorNumber, IN PKIPCR Pcr, IN PKIDTENTRY Idt, IN PKGDTENTRY Gdt, IN PKTSS Tss, IN PKTHREAD IdleThread, IN PVOID DpcStack)
 
static VOID KiVerifyCpuFeatures (PKPRCB Prcb)
 
VOID NTAPI KiInitializeKernel (IN PKPROCESS InitProcess, IN PKTHREAD InitThread, IN PVOID IdleStack, IN PKPRCB Prcb, IN CCHAR Number, IN PLOADER_PARAMETER_BLOCK LoaderBlock)
 
VOID FASTCALL KiGetMachineBootPointers (IN PKGDTENTRY *Gdt, IN PKIDTENTRY *Idt, IN PKIPCR *Pcr, IN PKTSS *Tss)
 
DECLSPEC_NORETURN VOID NTAPI KiSystemStartupBootStack (VOID)
 
static VOID KiMarkPageAsReadOnly (PVOID Address)
 
DECLSPEC_NORETURN VOID NTAPI KiSystemStartup (IN PLOADER_PARAMETER_BLOCK LoaderBlock)
 

Variables

ULONG_PTR P0BootStack = (ULONG_PTR)&P0BootStackData[KERNEL_STACK_SIZE]
 
ULONG_PTR KiDoubleFaultStack = (ULONG_PTR)&KiDoubleFaultStackData[KERNEL_STACK_SIZE]
 
KSPIN_LOCK KiFreezeExecutionLock
 
KSPIN_LOCK Ki486CompatibilityLock
 
ULONG ProcessCount
 
ULONGLONG BootCycles
 
ULONGLONG BootCyclesEnd
 

Macro Definition Documentation

◆ NDEBUG

#define NDEBUG

Definition at line 12 of file kiinit.c.

Function Documentation

◆ DECLSPEC_ALIGN()

UCHAR DECLSPEC_ALIGN ( PAGE_SIZE  )

Definition at line 19 of file kiinit.c.

19{0};

◆ KiGetMachineBootPointers()

VOID FASTCALL KiGetMachineBootPointers ( IN PKGDTENTRY Gdt,
IN PKIDTENTRY Idt,
IN PKIPCR Pcr,
IN PKTSS Tss 
)

Definition at line 646 of file kiinit.c.

650{
651 KDESCRIPTOR GdtDescriptor, IdtDescriptor;
652 KGDTENTRY TssSelector, PcrSelector;
653 USHORT Tr, Fs;
654
655 /* Get GDT and IDT descriptors */
656 Ke386GetGlobalDescriptorTable(&GdtDescriptor.Limit);
657 __sidt(&IdtDescriptor.Limit);
658
659 /* Save IDT and GDT */
660 *Gdt = (PKGDTENTRY)GdtDescriptor.Base;
661 *Idt = (PKIDTENTRY)IdtDescriptor.Base;
662
663 /* Get TSS and FS Selectors */
664 Tr = Ke386GetTr();
665 Fs = Ke386GetFs();
666
667 /* Get PCR Selector, mask it and get its GDT Entry */
668 PcrSelector = *(PKGDTENTRY)((ULONG_PTR)*Gdt + (Fs & ~RPL_MASK));
669
670 /* Get the KPCR itself */
671 *Pcr = (PKIPCR)(ULONG_PTR)(PcrSelector.BaseLow |
672 PcrSelector.HighWord.Bytes.BaseMid << 16 |
673 PcrSelector.HighWord.Bytes.BaseHi << 24);
674
675 /* Get TSS Selector, mask it and get its GDT Entry */
676 TssSelector = *(PKGDTENTRY)((ULONG_PTR)*Gdt + (Tr & ~RPL_MASK));
677
678 /* Get the KTSS itself */
679 *Tss = (PKTSS)(ULONG_PTR)(TssSelector.BaseLow |
680 TssSelector.HighWord.Bytes.BaseMid << 16 |
681 TssSelector.HighWord.Bytes.BaseHi << 24);
682}
#define Ke386GetGlobalDescriptorTable
Definition: intrin_i.h:452
__INTRIN_INLINE void __sidt(void *Destination)
Definition: intrin_x86.h:2064
#define PKTSS
Definition: ketypes.h:1034
#define PKGDTENTRY
Definition: ketypes.h:543
struct _KIPCR * PKIPCR
unsigned short USHORT
Definition: pedump.c:61
PVOID Base
Definition: ketypes.h:591
USHORT Limit
Definition: ketypes.h:590
struct _KGDTENTRY::@2707::@2708 Bytes
USHORT BaseLow
Definition: ketypes.h:390
union _KGDTENTRY::@2707 HighWord
uint32_t ULONG_PTR
Definition: typedefs.h:65

Referenced by KiSystemStartup().

◆ KiInitializeKernel()

VOID NTAPI KiInitializeKernel ( IN PKPROCESS  InitProcess,
IN PKTHREAD  InitThread,
IN PVOID  IdleStack,
IN PKPRCB  Prcb,
IN CCHAR  Number,
IN PLOADER_PARAMETER_BLOCK  LoaderBlock 
)

Definition at line 433 of file kiinit.c.

439{
440 ULONG PageDirectory[2];
441 PVOID DpcStack;
442 KIRQL DummyIrql;
443
444 /* Initialize the Power Management Support for this PRCB */
445 PoInitializePrcb(Prcb);
446
447 /* Set boot-level flags */
448 if (Number == 0)
449 KeFeatureBits = Prcb->FeatureBits | (ULONG64)Prcb->FeatureBitsHigh << 32;
450
451 /* Set the default NX policy (opt-in) */
452 SharedUserData->NXSupportPolicy = NX_SUPPORT_POLICY_OPTIN;
453
454 /* Check if NPX is always on */
455 if (strstr(KeLoaderBlock->LoadOptions, "NOEXECUTE=ALWAYSON"))
456 {
457 /* Set it always on */
460 }
461 else if (strstr(KeLoaderBlock->LoadOptions, "NOEXECUTE=OPTOUT"))
462 {
463 /* Set it in opt-out mode */
464 SharedUserData->NXSupportPolicy = NX_SUPPORT_POLICY_OPTOUT;
466 }
467 else if ((strstr(KeLoaderBlock->LoadOptions, "NOEXECUTE=OPTIN")) ||
468 (strstr(KeLoaderBlock->LoadOptions, "NOEXECUTE")))
469 {
470 /* Set the feature bits */
472 }
473 else if ((strstr(KeLoaderBlock->LoadOptions, "NOEXECUTE=ALWAYSOFF")) ||
474 (strstr(KeLoaderBlock->LoadOptions, "EXECUTE")))
475 {
476 /* Set disabled mode */
479 }
480
481 /* Save CPU state */
482 KiSaveProcessorControlState(&Prcb->ProcessorState);
483
484#if DBG
485 /* Print applied kernel features/policies and boot CPU features */
486 if (Number == 0)
487 KiReportCpuFeatures();
488#endif
489
490 /* Get cache line information for this CPU */
492
493 /* Initialize spinlocks and DPC data */
494 KiInitSpinLocks(Prcb, Number);
495
496 /* Set Node Data */
497 Prcb->ParentNode = KeNodeBlock[0];
498 Prcb->ParentNode->ProcessorMask |= Prcb->SetMember;
499
500 /* Check if this is the Boot CPU */
501 if (!Number)
502 {
503 /* Set boot-level flags */
504 KeI386CpuType = Prcb->CpuType;
505 KeI386CpuStep = Prcb->CpuStep;
507 KeProcessorLevel = (USHORT)Prcb->CpuType;
508 if (Prcb->CpuID) KeProcessorRevision = Prcb->CpuStep;
511
512 /* Set the current MP Master KPRCB to the Boot PRCB */
513 Prcb->MultiThreadSetMaster = Prcb;
514
515 /* Lower to APC_LEVEL */
517
518 /* Initialize some spinlocks */
521
522 /* Initialize portable parts of the OS */
523 KiInitSystem();
524
525 /* Initialize the Idle Process and the Process Listhead */
527 PageDirectory[0] = 0;
528 PageDirectory[1] = 0;
529 KeInitializeProcess(InitProcess,
530 0,
532 PageDirectory,
533 FALSE);
534 InitProcess->QuantumReset = MAXCHAR;
535 }
536 else
537 {
538 /* FIXME */
539 DPRINT1("Starting CPU#%u - you are brave\n", Number);
540 }
541
542 /* Setup the Idle Thread */
543 KeInitializeThread(InitProcess,
544 InitThread,
545 NULL,
546 NULL,
547 NULL,
548 NULL,
549 NULL,
550 IdleStack);
551 InitThread->NextProcessor = Number;
552 InitThread->Priority = HIGH_PRIORITY;
553 InitThread->State = Running;
554 InitThread->Affinity = 1 << Number;
555 InitThread->WaitIrql = DISPATCH_LEVEL;
556 InitProcess->ActiveProcessors |= 1 << Number;
557
558 /* HACK for MmUpdatePageDir */
559 ((PETHREAD)InitThread)->ThreadsProcess = (PEPROCESS)InitProcess;
560
561 /* Set basic CPU Features that user mode can read */
565 SharedUserData->ProcessorFeatures[PF_COMPARE_EXCHANGE_DOUBLE] =
577 // Note: On x86 we lack support for saving/restoring SSE state
586
587 /* Set up the thread-related fields in the PRCB */
588 Prcb->CurrentThread = InitThread;
589 Prcb->NextThread = NULL;
590 Prcb->IdleThread = InitThread;
591
592 /* Initialize start cycles */
593 Prcb->StartCycles = __rdtsc();
594
595 /* Initialize the Kernel Executive */
596 ExpInitializeExecutive(Number, LoaderBlock);
597
598 /* Only do this on the boot CPU */
599 if (!Number)
600 {
601 /* Calculate the time reciprocal */
605
606 /* Update DPC Values in case they got updated by the executive */
607 Prcb->MaximumDpcQueueDepth = KiMaximumDpcQueueDepth;
608 Prcb->MinimumDpcRate = KiMinimumDpcRate;
609 Prcb->AdjustDpcThreshold = KiAdjustDpcThreshold;
610
611 /* Allocate the DPC Stack */
612 DpcStack = MmCreateKernelStack(FALSE, 0);
613 if (!DpcStack) KeBugCheckEx(NO_PAGES_AVAILABLE, 1, 0, 0, 0);
614 Prcb->DpcStack = DpcStack;
615
616 /* Allocate the IOPM save area */
618 IOPM_SIZE,
619 TAG_KERNEL);
621 {
622 /* Bugcheck. We need this for V86/VDM support. */
623 KeBugCheckEx(NO_PAGES_AVAILABLE, 2, IOPM_SIZE, 0, 0);
624 }
625 }
626
627 /* Raise to Dispatch */
628 KeRaiseIrql(DISPATCH_LEVEL, &DummyIrql);
629
630 /* Set the Idle Priority to 0. This will jump into Phase 1 */
631 KeSetPriorityThread(InitThread, 0);
632
633 /* If there's no thread scheduled, put this CPU in the Idle summary */
634 KiAcquirePrcbLock(Prcb);
635 if (!Prcb->NextThread) KiIdleSummary |= 1 << Number;
636 KiReleasePrcbLock(Prcb);
637
638 /* Raise back to HIGH_LEVEL and clear the PRCB for the loader block */
639 KeRaiseIrql(HIGH_LEVEL, &DummyIrql);
640 LoaderBlock->Prcb = 0;
641}
ULONG64 KeFeatureBits
Definition: krnlinit.c:22
KSPIN_LOCK KiFreezeExecutionLock
Definition: kiinit.c:26
#define DPRINT1
Definition: precomp.h:8
#define MAXULONG_PTR
Definition: basetsd.h:97
DECLSPEC_NORETURN VOID NTAPI KeBugCheckEx(IN ULONG BugCheckCode, IN ULONG_PTR BugCheckParameter1, IN ULONG_PTR BugCheckParameter2, IN ULONG_PTR BugCheckParameter3, IN ULONG_PTR BugCheckParameter4)
Definition: debug.c:485
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
_ACRTIMP char *__cdecl strstr(const char *, const char *)
Definition: string.c:3420
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
UCHAR KIRQL
Definition: env_spec_w32.h:591
#define KeRaiseIrql(irql, oldIrql)
Definition: env_spec_w32.h:597
#define HIGH_LEVEL
Definition: env_spec_w32.h:703
#define APC_LEVEL
Definition: env_spec_w32.h:695
#define KeLowerIrql(oldIrql)
Definition: env_spec_w32.h:602
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
#define DISPATCH_LEVEL
Definition: env_spec_w32.h:696
#define KeInitializeSpinLock(sl)
Definition: env_spec_w32.h:604
#define PagedPool
Definition: env_spec_w32.h:308
KSPIN_LOCK Ki486CompatibilityLock
Definition: kiinit.c:26
#define HIGH_PRIORITY
PPC_QUAL unsigned long long __rdtsc(void)
Definition: intrin_ppc.h:688
FORCEINLINE VOID KiReleasePrcbLock(IN PKPRCB Prcb)
Definition: ke_x.h:230
FORCEINLINE VOID KiAcquirePrcbLock(IN PKPRCB Prcb)
Definition: ke_x.h:220
if(dx< 0)
Definition: linetemp.h:194
unsigned __int64 ULONG64
Definition: imports.h:198
#define KF_SSE4_2
Definition: ketypes.h:74
#define KF_SSSE3
Definition: ketypes.h:72
#define KF_NX_DISABLED
Definition: ketypes.h:62
#define KF_XMMI64
Definition: ketypes.h:48
#define KF_SSE4_1
Definition: ketypes.h:73
#define KF_CMPXCHG8B
Definition: ketypes.h:38
#define KF_NX_ENABLED
Definition: ketypes.h:63
#define KF_RDTSC
Definition: ketypes.h:32
#define KF_3DNOW
Definition: ketypes.h:45
#define KF_FXSR
Definition: ketypes.h:42
#define KF_RDRAND
Definition: ketypes.h:64
#define KF_XMMI
Definition: ketypes.h:44
#define KF_MMX
Definition: ketypes.h:39
#define KF_SSE3
Definition: ketypes.h:51
_In_ ULONG Number
Definition: haltypes.h:1872
#define IOPM_SIZE
Definition: ketypes.h:228
@ Running
Definition: ketypes.h:409
#define PROCESSOR_ARCHITECTURE_INTEL
Definition: ketypes.h:105
struct _EPROCESS * PEPROCESS
Definition: nt_native.h:30
struct _ETHREAD * PETHREAD
Definition: nt_native.h:29
VOID NTAPI ExpInitializeExecutive(IN ULONG Cpu, IN PLOADER_PARAMETER_BLOCK LoaderBlock)
Definition: init.c:928
ULONG KeI386XMMIPresent
Definition: cpu.c:32
VOID KiGetCacheInformation(VOID)
Definition: cpu.c:334
ULONG KeI386CpuType
Definition: cpu.c:25
ULONG KeI386FxsrPresent
Definition: cpu.c:33
ULONG KeI386CpuStep
Definition: cpu.c:26
PVOID Ki386IopmSaveArea
Definition: v86vdm.c:23
LARGE_INTEGER KiTimeIncrementReciprocal
Definition: timerobj.c:18
ULONG KiAdjustDpcThreshold
Definition: dpc.c:21
ULONG KiMaximumDpcQueueDepth
Definition: dpc.c:19
KAFFINITY KiIdleSummary
Definition: thrdschd.c:25
VOID NTAPI KeInitializeThread(IN PKPROCESS Process, IN OUT PKTHREAD Thread, IN PKSYSTEM_ROUTINE SystemRoutine, IN PKSTART_ROUTINE StartRoutine, IN PVOID StartContext, IN PCONTEXT Context, IN PVOID Teb, IN PVOID KernelStack)
Definition: thrdobj.c:891
UCHAR KiTimeIncrementShiftCount
Definition: timerobj.c:19
USHORT KeProcessorLevel
Definition: krnlinit.c:20
ULONG KiMinimumDpcRate
Definition: dpc.c:20
VOID NTAPI KiInitSystem(VOID)
Definition: krnlinit.c:67
PKNODE KeNodeBlock[1]
Definition: krnlinit.c:35
LARGE_INTEGER NTAPI KiComputeReciprocal(IN LONG Divisor, OUT PUCHAR Shift)
Definition: krnlinit.c:119
VOID NTAPI KiSaveProcessorControlState(OUT PKPROCESSOR_STATE ProcessorState)
Definition: cpu.c:487
VOID NTAPI KeInitializeProcess(struct _KPROCESS *Process, KPRIORITY Priority, KAFFINITY Affinity, PULONG_PTR DirectoryTableBase, IN BOOLEAN Enable)
USHORT KeProcessorRevision
Definition: krnlinit.c:21
VOID NTAPI KiInitSpinLocks(IN PKPRCB Prcb, IN CCHAR Number)
Definition: krnlinit.c:183
LIST_ENTRY KiProcessListHead
Definition: procobj.c:18
USHORT KeProcessorArchitecture
Definition: krnlinit.c:19
PVOID NTAPI MmCreateKernelStack(BOOLEAN GuiStack, UCHAR Node)
ULONG KeMaximumIncrement
Definition: clock.c:20
NTSYSAPI PLOADER_PARAMETER_BLOCK KeLoaderBlock
Definition: krnlinit.c:28
VOID NTAPI PoInitializePrcb(IN PKPRCB Prcb)
Definition: power.c:510
#define SharedUserData
KAFFINITY ProcessorMask
Definition: ketypes.h:1031
#define TAG_KERNEL
Definition: tag.h:42
KPRIORITY NTAPI KeSetPriorityThread(IN PKTHREAD Thread, IN KPRIORITY Priority)
Definition: thrdobj.c:1300
uint32_t ULONG
Definition: typedefs.h:59
#define MAXCHAR
Definition: umtypes.h:112
#define NX_SUPPORT_POLICY_ALWAYSOFF
#define PF_3DNOW_INSTRUCTIONS_AVAILABLE
Definition: ketypes.h:183
#define PF_SSE4_2_INSTRUCTIONS_AVAILABLE
Definition: ketypes.h:213
#define PF_MMX_INSTRUCTIONS_AVAILABLE
Definition: ketypes.h:179
#define PF_XMMI64_INSTRUCTIONS_AVAILABLE
Definition: ketypes.h:186
#define PF_XMMI_INSTRUCTIONS_AVAILABLE
Definition: ketypes.h:182
#define NX_SUPPORT_POLICY_OPTIN
#define PF_SSSE3_INSTRUCTIONS_AVAILABLE
Definition: ketypes.h:211
#define NX_SUPPORT_POLICY_OPTOUT
#define NX_SUPPORT_POLICY_ALWAYSON
#define PF_FLOATING_POINT_PRECISION_ERRATA
Definition: ketypes.h:176
#define PF_COMPARE_EXCHANGE_DOUBLE
Definition: ketypes.h:178
#define PF_SSE3_INSTRUCTIONS_AVAILABLE
Definition: ketypes.h:189
#define PF_RDRAND_INSTRUCTION_AVAILABLE
Definition: ketypes.h:204
#define PF_RDTSC_INSTRUCTION_AVAILABLE
Definition: ketypes.h:184
#define PF_SSE4_1_INSTRUCTIONS_AVAILABLE
Definition: ketypes.h:212

◆ KiInitializePcr()

VOID NTAPI KiInitializePcr ( IN ULONG  ProcessorNumber,
IN PKIPCR  Pcr,
IN PKIDTENTRY  Idt,
IN PKGDTENTRY  Gdt,
IN PKTSS  Tss,
IN PKTHREAD  IdleThread,
IN PVOID  DpcStack 
)

Definition at line 284 of file kiinit.c.

291{
292 /* Setup the TIB */
293 Pcr->NtTib.ExceptionList = EXCEPTION_CHAIN_END;
294 Pcr->NtTib.StackBase = 0;
295 Pcr->NtTib.StackLimit = 0;
296 Pcr->NtTib.Self = NULL;
297
298 /* Set the Current Thread */
299 Pcr->PrcbData.CurrentThread = IdleThread;
300
301 /* Set pointers to ourselves */
302 Pcr->SelfPcr = (PKPCR)Pcr;
303 Pcr->Prcb = &Pcr->PrcbData;
304
305 /* Set the PCR Version */
306 Pcr->MajorVersion = PCR_MAJOR_VERSION;
307 Pcr->MinorVersion = PCR_MINOR_VERSION;
308
309 /* Set the PCRB Version */
310 Pcr->PrcbData.MajorVersion = PRCB_MAJOR_VERSION;
311 Pcr->PrcbData.MinorVersion = PRCB_MINOR_VERSION;
312
313 /* Set the Build Type */
314 Pcr->PrcbData.BuildType = 0;
315#ifndef CONFIG_SMP
316 Pcr->PrcbData.BuildType |= PRCB_BUILD_UNIPROCESSOR;
317#endif
318#if DBG
319 Pcr->PrcbData.BuildType |= PRCB_BUILD_DEBUG;
320#endif
321
322 /* Set the Processor Number and current Processor Mask */
323 Pcr->PrcbData.Number = (UCHAR)ProcessorNumber;
324 Pcr->PrcbData.SetMember = 1 << ProcessorNumber;
325
326 /* Set the PRCB for this Processor */
327 KiProcessorBlock[ProcessorNumber] = Pcr->Prcb;
328
329 /* Start us out at PASSIVE_LEVEL */
330 Pcr->Irql = PASSIVE_LEVEL;
331
332 /* Set the GDI, IDT, TSS and DPC Stack */
333 Pcr->GDT = (PVOID)Gdt;
334 Pcr->IDT = Idt;
335 Pcr->TSS = Tss;
336 Pcr->TssCopy = Tss;
337 Pcr->PrcbData.DpcStack = DpcStack;
338
339 /* Setup the processor set */
340 Pcr->PrcbData.MultiThreadProcessorSet = Pcr->PrcbData.SetMember;
341}
#define PASSIVE_LEVEL
Definition: env_spec_w32.h:693
#define PRCB_MINOR_VERSION
Definition: ketypes.h:336
#define PRCB_MAJOR_VERSION
Definition: ketypes.h:337
#define PRCB_BUILD_UNIPROCESSOR
Definition: ketypes.h:339
#define PRCB_BUILD_DEBUG
Definition: ketypes.h:338
#define EXCEPTION_CHAIN_END
Definition: rtltypes.h:63
PKPRCB KiProcessorBlock[]
Definition: krnlinit.c:31
#define PCR_MINOR_VERSION
Definition: ke.h:290
struct _KPCR * PKPCR
#define PCR_MAJOR_VERSION
Definition: ke.h:291
unsigned char UCHAR
Definition: typedefs.h:53
void * PVOID
Definition: typedefs.h:50

Referenced by KeStartAllProcessors().

◆ KiInitMachineDependent()

VOID NTAPI KiInitMachineDependent ( VOID  )

Definition at line 37 of file kiinit.c.

38{
39 ULONG CpuCount;
40 BOOLEAN FbCaching = FALSE;
43 ULONG i, Affinity, Sample = 0;
44 PFX_SAVE_AREA FxSaveArea;
45 ULONG MXCsrMask = 0xFFBF;
46 CPU_INFO CpuInfo;
47 KI_SAMPLE_MAP Samples[10];
48 PKI_SAMPLE_MAP CurrentSample = Samples;
49 LARGE_IDENTITY_MAP IdentityMap;
50
51 /* Check for large page support */
53 {
54 /* Do an IPI to enable it on all CPUs */
57
58 /* Free the pages allocated for identity map */
59 Ki386FreeIdentityMap(&IdentityMap);
60 }
61
62 /* Check for global page support */
64 {
65 /* Do an IPI to enable it on all CPUs */
66 CpuCount = KeNumberProcessors;
68 }
69
70 /* Check for PAT and/or MTRR support */
72 {
73 /* Query the HAL to make sure we can use it */
75 sizeof(BOOLEAN),
76 &FbCaching,
78 if ((NT_SUCCESS(Status)) && (FbCaching))
79 {
80 /* We can't, disable it */
82 }
83 }
84
85 /* Check for PAT support and enable it */
87
88 /* Check for CR4 support */
90 {
91 /* Do an IPI call to enable the Debug Exceptions */
92 CpuCount = KeNumberProcessors;
94 }
95
96 /* Check if FXSR was found */
98 {
99 /* Do an IPI call to enable the FXSR */
100 CpuCount = KeNumberProcessors;
102
103 /* Check if XMM was found too */
105 {
106 /* Do an IPI call to enable XMMI exceptions */
107 CpuCount = KeNumberProcessors;
109
110 /* FIXME: Implement and enable XMM Page Zeroing for Mm */
111
112 /* Patch the RtlPrefetchMemoryNonTemporal routine to enable it */
113 *(PCHAR)RtlPrefetchMemoryNonTemporal = 0x90; // NOP
114 }
115 }
116
117 /* Check for, and enable SYSENTER support */
119
120 /* Loop every CPU */
122 for (Affinity = 1; i; Affinity <<= 1)
123 {
124 /* Check if this is part of the set */
125 if (i & Affinity)
126 {
127 /* Run on this CPU */
128 i &= ~Affinity;
130
131 /* Reset MHz to 0 for this CPU */
132 KeGetCurrentPrcb()->MHz = 0;
133
134 /* Check if we can use RDTSC */
136 {
137 /* Start sampling loop */
138 for (;;)
139 {
140 /* Do a dummy CPUID to start the sample */
141 KiCpuId(&CpuInfo, 0);
142
143 /* Fill out the starting data */
144 CurrentSample->PerfStart = KeQueryPerformanceCounter(NULL);
145 CurrentSample->TSCStart = __rdtsc();
146 CurrentSample->PerfFreq.QuadPart = -50000;
147
148 /* Sleep for this sample */
150 FALSE,
151 &CurrentSample->PerfFreq);
152
153 /* Do another dummy CPUID */
154 KiCpuId(&CpuInfo, 0);
155
156 /* Fill out the ending data */
157 CurrentSample->PerfEnd =
158 KeQueryPerformanceCounter(&CurrentSample->PerfFreq);
159 CurrentSample->TSCEnd = __rdtsc();
160
161 /* Calculate the differences */
162 CurrentSample->PerfDelta = CurrentSample->PerfEnd.QuadPart -
163 CurrentSample->PerfStart.QuadPart;
164 CurrentSample->TSCDelta = CurrentSample->TSCEnd -
165 CurrentSample->TSCStart;
166
167 /* Compute CPU Speed */
168 CurrentSample->MHz = (ULONG)((CurrentSample->TSCDelta *
169 CurrentSample->
170 PerfFreq.QuadPart + 500000) /
171 (CurrentSample->PerfDelta *
172 1000000));
173
174 /* Check if this isn't the first sample */
175 if (Sample)
176 {
177 /* Check if we got a good precision within 1MHz */
178 if ((CurrentSample->MHz == CurrentSample[-1].MHz) ||
179 (CurrentSample->MHz == CurrentSample[-1].MHz + 1) ||
180 (CurrentSample->MHz == CurrentSample[-1].MHz - 1))
181 {
182 /* We did, stop sampling */
183 break;
184 }
185 }
186
187 /* Move on */
188 CurrentSample++;
189 Sample++;
190
191 if (Sample == RTL_NUMBER_OF(Samples))
192 {
193 /* No luck. Average the samples and be done */
194 ULONG TotalMHz = 0;
195 while (Sample--)
196 {
197 TotalMHz += Samples[Sample].MHz;
198 }
199 CurrentSample[-1].MHz = TotalMHz / RTL_NUMBER_OF(Samples);
200 DPRINT1("Sampling CPU frequency failed. Using average of %lu MHz\n", CurrentSample[-1].MHz);
201 break;
202 }
203 }
204
205 /* Save the CPU Speed */
206 KeGetCurrentPrcb()->MHz = CurrentSample[-1].MHz;
207 }
208
209 /* Check if we have MTRR */
211 {
212 /* Then manually initialize MTRR for the CPU */
214 }
215
216 /* Check if we have AMD MTRR and initialize it for the CPU */
218
219 /* Check if this is a buggy Pentium and apply the fixup if so */
221
222 /* Check if the CPU supports FXSR */
224 {
225 /* Get the current thread NPX state */
227
228 /* Clear initial MXCsr mask */
229 FxSaveArea->U.FxArea.MXCsrMask = 0;
230
231 /* Save the current NPX State */
232 Ke386SaveFpuState(FxSaveArea);
233
234 /* Check if the current mask doesn't match the reserved bits */
235 if (FxSaveArea->U.FxArea.MXCsrMask != 0)
236 {
237 /* Then use whatever it's holding */
238 MXCsrMask = FxSaveArea->U.FxArea.MXCsrMask;
239 }
240
241 /* Check if nobody set the kernel-wide mask */
242 if (!KiMXCsrMask)
243 {
244 /* Then use the one we calculated above */
245 KiMXCsrMask = MXCsrMask;
246 }
247 else
248 {
249 /* Was it set to the same value we found now? */
250 if (KiMXCsrMask != MXCsrMask)
251 {
252 /* No, something is definitely wrong */
253 KeBugCheckEx(MULTIPROCESSOR_CONFIGURATION_NOT_SUPPORTED,
254 KF_FXSR,
256 MXCsrMask,
257 0);
258 }
259 }
260
261 /* Now set the kernel mask */
262 KiMXCsrMask &= MXCsrMask;
263 }
264 }
265 }
266
267 /* Return affinity back to where it was */
269
270 /* NT allows limiting the duration of an ISR with a registry key */
272 {
273 /* FIXME: TODO */
274 DPRINT1("ISR Time Limit not yet supported\n");
275 }
276
277 /* Set CR0 features based on detected CPU */
278 KiSetCR0Bits();
279}
_In_ PVOID _In_ ULONG _Out_ PVOID _In_ ULONG _Inout_ PULONG ReturnLength
#define RTL_NUMBER_OF(x)
Definition: RtlRegistry.c:12
unsigned char BOOLEAN
Definition: actypes.h:127
LONG NTSTATUS
Definition: precomp.h:26
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:33
#define KeDelayExecutionThread(mode, foo, t)
Definition: env_spec_w32.h:484
Status
Definition: gdiplustypes.h:24
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
LARGE_INTEGER NTAPI KeQueryPerformanceCounter(IN PLARGE_INTEGER PerformanceFreq)
Definition: timer.c:138
#define KeGetCurrentThread
Definition: hal.h:55
#define PCHAR
Definition: match.c:90
#define KF_MTRR
Definition: ketypes.h:37
#define KF_CR4
Definition: ketypes.h:33
FORCEINLINE struct _KPRCB * KeGetCurrentPrcb(VOID)
Definition: ketypes.h:1197
#define KF_AMDK6MTRR
Definition: ketypes.h:46
#define KF_LARGE_PAGE
Definition: ketypes.h:36
#define KF_PAT
Definition: ketypes.h:41
#define KF_GLOBAL_PAGE
Definition: ketypes.h:35
#define KernelMode
Definition: asm.h:38
VOID NTAPI KiInitializePAT(VOID)
Definition: patpge.c:61
ULONG_PTR NTAPI Ki386EnableTargetLargePage(IN ULONG_PTR Context)
Definition: patpge.c:70
VOID NTAPI KiI386PentiumLockErrataFixup(VOID)
Definition: cpu.c:1018
ULONG_PTR NTAPI Ki386EnableXMMIExceptions(IN ULONG_PTR Context)
Definition: cpu.c:995
VOID NTAPI KiAmdK6InitializeMTRR(VOID)
Definition: mtrr.c:31
ULONG_PTR NTAPI Ki386EnableFxsr(IN ULONG_PTR Context)
Definition: cpu.c:985
BOOLEAN NTAPI Ki386CreateIdentityMap(IN PLARGE_IDENTITY_MAP IdentityMap, IN PVOID StartPtr, IN ULONG Length)
VOID NTAPI Ki386EnableCurrentLargePage(IN ULONG_PTR StartAddress, IN ULONG Cr3)
VOID NTAPI KiRestoreFastSyscallReturnState(VOID)
Definition: cpu.c:941
BOOLEAN KiI386PentiumLockErrataPresent
Definition: cpu.c:42
ULONG_PTR NTAPI Ki386EnableGlobalPage(IN ULONG_PTR Context)
Definition: patpge.c:23
VOID NTAPI Ki386FreeIdentityMap(IN PLARGE_IDENTITY_MAP IdentityMap)
ULONG KiMXCsrMask
Definition: cpu.c:30
VOID NTAPI KiInitializeMTRR(IN BOOLEAN FinalCpu)
Definition: mtrr.c:22
VOID NTAPI KiSetCR0Bits(VOID)
Definition: cpu.c:658
FORCEINLINE PFX_SAVE_AREA KiGetThreadNpxArea(IN PKTHREAD Thread)
Definition: ke.h:769
ULONG_PTR NTAPI Ki386EnableDE(IN ULONG_PTR Context)
Definition: cpu.c:975
ULONG KiTimeLimitIsrMicroseconds
Definition: dpc.c:26
KAFFINITY KeActiveProcessors
Definition: processor.c:16
ULONG_PTR NTAPI KeIpiGenericCall(_In_ PKIPI_BROADCAST_WORKER Function, _In_ ULONG_PTR Argument)
Definition: ipi.c:44
CCHAR KeNumberProcessors
Definition: processor.c:19
VOID FASTCALL RtlPrefetchMemoryNonTemporal(IN PVOID Source, IN SIZE_T Length)
Definition: misc.c:214
ULONG MXCsrMask
Definition: ketypes.h:490
union _FX_SAVE_AREA::@2714 U
FXSAVE_FORMAT FxArea
Definition: ketypes.h:502
LARGE_INTEGER PerfEnd
Definition: ke.h:60
LONGLONG PerfDelta
Definition: ke.h:61
LARGE_INTEGER PerfFreq
Definition: ke.h:62
LONGLONG TSCStart
Definition: ke.h:63
LONGLONG TSCEnd
Definition: ke.h:64
ULONG MHz
Definition: ke.h:66
LARGE_INTEGER PerfStart
Definition: ke.h:59
LONGLONG TSCDelta
Definition: ke.h:65
VOID NTAPI KeSetSystemAffinityThread(IN KAFFINITY Affinity)
Definition: thrdobj.c:1107
VOID NTAPI KeRevertToUserAffinityThread(VOID)
Definition: thrdobj.c:1021
LONGLONG QuadPart
Definition: typedefs.h:114
_In_ ULONG _In_ ULONG _In_ ULONG _Out_ PKIRQL _Out_ PKAFFINITY Affinity
Definition: halfuncs.h:174
#define HalQuerySystemInformation
Definition: haltypes.h:304
@ HalFrameBufferCachingInformation
Definition: haltypes.h:37

Referenced by KeInitSystem().

◆ KiMarkPageAsReadOnly()

static VOID KiMarkPageAsReadOnly ( PVOID  Address)
static

Definition at line 717 of file kiinit.c.

719{
720 PHARDWARE_PTE PointerPte;
721
722 /* Make sure the address is page aligned */
724
725 /* Get the PTE address */
726 PointerPte = ((PHARDWARE_PTE)PTE_BASE) + ((ULONG_PTR)Address / PAGE_SIZE);
727 ASSERT(PointerPte->Valid);
728 ASSERT(PointerPte->Write);
729
730 /* Set as read-only */
731 PointerPte->Write = 0;
732
733 /* Flush the TLB entry */
735}
#define PTE_BASE
Definition: winldr.c:20
#define ULONG_PTR
Definition: config.h:101
#define PAGE_SIZE
Definition: env_spec_w32.h:49
__INTRIN_INLINE void __invlpg(void *Address)
Definition: intrin_x86.h:2000
#define ASSERT(a)
Definition: mode.c:44
#define PHARDWARE_PTE
Definition: mmtypes.h:187
static WCHAR Address[46]
Definition: ping.c:68
ULONG64 Write
Definition: mmtypes.h:67
ULONG64 Valid
Definition: mmtypes.h:66
#define ALIGN_DOWN_POINTER_BY(ptr, align)
Definition: umtypes.h:82

Referenced by KiSystemStartup().

◆ KiSystemStartup()

DECLSPEC_NORETURN VOID NTAPI KiSystemStartup ( IN PLOADER_PARAMETER_BLOCK  LoaderBlock)

Definition at line 741 of file kiinit.c.

742{
743 ULONG Cpu;
744 PKTHREAD InitialThread;
745 ULONG InitialStack;
746 PKGDTENTRY Gdt;
747 PKIDTENTRY Idt;
748 KIDTENTRY NmiEntry, DoubleFaultEntry;
749 PKTSS Tss;
750 PKIPCR Pcr;
751 KIRQL DummyIrql;
752
753 /* Boot cycles timestamp */
755
756 /* Save the loader block and get the current CPU */
757 KeLoaderBlock = LoaderBlock;
758 Cpu = KeNumberProcessors;
759 if (!Cpu)
760 {
761 /* If this is the boot CPU, set FS and the CPU Number*/
762 Ke386SetFs(KGDT_R0_PCR);
764
765 /* Set the initial stack and idle thread as well */
766 LoaderBlock->KernelStack = (ULONG_PTR)P0BootStack;
767 LoaderBlock->Thread = (ULONG_PTR)&KiInitialThread;
768 }
769
770 /* Save the initial thread and stack */
771 InitialStack = LoaderBlock->KernelStack;
772 InitialThread = (PKTHREAD)LoaderBlock->Thread;
773
774 /* Clean the APC List Head */
775 InitializeListHead(&InitialThread->ApcState.ApcListHead[KernelMode]);
776
777 /* Initialize the machine type */
779
780 /* Skip initial setup if this isn't the Boot CPU */
781 if (Cpu) goto AppCpuInit;
782
783 /* Get GDT, IDT, PCR and TSS pointers */
784 KiGetMachineBootPointers(&Gdt, &Idt, &Pcr, &Tss);
785
786 /* Setup the TSS descriptors and entries */
787 Ki386InitializeTss(Tss, Idt, Gdt);
788
789 /* Initialize the PCR */
791 KiInitializePcr(Cpu,
792 Pcr,
793 Idt,
794 Gdt,
795 Tss,
796 InitialThread,
798
799 /* Set us as the current process */
800 InitialThread->ApcState.Process = &KiInitialProcess.Pcb;
801
802 /* Clear DR6/7 to cleanup bootloader debugging */
806
807 /* Setup the IDT */
809
810 /* Load Ring 3 selectors for DS/ES */
811 Ke386SetDs(KGDT_R3_DATA | RPL_MASK);
812 Ke386SetEs(KGDT_R3_DATA | RPL_MASK);
813
814 /* Save NMI and double fault traps */
815 RtlCopyMemory(&NmiEntry, &Idt[2], sizeof(KIDTENTRY));
816 RtlCopyMemory(&DoubleFaultEntry, &Idt[8], sizeof(KIDTENTRY));
817
818 /* Copy kernel's trap handlers */
819 RtlCopyMemory(Idt,
822
823 /* Restore NMI and double fault */
824 RtlCopyMemory(&Idt[2], &NmiEntry, sizeof(KIDTENTRY));
825 RtlCopyMemory(&Idt[8], &DoubleFaultEntry, sizeof(KIDTENTRY));
826
827AppCpuInit:
828 //TODO: We don't setup IPIs yet so freeze other processors here.
829 if (Cpu)
830 {
832 LoaderBlock->Prcb = 0;
833
834 for (;;)
835 {
837 }
838 }
839
840 /* Loop until we can release the freeze lock */
841 do
842 {
843 /* Loop until execution can continue */
844 while (*(volatile PKSPIN_LOCK*)&KiFreezeExecutionLock == (PVOID)1);
846
847 /* Setup CPU-related fields */
852
854
855 /* Initialize the Processor with HAL */
857
858 /* Set active processors */
861
862 /* Check if this is the boot CPU */
863 if (!Cpu)
864 {
865 /* Initialize debugging system */
867
868 /* Check for break-in */
870
871 /* Make the lowest page of the boot and double fault stack read-only */
872 KiMarkPageAsReadOnly(P0BootStackData);
873 KiMarkPageAsReadOnly(KiDoubleFaultStackData);
874 }
875
876 /* Raise to HIGH_LEVEL */
877 KeRaiseIrql(HIGH_LEVEL, &DummyIrql);
878
879 /* Switch to new kernel stack and start kernel bootstrapping */
880 KiSwitchToBootStack(InitialStack & ~3);
881}
#define KGDT_R3_DATA
#define RPL_MASK
static VOID KiInitializePcr(_Out_ PKIPCR Pcr, _In_ ULONG ProcessorNumber, _In_ PKGDTENTRY64 GdtBase, _In_ PKIDTENTRY64 IdtBase, _In_ PKTSS64 TssBase, _In_ PKTHREAD IdleThread, _In_ PVOID DpcStack)
Definition: kiinit.c:92
ULONGLONG BootCycles
Definition: kiinit.c:37
VOID KiInitializeMachineType(VOID)
Definition: kiinit.c:309
KSPIN_LOCK * PKSPIN_LOCK
Definition: env_spec_w32.h:73
VOID NTAPI HalInitializeProcessor(IN ULONG ProcessorNumber, IN PLOADER_PARAMETER_BLOCK LoaderBlock)
Definition: processor.c:48
ULONG_PTR P0BootStack
Definition: kiinit.c:21
static VOID KiVerifyCpuFeatures(PKPRCB Prcb)
Definition: kiinit.c:346
VOID FASTCALL KiGetMachineBootPointers(IN PKGDTENTRY *Gdt, IN PKIDTENTRY *Idt, IN PKIPCR *Pcr, IN PKTSS *Tss)
Definition: kiinit.c:646
static VOID KiMarkPageAsReadOnly(PVOID Address)
Definition: kiinit.c:717
ULONG_PTR KiDoubleFaultStack
Definition: kiinit.c:22
#define InterlockedBitTestAndSet
Definition: interlocked.h:30
PPC_QUAL void __writefsdword(const unsigned long Offset, const unsigned long Data)
Definition: intrin_ppc.h:354
PPC_QUAL unsigned long __readfsdword(const unsigned long Offset)
Definition: intrin_ppc.h:382
BOOLEAN NTAPI KdInitSystem(_In_ ULONG BootPhase, _In_opt_ PLOADER_PARAMETER_BLOCK LoaderBlock)
Definition: kdinit.c:164
BOOLEAN NTAPI KdPollBreakIn(VOID)
Definition: kdlock.c:75
#define KPCR_PRCB_SET_MEMBER
Definition: asm.h:182
#define KPCR_TEB
Definition: asm.h:162
#define KPCR_SET_MEMBER_COPY
Definition: asm.h:161
#define KPCR_DR6
Definition: asm.h:186
#define KPCR_PROCESSOR_NUMBER
Definition: asm.h:181
#define KPCR_DR7
Definition: asm.h:187
#define KPCR_NUMBER
Definition: asm.h:175
#define KPCR_SET_MEMBER
Definition: asm.h:174
#define KGDT_R0_PCR
Definition: ketypes.h:128
#define DBG_STATUS_CONTROL_C
Definition: kdtypes.h:39
struct _KTHREAD * PKTHREAD
Definition: nt_native.h:28
DECLSPEC_NORETURN VOID KiSwitchToBootStack(IN ULONG_PTR InitialStack)
Definition: ke.h:925
VOID FASTCALL Ki386InitializeTss(IN PKTSS Tss, IN PKIDTENTRY Idt, IN PKGDTENTRY Gdt)
Definition: cpu.c:729
KDESCRIPTOR KiIdtDescriptor
Definition: except.c:51
EPROCESS KiInitialProcess
Definition: krnlinit.c:41
ETHREAD KiInitialThread
Definition: krnlinit.c:40
VOID NTAPI KeInitExceptions(VOID)
Definition: except.c:59
#define YieldProcessor
Definition: ke.h:48
FORCEINLINE VOID KeMemoryBarrier(VOID)
Definition: ke.h:58
KPROCESS Pcb
Definition: pstypes.h:1369
KPRCB Prcb
Definition: ketypes.h:1003
KAPC_STATE ApcState
Definition: ketypes.h:1925
Definition: ketypes.h:854
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
int32_t * PLONG
Definition: typedefs.h:58
__analysis_noreturn NTSYSAPI VOID NTAPI DbgBreakPointWithStatus(_In_ ULONG Status)

Referenced by KeStartAllProcessors(), and LoadAndBootWindowsCommon().

◆ KiSystemStartupBootStack()

DECLSPEC_NORETURN VOID NTAPI KiSystemStartupBootStack ( VOID  )

Definition at line 688 of file kiinit.c.

689{
691
692 /* Initialize the kernel for the current CPU */
699
700 /* Set the priority of this thread to 0 */
702 Thread->Priority = 0;
703
704 /* Force interrupts enabled and lower IRQL back to DISPATCH_LEVEL */
705 _enable();
707
708 /* Set the right wait IRQL */
709 Thread->WaitIrql = DISPATCH_LEVEL;
710
711 /* Jump into the idle loop */
712 KiIdleLoop();
713}
VOID NTAPI KiInitializeKernel(IN PKPROCESS InitProcess, IN PKTHREAD InitThread, IN PVOID IdleStack, IN PKPRCB Prcb, IN CCHAR Number, IN PLOADER_PARAMETER_BLOCK LoaderBlock)
Definition: kiinit.c:44
_In_opt_ PFILE_OBJECT _In_opt_ PETHREAD Thread
Definition: fltkernel.h:2653
#define KPCR_PRCB
Definition: asm.h:164
DECLSPEC_NORETURN VOID KiIdleLoop(VOID)
Definition: stubs.c:103
void __cdecl _enable(void)
Definition: intrin_arm.h:373
ULONG_PTR KernelStack
Definition: arc.h:831
ULONG_PTR Thread
Definition: arc.h:834

◆ KiVerifyCpuFeatures()

static VOID KiVerifyCpuFeatures ( PKPRCB  Prcb)
static

Definition at line 346 of file kiinit.c.

347{
348 CPU_INFO CpuInfo;
349
350 // 1. Check CPUID support
351 ULONG EFlags = __readeflags();
352
353 /* XOR out the ID bit and update EFlags */
354 ULONG NewEFlags = EFlags ^ EFLAGS_ID;
355 __writeeflags(NewEFlags);
356
357 /* Get them back and see if they were modified */
358 NewEFlags = __readeflags();
359
360 if (NewEFlags == EFlags)
361 {
362 /* The modification did not work, so CPUID is not supported. */
363 KeBugCheckEx(UNSUPPORTED_PROCESSOR, 0x1, 0, 0, 0);
364 }
365 else
366 {
367 /* CPUID is supported. Set the ID Bit again. */
368 EFlags |= EFLAGS_ID;
369 __writeeflags(EFlags);
370 }
371
372 /* Peform CPUID 0 to see if CPUID 1 is supported */
373 KiCpuId(&CpuInfo, 0);
374 if (CpuInfo.Eax == 0)
375 {
376 // 0x1 - missing CPUID instruction
377 KeBugCheckEx(UNSUPPORTED_PROCESSOR, 0x1, 0, 0, 0);
378 }
379
380 // 2. Detect and set the CPU Type
382
383 if (Prcb->CpuType == 3)
384 KeBugCheckEx(UNSUPPORTED_PROCESSOR, 0x386, 0, 0, 0);
385
386 // 3. Finally, obtain CPU features.
387 ULONG64 FeatureBits = KiGetFeatureBits();
388
389 // 4. Verify it supports everything we need.
390 if (!(FeatureBits & KF_RDTSC))
391 {
392 // 0x2 - missing CPUID features
393 // second paramenter - edx flag which is missing
394 KeBugCheckEx(UNSUPPORTED_PROCESSOR, 0x2, 0x00000010, 0, 0);
395 }
396
397 if (!(FeatureBits & KF_CMPXCHG8B))
398 {
399 KeBugCheckEx(UNSUPPORTED_PROCESSOR, 0x2, 0x00000100, 0, 0);
400 }
401
402 // Check x87 FPU is present. FIXME: put this into FeatureBits?
403 KiCpuId(&CpuInfo, 1);
404
405 if (!(CpuInfo.Edx & 0x00000001))
406 {
407 KeBugCheckEx(UNSUPPORTED_PROCESSOR, 0x2, 0x00000001, 0, 0);
408 }
409
410 // Set up FPU-related CR0 flags.
411 ULONG Cr0 = __readcr0();
412 // Disable emulation and monitoring.
413 Cr0 &= ~(CR0_EM | CR0_MP);
414 // Enable FPU exceptions.
415 Cr0 |= CR0_NE;
416
417 __writecr0(Cr0);
418
419 // Check for Pentium FPU bug.
421 {
422 KeBugCheckEx(UNSUPPORTED_PROCESSOR, 0x2, 0x00000001, 0, 0);
423 }
424
425 // 5. Save feature bits.
426 Prcb->FeatureBits = (ULONG)FeatureBits;
427 Prcb->FeatureBitsHigh = FeatureBits >> 32;
428}
__INTRIN_INLINE void __writeeflags(uintptr_t Value)
Definition: intrin_x86.h:1701
__INTRIN_INLINE unsigned long __readcr0(void)
Definition: intrin_x86.h:1836
__INTRIN_INLINE uintptr_t __readeflags(void)
Definition: intrin_x86.h:1706
__INTRIN_INLINE void __writecr0(unsigned int Data)
Definition: intrin_x86.h:1821
#define CR0_NE
Definition: ketypes.h:144
#define CR0_MP
Definition: ketypes.h:140
#define CR0_EM
Definition: ketypes.h:141
#define EFLAGS_ID
Definition: ketypes.h:211
ULONG64 KiGetFeatureBits(VOID)
Evaluates the KeFeatureFlag bits for the current CPU.
Definition: cpu.c:73
VOID KiSetProcessorType(VOID)
Definition: cpu.c:40
BOOLEAN NTAPI KiIsNpxErrataPresent(VOID)
Definition: cpu.c:1089
CHAR CpuType
Definition: ketypes.h:684
ULONG FeatureBits
Definition: ketypes.h:903
ULONG Eax
Definition: ketypes.h:401
ULONG Edx
Definition: ketypes.h:404

Referenced by KiSystemStartup().

Variable Documentation

◆ BootCycles

ULONGLONG BootCycles

Definition at line 30 of file kiinit.c.

Referenced by Ki386PerfEnd().

◆ BootCyclesEnd

ULONGLONG BootCyclesEnd

Definition at line 30 of file kiinit.c.

◆ Ki486CompatibilityLock

KSPIN_LOCK Ki486CompatibilityLock

Definition at line 26 of file kiinit.c.

Referenced by KiInitializeKernel().

◆ KiDoubleFaultStack

ULONG_PTR KiDoubleFaultStack = (ULONG_PTR)&KiDoubleFaultStackData[KERNEL_STACK_SIZE]

Definition at line 22 of file kiinit.c.

Referenced by Ki386InitializeTss(), and KiSystemStartup().

◆ KiFreezeExecutionLock

KSPIN_LOCK KiFreezeExecutionLock

Definition at line 25 of file kiinit.c.

◆ P0BootStack

ULONG_PTR P0BootStack = (ULONG_PTR)&P0BootStackData[KERNEL_STACK_SIZE]

Definition at line 21 of file kiinit.c.

Referenced by KiSystemStartup().

◆ ProcessCount

ULONG ProcessCount

Definition at line 29 of file kiinit.c.