中断好比计算机系统的脉搏,是系统生命力的源泉。在WinDBG做内核调试时该如何观察系统的中断分配和响应情况呢?WinDBG的帮助文件对此描述甚少,已经有的几个重要扩展命令居然也没有出现在帮助文件中。下面就以调试一个双核的G33系统为例简介绍一下常用的几个命令。
!pic
显示传统ISA中断(8259)的当前状态,例如:
1: kd> !pic
----- IRQ Number ----- 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
Physically in service: . . . . . . . . . . . . . . . .
Physically masked: Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y
Physically requested: . . . . . . . . Y Y Y Y . . . .
第一行是中断号,传统的ISA中断只有16个,其实是两个8259控制器级联在一起。第二行是CPU是否正在服务于对应的中断,.代表CPU没有在服务这个中断。第三行是中断屏蔽情况,因为观察时内核调试引擎将系统中断,屏蔽了大多数中断。第四行显示的是设备请求中断的情况。
如果多次执行这个命令,那么可能看到第四行内容有所变化:
0: kd> !pic
----- IRQ Number ----- 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
Physically in service: . . . . . . . . . . . . . . . .
Physically masked: Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y
Physically requested: Y . . . . . . . Y Y Y Y . . . .
!ioapic
显示位于芯片组中的IO APIC的状态
0: kd> !ioapic
IoApic @ FEC00000 ID:2 (20) Arb:170020
Inti00.: 000100ff Vec:FF FixedDel PhysDest:00 edg high masked
Inti01.: 00000951 Vec:51 LowestDl Lg:03000000 edg high
Inti02.: 000109ff Vec:FF LowestDl Lg:03000000 edg high masked
Inti03.: 000109ff Vec:FF LowestDl Lg:01000000 edg high masked
Inti04.: 000109ff Vec:FF LowestDl Lg:03000000 edg high masked
Inti05.: 000109ff Vec:FF LowestDl Lg:01000000 edg high masked
Inti06.: 000109ff Vec:FF LowestDl Lg:01000000 edg high masked
Inti07.: 000109ff Vec:FF LowestDl Lg:01000000 edg high masked
Inti08.: 000008d1 Vec:D1 FixedDel Lg:01000000 edg high
Inti09.: 0000d9b1 Vec:B1 LowestDl Lg:03000000-Pend lvl high rirr
Inti0A.: 000109ff Vec:FF LowestDl Lg:01000000 edg high masked
Inti0B.: 000109ff Vec:FF LowestDl Lg:01000000 edg high masked
Inti0C.: 00000961 Vec:61 LowestDl Lg:03000000 edg high
Inti0D.: 000109ff Vec:FF LowestDl Lg:01000000 edg high masked
Inti0E.: 00000952 Vec:52 LowestDl Lg:03000000 edg high
Inti0F.: 000009b3 Vec:B3 LowestDl Lg:03000000 edg high
Inti10.: 0000a9b2 Vec:B2 LowestDl Lg:03000000 lvl low
Inti11.: 0000f992 Vec:92 LowestDl Lg:03000000-Pend lvl low rirr
Inti12.: 0000f982 Vec:82 LowestDl Lg:03000000-Pend lvl low rirr
Inti13.: 0000f972 Vec:72 LowestDl Lg:03000000-Pend lvl low rirr
Inti14.: 000109ff Vec:FF LowestDl Lg:01000000 edg high masked
Inti15.: 0000f962 Vec:62 LowestDl Lg:03000000-Pend lvl low rirr
Inti16.: 0000a993 Vec:93 LowestDl Lg:03000000 lvl low
Inti17.: 0000f9a3 Vec:A3 LowestDl Lg:03000000-Pend lvl low rirr
这个表格中很有用的信息是显示出了中断号和IDT表中向量号的对应关系。比如IRQ8对应的向量号是0xD1。
执行!idt d1便可以看到这个中断/向量所对应的处理例程:
0: kd> !idt d1
Dumping IDT:
d1: 82ba4614 hal!HalpRtcClockInterrupt
在设备管理器中可以看到IRQ8分配给了RTC(Real time clock)设备,因此上面的显示是吻合的。
!apic
显示当前CPU内部的局部APIC状态。
0: kd> !apic
Apic @ fffe0000 ID:0 (50014) LogDesc:01000000 DestFmt:ffffffff TPR 00
TimeCnt: 0fe536c0clk SpurVec:1f FaultVec:e3 error:0
Ipi Cmd: 000c00e1 Vec:E1 FixedDel Dest=Othrs edg high
Timer..: 000300fd Vec:FD FixedDel Dest=Self edg high masked
Linti0.: 0001001f Vec:1F FixedDel Dest=Self edg high masked
Linti1.: 000004ff Vec:FF NMI Dest=Self edg high
TMR: 62, 72, 82, 92-93, A3, B1-b2
IRR: 62, 82, B1, D1
ISR: E1
每个CPU有一个局部的APIC,因此要观察另一个CPU的,应该先切换到另一个CPU:
0: kd> ~1s
1: kd> !apic
Apic @ fffe0000 ID:1 (50014) LogDesc:02000000 DestFmt:ffffffff TPR 00
TimeCnt: 0fe536c0clk SpurVec:1f FaultVec:e3 error:80
Ipi Cmd: 000c00e1 Vec:E1 FixedDel Dest=Othrs edg high
Timer..: 000300fd Vec:FD FixedDel Dest=Self edg high masked
Linti0.: 0001001f Vec:1F FixedDel Dest=Self edg high masked
Linti1.: 000004ff Vec:FF NMI Dest=Self edg high
TMR: 62, 72, 82, 92-93, A3, B1-b2
IRR: 61, 72, 92, A3
ISR: D1
其中的IRR代表Interrupt Request Register,ISR代表Interrupt Service Register,前者后面列出的是在请求队列中的中断向量号,ISR后面列出的是已经处理完的中断(在处理好队列中的)。