System: Windows 2000 professional•free • build • 2195 • X86 • Single CPU

Part I:

In this part, I’ll discuss the fundament of IRQL and the differences/relations between IRQL and CPU rings/thread
priority/hardware IRQ.

Definitions:
For a kernel developer, IRQL is not strange. Almost every kernel support routine has a limit of the working IRQL. But
what on earth an IRQL stands for ? This article is to disclose it’s mysterious veil.
See it’s definition from DDK:
Interrupt Request Level (IRQL)
The priority ranking of an interrupt. A processor has an IRQL setting that threads can raise or lower.
Interrupts that occur at or below the processor's IRQL setting are masked and will not interfere with the
current operation. Interrupts that occur above the processor's IRQL setting take precedence over the current
operation.
The particular IRQL at which a piece of kernel-mode code executes determines its hardware priority.
Kernel-mode code is always interruptible: an interrupt with a higher IRQL value can occur at any time,
thereby causing another piece of kernel-mode code with the system-assigned higher IRQL to be run
immediately on that processor. In other words, when a piece of code runs at a given IRQL, the Kernel masks
off all interrupt vectors with a lesser or equal IRQL value on the microprocessor.
It says that higer IRQL interrupt can interrupt other task or interrupt with lower IRQL and all the interrupts with IRQL
equal to or below current IRQL will be masked and wait until it get opportunity.
Each processor has an independent IRQL, which descripts the current IRQL of the processor, i.e. the IRQL of the
current instructions / codes being executed by this processor.
System support a kernel routine (KeGetCurrentIRQL) to get current processor’s IRQL. Let’s see the assemble

codes:

kd> u KeGetCurrentIrql
hal!KeGetCurrentIrql:
80063124 0fb70524f0dfff movzx eax,word ptr [ffdff024]
8006312b c3 ret


This routine is very simple. It tells us that current IRQL stores at krenel address 0xffdff024. And it’s a WORD (2
bytes), in fact it’s only one byte long, the upper 8 bits are zero.
The value of IRQL can be one of the followings.

Software IRQL:

PASSIVE_LEVEL 0 // Passive release level
LOW_LEVEL 0 // Lowest interrupt level
APC_LEVEL 1 // APC interrupt level
DISPATCH_LEVEL 2 // Dispatcher level
Hardware IRQL:
DIRQL: from 3 to 26 for device ISR
PROFILE_LEVEL 27 (0x1B) // timer used for profiling.
CLOCK1_LEVEL 28 (0x1C) // Interval clock 1 level - Not used on x86
CLOCK2_LEVEL 28 (0x1C) // Interval clock 2 level
SYNCH_LEVEL 28 (0x1C) // synchronization level
IPI_LEVEL 29 (0x1D) // Interprocessor interrupt level
POWER_LEVEL 30 (0x1E) // Power failure level
HIGH_LEVEL 31 (0x1F) // Highest interrupt level

The IRQL values are divided into two groups: Software ( 0,1,2 ) / Hardware IRQL ( >= 3). Hardware IRQL is for
device ISRs and system, it is similar to (but distinguished with) the level of hardware IRQ, which implemented by
i8259, but IRQL is only an action of Windows OS, not hardware’s. It’s realized by Windows OS. But hardware IRQ
level is achieved by 8259A (programmable interrupt controlor). We will detail the hardware IRQ later.
The bigger of it’s value, the higher level the IRQL has.
Let us see an example: