x86_64内存寻址 - 分页

通过前面两个章节我们知道了实地址寻址分段寻址,在这个章节我们将介绍分页寻址,在前面的文章我们知道,处理器访问内存的一个字节,首先将逻辑地址转换为线性地址,如果分页功能打开,那么线性地址会转换为最终的物理地址。在打开分页功能的处理器上,我们为了找到内存中的一个字节,一般经历了两个过程,即逻辑地址经过分段转化为线性地址线性地址经过分页转换为物理地址。分段和分页都有权限检查,而且有些是重合的,所以很多操作系统并没有使用处理器强大的权限检查,而只是选择使用分页权限检查。

32位的地址分页

处理器在 CR0.PG = 1 并且 CR4.PAE = 0 的情况下将使用32位的分页,在这里将详细的讲述32位地址的分页转换,32地址的分页支持4K和4M的页。4K表示在一个页支持4K空间的寻址。同理4M的页表示支持4M的内存寻址空间。现代处理器物理地址最大支持40位的地址空间,达到1TB,但由于线性地址宽度为32位,所以在一个应用最大可用的内存空间仍是2^32-1。

分页就像在字典中查找单词一样,首先我们根据首字母在目录中找到对应的页码,然后通过页码定位到最终的单词。处理器在将逻辑地址转换为线性地址后,首先根据 CR3 寄存器获得第一个页目录,通常处理器会根据物理内存的大小决定映射的层级。下面我们将分别描述 4K页的地址转换,4M页的地址转换,支持PAE的地址转换。

4K页的地址转换

上图是32位线性地址最终转换为4K页物理地址的过程:

  • 处理器通过将 CR3 寄存器的 [31:12] 和偏移量共同计算出PDE的地址,一个页目录包含1024个32位的PDE,一个32位的PDE物理地址由以下规则计算: [39:32] 为0 [31:12] 来源于 CR3 [12:2] 来源于线性地址的[31:22]位 [1:0] 为0
  • 如果 CR4.PSE=0 且 PDE.PS=0 那么映射的是一个4K的页,经过上个过程我们得到的物理地址地址存放了一个叫做页表的数据结构,这是因为支持4K的页大小的转换还需要经过一层转换,这个过程使用的数据结果叫做页表,页表中包含1024个32位的PTE,线性地址找到对应PTE的地址过程为: [39:32] 为0 [31:12] 来源于PDE [11:2] 来源于线性地址的[21:12] [1:0] 为0
  • 然后得到PTE的物理地址,PTE也是页转换的中间数据结构,最终由PTE和线性地址共同计算出最终的物理地址: [39:32] 为0 [31:12] 来源于PTE [11:0] 来源于线性地址

经过以上步骤得到物理地址就是处理器访问一个地址在支持分页功能需要寻址的过程。`PTE.P`表示数据是否在内存中,如果这个位没有被置位,表明数据不在内存中,访问这个地址会导致处理器触发页错误异常,而操作系统的按需取页通常都是按照这个特性实现的。

4M页的地址转换

上图是32位线性地址最终转换为4M页物理地址的过程:

  • 处理器通过将 CR3 寄存器的 [31:12] 和偏移量共同计算出PDE的地址,一个页目录包含1024个64位的PDE,一个32位的PDE物理地址由以下规则计算: [31:12] 来源于 CR3 [12:2] 来源于线性地址的[31:22]位 [1:0] 为0
  • 如果 CR4.PSE=1 且 PDE.PS 也是1,那么PDE映射的是一个4M的页,由于还没有使用的[21:0]正好是4M的大小,所以在支持4M的页在此层级上直接映射为最终的物理地址 [39:32] 来源于PDE的[20:13] [31:12] 来源于PDE的[31:22] [21:0] 来源于线性地址的[21:0]

经过第二不我们得到了一个32位宽度的物理地址,这个地址就是最终访问内存的地址。

支持PAE的32位地址转换

处理器在 CR0.PG = 1, CR4.PAE = 1, IA32_EFER.LME = 0,将打开PAE功能,这个功能支持将32位的线性地址转换为52位的物理地址。和之前说的一样,由于线性地址只有32位,所以最大访问的空间为2^32-1。为了实现这个功能,处理器提供了4个PDPTE寄存器。将线性地址分为了4个部分,每个部分1G。

当打开PAE功能时,CR3 不再应用PDE的地址,而是引用的是 PDPT(page-directory-pointer table)。这个表引用了4个 PDPTE 寄存器,每个寄存器管理1G的空间,分别叫`PDPTE0`, PDPTE1, PDPTE2, 和 PDPTE3。

PAE页映射支持4K和2M的页大小,下面将详细的描述PAE如何将32位的线性地址转换为52位的物理地址。

4K页的地址转换

线性地址被分割成了PDPTE偏移量,页目录,页表和偏移量。4K的页通过以下步骤找到最终的物理地址: - 线性地址的[31:30]用于选择使用哪一个PDPTE寄存器,通过这个值找到最终使用的是哪个PDPTEi,i表示这两位的索引值。使用 CR3 寄存器和这个索引值找到最终的PDPTEi,如果 PDPTE.P 没有被置位,表明这个地址空间没有被映射,访问这个空间将导致页错误异常 - 如果 PDPTE.P 被置位了,那么PDPTE将指向一个4K大小的页目录。处理器将使用以下规则找到最终的页目录 * [51:12] 来自PDPTEi寄存器 * [11:3] 来自线性地址的[29:21] * [2:0] 为0 - 由于剩下的线性地址[20:0]还没有被使用,所以处理器可以最大控制2M的内存空间,如果PDE.PS标志是0,表示映射的是4K大小的页,所以和32位映射一样,处理器继续寻址到页表,页表地址的计算方式如下: * [51:12] 来自PDE * [11:3] 来自线性地址的[20:12] * [2:0] 为0 - 现在只有偏移量还没有被使用,偏移量用于寻址4K大小的内存空间,通过页表和偏移量共同计算出最终访问的物理地址 * [51:12] 来自PTE * [2:0] 为0

2M页的地址转换

在支持2M的页大小的分页机制中,线性地址被分为了PDPTE偏移量,页目录,偏移量。和之前相比减少一个页目录数据结构。2M的页通过以下步骤找到最终的物理地址: - 线性地址的[31:30]用于选择使用哪一个PDPTE寄存器,通过这个值找到最终使用的是哪个PDPTEi,i表示这两位的索引值。使用 CR3 寄存器和这个索引值找到最终的PDPTEi,如果 PDPTE.P 没有被置位,表明这个地址空间没有被映射,访问这个空间将导致页错误异常 - 如果 PDPTE.P 被置位了,那么PDPTE将指向一个4K大小的页目录。处理器将使用以下规则找到最终的页目录项 * [51:12] 来自PDPTEi寄存器 * [11:3] 来自线性地址的[29:21] * [2:0] 为0 - 处理器通过以下规则寻址最终的物理地址 * [51:12] 来自PDE * [20:0] 来自线性地址

64位的地址分页 - 4级分页

当 CR0.PG = 1, CR4.PAE = 1, 且 IA32_EFER.LME = 1,处理器将使用64位的分页模式。64位的分页模式支持更大的寻址空间,页更加复杂。同样,它也是先从 CR3 寄存器获取页的基址信息,参与各级的分页计算。处理器将线性地址提高到了48位,物理地址最大支持52位的地址空间,需要注意,处理器仍然只支持48位的规范地址,也就是说线性地址空间限制在48位,但仍可寻址52位的物理地址空间。

64位处理器使用更加深的层级转换,`CR3`寄存器用于定位`PML4`表。64位处理器支持4K,2M,1G的页大小。

4K页的地址转换

  • 处理器通过 CR3 寄存器获得 `PML4`表结构,一个`PML4`表是包含512个64位表项(PLM4Es)的数据结构,处理器通过以下规则计算出需要的PLM4Es的地址(由于使用线性地址的[47:39],所以每一个表项可以访问512GB的内存空间): [51:12] 来自CR3 [11:3] 来自线性地址的[47:39] [2:0] 为0
  • 通过上面计算的地址指向一个4K大小的PLM4E,处理器需要通过PLM4E找到页目录的物理地址(由于使用线性地址的[47:30],所以每一个表项可以访问1GB的内存空间) [51:12] 来自PML4E [11:3] 来自线性地址的[38:30] [2:0] 为0
  • 如果`PDPTE.PS` 没有被置位,说明这个地址指向了页目录(PDPTE)。一个页目录由512个64位的PDPTE组成,一个PDPTE的地址由以下规则计算而成: [51:12] 来自PDPTE [11:3] 来自线性地址的[29:21] [2:0] 为0
  • 如果 PDE.PS 没有被置位,说明PDE映射的是页表,每个页表512个64位的PTE组成,一个PTE的物理地址计算方式如下(由于使用了线性地址的[47:12],所以每一个表项管理了4K的内存空间): [51:12] 来自PDE [11:3] 来自线性地址的[20:12] [2:0] 为0
  • 最后获得了PTE,最终由PTE和偏移量计算的物理地址: [51:12] 来自PTE [11:0] 来自线性地址

2M页的地址转换

  • 处理器通过 CR3 寄存器获得 `PML4`表结构,一个`PML4`表是包含512个64位表项(PLM4Es)的数据结构,处理器通过以下规则计算出需要的PLM4Es的地址(由于使用线性地址的[47:39],所以每一个表项可以访问512GB的内存空间): [51:12] 来自CR3 [11:3] 来自线性地址的[47:39] [2:0] 为0
  • 通过上面计算的地址指向一个4K大小的PLM4E,处理器需要通过PLM4E找到页目录的物理地址(由于使用线性地址的[47:30],所以每一个表项可以访问1GB的内存空间) [51:12] 来自PML4E [11:3] 来自线性地址的[38:30] [2:0] 为0
  • 如果`PDPTE.PS` 没有被置位,说明这个地址指向了页目录(PDPTE)。一个页目录由512个64位的PDPTE组成,一个PDPTE的地址由以下规则计算而成(由于使用了线性地址的[47:21],所以每一个表项管理了2M的内存空间): [51:12] 来自PDPTE [11:3] 来自线性地址的[29:21] [2:0] 为0
  • 如果 PDE.PS 被置位,说明PDE映射的是2M的页,最终的物理内存计算如下: [51:12] 来自PDE [20:0] 来自线性地址的

1G页的地址转换

  • 处理器通过 CR3 寄存器获得 `PML4`表结构,一个`PML4`表是包含512个64位表项(PLM4Es)的数据结构,处理器通过以下规则计算出需要的PLM4Es的地址(由于使用线性地址的[47:39],所以每一个表项可以访问512GB的内存空间): [51:12] 来自CR3 [11:3] 来自线性地址的[47:39] [2:0] 为0
  • 通过上面计算的地址指向一个4K大小的PLM4E,处理器需要通过PLM4E找到页目录的物理地址(由于使用线性地址的[47:30],所以每一个表项可以访问1GB的内存空间) [51:12] 来自PML4E [11:3] 来自线性地址的[38:30] [2:0] 为0
  • 如果 PDPTE.PS 被置位,那么 PDPTE 映射了一个1G的页,最终物理地址计算为: [51:30] 来自PDPTE [29:0] 来自线性地址

64位的地址分页 - 5级分页

(0)

相关推荐