Expand description
Compile-time IRQL (Interrupt Request Level) safety for Windows kernel drivers.
This crate provides compile-time verification of IRQL constraints using Rust’s type system. IRQL violations are caught by the compiler, preventing a common class of bugs in Windows kernel-mode code.
§Quick Start
use irql::{requires_irql, root_irql, Dispatch, Passive};
// Function requiring Dispatch IRQL or higher
#[requires_irql(Dispatch)]
fn acquire_spinlock() {
// Spinlock operations require Dispatch level
}
// Entry point at Passive IRQL
#[root_irql(Passive)]
fn driver_init() {
// Can call higher IRQL functions using call_irql!
call_irql!(acquire_spinlock());
}§IRQL Levels
The crate provides types for each Windows IRQL level:
Passive- Normal kernel execution (can access paged memory)Apc- Asynchronous Procedure Call levelDispatch- DPC level (most common for drivers)Dirql- Device interrupt levelProfile,Clock,Ipi,Power,High- Higher interrupt levels
§The IRQL Rule
IRQL can only stay the same or be raised, never lowered.
This fundamental rule is enforced at compile time through the IrqlCanRaiseTo trait.
Attempting to call a lower-IRQL function from a higher-IRQL context results in a
compile error with a clear diagnostic message.
§Attributes and Macros
requires_irql- Mark functions requiring a minimum IRQLroot_irql- Mark entry points with their IRQL levelcall_irql!- Call IRQL-constrained functions (available inside annotated functions)
§Example: Struct Methods
use irql::{requires_irql, root_irql, Dispatch};
struct Device {
id: u32,
}
#[requires_irql(Dispatch)]
impl Device {
fn new(id: u32) -> Self {
Device { id }
}
fn process_interrupt(&self) {
// All methods require Dispatch IRQL
}
}
#[root_irql(Dispatch)]
fn interrupt_handler() {
let device = call_irql!(Device::new(1));
call_irql!(device.process_interrupt());
}§Compile-Time Error Example
ⓘ
use irql::{requires_irql, Dispatch, Passive};
#[requires_irql(Passive)]
fn low_irql() { }
#[requires_irql(Dispatch)]
fn high_irql() {
call_irql!(low_irql()); // ERROR: Cannot lower IRQL!
}The compiler produces:
error: IRQL violation: cannot call function at `Passive` IRQL
from current IRQL level `Dispatch`§Safety
This crate provides compile-time guarantees only. You must ensure:
- Entry points are annotated with their actual runtime IRQL
- IRQL-raising operations (spinlocks, etc.) are properly tracked
- Runtime IRQL matches compile-time annotations
For more details, see the repository.
Macros§
Structs§
- Apc
- IRQL level: Apc
- Clock
- IRQL level: Clock
- Dirql
- IRQL level: Dirql
- Dispatch
- IRQL level: Dispatch
- High
- IRQL level: High
- Ipi
- IRQL level: Ipi
- Passive
- IRQL level: Passive
- Power
- IRQL level: Power
- Profile
- IRQL level: Profile
Traits§
- Irql
CanRaise To - Trait indicating that an IRQL level can be raised to a target level.
- Irql
Level - Marker trait for IRQL level types.
Attribute Macros§
- requires_
irql - Marks a function or impl block as requiring a minimum IRQL level.
- root_
irql - Marks an entry point function with a specific IRQL context.