基础的东西可以看一下 jiurl 写的 分页机制
这里只写一下最近看PAE,学到的东西
------------------------------------------------------
PAE 即为物理地址扩展(Physical Address Extension),
是 Intel x86 Pentium Pro处理器引入的一种内存映射模式。
在此模式下CPU可以访问多达64GB的物理内存。
cr4寄存器的第5位(从0开始算)可以看出系统是否启用了PAE。
0: kd> r cr4
cr4=000006f9
0: kd> .formats 000006f9
Evaluate expression:
Hex: 000006f9
Decimal: 1785
Octal: 00000003371
Binary: 00000000 00000000 00000110 11111001
Chars: ....
Time: Thu Jan 01 08:29:45 1970
Float: low 2.50132e-042 high 0
Double: 8.81907e-321
可以看到我的机器启用了PAE
------------------------------------------------------
在PAE 模式下 实现了三级地址转译,比非PAE模式多了一级,即
页目录指针表(4项,每项64位,每一项指向了一个页目录,CR3 寄存器指向了这里)
页目录(512项,每项64位,这里的每一项即为一个PDE)
页表(512项,每项64位,这里的每一项即为一个PTE)
------------------------------------------------------
在PAE模式下PDE和PTE为64位,而不是原来的32位。
其结构如下:
0: kd> dt nt!_hardware_pte
nt!_HARDWARE_PTE
+0x000 Valid : Pos 0, 1 Bit
+0x000 Write : Pos 1, 1 Bit
+0x000 Owner : Pos 2, 1 Bit
+0x000 WriteThrough : Pos 3, 1 Bit
+0x000 CacheDisable : Pos 4, 1 Bit
+0x000 Accessed : Pos 5, 1 Bit
+0x000 Dirty : Pos 6, 1 Bit
+0x000 LargePage : Pos 7, 1 Bit
+0x000 Global : Pos 8, 1 Bit
+0x000 CopyOnWrite : Pos 9, 1 Bit
+0x000 Prototype : Pos 10, 1 Bit
+0x000 reserved0 : Pos 11, 1 Bit
+0x000 PageFrameNumber : Pos 12, 26 Bits
+0x000 reserved1 : Pos 38, 26 Bits
+0x000 LowPart : Uint4B
+0x004 HighPart : Uint4B
其中 +0x000 PageFrameNumber : Pos 12, 26 Bits 为26位
------------------------------------------------------
那么PAE下是怎么进行地址的转译的呢?这和非PAE模式下有何不同?
首先来观察一下 页目录指针表
0: kd> r cr3
cr3=06f40440
通过cr3找到 页目录指针表,然后看看他的内容
0: kd> !dd 06f40440
# 6f40440 13190801 00000000 24b51801 00000000
# 6f40450 3c852801 00000000 1398f801 00000000
# 6f40460 295f4801 00000000 37135801 00000000
前面4项就是指向4个页目录的PDE了
第一项是 0000000013190801
对应的 pfn 为 13190,来看一下这个pfn
0: kd> !pfn 13190
PFN 00013190 at address 810BCBC0
flink 00000000 blink / share count 0000000C pteaddress C0603000
reference count 0001 Cached color 0
restore pte 000000C0 containing page 01398F Active M
Modified
可以看到这个物理页对应的pte地址为C0603000,
于是用 !pte 命令就可以找到对应的虚拟地址了
0: kd> !pte C0603000
VA c0600000
PDE at 00000000C0603018 PTE at 00000000C0603000
contains 0000000008BA2863 contains 00000000318E3863
pfn 8ba2 ---DA--KWEV pfn 318e3 ---DA--KWEV
对应的虚拟地址是 c0600000
------------------------------------------------------
按照这种找法,分别找出了后3项指向的虚拟地址
分别是 c0601000 c0602000 c0603000
正好是 c0600000 开始处的4页,即4个页目录,
和非PAE模式的不同之处在于非PAE模式下的页目录被映射到了c0300000处。
现在来看看每一个页目录的第一项
0: kd> dd c0600000 l2
c0600000 2fe54867 00000000
其中pfn为2fe54
0: kd> !pfn 2fe54
PFN 0002FE54 at address 813E3130
flink 00000BA5 blink / share count 00000118 pteaddress C0600000
reference count 0001 Cached color 0
restore pte 00000080 containing page 0318E3 Active M
Modified
0: kd> !pte C0600000
VA c0000000
PDE at 00000000C0603000 PTE at 00000000C0600000
contains 00000000318E3863 contains 000000002FE54867
pfn 318e3 ---DA--KWEV pfn 2fe54 ---DA--UWEV
即c0600000 对应的 512 个页表(2MB)从 c0000000 开始
同样的方法找出了其他页表的开始处,于是发现
c0600000 - c0000000
c0601000 - c0200000
c0602000 - c0400000
c0603000 - c0600000
正好是4个2兆,对应了4个512页
也就是说页表被映射到了 c0000000 - c07fffff 范围之内
下面再看看虚拟地址
由于虚拟地址(32位,这里全用0表示)
00,000000000,000000000,000000000000
高2位:页目录指针的索引
接下来9位:页目录的索引
再接下来9位:页表索引
低12位:页内偏移
由于页表和页目录都是顺序排列的
那么可以得出
pteaddress = C0000000 + (VA >> 12) * 8
下面找个地址证实一下
比如 f1e11243 这个地址
c0000000+(f1e11243>>12)*8=c078F088
用 !pte 看一下
0: kd> !pte f1e11243
VA f1e11243
PDE at 00000000C0603C78 PTE at 00000000C078F088
contains 0000000001037963 contains 00000000FB70596B
pfn 1037 -G-DA--KWEV pfn fb705 -G-DA-TKWEV
可以看到验证结果和上边等式相符。
写到现在也写的差不多了
最后,还有一个疑问就是
页目录地址为什么是 c0600000 ?
由于页目录和页表项的重合,所以
可以通过寻找c0000000地址的PTE来计算出来
c0000000 + (c0000000>>12)*8 = c0600000