What causes a bug check 0xD1 (IRQL_NOT_LESS_OR_EQUAL)

The MSDN document summarizes the cause for the D1 (IRQL_NOT_LESS_OR_EQUAL) pretty well, for people who know how the memory manager in Windows works. It basically says that the cause is: A driver tried to access an address that is pageable (or that is completely invalid) while the IRQL was too high. This bug check is usually caused by drivers that have used improper addresses.


Detour to the memory manager: in order to understand the D1 bugcheck we have to (briefly) discuss the memory manager subsystem and how it works. The memory manager runs at IRQL 0 (sometimes called PASSIVE) – in other words it runs as a thread with regular priority. If a driver tries to access some piece of memory the processor will throw an “exception” if the memory is not in the RAM (its not paged in). The memory manager will catch this exception, fetch the memory from disk and return the CPU’s attention to the driver that tried to access the memory in first place and now the memory will be paged in. The problem occurs when the driver that is trying to access the memory is running at a higher IRQL, for example IRQL 2 (a.k.a DPC – Deffered Procedure Call).


This is a problem because when the driver accesses paged out memory at IRQL 2, the memory manager will be invoked to page-in the memory and it runs at IRQL 0. Code at lower IRQL cannot preempt code at a higher IRQL so the memory manager bugchecks the system since no forward progress can be made (deadlock) at this point and the memory manager knows that this is unrecoverable error. Read this white paper [.doc] for a more in-depth explanation of thread scheduling, thread context and driver routines, driver threads, and Interrupt Request Levels (IRQL) in Windows.

It is important to remember that the driver can be merely trying to access paged-out memory or it can be trying to access some invalid memory address. For example if a driver is trying to access memory address 0x4E41F00F the system will crash with 0xD1 because  this is not a valid kernel mode address. The kernel address space usually starts at 0xFF… This reference is most likely a bug or memory corruption that eventually manifests itself as a bad pointer. When we try to reference memory at that bad pointer we get a D1 bug check.

– Rade Trimceski

Comments (9)

  1. William says:

    then how do i fix the problem?

  2. This bugcheck can only be fixed by the engineer that developed the driver.  You should check with the manufacturer to see if there is an updated driver to download.  Otherwise, you'll have to disable the device in Device Manager.

    If you ARE the developer of the driver, you should attach a kernel debugger and check the output of "!analyze -v".  Usually I see D1 bugchecks caused because of a bad pointer (e.g., dereferencing a NULL pointer, memory use-after-free, etc.)  Less commonly, it actually is an IRQL problem — make sure that you aren't accessing pageable memory at IRQL >= 2.  (This includes both data and code).

  3. Michael says:

    Thanks this was the first helpful explanation in the net. I will check my drivers now and search for the specific one causing the problem.

  4. moshe says:

    How can I know what driver is to blame ?


  5. TamilMagan says:

    say the driver is accessing a memory which is page-able, but at the time of access if it is in RAM will this give a bug-check? if the answer is yes, all address translation even for non-paged memory will be through memory manager only, then how it working without giving a bug-check when you access a non-paged memory?

  6. The answer is no – the system will not bugcheck if a driver accesses pageable memory while at DISPATCH_LEVEL, if the memory happens to be paged-in at the time of access.  This makes finding all the 0xD1 bugs in a driver difficult – it's nondeterministic whether the bugcheck will occur.

    If you are a driver developer or tester, Driver Verifier can help you find these types of bugs.  Driver Verifier has a mode that evicts pageable memory every time your driver raises to DISPATCH_LEVEL, making it much more likely that the 0xD1 bugcheck will occur.  More info at msdn.microsoft.com/…/ff546138(v=vs.85).aspx .

  7. Umar Yaqoob says:

    Why won't the Memory Manager simply block the pageable memory request made by a driver at IRQL >0 and unload the defaulting driver, instead of halting a system to BSOD? Maybe the question is too lame but humor me!

  8. The NT kernel has a "fail fast" policy.  If there's any indication that a programming contract has been broken, the NT kernel will halt the system.

    The rationale is that if one rule is broken, then all bets are off on the state of the system.  You might try to unload the driver, but maybe your "DriverUnload" routine will just enter an infinite loop, or corrupt the disk, or somehow else make the problem worse.

    To draw a (bad) analogy: if your car is racing along the highway, and you realize that the windshield has shattered; you wouldn't just try and keep driving.  You'd stop the car, inspect the damage, look for other damage elsewhere on the vehicle, and get the windshield replaced.

  9. Pedro Teixeira says:

    "Why won't the Memory Manager simply block the pageable memory request made by a driver at IRQL >0 and unload the defaulting driver, instead of halting a system to BSOD? Maybe the question is too lame but humor me!"

    "Block" is a concept that only exists at IRQL bellow 2. It doesn't have anything to do with the IRQL of MM (the article explanation is actually incorrect) bur rather the IRQL at which the scheduler runs. The scheduler runs at IRQL 2 (DISPATCH). Things at or above cannot "block". They can, at most.spin. And that's why MM can't do anything about a rogue access to pageable memory: it can't block it.