3 * LICENSE: GNU GPL - See COPYING in the top level directory
4 * FILE: hal/halx86/generic/apic.c
5 * PURPOSE: HAL APIC Management and Control Code
6 * PROGRAMMERS: Timo Kreuzer (timo.kreuzer@reactos.org)
7 * REFERENCES: http://www.joseflores.com/docs/ExploringIrql.html
8 * http://www.codeproject.com/KB/system/soviet_kernel_hack.aspx
9 * http://bbs.unixmap.net/thread-2022-1-1.html
12 /* INCLUDES *******************************************************************/
22 #define APIC_LAZY_IRQL
25 /* GLOBALS ********************************************************************/
28 UCHAR HalpVectorToIndex
[256];
34 0x00, /* 0 PASSIVE_LEVEL */
35 0x3d, /* 1 APC_LEVEL */
36 0x41, /* 2 DISPATCH_LEVEL */
49 0xb1, /* 15 DEVICE IRQL */
61 0xc1, /* 27 PROFILE_LEVEL */
62 0xd1, /* 28 CLOCK2_LEVEL */
63 0xe1, /* 29 IPI_LEVEL */
64 0xef, /* 30 POWER_LEVEL */
65 0xff, /* 31 HIGH_LEVEL */
71 0, /* 00 PASSIVE_LEVEL */
75 2, /* 41 DISPATCH_LEVEL */
79 7, /* 80 DEVICE IRQL */
83 27, /* C1 PROFILE_LEVEL */
84 28, /* D1 CLOCK2_LEVEL */
85 29, /* E1 IPI_LEVEL / EF POWER_LEVEL */
86 31, /* FF HIGH_LEVEL */
90 /* PRIVATE FUNCTIONS **********************************************************/
94 IOApicRead(UCHAR Register
)
96 /* Select the register, then do the read */
97 *(volatile UCHAR
*)(IOAPIC_BASE
+ IOAPIC_IOREGSEL
) = Register
;
98 return *(volatile ULONG
*)(IOAPIC_BASE
+ IOAPIC_IOWIN
);
103 IOApicWrite(UCHAR Register
, ULONG Value
)
105 /* Select the register, then do the write */
106 *(volatile UCHAR
*)(IOAPIC_BASE
+ IOAPIC_IOREGSEL
) = Register
;
107 *(volatile ULONG
*)(IOAPIC_BASE
+ IOAPIC_IOWIN
) = Value
;
112 ApicWriteIORedirectionEntry(
114 IOAPIC_REDIRECTION_REGISTER ReDirReg
)
116 IOApicWrite(IOAPIC_REDTBL
+ 2 * Index
, ReDirReg
.Long0
);
117 IOApicWrite(IOAPIC_REDTBL
+ 2 * Index
+ 1, ReDirReg
.Long1
);
121 IOAPIC_REDIRECTION_REGISTER
122 ApicReadIORedirectionEntry(
125 IOAPIC_REDIRECTION_REGISTER ReDirReg
;
127 ReDirReg
.Long0
= IOApicRead(IOAPIC_REDTBL
+ 2 * Index
);
128 ReDirReg
.Long1
= IOApicRead(IOAPIC_REDTBL
+ 2 * Index
+ 1);
135 ApicRequestInterrupt(IN UCHAR Vector
, UCHAR TriggerMode
)
137 APIC_COMMAND_REGISTER CommandRegister
;
139 /* Setup the command register */
140 CommandRegister
.Long0
= 0;
141 CommandRegister
.Vector
= Vector
;
142 CommandRegister
.MessageType
= APIC_MT_Fixed
;
143 CommandRegister
.TriggerMode
= TriggerMode
;
144 CommandRegister
.DestinationShortHand
= APIC_DSH_Self
;
146 /* Write the low dword to send the interrupt */
147 ApicWrite(APIC_ICR0
, CommandRegister
.Long0
);
154 //ApicWrite(APIC_EOI, 0);
160 ApicGetProcessorIrql(VOID
)
162 /* Read the TPR and convert it to an IRQL */
163 return TprToIrql(ApicRead(APIC_PPR
));
168 ApicGetCurrentIrql(VOID
)
171 return (KIRQL
)__readcr8();
172 #elif defined(APIC_LAZY_IRQL)
173 // HACK: some magic to Sync VBox's APIC registers
176 /* Return the field in the PCR */
177 return (KIRQL
)__readfsbyte(FIELD_OFFSET(KPCR
, Irql
));
179 // HACK: some magic to Sync VBox's APIC registers
182 /* Read the TPR and convert it to an IRQL */
183 return TprToIrql(ApicRead(APIC_TPR
));
189 ApicSetIrql(KIRQL Irql
)
193 #elif defined(APIC_LAZY_IRQL)
194 __writefsbyte(FIELD_OFFSET(KPCR
, Irql
), Irql
);
196 /* Convert IRQL and write the TPR */
197 ApicWrite(APIC_TPR
, IrqlToTpr(Irql
));
200 #define ApicRaiseIrql ApicSetIrql
202 #ifdef APIC_LAZY_IRQL
205 ApicLowerIrql(KIRQL Irql
)
207 __writefsbyte(FIELD_OFFSET(KPCR
, Irql
), Irql
);
209 /* Is the new Irql lower than set in the TPR? */
210 if (Irql
< KeGetPcr()->IRR
)
212 /* Save the new hard IRQL in the IRR field */
213 KeGetPcr()->IRR
= Irql
;
215 /* Need to lower it back */
216 ApicWrite(APIC_TPR
, IrqlToTpr(Irql
));
220 #define ApicLowerIrql ApicSetIrql
225 HalpIrqToVector(UCHAR Irq
)
227 IOAPIC_REDIRECTION_REGISTER ReDirReg
;
229 /* Read low dword of the redirection entry */
230 ReDirReg
.Long0
= IOApicRead(IOAPIC_REDTBL
+ 2 * Irq
);
232 /* Return the vector */
233 return (UCHAR
)ReDirReg
.Vector
;
238 HalpVectorToIrql(UCHAR Vector
)
240 return TprToIrql(Vector
);
245 HalpVectorToIrq(UCHAR Vector
)
247 return HalpVectorToIndex
[Vector
];
259 HalpInitializeLegacyPIC(VOID
)
266 /* Initialize ICW1 for master, interval 8, edge-triggered mode with ICW4 */
267 Icw1
.NeedIcw4
= TRUE
;
268 Icw1
.OperatingMode
= Cascade
;
269 Icw1
.Interval
= Interval8
;
270 Icw1
.InterruptMode
= EdgeTriggered
;
272 Icw1
.InterruptVectorAddress
= 0;
273 __outbyte(PIC1_CONTROL_PORT
, Icw1
.Bits
);
275 /* ICW2 - interrupt vector offset */
276 Icw2
.Bits
= PRIMARY_VECTOR_BASE
;
277 __outbyte(PIC1_DATA_PORT
, Icw2
.Bits
);
279 /* Connect slave to IRQ 2 */
281 Icw3
.SlaveIrq2
= TRUE
;
282 __outbyte(PIC1_DATA_PORT
, Icw3
.Bits
);
284 /* Enable 8086 mode, non-automatic EOI, non-buffered mode, non special fully nested mode */
285 Icw4
.SystemMode
= New8086Mode
;
286 Icw4
.EoiMode
= NormalEoi
;
287 Icw4
.BufferedMode
= NonBuffered
;
288 Icw4
.SpecialFullyNestedMode
= FALSE
;
290 __outbyte(PIC1_DATA_PORT
, Icw4
.Bits
);
292 /* Mask all interrupts */
293 __outbyte(PIC1_DATA_PORT
, 0xFF);
295 /* Initialize ICW1 for slave, interval 8, edge-triggered mode with ICW4 */
296 Icw1
.NeedIcw4
= TRUE
;
297 Icw1
.InterruptMode
= EdgeTriggered
;
298 Icw1
.OperatingMode
= Cascade
;
299 Icw1
.Interval
= Interval8
;
301 Icw1
.InterruptVectorAddress
= 0; /* This is only used in MCS80/85 mode */
302 __outbyte(PIC2_CONTROL_PORT
, Icw1
.Bits
);
304 /* Set interrupt vector base */
305 Icw2
.Bits
= PRIMARY_VECTOR_BASE
+ 8;
306 __outbyte(PIC2_DATA_PORT
, Icw2
.Bits
);
311 __outbyte(PIC2_DATA_PORT
, Icw3
.Bits
);
313 /* Enable 8086 mode, non-automatic EOI, non-buffered mode, non special fully nested mode */
314 Icw4
.SystemMode
= New8086Mode
;
315 Icw4
.EoiMode
= NormalEoi
;
316 Icw4
.BufferedMode
= NonBuffered
;
317 Icw4
.SpecialFullyNestedMode
= FALSE
;
319 __outbyte(PIC2_DATA_PORT
, Icw4
.Bits
);
321 /* Mask all interrupts */
322 __outbyte(PIC2_DATA_PORT
, 0xFF);
327 ApicInitializeLocalApic(ULONG Cpu
)
329 APIC_BASE_ADRESS_REGISTER BaseRegister
;
330 APIC_SPURIOUS_INERRUPT_REGISTER SpIntRegister
;
331 LVT_REGISTER LvtEntry
;
333 /* Enable the APIC if it wasn't yet */
334 BaseRegister
.Long
= __readmsr(MSR_APIC_BASE
);
335 BaseRegister
.Enable
= 1;
336 BaseRegister
.BootStrapCPUCore
= (Cpu
== 0);
337 __writemsr(MSR_APIC_BASE
, BaseRegister
.Long
);
339 /* Set spurious vector and SoftwareEnable to 1 */
340 SpIntRegister
.Long
= ApicRead(APIC_SIVR
);
341 SpIntRegister
.Vector
= APIC_SPURIOUS_VECTOR
;
342 SpIntRegister
.SoftwareEnable
= 1;
343 SpIntRegister
.FocusCPUCoreChecking
= 0;
344 ApicWrite(APIC_SIVR
, SpIntRegister
.Long
);
346 /* Read the version and save it globally */
347 if (Cpu
== 0) ApicVersion
= ApicRead(APIC_VER
);
349 /* Set the mode to flat (max 8 CPUs supported!) */
350 ApicWrite(APIC_DFR
, APIC_DF_Flat
);
352 /* Set logical apic ID */
353 ApicWrite(APIC_LDR
, ApicLogicalId(Cpu
) << 24);
355 /* Set the spurious ISR */
356 KeRegisterInterruptHandler(APIC_SPURIOUS_VECTOR
, ApicSpuriousService
);
358 /* Create a template LVT */
360 LvtEntry
.Vector
= 0xFF;
361 LvtEntry
.MessageType
= APIC_MT_Fixed
;
362 LvtEntry
.DeliveryStatus
= 0;
363 LvtEntry
.RemoteIRR
= 0;
364 LvtEntry
.TriggerMode
= APIC_TGM_Edge
;
366 LvtEntry
.TimerMode
= 0;
368 /* Initialize and mask LVTs */
369 ApicWrite(APIC_TMRLVTR
, LvtEntry
.Long
);
370 ApicWrite(APIC_THRMLVTR
, LvtEntry
.Long
);
371 ApicWrite(APIC_PCLVTR
, LvtEntry
.Long
);
372 ApicWrite(APIC_EXT0LVTR
, LvtEntry
.Long
);
373 ApicWrite(APIC_EXT1LVTR
, LvtEntry
.Long
);
374 ApicWrite(APIC_EXT2LVTR
, LvtEntry
.Long
);
375 ApicWrite(APIC_EXT3LVTR
, LvtEntry
.Long
);
378 LvtEntry
.Vector
= APIC_SPURIOUS_VECTOR
;
379 LvtEntry
.MessageType
= APIC_MT_ExtInt
;
380 ApicWrite(APIC_LINT0
, LvtEntry
.Long
);
382 /* Enable LINT1 (NMI) */
384 LvtEntry
.Vector
= APIC_NMI_VECTOR
;
385 LvtEntry
.MessageType
= APIC_MT_NMI
;
386 LvtEntry
.TriggerMode
= APIC_TGM_Level
;
387 ApicWrite(APIC_LINT1
, LvtEntry
.Long
);
389 /* Enable error LVTR */
390 LvtEntry
.Vector
= APIC_ERROR_VECTOR
;
391 LvtEntry
.MessageType
= APIC_MT_Fixed
;
392 ApicWrite(APIC_ERRLVTR
, LvtEntry
.Long
);
394 /* Set the IRQL from the PCR */
395 ApicSetIrql(KeGetPcr()->Irql
);
396 #ifdef APIC_LAZY_IRQL
397 /* Save the new hard IRQL in the IRR field */
398 KeGetPcr()->IRR
= KeGetPcr()->Irql
;
404 HalpAllocateSystemInterrupt(
408 IOAPIC_REDIRECTION_REGISTER ReDirReg
;
411 /* Start with lowest vector */
412 Vector
= IrqlToTpr(Irql
) & 0xF0;
414 /* Find an empty vector */
415 while (HalpVectorToIndex
[Vector
] != 0xFF)
419 /* Check if we went over the edge */
420 if (TprToIrql(Vector
) > Irql
)
422 /* Nothing free, return failure */
427 /* Save irq in the table */
428 HalpVectorToIndex
[Vector
] = Irq
;
430 /* Setup a redirection entry */
431 ReDirReg
.Vector
= Vector
;
432 ReDirReg
.DeliveryMode
= APIC_MT_LowestPriority
;
433 ReDirReg
.DestinationMode
= APIC_DM_Logical
;
434 ReDirReg
.DeliveryStatus
= 0;
435 ReDirReg
.Polarity
= 0;
436 ReDirReg
.RemoteIRR
= 0;
437 ReDirReg
.TriggerMode
= APIC_TGM_Edge
;
439 ReDirReg
.Reserved
= 0;
440 ReDirReg
.Destination
= 0;
442 /* Initialize entry */
443 IOApicWrite(IOAPIC_REDTBL
+ 2 * Irq
, ReDirReg
.Long0
);
444 IOApicWrite(IOAPIC_REDTBL
+ 2 * Irq
+ 1, ReDirReg
.Long1
);
451 ApicInitializeIOApic(VOID
)
454 IOAPIC_REDIRECTION_REGISTER ReDirReg
;
458 /* Map the I/O Apic page */
459 Pte
= HalAddressToPte(IOAPIC_BASE
);
460 Pte
->PageFrameNumber
= IOAPIC_PHYS_BASE
/ PAGE_SIZE
;
464 Pte
->CacheDisable
= 1;
468 /* Setup a redirection entry */
469 ReDirReg
.Vector
= 0xFF;
470 ReDirReg
.DeliveryMode
= APIC_MT_Fixed
;
471 ReDirReg
.DestinationMode
= APIC_DM_Physical
;
472 ReDirReg
.DeliveryStatus
= 0;
473 ReDirReg
.Polarity
= 0;
474 ReDirReg
.RemoteIRR
= 0;
475 ReDirReg
.TriggerMode
= APIC_TGM_Edge
;
477 ReDirReg
.Reserved
= 0;
478 ReDirReg
.Destination
= 0;
480 /* Loop all table entries */
481 for (Index
= 0; Index
< 24; Index
++)
483 /* Initialize entry */
484 IOApicWrite(IOAPIC_REDTBL
+ 2 * Index
, ReDirReg
.Long0
);
485 IOApicWrite(IOAPIC_REDTBL
+ 2 * Index
+ 1, ReDirReg
.Long1
);
488 /* Init the vactor to index table */
489 for (Vector
= 0; Vector
<= 255; Vector
++)
491 HalpVectorToIndex
[Vector
] = 0xFF;
494 // HACK: Allocate all IRQs, should rather do that on demand
495 for (Index
= 0; Index
<= 15; Index
++)
497 /* Map the IRQs to IRQLs like with the PIC */
498 HalpAllocateSystemInterrupt(Index
, 27 - Index
);
501 /* Enable the timer interrupt */
502 ReDirReg
.Vector
= APIC_CLOCK_VECTOR
;
503 ReDirReg
.DeliveryMode
= APIC_MT_Fixed
;
504 ReDirReg
.DestinationMode
= APIC_DM_Physical
;
505 ReDirReg
.TriggerMode
= APIC_TGM_Edge
;
507 ReDirReg
.Destination
= ApicRead(APIC_ID
);
508 IOApicWrite(IOAPIC_REDTBL
+ 2 * APIC_CLOCK_INDEX
, ReDirReg
.Long0
);
515 HalpInitializePICs(IN BOOLEAN EnableInterrupts
)
519 /* Save EFlags and disable interrupts */
520 EFlags
= __readeflags();
523 /* Initialize and mask the PIC */
524 HalpInitializeLegacyPIC();
526 /* Initialize the I/O APIC */
527 ApicInitializeIOApic();
529 /* Manually reserve some vectors */
530 HalpVectorToIndex
[APIC_CLOCK_VECTOR
] = 8;
531 HalpVectorToIndex
[APC_VECTOR
] = 99;
532 HalpVectorToIndex
[DISPATCH_VECTOR
] = 99;
534 /* Set interrupt handlers in the IDT */
535 KeRegisterInterruptHandler(APIC_CLOCK_VECTOR
, HalpClockInterrupt
);
537 KeRegisterInterruptHandler(APC_VECTOR
, HalpApcInterrupt
);
538 KeRegisterInterruptHandler(DISPATCH_VECTOR
, HalpDispatchInterrupt
);
541 /* Register the vectors for APC and dispatch interrupts */
542 HalpRegisterVector(IDT_INTERNAL
, 0, APC_VECTOR
, APC_LEVEL
);
543 HalpRegisterVector(IDT_INTERNAL
, 0, DISPATCH_VECTOR
, DISPATCH_LEVEL
);
545 /* Restore interrupt state */
546 if (EnableInterrupts
) EFlags
|= EFLAGS_INTERRUPT_MASK
;
547 __writeeflags(EFlags
);
551 /* SOFTWARE INTERRUPT TRAPS ***************************************************/
557 HalpApcInterruptHandler(IN PKTRAP_FRAME TrapFrame
)
559 KPROCESSOR_MODE ProcessorMode
;
561 ASSERT(ApicGetProcessorIrql() == APC_LEVEL
);
564 KiEnterInterruptTrap(TrapFrame
);
566 #ifdef APIC_LAZY_IRQL
567 if (!HalBeginSystemInterrupt(APC_LEVEL
, APC_VECTOR
, &OldIrql
))
569 /* "Spurious" interrupt, exit the interrupt */
570 KiEoiHelper(TrapFrame
);
573 /* Save the old IRQL */
574 OldIrql
= ApicGetCurrentIrql();
575 ASSERT(OldIrql
< APC_LEVEL
);
578 /* Raise to APC_LEVEL */
579 ApicRaiseIrql(APC_LEVEL
);
581 /* End the interrupt */
584 /* Kernel or user APC? */
585 if (KiUserTrap(TrapFrame
)) ProcessorMode
= UserMode
;
586 else if (TrapFrame
->EFlags
& EFLAGS_V86_MASK
) ProcessorMode
= UserMode
;
587 else ProcessorMode
= KernelMode
;
589 /* Enable interrupts and call the kernel's APC interrupt handler */
591 KiDeliverApc(ProcessorMode
, NULL
, TrapFrame
);
593 /* Disable interrupts */
596 /* Restore the old IRQL */
597 ApicLowerIrql(OldIrql
);
599 /* Exit the interrupt */
600 KiEoiHelper(TrapFrame
);
606 HalpDispatchInterruptHandler(IN PKTRAP_FRAME TrapFrame
)
609 ASSERT(ApicGetProcessorIrql() == DISPATCH_LEVEL
);
612 KiEnterInterruptTrap(TrapFrame
);
614 #ifdef APIC_LAZY_IRQL
615 if (!HalBeginSystemInterrupt(DISPATCH_LEVEL
, DISPATCH_VECTOR
, &OldIrql
))
617 /* "Spurious" interrupt, exit the interrupt */
618 KiEoiHelper(TrapFrame
);
621 /* Get the current IRQL */
622 OldIrql
= ApicGetCurrentIrql();
623 ASSERT(OldIrql
< DISPATCH_LEVEL
);
626 /* Raise to DISPATCH_LEVEL */
627 ApicRaiseIrql(DISPATCH_LEVEL
);
629 /* End the interrupt */
632 /* Enable interrupts and call the kernel's DPC interrupt handler */
634 KiDispatchInterrupt();
637 /* Restore the old IRQL */
638 ApicLowerIrql(OldIrql
);
640 /* Exit the interrupt */
641 KiEoiHelper(TrapFrame
);
646 /* SOFTWARE INTERRUPTS ********************************************************/
651 HalRequestSoftwareInterrupt(IN KIRQL Irql
)
653 /* Convert irql to vector and request an interrupt */
654 ApicRequestInterrupt(IrqlToSoftVector(Irql
), APIC_TGM_Edge
);
659 HalClearSoftwareInterrupt(
666 /* SYSTEM INTERRUPTS **********************************************************/
670 HalEnableSystemInterrupt(
673 IN KINTERRUPT_MODE InterruptMode
)
675 IOAPIC_REDIRECTION_REGISTER ReDirReg
;
676 PKPRCB Prcb
= KeGetCurrentPrcb();
678 ASSERT(Irql
<= HIGH_LEVEL
);
679 ASSERT((IrqlToTpr(Irql
) & 0xF0) == (Vector
& 0xF0));
681 /* Get the irq for this vector */
682 Index
= HalpVectorToIndex
[Vector
];
684 /* Check if its valid */
687 /* Interrupt is not in use */
691 /* Read the redirection entry */
692 ReDirReg
= ApicReadIORedirectionEntry(Index
);
694 /* Check if the interrupt was unused */
695 if (ReDirReg
.Vector
!= Vector
)
697 ReDirReg
.Vector
= Vector
;
698 ReDirReg
.DeliveryMode
= APIC_MT_LowestPriority
;
699 ReDirReg
.DestinationMode
= APIC_DM_Logical
;
700 ReDirReg
.Destination
= 0;
703 /* Check if the destination is logical */
704 if (ReDirReg
.DestinationMode
== APIC_DM_Logical
)
706 /* Set the bit for this cpu */
707 ReDirReg
.Destination
|= ApicLogicalId(Prcb
->Number
);
710 /* Set the trigger mode */
711 ReDirReg
.TriggerMode
= 1 - InterruptMode
;
714 ReDirReg
.Mask
= FALSE
;
716 /* Write back the entry */
717 ApicWriteIORedirectionEntry(Index
, ReDirReg
);
724 HalDisableSystemInterrupt(
728 IOAPIC_REDIRECTION_REGISTER ReDirReg
;
730 ASSERT(Irql
<= HIGH_LEVEL
);
731 ASSERT(Vector
< RTL_NUMBER_OF(HalpVectorToIndex
));
733 Index
= HalpVectorToIndex
[Vector
];
735 /* Read lower dword of redirection entry */
736 ReDirReg
.Long0
= IOApicRead(IOAPIC_REDTBL
+ 2 * Index
);
741 /* Write back lower dword */
742 IOApicWrite(IOAPIC_REDTBL
+ 2 * Irql
, ReDirReg
.Long0
);
748 HalBeginSystemInterrupt(
755 /* Get the current IRQL */
756 CurrentIrql
= ApicGetCurrentIrql();
758 #ifdef APIC_LAZY_IRQL
759 /* Check if this interrupt is allowed */
760 if (CurrentIrql
>= Irql
)
762 IOAPIC_REDIRECTION_REGISTER RedirReg
;
765 /* It is not, set the real Irql in the TPR! */
766 ApicWrite(APIC_TPR
, IrqlToTpr(CurrentIrql
));
768 /* Save the new hard IRQL in the IRR field */
769 KeGetPcr()->IRR
= CurrentIrql
;
771 /* End this interrupt */
774 /* Get the irq for this vector */
775 Index
= HalpVectorToIndex
[Vector
];
777 /* Check if its valid */
780 /* Read the I/O redirection entry */
781 RedirReg
= ApicReadIORedirectionEntry(Index
);
783 /* Re-request the interrupt to be handled later */
784 ApicRequestInterrupt(Vector
, (UCHAR
)RedirReg
.TriggerMode
);
788 /* Re-request the interrupt to be handled later */
789 ApicRequestInterrupt(Vector
, APIC_TGM_Edge
);
792 /* Pretend it was a spurious interrupt */
796 /* Save the current IRQL */
797 *OldIrql
= CurrentIrql
;
799 /* Set the new IRQL */
802 /* Turn on interrupts */
811 HalEndSystemInterrupt(
813 IN PKTRAP_FRAME TrapFrame
)
818 /* Restore the old IRQL */
819 ApicLowerIrql(OldIrql
);
823 /* IRQL MANAGEMENT ************************************************************/
827 KeGetCurrentIrql(VOID
)
829 /* Read the current TPR and convert it to an IRQL */
830 return ApicGetCurrentIrql();
839 /* Validate correct lower */
840 if (OldIrql
> ApicGetCurrentIrql())
843 KeBugCheck(IRQL_NOT_LESS_OR_EQUAL
);
846 /* Set the new IRQL */
847 ApicLowerIrql(OldIrql
);
857 /* Read the current IRQL */
858 OldIrql
= ApicGetCurrentIrql();
860 /* Validate correct raise */
861 if (OldIrql
> NewIrql
)
864 KeBugCheck(IRQL_NOT_GREATER_OR_EQUAL
);
867 /* Convert the new IRQL to a TPR value and write the register */
868 ApicRaiseIrql(NewIrql
);
870 /* Return old IRQL */
876 KeRaiseIrqlToDpcLevel(VOID
)
878 return KfRaiseIrql(DISPATCH_LEVEL
);
883 KeRaiseIrqlToSynchLevel(VOID
)
885 return KfRaiseIrql(SYNCH_LEVEL
);
888 #endif /* !_M_AMD64 */