This topic seems to recur way too often. So I'll post some explanation
When you look in the PCR with !pcr in the debugger, you're looking at what
has been written into some scratchpad space that may or may not be currently
in use by the HAL. Several HALs use the PCR to track IRQL. Other HALs use
the TPR (Task Priority Register) in the Local APIC. Still others may have
their own implementations. So you should always consider the value of IRQL
in the PCR to be suspect, simply because it may not be in use. A value like
0xFF, which corresponds to no actual IRQL should immediately clue you in to
the fact that the HAL that you're using ignores the value in the PCR.
Furthermore, you need to understand what, exactly, the debugger really is
and what it really does. (This discussion applies to the debugger that is
built into the NT kernel, and not Soft-ICE or an Arium or an ITP that is
debugging from outside of the kernel.) The debugger is just a piece of code
that runs within the kernel, trying to depend on as few services from
outside itself as possible. In order to become more deterministic, it
disables interrupts whenever it is entered. The NT way of disabling
interrupts securely and safely is to raise IRQL to HIGH_LEVEL. Thus,
whenever you're in the debugger, IRQL is actually HIGH_LEVEL, regardless of
what it was when it was executing the code that you were trying to debug.
Consequently, looking at the IRQL in the PCR from the debugger should always
tell you HIGH_LEVEL if the PCR is actually being used to track IRQL. If it
tells you anything else, it's meaningless. (This assumes that you actually
found some meaning in asking what the current IRQL is while you're in the
debugger, as you knew a-priori it should be HIGH_LEVEL.) This point also
applies if you try to read the APIC TPR on a HAL that uses the TPR to track
IRQL. It should always correspond to HIGH_LEVEL while you're in the
The only way you can reliably find out what IRQL your code was running at is
to look at where the debugger pushed your IRQL onto the stack when the
debugger was entered. Interestingly, this is beyond the end of the stack
frame that the debugger itself displays to you, as the debugger assumes that
you are primarily interested in the code that you wrote, not the debugger
itself. So it pretends that the stack ends at your code, not automatically
displaying the part of the stack that the debugger itself is currently
Lastly, the WinDbg team has taken note in recent years that lots of people
would be interested in knowing what IRQL their code was running at.
Unfortunately, they noticed this first for people who were trying to debug
crashdumps and only later (at my begging) extended their code to be able to
tell you for a running system.
So you can know what IRQL code was running at on Windows XP and later when
debugging a crashdump by using !irql. If you are debugging Windows Server
2003 or later, !irql will give you an accurate answer even if you're
debugging a live system. !irql does exactly what I suggested above. It
looks at the IRQL that the debugger itself stored as it was being entered.
Please, let us never see another posting saying that IRQL was 0xFF.
Windows Kernel Group
This posting is provided "AS IS" with no warranties, and confers no rights.