第五篇:风起于青萍之末-电源管理请求案例分析(上)

来源:互联网 发布:元数据系统 编辑:程序博客网 时间:2024/04/28 16:13

前一阵子,软件组的同事向我提交了几个与电源管理请求相关的BSOD转储文件,由于手头积压了较多的BSOD DUMP FILE待分析, 所以起初并没有对这几个与电源请求相关的DUMP FILE有足够的重视,随着同事后续又提交了一系列该类型的转储文件,而该BSOD又是每天都发生,在达到近20多个该类型的BSOD DUMP FILE后,我决定先放开别的事情,对这个问题花时间去研究研究.


在前面的文章中,已经提及,无论USB设备还是USB主机的开发,均离不开USB-IF的GOLDEN TREE/INTEROP测试.

对于xhci host的测试要求,目前最近版本为<<xHCI_Interoperability_Testing_v1_58>>, 下图为一个完整的GOLDEN TREE.

简而言之,在被测试设备/device或者主机/host,还是USB集线器/hub,纳入该GOLDEN TREE的情况下,所有GOLDEN TREE中的USB3.0 host, USB3.0/2.0/1.1/1.0设备与HUB都要能够正常正确地工作.

而这一系列的BSOD均是在操作系统将要把整个系统带入S3的过程中发生的. 因为当OS系统发出ENTER S3的请求,在足够长的时间内,系统并未按要求进入S3.

该问题明显是由这个GOLDEN TREE所导致的,但该GOLDEN中包括了近30个单元,每个单元又加载了一个到多个不等的驱动程序,如何将怀疑对象的范围缩小,是我第一步需要做的当务之急.



在跳进去进行分析之前,查找了一些相关的文章:

包括:

张银奎 <<格蠹汇编>>中的第6章<<再解电源服务溢出崩溃>>

   第7章<<三解电源服务溢出崩溃>>

           第16章<<转储分析之探寻唤醒失败原因>>.

   第31章<<在调试器中观察计算机的睡眠过程>>

其中,第16章<<转储分析之探寻唤醒失败原因>>确实给出了张银奎老师自己所碰到的关于电源管理导致的BSOD的一个案例具体分析过程,但问题是,与我所接收到一BSOD的问题正好相反.而且该文章,最后将系统无法唤醒的原因草草地归结为微软的USB3.0 HUB的usbhub驱动没有调用上层函数给出的完成例程,但却没有给出为什么上层函数给出的完成例程不被USBHUB驱动调用的原因. 实在有点遗憾.


之后,又查找到两篇相关文章:

http://www.yiiyee.cn/Blog/0x9f-2/

http://www.yiiyee.cn/Blog/fast_mutex/

在看完这两篇文章后,对电源管理BSOD的分析有了进一步的掌握与较多的收获,但离分析出结果还是征途漫漫,其根本原因是,都是电源管理的BSOD,但却是"形似神不似".


看来,要想从别人那里立马取得问题的解决方法,是不太可能的事情了,毕竟,人家出问题的环境与我们的GOLDEN TREE是不同的.

打开WINDBG,导入BSOD文件, 先进行初分析:

*************************************************************

DRIVER_POWER_STATE_FAILURE (9f)
A driver has failed to complete a power IRP within a specific time.
Arguments:
Arg1: 00000003, A device object has been blocking an Irp for too long a time
Arg2: 85be34c0, Physical Device Object of the stack
Arg3: 836c5a00, nt!TRIAGE_9F_POWER on Win7 and higher, otherwise the Functional Device Object of the stack
Arg4: bcd5eaa0, The blocked IRP

*************************************************************

对这个问题中文解释一下:

系统发给设备栈中的一个物理设备对象的IRP超时,导致了该BSOD.

于是问题就随之而来了:

1.这是什么类型的电源管理IRP,即他的MINOR FUNCTION是什么?

2.哪个物理设备对象是该IRP的接收者?

3.这种MAJOR/MINOR组合的IRP系统能够接收的处理时间范围是多少?

4.而这个IRP到底又被阻塞了多少时间?

5.为什么这个IRP会被阻塞?



第一个问题,这是什么具体类型的电源管理IRP?

是取得GET系统或者是设备的电源状态,还是设置SET?


电源管理方法,相关类型是指:

是系统还是针对于某个设备?

nt!_POWER_STATE_TYPE

   SystemPowerState =0n0

   DevicePowerState =0n1


如果是针对于系统的,该目标状态是多少?

nt!_SYSTEM_POWER_STATE

  PowerSystemUnspecified = 0n0

   PowerSystemWorking= 0n1

  PowerSystemSleeping1 = 0n2

  PowerSystemSleeping2 = 0n3

  PowerSystemSleeping3 = 0n4

  PowerSystemHibernate = 0n5

   PowerSystemShutdown= 0n6

   PowerSystemMaximum= 0n7


同样,如果针对于设备,它的目标状态又是多少?

nt!_DEVICE_POWER_STATE

  PowerDeviceUnspecified = 0n0

   PowerDeviceD0 = 0n1

   PowerDeviceD1 = 0n2

   PowerDeviceD2 = 0n3

   PowerDeviceD3 = 0n4

   PowerDeviceMaximum= 0n5



要得到这个答案,有两种方法,

方法一, 

通过该IRP指针取得它当前栈的指针(Tail.Overlay.CurrentStackLocation )

然后通过这个栈的指针,取得该IRP的MajorFunction与MinorFunction类型

MajorFunction=0x16

MinorFunction=0x02

查找对应的WDM.H, 得出,这是一个设置SET类型的电源管理IRP.

IRP_MJ_POWER = 0x16

IRP_MN_SET_POWER = 0x2


再进一步:

通过该CurrentStackLocation的偏移为4的Parameters,取得上面所述的电源设置类型:

++++++++++++++++++++++++++++++++++++++

 kd> dd 0xbcd5ef90+4 L4
bcd5ef94  00015400 00000001 00000004 00000003

++++++++++++++++++++++++++++++++++++++

我对以上一串数字进行一个注释:

bcd5ef94 地址

00015400 (System context,与该BSOD的分析无关)

00000001(DevicePowerState)

00000004(PowerDeviceD3) 

00000003 (Shutdown Type, 与该BSOD的分析无关)


这就是要将指定的物理设备对象设置为D3的状态.

这个IRP类型,与我们要将系统置入S3,但在这个时候系统BSOD了,也是相符合的.


第二种方法:

通过微软未公开的WINDBG调试命令:

!poaction

一步到位:如下输出

而且这个方便的命令,还给出了更加有用的内容

1. 该SET DEVICE D3的IRP前面,还有一个SET System S4的IRP.

2. 发出该IRP的线程.

++++++++++++++++++++++++++++++++++++++++++++++++++++++

Allocated power irps (PopIrpList - 825fb560)
  IRP: 8a90af48 (wait-wake/S3), PDO: 891050f0
  IRP: 91da2f00 (wait-wake/S4), PDO: 890dba50
  IRP: 80e7cc98 (wait-wake/S4), PDO: 86a54500
  IRP: 80eb4d50 (wait-wake/S4), PDO: a805c650
  IRP: 80fb8c30 (wait-wake/S4), PDO: a806a030
  IRP: 80f9cce0 (wait-wake/S4), PDO: 86a1e4d0
  IRP: 80eded70 (wait-wake/S4), PDO: 86a22620
  IRP: 81b8a9f0 (wait-wake/S4), PDO: b6cda080
  IRP: be9da9f0 (wait-wake/S4), PDO: b5186ce0
  IRP: 80350aa0 (wait-wake/S4), PDO: b6df2878
  IRP: b597c8a8 (wait-wake/S4), PDO: b5119ce0
  IRP: be8b4960 (wait-wake/S4), PDO: b511a030
  IRP: aed5a9f0 (wait-wake/S4), PDO: bae779e0
  IRP: 814c8aa0 (wait-wake/S4), PDO: b6df2bd8
  IRP: 80396b78 (wait-wake/S4), PDO: baf13490
  IRP: ab7b4aa0 (set/S4), PDO: 85be34c0, CURRENT: baf54bf8, NOTIFY: 86a3e038
  IRP: bcd5eaa0 (set/D3,), PDO: 85be34c0, CURRENT: baf54bf8
  IRP: bb7fcb78 (wait-wake/S4), PDO: baf42ac8
  IRP: aa70cde0 (wait-wake/S4), PDO: 85b81030
  IRP: 815eaeb8 (wait-wake/S3), PDO: 890de030
  IRP: 80ef0c50 (wait-wake/S4), PDO: 943aa148
  IRP: bb754e48 (wait-wake/S4), PDO: 8e0d7028
  IRP: ba774de0 (wait-wake/S4), PDO: 943b3650
  IRP: b58e4eb8 (wait-wake/S3), PDO: 890dc030
  IRP: bb7b6e48 (wait-wake/S4), PDO: 8e0ca028
  IRP: 97512d28 (wait-wake/S4), PDO: 86a37178


Irp worker threads (PopIrpThreadList - 825fad88)
  THREAD: 85ba55c0 (static)
  THREAD: 85b6b640 (static)
  THREAD: b745f500 (dynamic)
  THREAD: 8904db00 (dynamic)
  THREAD: 8bc34200 (dynamic), IRP: bcd5eaa0, DEVICE: 86a235e8
  THREAD: b6d7e040 (dynamic)
  THREAD: b514ad40 (dynamic)
  THREAD: bae16d40 (dynamic)

***********************************************************************************************


第二个问题: 这个电源管理IRP的接收对象是谁?

我们已经知道这个物理设备对象的指针:PDO: 85be34c0

所以,要得到这个答案并非难事:

通过分析,我发现,这个物理设备对象,是GOLDEN TREE上的第四级的SS HUB(USB3.0 HUB), 即上图中的HUB SS4.

在更进一步分析,推测与下结论之前, 我要问的问题是, 是不是所有的BSOD存在相同的情况, 还是不同的情况?

于是,我打开所有近20个该类型的BOSD, 得出的结论是: 所有的超时IRP类型相同, 而且都是发给第四级的SS HUB.

这样一个暂时的结论,对于我们后续的分析反而变得简单了, 相反,如果这些IRP类型不同,接收者又是位于GOLDEN TREE中的不同设备,或者不同级的HUB,这个问题反而难度更高.

下一篇 ,我将给出进一步的分析,直至ROOT CAUSE.





0 0
原创粉丝点击