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