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
;
34 PFX_SAVE_AREA FxSaveArea
;
35 ULONG MXCsrMask
= 0xFFBF, NewMask
;
37 /* Check for large page support */
38 if (KeFeatureBits
& KF_LARGE_PAGE
)
40 /* FIXME: Support this */
41 DPRINT1("Your machine supports PGE but ReactOS doesn't yet.\n");
44 /* Check for global page support */
45 if (KeFeatureBits
& KF_GLOBAL_PAGE
)
47 /* Do an IPI to enable it on all CPUs */
48 CpuCount
= KeNumberProcessors
;
49 KeIpiGenericCall(Ki386EnableGlobalPage
, (ULONG_PTR
)&CpuCount
);
52 /* Check for PAT and/or MTRR support */
53 if (KeFeatureBits
& (KF_PAT
| KF_MTRR
))
55 /* Query the HAL to make sure we can use it */
56 Status
= HalQuerySystemInformation(HalFrameBufferCachingInformation
,
60 if ((NT_SUCCESS(Status
)) && (FbCaching
))
62 /* We can't, disable it */
63 KeFeatureBits
&= ~(KF_PAT
| KF_MTRR
);
67 /* Check for PAT support and enable it */
68 if (KeFeatureBits
& KF_PAT
) KiInitializePAT();
70 /* Assume no errata for now */
71 SharedUserData
->ProcessorFeatures
[PF_FLOATING_POINT_PRECISION_ERRATA
] = 0;
73 /* If there's no NPX, then we're emulating the FPU */
74 SharedUserData
->ProcessorFeatures
[PF_FLOATING_POINT_EMULATED
] =
77 /* Check if there's no NPX, so that we can disable associated features */
78 if (!KeI386NpxPresent
)
80 /* Remove NPX-related bits */
81 KeFeatureBits
&= ~(KF_XMMI64
| KF_XMMI
| KF_FXSR
| KF_MMX
);
83 /* Disable kernel flags */
84 KeI386FxsrPresent
= KeI386XMMIPresent
= FALSE
;
86 /* Disable processor features that might've been set until now */
87 SharedUserData
->ProcessorFeatures
[PF_FLOATING_POINT_PRECISION_ERRATA
] =
88 SharedUserData
->ProcessorFeatures
[PF_XMMI64_INSTRUCTIONS_AVAILABLE
] =
89 SharedUserData
->ProcessorFeatures
[PF_XMMI_INSTRUCTIONS_AVAILABLE
] =
90 SharedUserData
->ProcessorFeatures
[PF_3DNOW_INSTRUCTIONS_AVAILABLE
] =
91 SharedUserData
->ProcessorFeatures
[PF_MMX_INSTRUCTIONS_AVAILABLE
] = 0;
94 /* Check for CR4 support */
95 if (KeFeatureBits
& KF_CR4
)
97 /* Do an IPI call to enable the Debug Exceptions */
98 CpuCount
= KeNumberProcessors
;
99 KeIpiGenericCall(Ki386EnableDE
, (ULONG_PTR
)&CpuCount
);
102 /* Check if FXSR was found */
103 if (KeFeatureBits
& KF_FXSR
)
105 /* Do an IPI call to enable the FXSR */
106 CpuCount
= KeNumberProcessors
;
107 KeIpiGenericCall(Ki386EnableFxsr
, (ULONG_PTR
)&CpuCount
);
109 /* Check if XMM was found too */
110 if (KeFeatureBits
& KF_XMMI
)
112 /* Do an IPI call to enable XMMI exceptions */
113 CpuCount
= KeNumberProcessors
;
114 KeIpiGenericCall(Ki386EnableXMMIExceptions
, (ULONG_PTR
)&CpuCount
);
116 /* FIXME: Implement and enable XMM Page Zeroing for Mm */
118 /* Patch the RtlPrefetchMemoryNonTemporal routine to enable it */
119 Protect
= MmGetPageProtect(NULL
, RtlPrefetchMemoryNonTemporal
);
120 MmSetPageProtect(NULL
,
121 RtlPrefetchMemoryNonTemporal
,
122 Protect
| PAGE_IS_WRITABLE
);
123 *(PCHAR
)RtlPrefetchMemoryNonTemporal
= 0x90;
124 MmSetPageProtect(NULL
, RtlPrefetchMemoryNonTemporal
, Protect
);
128 /* Check for, and enable SYSENTER support */
129 KiRestoreFastSyscallReturnState();
132 i
= KeActiveProcessors
;
133 for (Affinity
= 1; i
; Affinity
<<= 1)
135 /* Check if this is part of the set */
138 /* Run on this CPU */
140 KeSetSystemAffinityThread(Affinity
);
142 /* Reset MHz to 0 for this CPU */
143 KeGetCurrentPrcb()->MHz
= 0;
145 /* Check if we can use RDTSC */
146 if (KeFeatureBits
& KF_RDTSC
)
148 /* Start sampling loop */
158 /* Check if we have MTRR without PAT */
159 if (!(KeFeatureBits
& KF_PAT
) && (KeFeatureBits
& KF_MTRR
))
161 /* Then manually initialize MTRR for the CPU */
162 KiInitializeMTRR((BOOLEAN
)i
);
165 /* Check if we have AMD MTRR and initialize it for the CPU */
166 if (KeFeatureBits
& KF_AMDK6MTRR
) KiAmdK6InitializeMTRR();
168 /* Check if this is a buggy Pentium and apply the fixup if so */
169 if (KiI386PentiumLockErrataPresent
) KiI386PentiumLockErrataFixup();
171 /* Get the current thread NPX state */
173 ((ULONG_PTR
)KeGetCurrentThread()->InitialStack
-
176 /* Clear initial MXCsr mask */
177 FxSaveArea
->U
.FxArea
.MXCsrMask
= 0;
179 /* Save the current NPX State */
181 asm volatile("fxsave %0\n\t" : "=m" (*FxSaveArea
));
183 __asm fxsave
[FxSaveArea
]
185 /* Check if the current mask doesn't match the reserved bits */
186 if (FxSaveArea
->U
.FxArea
.MXCsrMask
!= MXCsrMask
)
188 /* Then use whatever it's holding */
189 MXCsrMask
= FxSaveArea
->U
.FxArea
.MXCsrMask
;
192 /* Check if nobody set the kernel-wide mask */
195 /* Then use the one we calculated above */
200 /* Use the existing mask */
201 NewMask
= KiMXCsrMask
;
203 /* Was it set to the same value we found now? */
204 if (NewMask
!= MXCsrMask
)
206 /* No, something is definitely wrong */
207 KEBUGCHECKEX(MULTIPROCESSOR_CONFIGURATION_NOT_SUPPORTED
,
215 /* Now set the kernel mask */
216 KiMXCsrMask
= NewMask
& MXCsrMask
;
220 /* Return affinity back to where it was */
221 KeRevertToUserAffinityThread();
223 /* NT allows limiting the duration of an ISR with a registry key */
224 if (KiTimeLimitIsrMicroseconds
)
227 DPRINT1("ISR Time Limit not yet supported\n");
233 KiInitializePcr(IN ULONG ProcessorNumber
,
238 IN PKTHREAD IdleThread
,
242 Pcr
->NtTib
.ExceptionList
= EXCEPTION_CHAIN_END
;
243 Pcr
->NtTib
.StackBase
= 0;
244 Pcr
->NtTib
.StackLimit
= 0;
247 /* Set the Current Thread */
248 Pcr
->PrcbData
.CurrentThread
= IdleThread
;
250 /* Set pointers to ourselves */
251 Pcr
->Self
= (PKPCR
)Pcr
;
252 Pcr
->Prcb
= &Pcr
->PrcbData
;
254 /* Set the PCR Version */
255 Pcr
->MajorVersion
= PCR_MAJOR_VERSION
;
256 Pcr
->MinorVersion
= PCR_MINOR_VERSION
;
258 /* Set the PCRB Version */
259 Pcr
->PrcbData
.MajorVersion
= 1;
260 Pcr
->PrcbData
.MinorVersion
= 1;
262 /* Set the Build Type */
263 Pcr
->PrcbData
.BuildType
= 0;
265 Pcr
->PrcbData
.BuildType
|= PRCB_BUILD_UNIPROCESSOR
;
268 Pcr
->PrcbData
.BuildType
|= PRCB_BUILD_DEBUG
;
271 /* Set the Processor Number and current Processor Mask */
272 Pcr
->PrcbData
.Number
= (UCHAR
)ProcessorNumber
;
273 Pcr
->PrcbData
.SetMember
= 1 << ProcessorNumber
;
275 /* Set the PRCB for this Processor */
276 KiProcessorBlock
[ProcessorNumber
] = Pcr
->Prcb
;
278 /* Start us out at PASSIVE_LEVEL */
279 Pcr
->Irql
= PASSIVE_LEVEL
;
281 /* Set the GDI, IDT, TSS and DPC Stack */
282 Pcr
->GDT
= (PVOID
)Gdt
;
285 Pcr
->PrcbData
.DpcStack
= DpcStack
;
290 KiInitializeKernel(IN PKPROCESS InitProcess
,
291 IN PKTHREAD InitThread
,
295 IN PLOADER_PARAMETER_BLOCK LoaderBlock
)
299 LARGE_INTEGER PageDirectory
;
301 ULONG NXSupportPolicy
;
303 /* Detect and set the CPU Type */
304 KiSetProcessorType();
306 /* Set CR0 features based on detected CPU */
309 /* Check if an FPU is present */
310 NpxPresent
= KiIsNpxPresent();
312 /* Initialize the Power Management Support for this PRCB */
313 PoInitializePrcb(Prcb
);
315 /* Bugcheck if this is a 386 CPU */
316 if (Prcb
->CpuType
== 3) KeBugCheckEx(0x5D, 0x386, 0, 0, 0);
318 /* Get the processor features for the CPU */
319 FeatureBits
= KiGetFeatureBits();
321 /* Set the default NX policy (opt-in) */
324 /* Check if NPX is always on */
325 if (strstr(KeLoaderBlock
->LoadOptions
, "NOEXECUTE=ALWAYSON"))
327 /* Set it always on */
329 FeatureBits
|= KF_NX_ENABLED
;
331 else if (strstr(KeLoaderBlock
->LoadOptions
, "NOEXECUTE=OPTOUT"))
333 /* Set it in opt-out mode */
335 FeatureBits
|= KF_NX_ENABLED
;
337 else if ((strstr(KeLoaderBlock
->LoadOptions
, "NOEXECUTE=OPTIN")) ||
338 (strstr(KeLoaderBlock
->LoadOptions
, "NOEXECUTE")))
340 /* Set the feature bits */
341 FeatureBits
|= KF_NX_ENABLED
;
343 else if ((strstr(KeLoaderBlock
->LoadOptions
, "NOEXECUTE=ALWAYSOFF")) ||
344 (strstr(KeLoaderBlock
->LoadOptions
, "EXECUTE")))
346 /* Set disabled mode */
348 FeatureBits
|= KF_NX_DISABLED
;
351 /* Save feature bits */
352 Prcb
->FeatureBits
= FeatureBits
;
355 KiSaveProcessorControlState(&Prcb
->ProcessorState
);
357 /* Get cache line information for this CPU */
358 KiGetCacheInformation();
360 /* Initialize spinlocks and DPC data */
361 KiInitSpinLocks(Prcb
, Number
);
363 /* Check if this is the Boot CPU */
367 KeNodeBlock
[0] = &KiNode0
;
368 Prcb
->ParentNode
= KeNodeBlock
[0];
369 KeNodeBlock
[0]->ProcessorMask
= Prcb
->SetMember
;
371 /* Set boot-level flags */
372 KeI386NpxPresent
= NpxPresent
;
373 KeI386CpuType
= Prcb
->CpuType
;
374 KeI386CpuStep
= Prcb
->CpuStep
;
375 KeProcessorArchitecture
= 0;
376 KeProcessorLevel
= (USHORT
)Prcb
->CpuType
;
377 if (Prcb
->CpuID
) KeProcessorRevision
= Prcb
->CpuStep
;
378 KeFeatureBits
= FeatureBits
;
379 KeI386FxsrPresent
= (KeFeatureBits
& KF_FXSR
) ? TRUE
: FALSE
;
380 KeI386XMMIPresent
= (KeFeatureBits
& KF_XMMI
) ? TRUE
: FALSE
;
382 /* Set the current MP Master KPRCB to the Boot PRCB */
383 Prcb
->MultiThreadSetMaster
= Prcb
;
385 /* Lower to APC_LEVEL */
386 KfLowerIrql(APC_LEVEL
);
388 /* Initialize some spinlocks */
389 KeInitializeSpinLock(&KiFreezeExecutionLock
);
390 KeInitializeSpinLock(&Ki486CompatibilityLock
);
392 /* Initialize portable parts of the OS */
395 /* Initialize the Idle Process and the Process Listhead */
396 InitializeListHead(&KiProcessListHead
);
397 PageDirectory
.QuadPart
= 0;
398 KeInitializeProcess(InitProcess
,
403 InitProcess
->QuantumReset
= MAXCHAR
;
408 DPRINT1("SMP Boot support not yet present\n");
411 /* Setup the Idle Thread */
412 KeInitializeThread(InitProcess
,
420 InitThread
->NextProcessor
= Number
;
421 InitThread
->Priority
= HIGH_PRIORITY
;
422 InitThread
->State
= Running
;
423 InitThread
->Affinity
= 1 << Number
;
424 InitThread
->WaitIrql
= DISPATCH_LEVEL
;
425 InitProcess
->ActiveProcessors
= 1 << Number
;
427 /* HACK for MmUpdatePageDir */
428 ((PETHREAD
)InitThread
)->ThreadsProcess
= (PEPROCESS
)InitProcess
;
430 /* Initialize Kernel Memory Address Space */
431 MmInit1(MmFreeLdrFirstKrnlPhysAddr
,
432 MmFreeLdrLastKrnlPhysAddr
,
433 MmFreeLdrLastKernelAddress
,
438 /* Sets up the Text Sections of the Kernel and HAL for debugging */
441 /* Set the NX Support policy */
442 SharedUserData
->NXSupportPolicy
= (UCHAR
)NXSupportPolicy
;
444 /* Set basic CPU Features that user mode can read */
445 SharedUserData
->ProcessorFeatures
[PF_MMX_INSTRUCTIONS_AVAILABLE
] =
446 (KeFeatureBits
& KF_MMX
) ? TRUE
: FALSE
;
447 SharedUserData
->ProcessorFeatures
[PF_COMPARE_EXCHANGE_DOUBLE
] =
448 (KeFeatureBits
& KF_CMPXCHG8B
) ? TRUE
: FALSE
;
449 SharedUserData
->ProcessorFeatures
[PF_XMMI_INSTRUCTIONS_AVAILABLE
] =
450 ((KeFeatureBits
& KF_FXSR
) && (KeFeatureBits
& KF_XMMI
)) ? TRUE
: FALSE
;
451 SharedUserData
->ProcessorFeatures
[PF_XMMI64_INSTRUCTIONS_AVAILABLE
] =
452 ((KeFeatureBits
& KF_FXSR
) && (KeFeatureBits
& KF_XMMI64
)) ? TRUE
: FALSE
;
453 SharedUserData
->ProcessorFeatures
[PF_3DNOW_INSTRUCTIONS_AVAILABLE
] =
454 (KeFeatureBits
& KF_3DNOW
) ? TRUE
: FALSE
;
455 SharedUserData
->ProcessorFeatures
[PF_RDTSC_INSTRUCTION_AVAILABLE
] =
456 (KeFeatureBits
& KF_RDTSC
) ? TRUE
: FALSE
;
458 /* Set up the thread-related fields in the PRCB */
459 Prcb
->CurrentThread
= InitThread
;
460 Prcb
->NextThread
= NULL
;
461 Prcb
->IdleThread
= InitThread
;
463 /* Initialize the Kernel Executive */
464 ExpInitializeExecutive(Number
, LoaderBlock
);
466 /* Only do this on the boot CPU */
469 /* Calculate the time reciprocal */
470 KiTimeIncrementReciprocal
=
471 KiComputeReciprocal(KeMaximumIncrement
,
472 &KiTimeIncrementShiftCount
);
474 /* Update DPC Values in case they got updated by the executive */
475 Prcb
->MaximumDpcQueueDepth
= KiMaximumDpcQueueDepth
;
476 Prcb
->MinimumDpcRate
= KiMinimumDpcRate
;
477 Prcb
->AdjustDpcThreshold
= KiAdjustDpcThreshold
;
479 /* Allocate the DPC Stack */
480 DpcStack
= MmCreateKernelStack(FALSE
);
481 if (!DpcStack
) KeBugCheckEx(NO_PAGES_AVAILABLE
, 1, 0, 0, 0);
482 Prcb
->DpcStack
= DpcStack
;
484 /* Allocate the IOPM save area. */
485 Ki386IopmSaveArea
= ExAllocatePoolWithTag(PagedPool
,
487 TAG('K', 'e', ' ', ' '));
488 if (!Ki386IopmSaveArea
)
490 /* Bugcheck. We need this for V86/VDM support. */
491 KeBugCheckEx(NO_PAGES_AVAILABLE
, 2, PAGE_SIZE
* 2, 0, 0);
495 /* Raise to Dispatch */
496 KfRaiseIrql(DISPATCH_LEVEL
);
498 /* Set the Idle Priority to 0. This will jump into Phase 1 */
499 KeSetPriorityThread(InitThread
, 0);
501 /* If there's no thread scheduled, put this CPU in the Idle summary */
502 if (!Prcb
->NextThread
) KiIdleSummary
|= 1 << Number
;
504 /* Raise back to HIGH_LEVEL and clear the PRCB for the loader block */
505 KfRaiseIrql(HIGH_LEVEL
);
506 LoaderBlock
->Prcb
= 0;
511 KiGetMachineBootPointers(IN PKGDTENTRY
*Gdt
,
516 KDESCRIPTOR GdtDescriptor
, IdtDescriptor
;
517 KGDTENTRY TssSelector
, PcrSelector
;
520 /* Get GDT and IDT descriptors */
521 Ke386GetGlobalDescriptorTable(GdtDescriptor
);
522 Ke386GetInterruptDescriptorTable(IdtDescriptor
);
524 /* Save IDT and GDT */
525 *Gdt
= (PKGDTENTRY
)GdtDescriptor
.Base
;
526 *Idt
= (PKIDTENTRY
)IdtDescriptor
.Base
;
528 /* Get TSS and FS Selectors */
530 if (Tr
!= KGDT_TSS
) Tr
= KGDT_TSS
; // FIXME: HACKHACK
533 /* Get PCR Selector, mask it and get its GDT Entry */
534 PcrSelector
= *(PKGDTENTRY
)((ULONG_PTR
)*Gdt
+ (Fs
& ~RPL_MASK
));
536 /* Get the KPCR itself */
537 *Pcr
= (PKIPCR
)(ULONG_PTR
)(PcrSelector
.BaseLow
|
538 PcrSelector
.HighWord
.Bytes
.BaseMid
<< 16 |
539 PcrSelector
.HighWord
.Bytes
.BaseHi
<< 24);
541 /* Get TSS Selector, mask it and get its GDT Entry */
542 TssSelector
= *(PKGDTENTRY
)((ULONG_PTR
)*Gdt
+ (Tr
& ~RPL_MASK
));
544 /* Get the KTSS itself */
545 *Tss
= (PKTSS
)(ULONG_PTR
)(TssSelector
.BaseLow
|
546 TssSelector
.HighWord
.Bytes
.BaseMid
<< 16 |
547 TssSelector
.HighWord
.Bytes
.BaseHi
<< 24);
552 KiSystemStartup(IN PLOADER_PARAMETER_BLOCK LoaderBlock
)
555 PKTHREAD InitialThread
;
562 /* Save the loader block and get the current CPU */
563 KeLoaderBlock
= LoaderBlock
;
564 Cpu
= KeNumberProcessors
;
567 /* If this is the boot CPU, set FS and the CPU Number*/
568 Ke386SetFs(KGDT_R0_PCR
);
569 __writefsdword(KPCR_PROCESSOR_NUMBER
, Cpu
);
571 /* Set the initial stack and idle thread as well */
572 LoaderBlock
->KernelStack
= (ULONG_PTR
)P0BootStack
;
573 LoaderBlock
->Thread
= (ULONG_PTR
)&KiInitialThread
;
576 /* Save the initial thread and stack */
577 InitialStack
= LoaderBlock
->KernelStack
;
578 InitialThread
= (PKTHREAD
)LoaderBlock
->Thread
;
580 /* Clean the APC List Head */
581 InitializeListHead(&InitialThread
->ApcState
.ApcListHead
[KernelMode
]);
583 /* Initialize the machine type */
584 KiInitializeMachineType();
586 /* Skip initial setup if this isn't the Boot CPU */
587 if (Cpu
) goto AppCpuInit
;
589 /* Get GDT, IDT, PCR and TSS pointers */
590 KiGetMachineBootPointers(&Gdt
, &Idt
, &Pcr
, &Tss
);
592 /* Setup the TSS descriptors and entries */
593 Ki386InitializeTss(Tss
, Idt
, Gdt
);
595 /* Initialize the PCR */
596 RtlZeroMemory(Pcr
, PAGE_SIZE
);
605 /* Set us as the current process */
606 InitialThread
->ApcState
.Process
= &KiInitialProcess
.Pcb
;
608 /* Clear DR6/7 to cleanup bootloader debugging */
609 __writefsdword(KPCR_TEB
, 0);
610 __writefsdword(KPCR_DR6
, 0);
611 __writefsdword(KPCR_DR7
, 0);
616 /* Load Ring 3 selectors for DS/ES */
617 Ke386SetDs(KGDT_R3_DATA
| RPL_MASK
);
618 Ke386SetEs(KGDT_R3_DATA
| RPL_MASK
);
621 /* Loop until we can release the freeze lock */
624 /* Loop until execution can continue */
625 while ((volatile KSPIN_LOCK
)KiFreezeExecutionLock
== 1);
626 } while(InterlockedBitTestAndSet((PLONG
)&KiFreezeExecutionLock
, 0));
628 /* Setup CPU-related fields */
629 __writefsdword(KPCR_NUMBER
, Cpu
);
630 __writefsdword(KPCR_SET_MEMBER
, 1 << Cpu
);
631 __writefsdword(KPCR_SET_MEMBER_COPY
, 1 << Cpu
);
632 __writefsdword(KPCR_PRCB_SET_MEMBER
, 1 << Cpu
);
634 /* Initialize the Processor with HAL */
635 HalInitializeProcessor(Cpu
, KeLoaderBlock
);
637 /* Set active processors */
638 KeActiveProcessors
|= __readfsdword(KPCR_SET_MEMBER
);
639 KeNumberProcessors
++;
641 /* Check if this is the boot CPU */
644 /* Initialize debugging system */
645 KdInitSystem(0, KeLoaderBlock
);
647 /* Check for break-in */
648 if (KdPollBreakIn()) DbgBreakPointWithStatus(1);
651 /* Raise to HIGH_LEVEL */
652 KfRaiseIrql(HIGH_LEVEL
);
654 /* Align stack and make space for the trap frame and NPX frame */
655 InitialStack
&= ~KTRAP_FRAME_ALIGN
;
657 __asm__
__volatile__("movl %0,%%esp" : :"r" (InitialStack
));
658 __asm__
__volatile__("subl %0,%%esp" : :"r" (NPX_FRAME_LENGTH
+
661 __asm__
__volatile__("push %0" : :"r" (CR0_EM
+ CR0_TS
+ CR0_MP
));
663 __asm mov esp
, InitialStack
;
664 __asm sub esp
, NPX_FRAME_LENGTH
+ KTRAP_FRAME_ALIGN
+ KTRAP_FRAME_LENGTH
;
665 __asm push CR0_EM
+ CR0_TS
+ CR0_MP
668 /* Call main kernel initialization */
669 KiInitializeKernel(&KiInitialProcess
.Pcb
,
672 (PKPRCB
)__readfsdword(KPCR_PRCB
),
676 /* Set the priority of this thread to 0 */
677 KeGetCurrentThread()->Priority
= 0;
679 /* Force interrupts enabled and lower IRQL back to DISPATCH_LEVEL */
681 KfLowerIrql(DISPATCH_LEVEL
);
683 /* Set the right wait IRQL */
684 KeGetCurrentThread()->WaitIrql
= DISPATCH_LEVEL
;
686 /* Set idle thread as running on UP builds */
688 KeGetCurrentThread()->State
= Running
;
691 /* Jump into the idle loop */