Debugging Stop 0xA0 – Dude, Where’s My IRP?

Stop 0xA0’s or internal power error crashes are usually quite difficult to debug, and tend to include very little useful information. However, in this case, the first parameter was 0x608 which indicated problems with the component power manager. According to WinDbg, the exact reason is the following:

A driver has attempted to transition a component to idle without a preceding active request.

From the description above, we can see that a power transition has occurred within the appropriate power IRP. However, the dump file doesn’t pinpoint the exact IRP like a Stop 0x9F would and therefore we’ll need to do some investigation.

Before we do that, let me provide some background information for this bugcheck. With the launch of Windows 8, PoFx or Power Management Framework introduced a new framework which enabled driver developers to manage the power states of individual device components rather than the entire device. The change was designed to reduce the complexity of managing components and to also enable components to be powered down if they were idle.

PoFx created a new set of power states for components, which begin with the “F” prefix e.g. F0. The ordering follows the same conventions as D0 and S0 i.e. the fully on state.

Typically, components will either be in an active or idle state. This state is controlled by two different functions – PoFxActivateComponent and PoFxIdleComponent. When a driver wishes to use a device component, then they call the activate function, which increments an activation counter. This enables the framework to determine which components to power down or keep active. The idle function does the opposite, and decrements the activation counter.

Now, this brings me to a very important point which will help to clarify the bugcheck description. When the activation count has reached 0, then the component will transition into the idle power state. The opposite is true, for when the activation count is incremented from 0 to 1, the component will then transition into the active power state.

To illustrate this point, let’s dump the call stack.

0: kd> knL
 # Child-SP          RetAddr           Call Site
00 fffff002`01007678 fffff803`286f27ec nt!KeBugCheckEx
01 fffff002`01007680 fffff803`286065c0 nt!PopFxBugCheck+0x1c
02 fffff002`010076c0 fffff803`28462549 nt!PopFxIdleComponent+0x1a4060
03 fffff002`01007720 fffff803`2a75ba73 nt!PoFxIdleComponent+0x39
04 (Inline Function) --------`-------- Wdf01000!FxPoxInterface::PoxIdleComponent+0x15
05 fffff002`01007790 fffff803`2a7bc227 Wdf01000!FxPoxInterface::DeclareComponentIdle+0x15e47
06 fffff002`010077c0 fffff803`2a74186b Wdf01000!FxPkgPnp::PowerPolWakeCapableDeviceIdle+0x17
07 (Inline Function) --------`-------- Wdf01000!FxPkgPnp::PowerPolicyEnterNewState+0x10a
08 fffff002`010077f0 fffff803`2a741008 Wdf01000!FxPkgPnp::PowerPolicyProcessEventInner+0x20b
09 fffff002`01007970 fffff803`2a745a7a Wdf01000!FxPkgPnp::_PowerPolicyProcessEventInner+0x68
0a (Inline Function) --------`-------- Wdf01000!FxEventQueue::EventQueueWorker+0x86
0b fffff002`010079b0 fffff803`28467c0f Wdf01000!FxThreadedEventQueue::_WorkItemCallback+0x9a
0c fffff002`01007a00 fffff803`284bd095 nt!IopProcessWorkItem+0xff
0d fffff002`01007a70 fffff803`2852a7a5 nt!ExpWorkerThread+0x105
0e fffff002`01007b10 fffff803`285c8b2a nt!PspSystemThreadStartup+0x55
0f fffff002`01007b60 00000000`00000000 nt!KiStartSystemThread+0x2a

As we can see, the activation count will have reached 0 and thereby the component will begin to transition to the idle power state. Although, where is our accompanying power IRP for this request?! Let’s find out!

Firstly, let’s dump the component which was transistioning to the idle state. From here, we can find the device which the component belongs to.

0: kd> dt _POP_FX_COMPONENT ffffc301c24404b8
nt!_POP_FX_COMPONENT
   +0x000 Id               : _GUID {00000000-0000-0000-0000-000000000000}
   +0x010 Index            : 0
   +0x018 WorkOrder        : _POP_FX_WORK_ORDER
   +0x050 Device           : 0xffffc301`c19d2010 _POP_FX_DEVICE
   +0x058 Flags            : _POP_FX_COMPONENT_FLAGS
   +0x060 Resident         : 0n0
   +0x068 ActiveEvent      : _KEVENT
   +0x080 IdleLock         : 0
   +0x088 IdleConditionComplete : 0n0
   +0x08c IdleStateComplete : 0n0
   +0x090 IdleStamp        : 0x90afe7bb
   +0x098 CurrentIdleState : 1
   +0x09c IdleStateCount   : 2
   +0x0a0 IdleStates       : 0xffffc301`c2440670 _POP_FX_IDLE_STATE
   +0x0a8 DeepestWakeableIdleState : 1
   +0x0ac ProviderCount    : 0
   +0x0b0 Providers        : (null) 
   +0x0b8 IdleProviderCount : 0
   +0x0bc DependentCount   : 0
   +0x0c0 Dependents       : (null) 
   +0x0c8 Accounting       : _POP_FX_ACCOUNTING
   +0x1a8 Performance      : (null) 
   +0x1b0 PowerProfile     : (null)

Let’s dump the device information, usually we can find which device the IRP was being sent to.

0: kd> dt _POP_FX_DEVICE 0xffffc301`c19d2010
nt!_POP_FX_DEVICE
   +0x000 Link             : _LIST_ENTRY [ 0xffffc301`c19d1560 - 0xffffc301`c19d29b0 ]
   +0x010 Irp              : 0xffffc301`c1a92b90 _IRP
   +0x018 IrpData          : 0xffffc301`c24406a0 _POP_IRP_DATA
   +0x020 Status           : _POP_FX_DEVICE_STATUS
   +0x024 PowerReqCall     : 0n0
   +0x028 PowerNotReqCall  : 0n0
   +0x030 DevNode          : 0xffffc301`a9bb1bd0 _DEVICE_NODE
   +0x038 DpmContext       : 0xffffc301`bf3b7bf0 PEPHANDLE__
   +0x040 Plugin           : 0xffffc301`a8e75ad0 _POP_FX_PLUGIN
   +0x048 PluginHandle     : 0xffffc301`a9bbabc0 PEPHANDLE__
   +0x050 AcpiPlugin       : (null) 
   +0x058 AcpiPluginHandle : (null) 
   +0x060 DeviceObject     : 0xffffc301`a9b79060 _DEVICE_OBJECT
   +0x068 TargetDevice     : 0xffffc301`a9f22cc0 _DEVICE_OBJECT << This is the clue!        
   +0x070 Callbacks        : _POP_FX_DRIVER_CALLBACKS        
   +0x0c0 DriverContext    : 0xffffc301`bf273508 Void    
   +0x0c8 AcpiLink         : _LIST_ENTRY [ 0xffffc301`c19d20d8 - 0xffffc301`c19d20d8 ]        
   +0x0d8 DeviceId         : _UNICODE_STRING "\_SB.PCI0.HDAS"        
   +0x0e8 RemoveLock       : _IO_REMOVE_LOCK        
   +0x108 AcpiRemoveLock   : _IO_REMOVE_LOCK        
   +0x128 WorkOrder        : _POP_FX_WORK_ORDER        
   +0x160 IdleLock         : 0        
   +0x168 IdleTimer        : _KTIMER        
   +0x1a8 IdleDpc          : _KDPC        
   +0x1e8 IdleTimeout      : 0x1c9c380        
   +0x1f0 IdleStamp        : 0x90afe5c2        
   +0x1f8 NextIrpDeviceObject : [2] (null)         
   +0x208 NextIrpPowerState : [2] _POWER_STATE        
   +0x210 NextIrpCallerCompletion : [2] (null)         
   +0x220 NextIrpCallerContext : [2] (null)         
   +0x230 IrpCompleteEvent : _KEVENT        
   +0x248 PowerOnDumpDeviceCallback : (null)         
   +0x250 Accounting       : _POP_FX_ACCOUNTING        
   +0x330 Flags            : 0x130        
   +0x334 ComponentCount   : 1    
   +0x338 Components       : 0xffffc301`c24404b0  -> 0xffffc301`c24404b8 _POP_FX_COMPONENT
   +0x340 LogEntries       : 0x40
   +0x348 Log              : 0xffffc301`c24407a0 _POP_FX_LOG_ENTRY
   +0x350 LogIndex         : 0n65
   +0x358 DripsWatchdogDriverObject : (null) 
   +0x360 DripsWatchdogContext : _POP_FX_DRIPS_WATCHDOG_CONTEXT
   +0x388 DirectedTimeout  : 0x78
   +0x390 DirectedWorkOrder : _POP_FX_WORK_ORDER
   +0x3c8 DirectedWorkWatchdogInfo : _POP_FX_WORK_ORDER_WATCHDOG_INFO

We’ve now found our IRP which meant to handle our power transistion for the component and as we can see the IRP is still pending, which fits the bugcheck description perfectly!

0: kd> !irp 0xffffc301`c1a92b90
Irp is active with 6 stacks 6 is current (= 0xffffc301c1a92dc8)
 No Mdl: No System Buffer: Thread 00000000:  Irp stack trace.  Pending has been returned
     cmd  flg cl Device   File     Completion-Context
 [N/A(0), N/A(0)]
            0  0 00000000 00000000 00000000-00000000    

            Args: 00000000 00000000 00000000 00000000
 [N/A(0), N/A(0)]
            0  0 00000000 00000000 00000000-00000000    

            Args: 00000000 00000000 00000000 00000000
ffffc301c1a92cf0: Could not read IrpStack

Let’s check the device object which the IRP was intended for. We can find this in the TargetDevice field of the PO_FX_DEVICE structure.

0: kd> !devobj 0xffffc301`a9f22cc0
Device object (ffffc301a9f22cc0) is for:
 InfoMask field not found for _OBJECT_HEADER at ffffc301a9f22c90
*** WARNING: Unable to verify timestamp for IntcAudioBus.sys
 \Driver\IntcAudioBus DriverObject ffffc301a9e7adc0
Current Irp 00000000 RefCount 0 Type 0000002a Flags 0000200c
SecurityDescriptor ffffd70a016ad5e0 DevExt ffffc301bf69a310 DevObjExt ffffc301a9f22e38 
ExtensionFlags (0000000000)  
Characteristics (0x00000100)  FILE_DEVICE_SECURE_OPEN
AttachedTo (Lower) ffffc301a9bd7df0ffffc301a9bd7df0: Could not read device object or _DEVICE_OBJECT not found

Device queue is not busy.

As we can see, it appears to belong to the Intel Smart Sound Technology (Intel SST) Bus.

0: kd> lmvm IntcAudioBus
Browse full module list
start             end                 module name
fffff803`31430000 fffff803`31468000   IntcAudioBus T (no symbols)           
    Loaded symbol image file: IntcAudioBus.sys
    Image path: \SystemRoot\System32\drivers\IntcAudioBus.sys
    Image name: IntcAudioBus.sys
    Browse all global symbols  functions  data
    Timestamp:        Wed Dec 21 05:21:41 2016 (585A81E5)
    CheckSum:         0003FE8D
    ImageSize:        00038000
    Translations:     0000.04b0 0000.04e4 0409.04b0 0409.04e4
    Information from resource tables:

The driver is most likely outdated by this point and therefore I would suggest updating the driver.

References:

Component-Level Power Management – Windows drivers

Bug Check 0xA0: INTERNAL_POWER_ERROR

This entry was posted in Debugging, WinDbg, Windows Internals. Bookmark the permalink.

2 Responses to Debugging Stop 0xA0 – Dude, Where’s My IRP?

  1. bunty says:

    Hey , I got similar bugcheck . But my irp stack says :
    Irp is active with 6 stacks 7 is current (= 0xffff800bd19ec730)
    No Mdl: No System Buffer: Thread 00000000: Irp is completed.
    So what does that mean now ? IRP associated with power down is success , why hit the bugcheck then ?

    Like

Leave a comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.