BBYR Achieve
返回信息流
这是一条镜像帖。来源:北邮人论坛 / security / #4294同步于 2006/11/2
Security机器人发帖

[原创]x86_winxp_sp2内存分页管理模式的研究

flyingkisser
2006/11/2镜像同步0 回复
直接从txt中考过来的,格式上有些不太整齐,以后再整理吧,呵呵。 --------------------------------------- x86_winxp_sp2内存分页管理模式的研究 by flyingkisser 06.11 以前我一直在win2k系统里捣鼓它的内核,对页目录,页表的二级转换结构自认为已经很熟悉了。 可到了winxp+sp2的系统里,发现这一块发生了不少变化。 我想有必要对此总结一下。 以下的叙述中可能存在错误,也可能存在笔误,希望大家看到的话给我指出来:) 我的email是flyingkisser@163.com 我的机器的平台是:winxp_32bit+sp2(虽然我用的是64位CY,嘿嘿:) 先来看看和页表,页目录相关的东西发生了哪些变化 1.页表项PTE和页目录项PDE从过去的32bit变成现在的64bit 2.可寻址的最大物理内存由于过去的4G变成了现在的64G 3.页目录的虚拟首地址从过去的0xc0300000变成现在的0xc0600000 4.CR4寄存器的PAE位默认情况就enable了,仅管我的机器只有可怜的512M内存,还被集成显卡共享掉64M :< 这些显著的变化,归根到底都是启用PAE位造成的。 PAE位是CR4的bit4位(从bit0开始计数),全称是Physical Address Extension,即物理内存扩展。 当这个位被置位即是1的时候,CPU可寻址的最大物理内存是64G。 物理上32bit的CPU多出了4个管脚,用于支持PAE。 winxp+sp2及win2k03+sp1系统默认是启用PAE的。 这时,分页机制上发生了一定的变化。 1.页 现在一页的大小,要么是4K,要么是2M,即所谓的LargePage.不会有4M页了。 2.页目录 每个进程的页目录,位于虚拟地址空间0xC0600000,结束于0xC0604000(注意最后一个PDE的地址是0xC0603FF8) 占用大小是0x4000,即16K字节,所以可以说PDE总共占用了4页的内存大小 每个页目录项的大小是8个字节,即2个双字,一页里有512个PDE,共有2048个PDE,分布在从0xC0600000开始的连续 的4页虚拟地址空间中(其物理上不一定连续) 3.页表 每个进程的页表,还是起始于0xC000000,但结束于0xC0800000(注意最后一个PTE的地址是0xC07FFFF8) 占用大小是0x800000,即8M字节,所以可以说页表总共占用了2048个页的内存大小 每个页表项的大小是8个字节,即2个双字,一张页表里有512个PTE,共有2048*512个PTE,分页在从0xC0800000 开始的连续的2048页虚拟地址空间中 现在一个PTE还是负责管理4K大小的虚拟地址空间,一张页表管理2M大小的虚拟地址空间。 而一个PDE对应一张页表,有2048个PDE,所以就会有2048张页表,2048*2M,其结果是4G,刚好等于进程的虚拟地址空间大小。 4.PTE、PDE的结构,虚拟地址的结构,虚拟地址-->物理地址的转换公式 要分2种情况讨论,非LargePage和LargePage 1>非LargePapg,即4K页 a.PTE的结构 63 62 ... 36 35 34 33 32 31 ... 12 11 10 9 8 7 6 5 4 3 2 1 0 -------------------------------------------------------------------------------------------- |EXB| Reserved 0 | PFN | Avail | G |PAT| D | A |PCD|PWT|U/S|R/W| P | -------------------------------------------------------------------------------------------- EXB(Execution Bit) 1 此页不可执行 0 此页可执行 PFN(Page Frame Number) 由24个bit组成,所以可以寻址16M物理页,整好是64G大小(假设每页4K大小) Avail 留给操作系统使用的,这里winxp把 bit11定为0 bit10用于ProtoType bit9用于CopyOnWrite G(Global) 1 此页为全局页 0 引页非全局页 PAT(Page Attribute Table) 一般为0,不用此位 D(Dirty) 1 此页为脏页,即被修改过 0 此页非脏页,没有被修改过 A(Accessed) 1 此页被访问过 0 此页没有被访问过 PCD(Page Cache Diable) 1 禁止cache此页 0 允许cache此页 PWT(Page Write Through) 1 对该页采用Write-through cathing策略 0 对该页采用Write-back caching策略 U/S(User/Supervisor) 1 用户页,ring3,ring0都可访问 0 内核页,只有ring0可访问 R/W(Read/Write) 1 可读,可写 0 只读 P(Present) 1 此页有效 0 此页无效 b.PDE的结构 63 62 ... 36 35 34 33 32 31 ... 12 11 10 9 8 7 6 5 4 3 2 1 0 -------------------------------------------------------------------------------------------- |EXB| Reserved 0 | PFN | Avail | G |PS | D | A |PCD|PWT|U/S|R/W| P | -------------------------------------------------------------------------------------------- 只有bit7有所变化, PS(Page Size) 1 此页为LargePage 0 此页不是LargePage 由于这里讨论的是4K页,所以此位必为0 c.虚拟地址的结构 31 ... 21 20 ... 12 11 ... 0 -------------------------------------- | PDE_index | PTE_index | Page_offset| -------------------------------------- 即: 高11bit作为页目录,即页表的索引 中间9个bit作为页表项的索引 最后12个bit作为在物理页内部的页内偏移 d.虚拟地址-->物理地址的转换公式 PDE的地址: PDE=(VA>>21)<<3+0xc0600000 页表的地址: PT=(VA>>21)*4K+c0000000 PTE的地址: PTE=PT+((VA>>12)&0x1ff])*8 物理地址: PA= PTE(64位) & 0x0000000f fffff000 + VA & 0xfff e.windows内核的算法 以下都假设ESI中存放的是虚拟地址 摘自nt!MmGetPhysicalAddress: 计算PDE的地址 805ad105 8bce mov ecx,esi ;esi=内存区域的起始页边界地址 805ad107 c1e912 shr ecx,12h 805ad10a 81e1f83f0000 and ecx,3FF8h 805ad110 81e90000a03f sub ecx,3FA00000h 计算PTE的地址 805ad119 c1ee09 shr esi,9 805ad11c baf8ff7f00 mov edx,7FFFF8h 805ad121 23f2 and esi,edx 805ad123 81ee00000040 sub esi,40000000h 计算物理地址 80505703 0facd00c shrd eax,edx,0Ch ;edx=pte高双字 eax=pte低双字 80505707 c1ea0c shr edx,0Ch 8050570a 25ffffff03 and eax,3FFFFFFh ;0000 0011 8050570f 33c9 xor ecx,ecx 80505711 0fa4c10c shld ecx,eax,0Ch ;ecx=物理页的高地址 80505715 c1e00c shl eax,0Ch ;eax=物理页的低地址 80505718 81e7ff0f0000 and edi,0FFFh ;edi=页内偏移 8050571e 03c7 add eax,edi ;eax=物理地址的低地址 80505720 8bd1 mov edx,ecx ;edx=物理地址的高地址 2>LargePage,即2M页 a.PTE的结构 因为当一个页是Large页时,只需要用到页目录,页表项已经没有意义 b.PDE的结构 63 62 ... 36 35 34 33 32 31 ... 21 20 ... 13 12 11 10 9 8 7 6 5 4 3 2 1 0 ---------------------------------------------------------------------------------------------------------- |EXB| Reserved 0 | PFN | Reserved0 | PAT | Avail | G | PS | D | A |PCD|PWT|U/S|R/W| P | ---------------------------------------------------------------------------------------------------------- 发生的变化是从bit35到bit21共15个bit作为PFN,可以寻址32K个Large物理页,一个Large物理页是2M,所以总共是64G大小。 c.虚拟地址的结构 31 ... 21 20 ... 0 -------------------------------------- | PDE_index | Page_offset | -------------------------------------- 高11个bit是PDE在页目录中的索引 低21个bit是地址在物理页中的页内偏移,21个bit可以寻址的空间的是2M,正好符合LargePage一页2M大小的说明。 d.虚拟地址-->物理地址的转换公式 PDE的地址: PDE=(VA>>21)<<3+0xc0600000 物理地址: PA= PDE(64位) & 0x0000000f ffe0 0000 + VA & 0x1fffff e.windows内核的算法 以下都假设ESI中存放的是虚拟地址 摘自nt!MmGetPhysicalAddress: 805056b5 0facc80c shrd eax,ecx,0Ch ;eax=pde的低双字值 ecx=pde的高双字值 805056b9 c1e90c shr ecx,0Ch ;eax=pde>>12 805056bc 8bcf mov ecx,edi ;edi=va ecx=va 805056be c1e90c shr ecx,0Ch ;ecx=va>>12 805056c1 25ffffff03 and eax,3FF FFFFh ;eax=(pde>>12)&0x3ffffff 805056c6 81e1ff010000 and ecx,1FFh ;ecx=(va>>12)&0x1ff 805056cc 03c1 add eax,ecx ;eax=(pde>>12)&0x3ffffff+(va>>12)&0x1ff 805056ce eb3f jmp nt!MmGetPhysicalAddress+0x8f (8050570f) 8050570f 33c9 xor ecx,ecx ;ecx=0,eax=(pde>>12)&0x3ffffff+(va>>12)&0x1ff 80505711 0fa4c10c shld ecx,eax,0Ch ;ecx=物理页的高地址 80505715 c1e00c shl eax,0Ch ;eax=物理页的低地址 80505718 81e7ff0f0000 and edi,0FFFh ;edi=页内偏移 8050571e 03c7 add eax,edi ;eax=物理地址的低地址eax=[ (pde>>12)&0x3ffffff+(va>>12)&0x1ff ] << 12 + va&0xfffh 80505720 8bd1 mov edx,ecx ;edx=物理地址的高地址 总结一下,就是: eax=[ (pde>>12)&0x3ffffff+(va>>12)&0x1ff ] << 12 + va&0xfff 再变化一下,就是 [ (pde>>12)&0x3ffffff ] <<12 + [ (va>>12)&0x1ff<< 12 + va&0xfff ] 可以分成两部分看, 后半部分就是虚拟地址的页内偏移 前半部分是PDE内部的PFN对应的物理页的地址,不过,它是把PDE右移了12位,再与上0x3ffffff,虽然理论上这种算法 和我上面列出的公式PDE(64位) & 0x0000000f ffe0 0000得到的物理页的地址是一样的,不过确实有点不妥。 另外细心一点还能发现,在计算4K页的物理页的地址时,也是把PTE右移了12位再与上0x3ffffff,也就是说windows 把有效的PFN定义为27位, 对于4K页来说,4K是2的12次方,所以PFN需要36-12即24个bit就行了 对了2M页来说,2M是2的21次方,所以PFN需要36-21即15个bit就行了 而0x3ff ffff总是26个bit,确实有点不够严瑾. 嗯,就先写这么多了,以上的分析可能存在错误,大家看到了要给我指出啊,呵呵。 主要参考资料: <<IA-32 Intel Architecture Software Developer's Manual>>
订阅后,新回复会通过你的通知中心匿名送达。
0 条回复
暂无回复 · 你可以订阅本帖等待新回复。