割り込みストームのデバッグ
停止したシステムの最も一般的な例の 1 つは、割り込みストームです。 割り込みストームは、アサートされた状態のままのレベル トリガーされた割り込みシグナルです。
以下のイベントで、割り込みストームが発生する可能性があります。
ハードウェア デバイスが、デバイス ドライバーから割り込みシグナルを解除するように指示された後も、解除しない。
デバイス ドライバーが、割り込みがハードウェアから開始されたことを検出せず、割り込みシグナルを解放するようハードウェアに指示しない。
割り込みがハードウェアから開始されなかった場合でも、デバイス ドライバーが割り込みを要求する。 この状況は、複数のデバイスが同じ IRQ を共有しているときにのみ発生します。
エッジ レベル制御レジスタ (ELCR) が正しく設定されていない。
エッジおよびレベル割り込みによってトリガーされるデバイスが、IRQ を共有している (COM ポートや PCI SCSI コントローラーなど)。
この例では、割り込みストームを検出してデバッグするための 1 つの方法を示します。
マシンがハングしたら、カーネル デバッガーを使用して割り込みます。 !irpfind 拡張機能コマンドを使用して、保留中の IRP を探します。 次に、!irp 拡張機能を使用して、保留中の IRP に関する詳細情報を取得します。 次に例を示します。
kd> !irp 81183468
Irp is active with 2 stacks 2 is current (= 0x811834fc)
No Mdl Thread 00000000: Irp stack trace.
cmd flg cl Device File Completion-Context
[ 0, 0] 0 0 8145f470 00000000 00000000-00000000
\Driver\E100B
Args: 00000000 00000000 00000000 00000000
>[ 16, 2] 0 e1 8145f470 00000000 8047f744-814187a8 Success Error Cancel pending
\Driver\E100B ntoskrnl!PopCompleteSystemPowerIrp
Args: 00000000 00000000 00000002 00000002
この例は、\driver\e100b が ntoskrnl!PopCompleteSystemPowerIrp のIRP を返していないことを示しています。 スタックしているように思われ、割り込みストームが発生している可能性があります。
調査するには、kb コマンドを使用してスタック トレースを要求します。 次に例を示します。
kd> kb
ChildEBP RetAddr Args to Child
f714ee68 8046355a 00000001 80068c10 00000030 ntoskrnl!RtlpBreakWithStatusInstruction
f714ee68 80067a4f 00000001 80068c10 00000030 ntoskrnl!KeUpdateSystemTime+0x13e
f714eeec 8046380b 01001010 0000003b f714ef00 halacpi!HalBeginSystemInterrupt+0x83
f714eeec 80463c50 01001010 0000003b f714ef00 ntoskrnl!KiChainedDispatch+0x1b
f714ef78 80067cc2 00000000 00000240 8000017c ntoskrnl!KiDispatchInterrupt
f714ef78 80501cb5 00000000 00000240 8000017c halacpi!HalpDispatchInterrupt2ndEnt
halacpi!HalBeginSystemInterrupt
で始まるセクションは割り込みディスパッチであることに注意してください。 g コマンドを使用してもう一度割り込むと、異なるスタック トレースが表示される可能性が非常に高くなりますが、割り込みディスパッチは引き続き表示されます。 システム停止の原因となる割り込みを特定するには、HalBeginSystemInterrupt (この場合は 0x3B) に渡された 2 つ目のパラメーターを確認します。 標準ルールは、表示される割り込みベクター (0x3B) が IRQ 行に 0x30 を加えたものであるため、割り込みは 0xB です。 別のスタック トレースを実行すると、割り込みサービス要求 (ISR) を発行したデバイスに関する詳細情報が提供されることがあります。 この場合、2 つ目のスタック トレースの結果は次のようになります。
kd> kb
ChildEBP RetAddr Args to Child
f714ee24 8046355a 00000001 00000010 00000030 ntoskrnl!RtlpBreakWithStatusInstruction
f714ee24 bfe854b9 00000001 00000010 00000030 ntoskrnl!KeUpdateSystemTime+0x13e
f714eed8 f7051796 00000000 80463850 8143ec88 atimpab!AtiInterrupt+0x109
f714eee0 80463850 8143ec88 81444038 8046380b VIDEOPRT!pVideoPortInterrupt+0x16
f714eef8 80463818 00000202 0000003b 80450bb8 ntoskrnl!KiChainedDispatch2ndLvl+0x28
f714eef8 80463c50 00000202 0000003b 80450bb8 ntoskrnl!KiChainedDispatch+0x28
f714ef78 80067cc2 00000000 00000240 8000017c ntoskrnl!KiDispatchInterrupt
f714ef78 80501cb5 00000000 00000240 8000017c halacpi!HalpDispatchInterrupt2ndEntry+0x1b
f714f084 8045f744 f714f16c 00020019 f714f148 ntoskrnl!NtCreateKey+0x113
f714f084 8042e487 f714f16c 00020019 f714f148 ntoskrnl!KiSystemService+0xc4
f714f118 804ab556 f714f16c 00020019 f714f148 ntoskrnl!ZwCreateKey+0xb
f714f184 8041f75b f714f1e8 8000017c f714f1d0 ntoskrnl!IopCreateRegistryKeyEx+0x4e
f714f204 804965cd 8145f630 00000000 00000001 ntoskrnl!IopProcessSetInterfaceState+0x93
f714f220 bfee1eb9 8145f630 00000000 8145f5a0 ntoskrnl!IoSetDeviceInterfaceState+0x2b
f714f254 bfedb416 00000004 00000800 0045f570 NDIS!ndisMCommonHaltMiniport+0x1f
f714f268 bfed4ddb bfed0660 811a2708 811a2708 NDIS!ndisPmHaltMiniport+0x9a
f714f288 bfed5146 811a2708 00000004 8145f570 NDIS!ndisSetPower+0x1d1
f714f2a8 8041c60f 81453a30 811a2708 80475b18 NDIS!ndisPowerDispatch+0x84
f714f2bc 8044cc52 80475b18 811a2708 811a279c ntoskrnl!IopfCallDriver+0x35
f714f2d4 8044cb89 811a279c 811a2708 811a27c0 ntoskrnl!PopPresentIrp+0x62
システムは現在、ビデオ カードに対して ISR を実行しています。 システムは、IRQ 0xB を共有する各デバイスに対して ISR を実行します。 プロセスが割り込みを要求しない場合、オペレーティング システムは無限に待機し、ドライバーの ISR に割り込みを処理するよう要求します。 プロセスが割り込みを処理して停止する可能性もありますが、ハードウェアが破損している場合、割り込みは単に再アサートされる可能性があります。
!arbiter 4 拡張機能を使用して、IRQ 0xB 上のデバイスを特定します。 IRQ 0xB にデバイスが 1 つしかない場合は、これで問題の原因が見つかりました。 割り込みを共有するデバイスが複数ある場合 (99% のケース)、LNK ノードを手動でプログラミングするか (システム状態に対して破壊的)、またはハードウェアを削除または無効にして、デバイスを分離する必要があります。
kd> !arbiter 4
DEVNODE 8149a008 (HTREE\ROOT\0)
Interrupt Arbiter "RootIRQ" at 80472a20
Allocated ranges:
0000000000000000 - 0000000000000000 B 8149acd0
0000000000000001 - 0000000000000001 B 8149acd0
0000000000000002 - 0000000000000002 B 8149acd0
0000000000000003 - 0000000000000003 B 8149acd0
0000000000000004 - 0000000000000004 B 8149acd0
0000000000000005 - 0000000000000005 B 8149acd0
0000000000000006 - 0000000000000006 B 8149acd0
0000000000000007 - 0000000000000007 B 8149acd0
0000000000000008 - 0000000000000008 B 8149acd0
0000000000000009 - 0000000000000009 B 8149acd0
000000000000000a - 000000000000000a B 8149acd0
000000000000000b - 000000000000000b B 8149acd0
000000000000000c - 000000000000000c B 8149acd0
000000000000000d - 000000000000000d B 8149acd0
000000000000000e - 000000000000000e B 8149acd0
000000000000000f - 000000000000000f B 8149acd0
0000000000000010 - 0000000000000010 B 8149acd0
0000000000000011 - 0000000000000011 B 8149acd0
0000000000000012 - 0000000000000012 B 8149acd0
0000000000000013 - 0000000000000013 B 8149acd0
0000000000000014 - 0000000000000014 B 8149acd0
0000000000000015 - 0000000000000015 B 8149acd0
0000000000000016 - 0000000000000016 B 8149acd0
0000000000000017 - 0000000000000017 B 8149acd0
0000000000000018 - 0000000000000018 B 8149acd0
0000000000000019 - 0000000000000019 B 8149acd0
000000000000001a - 000000000000001a B 8149acd0
000000000000001b - 000000000000001b B 8149acd0
000000000000001c - 000000000000001c B 8149acd0
000000000000001d - 000000000000001d B 8149acd0
000000000000001e - 000000000000001e B 8149acd0
000000000000001f - 000000000000001f B 8149acd0
0000000000000020 - 0000000000000020 B 8149acd0
0000000000000021 - 0000000000000021 B 8149acd0
0000000000000022 - 0000000000000022 B 8149acd0
0000000000000023 - 0000000000000023 B 8149acd0
0000000000000024 - 0000000000000024 B 8149acd0
0000000000000025 - 0000000000000025 B 8149acd0
0000000000000026 - 0000000000000026 B 8149acd0
0000000000000027 - 0000000000000027 B 8149acd0
0000000000000028 - 0000000000000028 B 8149acd0
0000000000000029 - 0000000000000029 B 8149acd0
000000000000002a - 000000000000002a B 8149acd0
000000000000002b - 000000000000002b B 8149acd0
000000000000002c - 000000000000002c B 8149acd0
000000000000002d - 000000000000002d B 8149acd0
000000000000002e - 000000000000002e B 8149acd0
000000000000002f - 000000000000002f B 8149acd0
0000000000000032 - 0000000000000032 B 8149acd0
0000000000000039 - 0000000000000039 S 814776d0 (ACPI)
Possible allocation:
< none >
DEVNODE 81476f28 (ACPI_HAL\PNP0C08\0)
Interrupt Arbiter "ACPI_IRQ" at bfff10e0
Allocated ranges:
0000000000000000 - 0000000000000000 B 81495bb0
0000000000000001 - 0000000000000001 814952b0 (i8042prt)
0000000000000003 - 0000000000000003 S 81495610 (Serial)
0000000000000004 - 0000000000000004 B 8149acd0
0000000000000006 - 0000000000000006 81495730 (fdc)
0000000000000008 - 0000000000000008 81495a90
0000000000000009 - 0000000000000009 S 814776d0 (ACPI)
000000000000000b - 000000000000000b S
000000000000000b - 000000000000000b S 81453c30 (ds1)
000000000000000b - 000000000000000b S 81453a30 (E100B)
000000000000000b - 000000000000000b S 81493c30 (uhcd)
000000000000000b - 000000000000000b S 8145c390 (atirage3)
000000000000000c - 000000000000000c 814953d0 (i8042prt)
000000000000000d - 000000000000000d B 81495850
000000000000000e - 000000000000000e 8145bb50 (atapi)
000000000000000f - 000000000000000f 8145b970 (atapi)
Possible allocation:
< none >
この場合、オーディオ、ユニバーサル シリアル バス (USB)、ネットワーク インターフェイス カード (NIC)、ビデオがすべて同じ IRQ を使用しています。
どの ISR が割り込みの所有権を要求しているかを調べるには、ISR からの戻り値を調べます。 !arbiter 表示で指定されたアドレスで U コマンドを使用して ISR を逆アセンブルし、ISR の最後の命令 ('ret' 命令) にブレークポイントを設定します。 コマンド g <address> を使用することは、そのアドレスにブレークポイントを設定することと同じです。
kd> g bfe33e7b
ds1wdm!AdapterIsr+ad:
bfe33e7b c20800 ret 0x8
r コマンドを使用してレジスタを調べます。 特に、EAX レジスタを調べます。 次のコード例に示される EAX レジスタの内容が 0 以外である場合、この ISR が割り込みを要求しました。 それ以外の場合、割り込みは要求されてなくて、オペレーティング システムが次の ISR を呼び出します。 この例は、ビデオ カードが割り込みを要求していないことを示しています。
kd> r
eax=00000000 ebx=813f4ff0 ecx=00000010 edx=ffdff848 esi=8145d168 edi=813f4fc8
eip=bfe33e7b esp=f714eec4 ebp=f714eee0 iopl=0 nv up ei pl zr na po nc
cs=0008 ss=0010 ds=0023 es=0023 fs=0030 gs=0000 efl=00000246
ds1wdm!AdapterIsr+ad:
bfe33e7b c20800 ret 0x8
実際、この場合、割り込みは IRQ 0xb 上のどのデバイスからも要求されません。 この問題が発生した場合は、割り込みに関連付けられているハードウェアの各部分が実際に有効になっているかどうかを確認する必要もあります。 PCI の場合、これは簡単です。!pci 拡張機能の出力によって表示される CMD レジスタを確認します。
kd> !pci 0 0
PCI Bus 0
00:0 8086:7190.03 Cmd[0006:.mb...] Sts[2210:c....] Device Host bridge
01:0 8086:7191.03 Cmd[0107:imb..s] Sts[0220:.6...] PciBridge 0->1-1 PCI-PCI bridge
03:0 1073:000c.03 Cmd[0000:......] Sts[0210:c....] Device SubID:1073:000c Audio device
04:0 8086:1229.05 Cmd[0007:imb...] Sts[0290:c....] Device SubID:8086:0008 Ethernet
07:0 8086:7110.02 Cmd[000f:imb...] Sts[0280:.....] Device ISA bridge
07:1 8086:7111.01 Cmd[0005:i.b...] Sts[0280:.....] Device IDE controller
07:2 8086:7112.01 Cmd[0005:i.b...] Sts[0280:.....] Device USB host controller
07:3 8086:7113.02 Cmd[0003:im....] Sts[0280:.....] Device Class:6:80:0
オーディオ チップ ("オーディオ デバイス" というラベルが付いている) CMD レジスタが 0 であることに注意してください。 これは、現時点でオーディオ チップが効果的に無効になっていることを意味します。 これは、オーディオ チップがドライバーによるアクセスに応答できないことも意味します。
この場合、オーディオ チップを手動で再度有効にする必要があります。