原貼最初發表在QQ空間:
Win7下的段和門 (2)
,http://user.qzone.qq.com/31731705/blog/1322121566
代碼和相關的分析在這:
Win7下的段和門 (2) (附錄),http://user.qzone.qq.com/31731705/blog/1322535584
不久前寫過一篇
Win7下的段和門(http://user.qzone.qq.com/31731705/blog/1313733365),分析了Win7平台上保護模式中使用到的資料結構,主要就是GDT和IDT的資料分析。實際上,在Win7下,GDT和IDT都和CPU有關係,我的電腦是雙核處理器,測試結果如下,
0: kd> !sysinfo cpuinfo
[CPU Information]
~MHz = REG_DWORD 2527
Component Information = REG_BINARY 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
Configuration Data = REG_FULL_RESOURCE_DESCRIPTOR ff,ff,ff,ff,ff,ff,ff,ff,0,0,0,0,0,0,0,0
Identifier = REG_SZ x86 Family 6 Model 23 Stepping 10
ProcessorNameString = REG_SZ Intel(R) Core(TM)2 Duo CPU P8700 @ 2.53GHz
Update Signature = REG_BINARY 0,0,0,0,7,a,0,0
Update Status = REG_DWORD 6
VendorIdentifier = REG_SZ GenuineIntel
MSR8B = REG_QWORD a0700000000
0: kd> r gdtr, gdtl, idtr, idtl
gdtr=80b95000 gdtl=000003ff idtr=80b95400 idtl=000007ff
1: kd> r gdtr, gdtl, idtr, idtl
gdtr=807d2c20 gdtl=000003ff idtr=807d3020 idtl=000007ff可見,針對不同的CPU,IDT和GDT的地址是不一樣的,那麼,它們中的內容是否是一樣的呢?因為Win7是對稱式多處理系統,理論上即使使用了多個表,它們中的內容應該是相同的。為了研究這個問題,也順便寫了個指令碼,測試一下我的想法。
0: kd> $$>a< ${sp}\cmp_gdt.wds
This script is to compare 2 CPU information.
First argument (0)...
0x1 is to compare GDT.
0x2 is to compare IDT.
====================================================================================
這個指令碼帶1個參數,用來指出是比較哪張表,GDT還是IDT。
看下指令碼啟動並執行結果,給上參數3,就是1+2的意思,同時比較GDT和IDT。
0: kd> $$>a< ${sp}\cmp_gdt.wds 3
GDT base address: 80b95000, 807d2c20, Number of items: 0n128, 0n128
Index Selector Address 1st value 2nd value
0005 0028/0028 (80b95028, 807d2c48) (80008b1e, d00020ab) (80008b7c, d75020ab)
0006 0030/0030 (80b95030, 807d2c50) (84409396, 9c003748) (8040937c, a0003748)
0007 003B/003B (80b95038, 807d2c58) (7f40f3fd, e0000fff) (7f40f3fd, e0004000)
000A 0050/0050 (80b95050, 807d2c70) (84008996, 70000068) (8000897c, fac00068)
000B 0058/0058 (80b95058, 807d2c78) (84008996, 70680068) (8000897c, fb300068)
0014 00A0/00A0 (80b950a0, 807d2cc0) (870089bb, 91c00068) (870089ab, 8f980068)
There are total 0n6 items different.IDT base address: 80b95400, 807d3020, Number of items: 0n256, 0n256
Index Address 1st value 2nd value
0052 (80b95690, 807d32b0) (8aa78e00, 000812d8) (8aa68e00, 0008c558)
0062 (80b95710, 807d3330) (8aa78e00, 000817d8) (8aa68e00, 0008ca58)
0071 (80b95788, 807d33a8) (8c6b8e00, 00087058) (8c6a8e00, 000892d8)
0072 (80b95790, 807d33b0) (887f8e00, 00088a58) (887f8e00, 00089a58)
0081 (80b95808, 807d3428) (8c6b8e00, 000872d8) (8c6a8e00, 00089558)
0082 (80b95810, 807d3430) (887f8e00, 00088058) (887f8e00, 00089058)
0092 (80b95890, 807d34b0) (8aa78e00, 00081cd8) (8aa68e00, 0008ccd8)
00A0 (80b95900, 807d3520) (8afb8e00, 0008fcd8) (8aa68e00, 0008c058)
00A2 (80b95910, 807d3530) (887f8e00, 00088558) (887f8e00, 00089558)
00B0 (80b95980, 807d35a0) (8aa78e00, 00081a58) (84878e00, 0008cbc0)
00B1 (80b95988, 807d35a8) (887f8e00, 00088cd8) (887f8e00, 00089cd8)
00B3 (80b95998, 807d35b8) (8aa78e00, 00081558) (8aa68e00, 0008c7d8)
00D1 (80b95a88, 807d36a8) (84808e00, 0008a634) (84808e00, 0008b2d8)
There are total 0n13 items different.
====================================================================================
乍一看不同項挺多的,實際上總共GDT有128項,IDT有256項,不同的項占的比例並不多。那麼,這些不同的項到底是些什麼內容呢?先看GDT,有6項,結合第一篇
Win7下的段和門(http://user.qzone.qq.com/31731705/blog/1313733365)中描述的,30/3B分別是核心態和使用者態的FS段,它們確實是CPU相關的,因此不一樣。28呢?它是當前任務的TSS段,與當前的任務相關,也是CPU相關的。
1: kd> r @tr
tr=00000028
剩下的是什嗎?分析下就知道,實際上是三個TSS,分別對應著IDT中的三個任務門,用來處理異常 NMI (0x2), #DF (0x8), #MC (0x12)
1: kd> !idt 2; !idt 8; !idt 12
Dumping IDT:
02: Task Selector =
0x0058
Dumping IDT:
08: Task Selector =
0x0050
Dumping IDT:
12: Task Selector =
0x00A0
關於TSS和FS段的作用,參見
http://user.qzone.qq.com/31731705/blog/1304389170。
接下來繼續分析IDT,有13個,都是中斷門。(關於門格式,參見
INTEL-X86保護模式下的記憶體管理,http://user.qzone.qq.com/31731705/blog/1307847866)。先引用一段 Windows Internals (Fifth Edition)上的話,瞭解些基本概念。
Each processor has a separate IDT so that different processors can run different ISRs, ifappropriate. For example, in a multiprocessor system, each processor receives the clock interrupt,but only one processor updates the system clock in response to this interrupt.
All the processors, however, use the interrupt to measure thread quantum and to initiate rescheduling when a thread’s quantum ends. Similarly, some system configurations might require thata particular processor handle certain device interrupts.
在我的系統上,D1是時鐘中斷,2個處理器各自有不同的處理函數。
1: kd> ~0s; !idt d1; ~1s; !idt d1
Dumping IDT:
d1: 8480a634 hal!HalpHpetClockInterrupt
Dumping IDT:
d1: 8480b2d8 hal!HalpClockInterruptPn
B0也很奇怪,
1: kd> ~0s;!idt b0;~1s;!idt b0;
Dumping IDT:
b0: 8aa71a58 ndis!ndisMiniportMessageIsr (KINTERRUPT 8aa71a00)
Dumping IDT:
b0: 8487cbc0 nt!KiUnexpectedInterrupt128
這是不是意味著這個中斷只能由0號CPU來處理?困惑中。其它的是裝置中斷,每個處理器分配和使用自己的中斷對象,因此比較出來會有差異。以0x82為例,上面的輸出如下,
0082 (80b95810, 807d3430) (887f8e00, 00082058) (887f8e00, 00083058)
1: kd> ~0s; !idt 82; ~1s; !idt 82
Dumping IDT:
82: 887f2058 ataport!IdePortInterrupt (KINTERRUPT 887f2000)
ataport!IdePortInterrupt (KINTERRUPT 887f2780)
sdbus!SdbusInterrupt (KINTERRUPT 8c5c2a00)
rimmptsk+0x7674 (KINTERRUPT 8c5c2780)
Dumping IDT:
82: 887f3058 ataport!IdePortInterrupt (KINTERRUPT 887f3000)
ataport!IdePortInterrupt (KINTERRUPT 887f3780)
sdbus!SdbusInterrupt (KINTERRUPT 8c5c4c80)
rimmptsk+0x7674 (KINTERRUPT 8c5c4a00)
中斷對象不一樣,但ISR是一樣的,中斷的處理流程是一樣的。