1、基本知识
-
控制寄存器:x86/x86_64 CPU中提供了控制寄存器,来决定CPU的操作模式和当前执行任务的属性。其中包括CR0-CR8 9个控制寄存器,其中CR5-CR7保留。跟内存分页相关的主要是CR0、CR2和CR3。
-
CR0: 包含当前处理器运行的控制标志。如位31(PG位)则决定了是否启用分页机制;位0(PE位)决定了处理器是在实模式还是保护模式下运行。位16(WP位)则是写保护位。
-
CR2:页故障线性地址寄存器,保存最后一次出现页故障的全32位线性地址。
-
CR3:页目录基址寄存器,保存页目录表的物理地址,该寄存器的12-31位(高20位)保存页目录的地址,低12位保存主要有两个标志位PCD和PWT,控制处理器内部中的分页缓存。
-
-
PDE:页目录表项,每个页目录占1个4KB内存页,每个PDE的长度为32比特位(4字节),因此每个页目录表中最多包含1024个PDE。PS位比较重要, 只存在于页目录表。0表示这是4KB页,指向一个页表。1表示这是4MB大页,直接指向物理页。物理地址计算为 PDE的高10位 + 线性地址的低22位。
|<------ 31~12------>|<------ 11~0 --------->| 比特 |b a 9 8 7 6 5 4 3 2 1 0| |--------------------|-|-|-|-|-|-|-|-|-|-|-|-| 占位 |<-------index------>| AVL |G|P|0|A|P|P|U|R|P| 属性 |S| |C|W|/|/| |D|T|S|W|
-
PTE:页表表项,一个大小为 1024 个元素的数组,用来保存页索引号。数组中的每个元素的高20 bit 用来保存页索引号,低 12 bit 保存页属性。
|<------ 31~12------>|<------ 11~0 --------->| 比特 |b a 9 8 7 6 5 4 3 2 1 0| |--------------------|-|-|-|-|-|-|-|-|-|-|-|-| 占位 |<-------index------>| AVL |G|P|D|A|P|P|U|R|P| 属性 |A| |C|W|/|/| |T| |D|T|S|W|
————————————————
P:有效位。0 表示当前表项无效。
R/W: 0 表示只读。1表示可读写。
U/S: 0 表示只能0、1、2特权级可访问。3 表示只有特权级程序可访问
A: 0 表示该页未被访问,1表示已被访问。
D: 脏位。0表示该页未写过,1表示该页被写过。
PS: 只存在于页目录表。0表示这是4KB页,指向一个页表。1表示这是4MB大页,直接指向物理页。
————————————————
2、分页原理
x86的分页机制分为普通的32位经典分页机制以及开启PAE的分页机制。
- 32位经典分页(二级分页机制):10-10-12
① 通过CR3寄存器(12-31位)定位到页目录的起始地址,取线性地址的高10位作为索引选取页目录的一个表项,也就是PDE。
② 判断PDE的PS位,如果为1,代表这个PDE指向一个4MB的大内存页,PDE的高10位便是4MB内存页物理地址的高10位,线性地址的低22位是页内偏移。将二者合并起来便得到了物理地址。如果PS位是0,那么根据PDE中的页表基地址(取PDE的高20位,低12位设为0)定位到页表。
③ 取线性地址的12位到21位(共10位)作为索引选取页表的一个表项,也就是PTE。
④ 取出PTE中的内存页基地址(取PTE的高20位,低12位设为0)。
⑤ 取线性地址的低12位作为页中偏移与上一步的内存页基地址相加便得到物理地址。
- PAE分页(三级分页机制)2-9-9-12
PDE和PTE被扩展到64位,低12位仍然是标志位,12-35表示物理地址的高24位,物理地址从32位变成36位,最大支持64G。PDE和PTE的最后一位是XD位,为禁止执行位,对应页的数据无法被执行。
新增页目录指针表(PDPT)、二级分页机制变成三级,页目录指针表只有4个表项,每个表项寻址1G空间,共4G线性地址空间。其中CR3寄存器发生变化,低5位不用,高27位指向PDPT的起始物理地址。
32位的线性地址被分成2-9-9-12,其中2位的页目录指针索引,9位的页目录表项索引,9位的页表表项索引,12位的页内偏移。对比经典32位分页机制,页目录表项和页表表项的索引都少了1位,因此只能索引512项,每项8个字节,共4X512X512 =2^20个页。
硬件DEP就是从引入了PAE以后采用的,主要是PDE和PTE的最后1位XD(intel)位,NX(AMD)。
疑问:
1、VirtualProtect 修改内存的权限原理,为什么可以PAGE_EXECUTE,PAGE_EXECUTE_READ,PAGE_EXECUTE_READWRITE,PAGE_EXECUTE_WRITECOPY,PAGE_NO?ACCESS,PAGE_READONLY,PAGE_READWRITE,PAGE_WRITECOPY,PAGE_TARGETS_INVALID,PAGE_TARGETS_NO_UPDATE?
答:猜测是XD位 和页表的PS属性有关。