3. 页表层级设计:单级页表、多级页表(2级/3级/4级)、ARMv8-A页表架构
页表是MMU将虚拟地址转换为物理地址的核心数据结构。页表层级的设计直接决定了地址空间大小、内存占用、TLB命中率和上下文切换开销。本章从单级页表出发,逐步深入到多级页表的设计原理,最后以ARMv8-A的4级页表架构作为实战案例进行剖析。
3.1 单级页表:简单但低效
单级页表是最直接的地址转换方案:整个虚拟地址空间由一张线性页表覆盖。每个虚拟页对应一个页表项(PTE),PTE中存放物理页帧号(PPN)和权限属性。
虚拟地址位数:32位 | 页大小:4KB | 页表项大小:4字节
页表项数量:2^20 = 1,048,576 | 页表总大小:4MB
3.2 多级页表:按需分配与稀疏空间支持
多级页表将线性页表拆分为层级结构,每一级负责虚拟地址的一部分位段。核心思想是:只分配实际使用的页表层级,未使用的上层页表项可以置空,从而大幅减少内存占用。
3.2.1 两级页表(32位经典设计)
以32位x86架构为例,虚拟地址被拆分为10位页目录索引 + 10位页表索引 + 12位页内偏移。
| 层级 | 位段 | 位数 | 表项数 | 每表大小 |
|---|---|---|---|---|
| 页目录(PD) | VPN[31:22] | 10 | 1024 | 4KB |
| 页表(PT) | VPN[21:12] | 10 | 1024 | 4KB |
| 页内偏移 | VA[11:0] | 12 | — | — |
3.2.2 三级页表(32位PAE/36位物理地址)
当物理地址扩展到36位(PAE)时,两级页表无法容纳更多物理页帧号,引入第三级——页目录指针表(PDPT)。
| 层级 | 位段 | 位数 | 表项数 | 每表大小 |
|---|---|---|---|---|
| PDPT | VPN[31:30] | 2 | 4 | 32字节 |
| 页目录(PD) | VPN[29:21] | 9 | 512 | 4KB |
| 页表(PT) | VPN[20:12] | 9 | 512 | 4KB |
| 页内偏移 | VA[11:0] | 12 | — | — |
3.2.3 四级页表(64位架构标准)
64位架构需要覆盖巨大的虚拟地址空间(当前通常使用48位或52位有效地址)。四级页表成为主流设计,每级索引通常使用9位(页大小4KB时)。
L0: PGD(页全局目录) — 索引位[47:39],9位,512项
L1: PUD(页上级目录) — 索引位[38:30],9位,512项
L2: PMD(页中间目录) — 索引位[29:21],9位,512项
L3: PTE(页表项) — 索引位[20:12],9位,512项
页内偏移 — 位[11:0],12位
3.3 ARMv8-A页表架构详解
ARMv8-A架构支持AArch64(64位)和AArch32(32位)两种执行状态。在AArch64状态下,MMU使用4级页表(当使用48位虚拟地址时)或5级页表(当使用52位虚拟地址时)。
3.3.1 页表层级与粒度
| 粒度 | 页大小 | L0索引位数 | L1索引位数 | L2索引位数 | L3索引位数 | 覆盖地址空间 |
|---|---|---|---|---|---|---|
| 4KB | 4KB | 9位(VA[47:39]) | 9位(VA[38:30]) | 9位(VA[29:21]) | 9位(VA[20:12]) | 48位/256TB |
| 16KB | 16KB | — | 13位(VA[47:35]) | 13位(VA[34:22]) | 11位(VA[21:14]) | 48位/256TB |
| 64KB | 64KB | — | — | 14位(VA[47:34]) | 13位(VA[33:16]) | 48位/256TB |
3.3.2 页表描述符格式
ARMv8-A的每个页表项(描述符)为8字节(64位)。描述符类型由最低两位决定:
- 00:无效描述符(表项未使用)
- 01:表描述符(指向下一级页表)
- 10:块描述符(直接映射到大块内存,仅L1/L2可用)
- 11:页描述符(仅L3可用,映射4KB/16KB/64KB页)
位[63:48]:物理地址高位(取决于物理地址宽度)
位[47:12]:物理页帧号(PPN)
位[11:10]:Access Flag(AF)
位[7:6]:属性索引(AttrIndx)
位[5]:非安全(NS)
位[4]:用户/特权(AP[1])
位[3]:读写/只读(AP[2])
位[2]:可共享(Shareable)
位[1:0]:类型(11 = 页描述符)
3.3.3 转换表基址寄存器(TTBR)
ARMv8-A使用两个转换表基址寄存器:
- TTBR0_EL1:用户空间页表基址(虚拟地址高位为0)
- TTBR1_EL1:内核空间页表基址(虚拟地址高位为1)
通过TCR(Translation Control Register)配置地址分割点,典型配置为:用户空间0x0000000000000000-0x0000FFFFFFFFFFFF(48位),内核空间0xFFFF000000000000-0xFFFFFFFFFFFFFFFF(48位)。
3.4 页表层级设计对比总结
| 特性 | 单级页表 | 两级页表 | 三级页表 | 四级页表(ARMv8-A) |
|---|---|---|---|---|
| 适用架构 | 早期32位MCU | x86 32位 | x86 PAE | ARMv8-A/x86_64 |
| 虚拟地址宽度 | 32位 | 32位 | 32位(36位物理) | 48位/52位 |
| 页表层级数 | 1 | 2 | 3 | 4(或5) |
| 最小页表内存(空进程) | 4MB(固定) | 4KB(仅页目录) | 32B(PDPT) | 4KB(PGD) |
| 典型页表内存(1GB进程) | 4MB | ~1MB | ~1MB | ~2MB |
| TLB缺失代价 | 1次内存访问 | 2次内存访问 | 3次内存访问 | 4次内存访问 |
| 大页支持 | 不支持 | 4MB大页 | 2MB/4MB | 2MB/1GB |
| 硬件遍历 | 是 | 是 | 是 | 是 |
3.5 页表层级与DMA缓冲区设计的关联
页表层级设计直接影响DMA缓冲区的分配和映射策略:
- 物理连续性要求:DMA设备通常要求缓冲区物理地址连续。多级页表可以通过大页映射(2MB/1GB)确保大块物理连续区域。
- 页表锁定:DMA缓冲区对应的页表项必须标记为"不可换出",防止DMA操作期间物理页被回收。
- 一致性管理:ARMv8-A页表属性中的Shareable位和Cache属性位控制DMA缓冲区的缓存策略(非缓存/写通/写回)。
- IOMMU/SMMU:系统MMU(SMMU)为DMA设备提供独立的地址转换,其页表结构与ARMv8-A MMU兼容,但使用独立的转换表基址寄存器。