deroko
February 3rd, 2008, 12:50
I was playing with IRQL and spotted one interesting thing. If IRQL is raised to HIGH_LEVEL, then KeGetCurrentIrql will return wrong info about IRQL:
Decode IRQL to Task Priority Register [APIC_base+0x80]
Also there is a array used to decode Task Priority Register to IRQL:
Basically if we are running at HIGH_LEVEL, KeGetCurrentIrql will always return POWER_LEVEL. Calculaion is simple here, it uses Task Priority, upper 8 bits of TPR (Task Priority Register) as index into _HalpVectorToIRQL or better name would be _HalpTPRtoIRQL for this 2nd array.
So are you sure that you are running at HIGH_IRQL? or POWER_LEVEL?
Code:
.text:800123B8 ; __fastcall KfRaiseIrql(x)
.text:800123B8 public @KfRaiseIrql@4
.text:800123B8 @KfRaiseIrql@4 proc near
.text:800123B8
.text:800123B8 movzx edx, cl
.text:800123BB movzx ecx, ds:_HalpIRQLtoTPR[edx]
.text:800123C2 mov eax, ds:0FFFE0080h
.text:800123C7 mov ds:0FFFE0080h, ecx
.text:800123CD shr eax, 4
.text:800123D0 movzx eax, ds:_HalpVectorToIRQL[eax]
.text:800123D7 retn
.text:800123D7 @KfRaiseIrql@4 endp
Decode IRQL to Task Priority Register [APIC_base+0x80]
Code:
.text:80012398 _HalpIRQLtoTPR db 0h <--- PASSIVE_LEVEL (0)
.text:80012399 db 3Dh <--- APC_LEVEL (1)
.text:8001239A db 41h <--- DISPATCH_LEVEL (2)
.text:8001239B db 41h
.text:8001239C db 51h
.text:8001239D db 61h <--- CMCI_LEVEL (5)
.text:8001239E db 71h
.text:8001239F db 81h
.text:800123A0 db 91h
.text:800123A1 db 0A1h
.text:800123A2 db 0B1h
.text:800123A3 db 0B1h
.text:800123A4 db 0B1h
.text:800123A5 db 0B1h
.text:800123A6 db 0B1h
.text:800123A7 db 0B1h
.text:800123A8 db 0B1h
.text:800123A9 db 0B1h
.text:800123AA db 0B1h
.text:800123AB db 0B1h
.text:800123AC db 0B1h
.text:800123AD db 0B1h
.text:800123AE db 0B1h
.text:800123AF db 0B1h
.text:800123B0 db 0B1h
.text:800123B1 db 0B1h
.text:800123B2 db 0B1h
.text:800123B3 db 0C1h <--- PROFILE_LEVEL (27)
.text:800123B4 db 0D1h <--- CLOCK1/2_LEVEL (28)
.text:800123B5 db 0E1h <--- IPI_LEVEL (29)
.text:800123B6 db 0EFh <--- POWER_LEVEL(30)
.text:800123B7 db 0FFh <--- HIGH_LEVEL (31)
Also there is a array used to decode Task Priority Register to IRQL:
Code:
.data:8001D218 _HalpVectorToIRQL db 0h <--- PASSIVE_IRQL
.data:8001D219 db 0FFh
.data:8001D21A db 0FFh
.data:8001D21B db 1 <--- APC_LEVEL
.data:8001D21C db 2 <--- DISPATCH_LEVEL
.data:8001D21D db 0FFh
.data:8001D21E db 0FFh
.data:8001D21F db 0FFh
.data:8001D220 db 0FFh
.data:8001D221 db 0FFh
.data:8001D222 db 0FFh
.data:8001D223 db 0FFh
.data:8001D224 db 1Bh PROFILE_LEVEL
.data:8001D225 db 1Ch CLOCK1/2_LEVEL
.data:8001D226 db 1Dh IPI_LEVEL and POWER LEVEL
are different in Task priority sub-class
(lower 8bits of Task Priority Register)
.data:8001D227 db 1Eh POWER_LEVEL
Basically if we are running at HIGH_LEVEL, KeGetCurrentIrql will always return POWER_LEVEL. Calculaion is simple here, it uses Task Priority, upper 8 bits of TPR (Task Priority Register) as index into _HalpVectorToIRQL or better name would be _HalpTPRtoIRQL for this 2nd array.
So are you sure that you are running at HIGH_IRQL? or POWER_LEVEL?