分享

IA32和x64架构分页数据结构

 waston 2022-09-14 发布于上海

1. 概述

分页是更加粒度化的内存管理机制, 分页是用粒度化的单位"页"来管理线性地址空间和物理地址空间. x86下一个典型的页大小是4KB, 则一个4GB的虚拟地址空间可以划分为1024X1024个页面. 物理地址空间的划分同理. x86允许大于4KB的页面大小, 这里只介绍4KB页面.

同时, 分页机制让操作系统中的虚拟内存机制称为可能. 一个页面可以存在于物理内存(!!!)中, 也可以存放在磁盘的交换区域!!!(如Linux下的Swap分区!!!, Windows的虚拟内存文件!!!)中, 程序可以使用比机器物理内存更大的内存区域!!!.

分页机制的核心思想是通过页表线性地址转换为物理地址, 并配合旁路转换缓冲区(Translation Lookaside Buffer, TLB!!!)来加速地址转换过程. 操作系统启动过程中, 通过将CR0寄存器PG位置1来启动分页机制.

config

从图中看到, 分页机制主要由页表、CR3和TLB三个部件构成. 下面以4KB页面的32位分页为例进行讲解.

1.1. 页表

页表(Page Table)是用于将线性地址转换成物理地址的主要数据结构. 一个地址对齐到页边界(!!!)后的值称为页帧号, 它实际是该地址所在页面的基地址. 线性地址对应的页帧号!!!虚拟页帧号(Virtual Frame Number, VFN!!!), 物理地址对应的页帧号!!!物理页帧号(Physical Frame Number, PFN!!!)或机器页帧号(Machine Frame Number). 页表就是存储VFN到PFN映射的数据结构。

4KB的32位分页使用两级页表, 如图.

config

页目录项(Page Directory Entry): 包含页表的物理地址(!!!不是线性地址!!!). 页目录项存放在页目录(Page Directory, 也称为页目录表PDT!!!)中, CPU使用线性地址的22~31位(高10位)索引页目录, 以获得该线性地址对应的页目录项. 每个页目录项为4B大小, 故页目录占用4KB大小的物理页面, 共包含1024的页目录项.

⓶ 页表项(Page Table Entry): 页表项包含该线性地址对应的PFN(!!!物理地址页帧号!!!)。页表项存放在页表(Page Table)中, CPU使用线性地址的12~21位索引页表, 获得该线性地址对应的页表项. 通过将线性地址0~11位偏移量和基地址相加, 就可以得到线性地址对应的物理地址. 页表项为4B大小, 故页表包含1024个页表项, 占用一个4KB页面.

config

图2-9显示了页目录项、页表项的构成, 通过其中的各个字段, 可以对页面访问权限, 缓存机制, 全局页等属性进行控制. 这里只关注P(Present)字段, 该字段使虚拟内存的实现成为可能. P根据其值不同, 可以代表两种情况:

  1. P=1: 物理页面存在于物理内存中, CPU完成地址转换后, 可以直接访问该页面.
  2. P=0: 页面不在物理内存中, 当CPU访问该页面时会产生一个缺页错误(Page Fault)并交由操作系统缺页错误处理程序处理. 通常操作系统会将存放在磁盘上的页面(!!!)调入物理内存, 使访问可以继续. P=0时, 页目录项页表项格式变成图2-10中的格式。此时1~31位供操作系统使用以记录物理页面在磁盘上的信息, 通常是物理页面在磁盘上的位置!!!.

config

CPU在索引页目录前, 必须知道页目录所在的物理地址, 该物理地址存放在CR3(Control Register 3)寄存器中, 也称为页目录基地址寄存器(Page-directory base register, PDBR). 一个进程在运行前(!!!), 必须将其页目录的基地址存入CR3. 页目录的基地址必须对齐到4K边界.

1.2. TLB

为提高地址转换效率, x86架构使用TLB对最近用到的页面映射进行缓存, 当CPU访问某个线性地址, 其所在页面的映射存在于TLB中, 无须查找页表即可进行地址转换. 注意, 很多资料说TLB存放的是线性地址到物理地址的转换, 准确来说应该是: VFN到PFN的转换!!!. 即, CPU从TLB获得一个线性地址对应的PFN后, 仍然要和线性地址的偏移相加, 才能得到最后的物理地址, 而非直接从TLB中获取物理地址.

TLB作为缓存, 其能存放的映射条目有限, 当TLB中没有空闲条目可用时, 替换哪一个旧条目由CPU决定.

TLB也有缓存一致性的问题,这主要是指TLB中的映射条目(!!!)和页表中的映射条目(!!!)的一致性。当操作系统页表进行修改,要负责对TLB中对应条目或整个TLB进行刷新(!!!)。从软件的角度来看, x86提供了两种方式刷新TLB:

更新CR3: 此操作可以导致TLB被整体刷新, TLB中所有映射条目失效(全局TLB除外). 操作系统将当前CR3中的值重新写会CR3刷新整个TLB. 进程切换时, 新进程的页目录基地址会写入CR3而使老进程在TLB中的条目失效.

INVLPG指令: 这是一种更细粒度的刷新, 操作系统用它对TLB单独的页目录项页表项进行刷新. 这通常是在操作系统修改页表后进行的(例如分配/释放页面!!!).

1.3. 线性地址转换为物理地址的过程

⓵ CPU访问一个线性地址, 映射在TLB中跳到⓺. 如映射不存在于TLB中, 称为TLB Miss发生, 进行下一步.

查找页表, 页面在物理内存!!! 中跳到⓸, 不会再进行下一步.

⓷ 操作系统的缺页处理函数接管, 通常进行如下操作: a)将页面从磁盘复制到物理内存中; b)更改对应页表项, 设置P为1, 并对其他字段相应设置; c)刷新TLB中对应的页表项; d)从缺页错误处理函数中返回.

⓸ 到这一步, 页面已经存在于物理内存中, 并且页表已经包含了该映射. 此时, 重新执行引发TLB Miss的指令.

TLB Miss再次发生(!!!), CPU重新查页表, 把相应的映射插入到TLB中.

⓺ 到这一步, TLB已经包含了该线性地址对应的PFN. 通过将线性地址中的偏移部分和PFN相加, 就得到了对应的物理地址.

翻译自《Intel® 64 and IA-32 Architectures Software Developer Manual Volume 3A》

config

config

每个table里的entry(表项)分别被称为PTE(Page Table Entry)、PDE(Page Directory Table Entry)、PDPE(Page Directory Pointer Table Entry)和PML4E(Page-Map Leve-4 Table Entry)。

注: CR3存放的是物理地址, 表项中也是物理地址.

2. 32位分页

线性地址是32位宽, 采用一级或两级页转换表.

每个表项大小是4字节宽, 32位.

CR3使用32位.

2.1. 4KB页面线性地址翻译

使用PDT(page directory table,页目录表)和PT(page table,页表)两级表格。

用32位分页的到一个4KB页面的线性地址翻译

config

4KB页面线性地址构成: 10(PDT索引, 1024个项) + 10(PT索引, 1024个项) + 12(Page offset, 4KB页)

一个table的大小:

  • 一个PDT有1024项(2^10); 占用空间: 1024 x 4字节 = 4KB.
  • 一个PT有1024项(2^10); 占用空间: 1024 x 4字节 = 4KB.

一个进程一次性全部表示需要的页表结构内存:

  • PDTE可能共有: 1024(2^10) 个; 占用空间: 1024 x 4字节 = 4KB.
  • PTE可能共有: 1024(2^10) x 1024(2^10) 个; 占用空间: 1024 x 1024 x 4字节 = 4MB.

2.2. 4MB页面线性地址翻译

使用PDT(page directory table)一级表格。

用32位分页的到一个4MB页面的线性地址翻译

config

4MB页面线性地址构成: 10(PDT索引, 1024个项) + 22(Page offset, 4MB页)

一个table的大小:

  • 一个PDT有1024项(2^10), 占用空间: 1024 x 4字节 = 4KB.

一个进程一次性全部表示需要的页表结构内存:

  • PDTE可能共有: 1024(2^10) 个; 占用空间: 1024 x 4字节 = 4KB.

2.3. CR3和分页结构项

32位分页的CR3和分页结构项的格式

config

2.4. 物理地址组成

32位paging下最高为40位物理地址(!!!)(依赖于PSE-36MAXPHYADDR值)。如果不使用PSE-36机制, 那么最高为32位物理地址(!!!).

4K页面,能映射的物理地址最高是32位(!!!)

2.4.1. CR3生成PDT物理基地址

在32位paging模式下,CR3使用低32位(在Intel64或AMD64机器上64位, 只使用低32位!!!),CR3的Bit 31到Bit 12位提供20位的Page Directory Table的物理基地址(物理基地址!!!高20位!!!)。

那么以36位的物理基地址为例,它是这样形成的。

base of PDT[35:32]=0值(高4位Bit 35到Bit 32为0值!!!如果是40位物理地址高位也会是补0!!!)。

base of PDT[31:12]=CR3[31:12]中间20位CR3的Page Driectory base域提供)。

base of PDT[11:00]=0值(低12位补0!!!)。

因此CR3提供的PDT物理基地址(!!!)是4K边界对齐(!!!)的。和4KB分页的物理地址形成方式一致(!!!).

2.4.2. 4KB页PDE生成PT的物理基地址

32位paging模式的4K页面里,能映射的物理地址最高是32位(!!!4K页最高32位物理地址!!!),下一级32位的page table物理地址形成如下。

base of PT[31:12](高20位)=PDE[31:12],它是PDE的高20位值

base of PT[11:0](低12位)=0值,32位地址的低12位补0

因此,PDE里提供的PT物理基地址(!!!)是4K边界对齐(!!!由PT物理基地址组成决定的!!!)的。

2.4.3. 4KB页PTE生成页面的物理基地址

在32位paging模式下4K页面使用的是32位的最高映射物理地址(!!!只能使用最高32位物理地址!!!)。因此page frame的形成如下。

page base[31:12]=PTE[31:12],PTE的高20位对应物理页面的高20位

page base[12:0]=0值。物理页面的低12位补0

所以物理页面在4KB边界对齐.

2.4.4. 4MB页PDE生成页面的物理基地址

4MB页面没有PT, PDE直接指向页面.

4MB页面PDE结构提供4MB页面的物理基地址, 地址组成方式如下:

① 当处理器不支持PSE-36功能时,4M page frame只能映射到32位的物理地址空间(!!!)上,PDE[31: 22]是4M page base[31: 22](高10位), 这时候PDE[21:13]9位是保留位,必须设置为0值。

② 当MAXPHYADDR值为36位时,PDE[16:13]4M page base[35:32]位(高4位),PDE[31: 22]4M page base[31: 22](中间10位), 而PDE[21:17]是保留位,必须设置为0值。

③ 当MAXPHYADDR值为40位时,PDE[20:13]4M page base[39:32]位(高8位), PDE[31: 22]4M page base[31: 22](中间10位),而PDE[21]位是保留位,必须设置为0值。

④ 当MAXPHYADDR值为52位时,也仅能使用40位的物理地址(!!!),同③。

因此,4M page frame的基地址形成除上述所说外,36位或40位的物理地址低22位将补0(!!!),物理页面将在4M边界上对齐(!!!)。

2.4.5. 最终物理地址的生成

上面可以看到, 所有页面基地址都是4KB或4MB边界对齐的, 再加上线性地址低位的偏移offset, 生成最终的物理地址.

3. PAE分页

线性地址32位宽, 使用两级或三级页转换表.

每个表项8字节宽.

新CR3仍然32位宽, 但只使用了27位, 拼凑了32位PDPT物理地址。

3.1. 4KB页面线性地址翻译

使用PDPT(page directory pointer table,页目录指针表),PDTPT

用PAE分页的到一个4KB页面的线性地址翻译

config

4KB页面线性地址构成: 2(PDPT索引, 4个项) + 9(PDT索引, 512个项) + 9(PT索引, 512个项) + 12(Page offset, 4KB页)

一个table的大小:

  • 一个PDPT有4项(2^2); 占用空间: 4 x 8字节 = 32字节.
  • 一个PDT有512项(2^9); 占用空间: 512 x 8字节 = 4KB.
  • 一个PT有512项(2^9); 占用空间: 512 x 8字节 = 4KB.

一个进程一次性全部表示需要的页表结构内存:

  • PDPTE可能共有: 4(2^2) 个; 占用空间: 4 x 8字节 = 32字节.
  • PDE可能共有: 4(2^2) x 512(2^9) 个; 占用空间: 4 x 512 x 8字节 = 16KB.
  • PTE可能共有: 4(2^2) x 512(2^9) x 512(2^9) 个; 占用空间: 4 x 512 x 512 x 8字节 = 8MB.

3.2. 2MB页面线性地址翻译

使用PDPTPDT

用PAE分页的到一个2MB页面的线性地址翻译

config

2MB页面线性地址构成: 2(PDPT索引, 4个项) + 9(PDT索引, 512个项) + 21(Page offset, 2MB页)

一个table的大小:

  • 一个PDPT有4项(2^2); 占用空间: 4 x 8字节 = 32字节.
  • 一个PDT有512项(2^9); 占用空间: 512 x 8字节 = 4KB.

一个进程一次性全部表示需要的页表结构内存:

  • PDPTE可能共有: 4(2^2) 个; 占用空间: 4 x 8字节 = 32字节.
  • PDE可能共有: 4(2^2) x 512(2^9) 个; 占用空间: 4 x 512 x 8字节 = 16KB.

3.3. CR3和分页结构项

config

3.4. 物理地址组成

PAE下, 线性地址仍然32位宽(!!!), CR3还是32位宽, 支持最高52位的物理地址,依赖于MAXPHYADDR值。当MAXPHYADDR为36时只能映射到36位的物理地址,以此类推。

3.4.1. CR3生成PDPT物理基地址

CR3低5位被忽略,提供27位的PDPT基地址.

32位的PDPT物理地址形成如下:

base of PDPT[31:5]=CR3[31:5]高27位由CR3提供。

base of PDPT[4:0]=0值,低5位补0

如果是36位或更大物理地址, 则进行高位补0.

因此,PDPT的基地址是32字节边界对齐(2^5!!!)的。

3.4.2. PDPTE生成PDT的物理基地址

4KB页和2MB页这是一致的

PDT(page directory table)物理基地址上,它的地址为52位(最高支持)、40位或是36位,它的形成如下。

① 当MAXPHYADDR为52位时,base of PDT[51:12]=PDPTE[51:12],由PDPTE结构的[51:12]提供PDT的高40位

② 当MAXPHYADDR为40位时,base of PDT[39:12]=PDPTE[39:12],由PDPTE结构的[39:12]提供PDT的高28位。此时PDPTE[51:40]是保留位,必须为0值。

③ 当MAXPHYADDR为36位时,base of PDT[35:12]=PDPTE[35:12],由PDPTE结构的[35:12]提供PDT的高24位。此时PDPTE[51:36]是保留位,必须为0值。

PDT的低12位(!!!)将补0值,因此PDT物理基地址将在4K边界上对齐(!!!)。

3.4.3. 4KB页PDE生成PT的物理基地址

PDE[51:12](最多30位, 加上12位0, 最大52位物理地址)提供PT的物理基地址高位低12位全部补0, PT地址为4K边界对齐

如果物理地址比较小, bit 51往下减少.

3.4.4. 4KB页PTE生成页面的物理基地址

PTE[51:12]提供4K页面的高物理地址位(最多40位), 低12位全部补0, 页面地址4K边界对齐.

如果物理地址比较小, bit 51往下减少.

3.4.5. 2MB页PDE生成页面的物理基地址

2MB页面没有PT, PDE直接指向页面.

① MAXPHYADDR为52位时,2M page frame地址的[51:21](高31位)由PDE[51:21]提供。

② MAXPHYADDR为40位时,2M page frame地址的[39:21](高19位)由PDE[39:21]提供,此时PDE[51:22]为保留位,必须为0。

③ MAXPHYADDR为36位时,2M page frame地址的[35:21](高15位)由PDE[35:21]提供,此时PDE[51:36]为保留位,必须为0

2M page frame地址的[20:0](低21位!!!)补0,因此2M页面的地址在2M边界上对齐

3.4.6. 最终物理地址的生成

上面可以看到, 所有页面基地址都是4KB或2MB边界对齐的, 再加上线性地址低位的偏移offset, 生成最终的物理地址.

4. IA-32e分页

线性地址48位宽, 使用两级到四级的页转换表.

每个表项都是8字节宽.

CR3是64位宽, 针对是否支持PCIDE功能, CR3使用不一样。

4.1. 4KB页面线性地址翻译

使用PML4T(page map level-4 table,四层映射表),PDPTPDTPT

用IA-32e分页的到一个4KB页面的线性地址翻译

config

4KB页面线性地址构成: 9(PML4T索引, 512个项) + 9(PDPT索引, 512个项) + 9(PDT索引, 512个项) + 9(PT索引, 512个项) + 12(Page offset, 4KB页)

一个table的大小:

  • 一个PML4T有512项(2^9); 占用空间: 512 x 8字节 = 4KB.
  • 一个PDPT有512项(2^9); 占用空间: 512 x 8字节 = 4KB.
  • 一个PDT有512项(2^9); 占用空间: 512 x 8字节 = 4KB.
  • 一个PT有512项(2^9); 占用空间: 512 x 8字节 = 4KB.

一个进程一次性全部表示需要的页表结构内存:

  • PML4E可能共有: 512(2^9)个; 占用空间: 512 x 8字节 = 4KB.
  • PDPTE可能共有: 512(2^9) x 512(2^9) 个; 占用空间: 512 x 512 x 8字节 = 2MB.
  • PDE可能共有: 512(2^9) x 512(2^9) x 512(2^9) 个; 占用空间: 512 x 512 x 512 x 8字节 = 1GB.
  • PTE可能共有: 512(2^9) x 512(2^9) x 512(2^9) x 512(2^9)个; 占用空间: 512 x 512 x 512 x 512 x 8字节 = 512GB.

4.2. 2MB页面线性地址翻译

使用PML4TPDPTPDT

用IA-32e分页的到一个2MB页面的线性地址翻译

config

2MB页面线性地址构成: 9(PML4T索引, 512个项) + 9(PDPT索引, 512个项) + 9(PDT索引, 512个项) + 21(Page offset, 2MB页)

一个table的大小:

  • 一个PML4T有512项(2^9); 占用空间: 512 x 8字节 = 4KB.
  • 一个PDPT有512项(2^9); 占用空间: 512 x 8字节 = 4KB.
  • 一个PDT有512项(2^9); 占用空间: 512 x 8字节 = 4KB.

一个进程一次性全部表示需要的页表结构内存:

  • PML4E可能共有: 512(2^9)个; 占用空间: 512 x 8字节 = 4KB.
  • PDPTE可能共有: 512(2^9) x 512(2^9) 个; 占用空间: 512 x 512 x 8字节 = 2MB.
  • PDE可能共有: 512(2^9) x 512(2^9) x 512(2^9) 个; 占用空间: 512 x 512 x 512 x 8字节 = 1GB.

4.3. 1GB页面线性地址翻译

使用PML4TPDPT

用IA-32e分页的到一个1GB页面的线性地址翻译

config

1GB页面线性地址构成: 9(PML4T索引, 512个项) + 9(PDPT索引, 512个项) + 30(Page offset, 1GB页)

一个table的大小:

  • 一个PML4T有512项(2^9); 占用空间: 512 x 8字节 = 4KB.
  • 一个PDPT有512项(2^9); 占用空间: 512 x 8字节 = 4KB.

一个进程一次性全部表示需要的页表结构内存:

  • PML4E可能共有: 512(2^9)个; 占用空间: 512 x 8字节 = 4KB.
  • PDPTE可能共有: 512(2^9) x 512(2^9) 个; 占用空间: 512 x 512 x 8字节 = 2MB.

4.4. CR3和分页结构项

IA-32e分页的CR3和分页结构项的格式

config

4.5. 物理地址组成

线性地址48位宽(!!!), CR3已经是64位宽, 支持最高52位的物理地址,依赖于MAXPHYADDR值。当MAXPHYADDR为36时只能映射到36位的物理地址,以此类推。

4.5.1. CR3生成PML4T物理基地址

CR3[51:12]提供PML4T的物理地址高位(最多40位), 低12位全部补0, PML4T地址4K边界对齐.

如果物理地址比较小, bit 51往下减少.

4.5.2. PML4E生成PDPT的物理基地址

PML4E[51:12]提供PDPT的物理地址高位(最多40位), 低12位全部补0, PDPT地址4K边界对齐.

如果物理地址比较小, bit 51往下减少.

4.5.3. 4KB页和2MB页PDPTE生成PDT的物理基地址

PDPTE[51:12]提供PDT的物理地址高位(最多40位), 低12位全部补0, PDT地址4K边界对齐.

如果物理地址比较小, bit 51往下减少.

4.5.4. 1GB页PDPTE生成页面的物理基地址

1GB页面没有PDT, 没有PT, PDPTE直接指向页面.

PDPTE[51:30]提供PDT的物理地址高位(最多22位), 页面地址低30位全部补0, 页面地址1GB边界对齐.

如果物理地址比较小, bit 51往下减少.

4.5.5. 4KB页PDE生成PT的物理基地址

PDE[51:12]提供PT的物理地址高位(最多40位), 页表PT地址低12位全部补0, 页表PT地址4K边界对齐.

如果物理地址比较小, bit 51往下减少.

4.5.6. 4KB页PTE生成页面的物理基地址

PTE[51:12]提供页面的物理地址高位(最多40位), 页面地址低12位全部补0, 页面地址4K边界对齐.

如果物理地址比较小, bit 51往下减少.

4.5.7. 2MB页PDE生成页面的物理基地址

2MB页面没有PT, PDE直接指向页面.

PDE[51:21]提供页面的物理地址高位(最多31位), 页面地址低21位全部补0, 页面地址2MB边界对齐.

如果物理地址比较小, bit 51往下减少.

4.5.8. 最终物理地址的生成

上面可以看到, 所有页面基地址都是4KB, 2MB或1GB边界对齐的, 再加上线性地址低位的偏移offset, 生成最终的物理地址.

5. 分页错误代码

config

6. 参考

https://blog.csdn.net/Firas/article/details/17207813

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多