IRQLs are interrupt priority levels, each IRQ is mapped to a particular IRQL through the HAL. On x64 systems, the IRQLs run from 0 (the lowest) to 15 (the highest). On x86 systems, the IRQLs run from 0 to 31.
IRQLs are used to determine which interrupts a processor is able to be interrupted by and subsequently process. A higher IRQL interrupt will take precedence over a lower IRQL one. Every processor will have a current IRQL which can be found within the Processor Control Region (PCR). We can dump this structure in WinDbg using the !pcr extension:
5: kd> !pcr KPCR for Processor 5 at fffff880030a5000: Major 1 Minor 1 NtTib.ExceptionList: fffff880030b0640 NtTib.StackBase: fffff880030aa040 NtTib.StackLimit: 00000000001ad328 NtTib.SubSystemTib: fffff880030a5000 NtTib.Version: 00000000030a5180 NtTib.UserPointer: fffff880030a57f0 NtTib.SelfTib: 000007fffffde000 SelfPcr: 0000000000000000 Prcb: fffff880030a5180 Irql: 0000000000000000 IRR: 0000000000000000 IDR: 0000000000000000 InterruptMode: 0000000000000000 IDT: 0000000000000000 GDT: 0000000000000000 TSS: 0000000000000000 CurrentThread: fffffa800d716060 NextThread: 0000000000000000 IdleThread: fffff880030b00c0 DpcQueue:
If a processor receives an interrupt which is lower than it’s current IRQL, then the interrupt is masked, and will either be scheduled to be run when the IRQL has been lowered or will be scheduled to run on a different processor.
In the event that the processor is able to service the interrupt, the current IRQL will be saved along with the current thread context, the IRQL level of the processor will then be raised to IRQL level associated to the interrupt and the appropriate ISR will be called. It should be noted that the processor will always try to return to the lowest possible IRQL as soon as possible to ensure that interrupts can be serviced efficiently.
We can dump the saved IRQL for the processor using the !irql extension:
5: kd> !irql Debugger saved IRQL for processor 0x5 -- 0 (LOW_LEVEL)
Alternatively, the saved IRQL for the process can also be found within the PRCB (Processor Region Control Block), we can be dumped using WinDbg using !prcb:
5: kd> !prcb PRCB for Processor 5 at fffff880030a5180: Current IRQL -- 0 Threads-- Current fffffa800d716060 Next 0000000000000000 Idle fffff880030b00c0 Processor Index 5 Number (0, 5) GroupSetMember 20 Interrupt Count -- 001e9395 Times -- Dpc 00000218 Interrupt 00000839 Kernel 0000e9d7 User 000030aa
Sources:
Windows Internals 5th Edition
CodeMachine – Interrupt Dispatching Internals
.:: Phrack Magazine ::.
Windows: Line-Based vs. Message Signaled-Based Interrupts. MSI tool.
Introduction to Spin Locks – Windows drivers
Introduction to Message-Signaled Interrupts – Windows drivers