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 /* FUNCTIONS *****************************************************************/
25 KiInitializePcr(IN ULONG ProcessorNumber
,
30 IN PKTHREAD IdleThread
,
34 Pcr
->NtTib
.ExceptionList
= EXCEPTION_CHAIN_END
;
35 Pcr
->NtTib
.StackBase
= 0;
36 Pcr
->NtTib
.StackLimit
= 0;
39 /* Set the Current Thread */
40 //Pcr->PrcbData.CurrentThread = IdleThread;
42 /* Set pointers to ourselves */
43 Pcr
->Self
= (PKPCR
)Pcr
;
44 Pcr
->Prcb
= &Pcr
->PrcbData
;
46 /* Set the PCR Version */
47 Pcr
->MajorVersion
= PCR_MAJOR_VERSION
;
48 Pcr
->MinorVersion
= PCR_MINOR_VERSION
;
50 /* Set the PCRB Version */
51 Pcr
->PrcbData
.MajorVersion
= 1;
52 Pcr
->PrcbData
.MinorVersion
= 1;
54 /* Set the Build Type */
55 Pcr
->PrcbData
.BuildType
= 0;
57 /* Set the Processor Number and current Processor Mask */
58 Pcr
->PrcbData
.Number
= (UCHAR
)ProcessorNumber
;
59 Pcr
->PrcbData
.SetMember
= 1 << ProcessorNumber
;
61 /* Set the PRCB for this Processor */
62 KiProcessorBlock
[ProcessorNumber
] = Pcr
->Prcb
;
64 /* Start us out at PASSIVE_LEVEL */
65 Pcr
->Irql
= PASSIVE_LEVEL
;
67 /* Set the GDI, IDT, TSS and DPC Stack */
68 Pcr
->GDT
= (PVOID
)Gdt
;
71 Pcr
->PrcbData
.DpcStack
= DpcStack
;
76 KiInitializeKernel(IN PKPROCESS InitProcess
,
77 IN PKTHREAD InitThread
,
81 IN PROS_LOADER_PARAMETER_BLOCK LoaderBlock
)
85 LARGE_INTEGER PageDirectory
;
88 /* Detect and set the CPU Type */
91 /* Set CR0 features based on detected CPU */
94 /* Check if an FPU is present */
95 NpxPresent
= KiIsNpxPresent();
97 /* Initialize the Power Management Support for this PRCB */
98 PoInitializePrcb(Prcb
);
100 /* Bugcheck if this is a 386 CPU */
101 if (Prcb
->CpuType
== 3) KeBugCheckEx(0x5D, 0x386, 0, 0, 0);
103 /* Get the processor features for the CPU */
104 FeatureBits
= KiGetFeatureBits();
106 /* Save feature bits */
107 Prcb
->FeatureBits
= FeatureBits
;
109 /* Get cache line information for this CPU */
110 KiGetCacheInformation();
112 /* Initialize spinlocks and DPC data */
113 KiInitSpinLocks(Prcb
, Number
);
115 /* Check if this is the Boot CPU */
119 KeNodeBlock
[0] = &KiNode0
;
120 Prcb
->ParentNode
= KeNodeBlock
[0];
121 KeNodeBlock
[0]->ProcessorMask
= Prcb
->SetMember
;
123 /* Set boot-level flags */
124 KeI386NpxPresent
= NpxPresent
;
125 KeI386CpuType
= Prcb
->CpuType
;
126 KeI386CpuStep
= Prcb
->CpuStep
;
127 KeProcessorArchitecture
= 0;
128 KeProcessorLevel
= (USHORT
)Prcb
->CpuType
;
129 if (Prcb
->CpuID
) KeProcessorRevision
= Prcb
->CpuStep
;
130 KeFeatureBits
= FeatureBits
;
131 KeI386FxsrPresent
= (KeFeatureBits
& KF_FXSR
) ? TRUE
: FALSE
;
132 KeI386XMMIPresent
= (KeFeatureBits
& KF_XMMI
) ? TRUE
: FALSE
;
134 /* Set the current MP Master KPRCB to the Boot PRCB */
135 Prcb
->MultiThreadSetMaster
= Prcb
;
137 /* Initialize some spinlocks */
138 KeInitializeSpinLock(&KiFreezeExecutionLock
);
139 KeInitializeSpinLock(&Ki486CompatibilityLock
);
141 /* Initialize portable parts of the OS */
144 /* Initialize the Idle Process and the Process Listhead */
145 InitializeListHead(&KiProcessListHead
);
146 PageDirectory
.QuadPart
= 0;
147 KeInitializeProcess(InitProcess
,
152 InitProcess
->QuantumReset
= MAXCHAR
;
157 DPRINT1("SMP Boot support not yet present\n");
161 /* Setup the Idle Thread */
162 KeInitializeThread(InitProcess
,
171 InitThread
->NextProcessor
= Number
;
172 InitThread
->Priority
= HIGH_PRIORITY
;
173 InitThread
->State
= Running
;
174 InitThread
->Affinity
= 1 << Number
;
175 InitThread
->WaitIrql
= DISPATCH_LEVEL
;
176 InitProcess
->ActiveProcessors
= 1 << Number
;
178 /* Set up the thread-related fields in the PRCB */
179 //Prcb->CurrentThread = InitThread;
180 Prcb
->NextThread
= NULL
;
181 //Prcb->IdleThread = InitThread;
183 /* Initialize the Kernel Executive */
184 ExpInitializeExecutive();
186 /* Only do this on the boot CPU */
189 /* Calculate the time reciprocal */
190 KiTimeIncrementReciprocal
=
191 KiComputeReciprocal(KeMaximumIncrement
,
192 &KiTimeIncrementShiftCount
);
194 /* Update DPC Values in case they got updated by the executive */
195 Prcb
->MaximumDpcQueueDepth
= KiMaximumDpcQueueDepth
;
196 Prcb
->MinimumDpcRate
= KiMinimumDpcRate
;
197 Prcb
->AdjustDpcThreshold
= KiAdjustDpcThreshold
;
199 /* Allocate the DPC Stack */
200 DpcStack
= MmCreateKernelStack(FALSE
);
201 if (!DpcStack
) KeBugCheckEx(NO_PAGES_AVAILABLE
, 1, 0, 0, 0);
202 Prcb
->DpcStack
= DpcStack
;
204 /* Allocate the IOPM save area. */
205 Ki386IopmSaveArea
= ExAllocatePoolWithTag(PagedPool
,
207 TAG('K', 'e', ' ', ' '));
208 if (!Ki386IopmSaveArea
)
210 /* Bugcheck. We need this for V86/VDM support. */
211 KeBugCheckEx(NO_PAGES_AVAILABLE
, 2, PAGE_SIZE
* 2, 0, 0);
215 /* Free Initial Memory */
220 LARGE_INTEGER Timeout
;
221 Timeout
.QuadPart
= 0x7fffffffffffffffLL
;
222 KeDelayExecutionThread(KernelMode
, FALSE
, &Timeout
);
225 /* Bug Check and loop forever if anything failed */
232 KiSystemStartup(IN PROS_LOADER_PARAMETER_BLOCK LoaderBlock
)
235 PKIPCR Pcr
= (PKIPCR
)KPCR_BASE
;
238 /* Save the loader block and get the current CPU */
239 //KeLoaderBlock = LoaderBlock;
240 Cpu
= KeNumberProcessors
;
243 /* If this is the boot CPU, set FS and the CPU Number*/
244 Ke386SetFs(KGDT_R0_PCR
);
245 KeGetPcr()->Number
= Cpu
;
248 /* Skip initial setup if this isn't the Boot CPU */
249 if (Cpu
) goto AppCpuInit
;
251 /* Setup the boot (Freeldr should've done), double fault and NMI TSS */
252 Ki386InitializeTss();
254 /* Initialize the PCR */
255 RtlZeroMemory(Pcr
, PAGE_SIZE
);
261 &KiInitialThread
.Tcb
,
264 /* Set us as the current process */
265 KiInitialThread
.Tcb
.ApcState
.Process
= &KiInitialProcess
.Pcb
;
267 /* Clear DR6/7 to cleanup bootloader debugging */
268 Pcr
->PrcbData
.ProcessorState
.SpecialRegisters
.KernelDr6
= 0;
269 Pcr
->PrcbData
.ProcessorState
.SpecialRegisters
.KernelDr7
= 0;
271 /* Load Ring 3 selectors for DS/ES */
272 Ke386SetDs(KGDT_R3_DATA
| RPL_MASK
);
273 Ke386SetEs(KGDT_R3_DATA
| RPL_MASK
);
275 /* Setup CPU-related fields */
279 Pcr
->SetMember
= 1 << Cpu
;
280 Pcr
->SetMemberCopy
= 1 << Cpu
;
281 Prcb
->SetMember
= 1 << Cpu
;
283 /* Initialize the Processor with HAL */
284 HalInitializeProcessor(Cpu
, (PLOADER_PARAMETER_BLOCK
)&KeLoaderBlock
);
286 /* Set active processors */
287 KeActiveProcessors
|= Pcr
->SetMember
;
288 KeNumberProcessors
++;
290 /* Initialize the Debugger for the Boot CPU */
291 if (!Cpu
) KdInitSystem (0, &KeLoaderBlock
);
293 /* Check for break-in */
294 if (KdPollBreakIn()) DbgBreakPointWithStatus(1);
296 /* Raise to HIGH_LEVEL */
297 KfRaiseIrql(HIGH_LEVEL
);
299 /* Call main kernel intialization */
300 KiInitializeKernel(&KiInitialProcess
.Pcb
,
301 &KiInitialThread
.Tcb
,