인터럽트 스톰 디버깅
중단된 시스템의 가장 일반적인 예 중 하나는 인터럽트 폭풍입니다. 인터럽트 폭풍은 어설션된 상태에서 다시 기본 수준 트리거 인터럽트 신호입니다.
다음 이벤트는 인터럽트 폭풍을 일으킬 수 있습니다.
하드웨어 디바이스는 디바이스 드라이버에 의해 수행하도록 지시된 후 인터럽트 신호를 해제하지 않습니다.
디바이스 드라이버는 하드웨어에서 인터럽트를 시작한 것을 감지하지 않으므로 하드웨어에 인터럽트 신호를 해제하도록 지시하지 않습니다.
디바이스 드라이버는 인터럽트를 하드웨어에서 시작하지 않았더라도 인터럽트를 주장합니다. 이 상황은 여러 디바이스가 동일한 IRQ를 공유하는 경우에만 발생할 수 있습니다.
ELCR(에지 수준 컨트롤 레지스터)이 올바르게 설정되지 않았습니다.
Edge 및 수준 인터럽트 트리거 디바이스는 IRQ(예: COM 포트 및 PCI SCSI 컨트롤러)를 공유합니다.
이 예제에서는 인터럽트 폭풍을 감지하고 디버깅하는 한 가지 방법을 보여 줍니다.
컴퓨터가 중단되면 커널 디버거를 사용하여 침입합니다. !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에 대한 IRP를 반환하지 않은 것을 보여 줍니다. PopCompleteSystemPowerIrp. 중단된 것으로 보이며 인터럽트 폭풍이 발생할 수 있습니다.
조사하려면 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). 표준 규칙은 표시된 인터럽트 벡터(0x3B)가 IRQ 줄과 0x30 더하기 때문에 인터럽트는 숫자 0xB. 다른 스택 추적을 실행하면 ISR(인터럽트 서비스 요청)을 실행한 디바이스에 대한 자세한 정보가 제공될 수 있습니다. 이 경우 두 번째 스택 추적의 결과는 다음과 같습니다.
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이 인터럽트 처리를 요청합니다. 프로세스에서 인터럽트를 처리하고 중지할 수도 있지만 하드웨어가 중단되면 인터럽트를 다시 어설션할 수 있습니다.
!중재자 4 확장을 사용하여 IRQ 0xB 있는 디바이스를 확인합니다. IRQ 0xB 디바이스가 하나만 있는 경우 문제의 원인을 찾았습니다. 인터럽트(사례의 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 <주소를 사용하는 것은 해당 주소> 에 중단점을 설정하는 것과 같습니다.
kd> g bfe33e7b
ds1wdm!AdapterIsr+ad:
bfe33e7b c20800 ret 0x8
r 명령을 사용하여 레지스터를 검사합니다. 특히 EAX 레지스터를 확인합니다. 다음 코드 예제에 표시된 EAX 레지스터 콘텐츠가 0이 아닌 경우 이 ISR은 인터럽트(interrupt)를 요청했습니다. 그렇지 않으면 인터럽트는 클레임되지 않으며 운영 체제는 다음 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입니다. 즉, 오디오 칩은 현재 효과적으로 비활성화됩니다. 이는 또한 오디오 칩이 드라이버의 액세스에 응답할 수 없음을 의미합니다.
이 경우 오디오 칩을 수동으로 다시 사용하도록 설정해야 합니다.