4. 页表层级与粒度:4KB/16KB/64KB页面粒度、3级/4级/5级页表配置、VA空间划分
ARM64 架构的页表配置是内存管理单元(MMU)的核心,它决定了虚拟地址(VA)到物理地址(PA)的转换方式。本章深入剖析页面粒度、页表层级以及虚拟地址空间的划分,这些参数直接影响 TLB 的覆盖范围和系统性能。
4.1 页面粒度(Page Granularity)
ARM64 支持三种页面粒度:4KB、16KB 和 64KB。页面粒度决定了页表层级中每个叶子页表项(PTE)所映射的内存块大小,也决定了页表层级数。
| 特性 | 4KB 页面 | 16KB 页面 | 64KB 页面 |
|---|---|---|---|
| 页面大小 | 4 KB | 16 KB | 64 KB |
| 页内偏移位数 | 12 bits | 14 bits | 16 bits |
| 典型页表层级 | 4 级 (L0-L3) | 4 级 (L0-L3) | 3 级 (L0-L2) |
| TLB 覆盖范围 | 较小 | 中等 | 较大 |
| 内部碎片 | 较少 | 中等 | 较多 |
| 适用场景 | 通用计算、嵌入式 | 特定嵌入式、网络设备 | 高性能计算、大内存服务器 |
粒度选择权衡: 4KB 粒度提供最精细的内存管理,减少内部碎片,但需要更多页表层级和 TLB 条目来覆盖相同大小的地址空间。64KB 粒度则相反,它减少了页表层级和 TLB 压力,但可能造成更多的内部碎片。Linux 内核默认使用 4KB 页面粒度。
4.2 页表层级配置
ARM64 的页表层级可以是 3 级、4 级 或 5 级,具体取决于页面粒度和虚拟地址宽度。层级数决定了虚拟地址中用于页表索引的位数。
4.2.1 层级与地址位宽
对于 48 位虚拟地址空间,不同页面粒度对应的页表层级如下:
- 4KB 页面: 4 级页表(L0, L1, L2, L3)。每级页表使用 9 位索引(512 个条目)。
- 16KB 页面: 4 级页表(L0, L1, L2, L3)。每级页表使用 11 位索引(2048 个条目)。
- 64KB 页面: 3 级页表(L0, L1, L2)。每级页表使用 13 位索引(8192 个条目)。
对于 52 位虚拟地址空间(ARMv8.2 引入),则需要 5 级页表(L0-L4),以容纳更大的地址范围。
关键公式: VA 位数 = 页内偏移位数 + Σ(每级页表索引位数)。例如,4KB 页面 + 4 级页表:12 + 9 + 9 + 9 + 9 = 48 位。
4.2.2 页表层级结构对比
| 页面粒度 | 页表层级 | L0 索引 | L1 索引 | L2 索引 | L3 索引 | 页内偏移 |
|---|---|---|---|---|---|---|
| 4KB | 4 级 | bits [47:39] | bits [38:30] | bits [29:21] | bits [20:12] | bits [11:0] |
| 16KB | 4 级 | bits [47:47] | bits [46:36] | bits [35:25] | bits [24:14] | bits [13:0] |
| 64KB | 3 级 | bits [47:47] | bits [46:42] | bits [41:29] | bits [28:16] | bits [15:0] |
注意: 对于 64KB 页面,L0 和 L1 级页表仅使用 1 位索引(2 个条目),这实际上是一种优化,因为 64KB 页面只需要 3 级页表即可覆盖 48 位地址空间。L0 级页表仅用于区分高/低地址空间。
4.3 虚拟地址空间划分
ARM64 架构将虚拟地址空间划分为两个区域:用户空间(低地址)和 内核空间(高地址)。划分由 TCR_EL1 寄存器中的 T1SZ 和 T0SZ 字段控制。
4.3.1 经典 48 位地址空间划分
在典型的 Linux 内核配置中,48 位虚拟地址空间被对半划分:
- 用户空间: 0x0000_0000_0000_0000 ~ 0x0000_FFFF_FFFF_FFFF(256 TB)
- 内核空间: 0xFFFF_0000_0000_0000 ~ 0xFFFF_FFFF_FFFF_FFFF(256 TB)
这种划分方式使得内核和用户空间各自拥有独立的 48 位地址范围,中间存在一个巨大的“空洞”,用于捕获非法访问。
4.3.2 非对称划分
通过调整 T0SZ 和 T1SZ,可以实现非对称的地址空间划分。例如,可以为用户空间分配更多地址空间,而压缩内核空间。
| 配置 | T0SZ (用户) | T1SZ (内核) | 用户空间大小 | 内核空间大小 |
|---|---|---|---|---|
| 对称 48 位 | 16 | 16 | 256 TB | 256 TB |
| 用户空间扩展 | 12 | 20 | 4 PB | 4 TB |
| 内核空间压缩 | 20 | 12 | 4 TB | 4 PB |
实践提示: Linux 内核默认使用对称划分。但在某些场景下(如大型数据库或 HPC),可能需要为用户空间分配更大的地址范围,此时可以通过修改内核配置实现非对称划分。
4.4 页表遍历与地址转换流程
下图展示了 ARM64 4 级页表(4KB 页面)的地址转换流程:
4.5 页表配置寄存器
页表配置的核心寄存器是 TCR_EL1(Translation Control Register)。它控制着页表层级、页面粒度、地址空间划分等关键参数。
// TCR_EL1 关键字段示例 (4KB页面, 48位地址空间)
TCR_EL1 =
T0SZ = 16, // 用户空间大小 = 2^(64-16) = 2^48 = 256TB
T1SZ = 16, // 内核空间大小 = 2^(64-16) = 2^48 = 256TB
TG0 = 0b00, // 用户空间页面粒度: 4KB
TG1 = 0b10, // 内核空间页面粒度: 4KB
IPS = 0b010, // 中间物理地址大小: 40位 (1TB)
ORGN0 = 0b01, // 用户空间外部缓存属性: 写回
IRGN0 = 0b01, // 用户空间内部缓存属性: 写回
SH0 = 0b11, // 用户空间可共享性: 内部共享
ORGN1 = 0b01, // 内核空间外部缓存属性: 写回
IRGN1 = 0b01, // 内核空间内部缓存属性: 写回
SH1 = 0b11; // 内核空间可共享性: 内部共享
配置要点:
TCR_EL1 的 TG0 和 TG1 字段分别控制用户空间和内核空间的页面粒度。它们可以独立配置,但通常设置为相同值。如果配置不一致,MMU 将使用两者中较大的粒度进行页表遍历。
4.6 页表配置对 TLB 的影响
页面粒度和页表层级直接影响 TLB 的覆盖范围和命中率:
- 大页面粒度(64KB): 每个 TLB 条目覆盖更大的内存区域,从而减少 TLB 缺失。适用于内存访问模式具有良好空间局部性的工作负载。
- 多级页表(4级/5级): 增加页表遍历的深度,可能增加 TLB 缺失的惩罚(需要多次内存访问)。但允许更精细的内存管理。
- TLB 条目格式: ARM64 TLB 条目通常包含虚拟地址、物理地址、页面大小、权限和属性。页面大小信息用于确定 TLB 条目的覆盖范围。
| 页面粒度 | TLB 条目覆盖范围 | 典型 TLB 缺失率 | 页表遍历开销 |
|---|---|---|---|
| 4KB | 4 KB | 较高 | 4 次内存访问 |
| 16KB | 16 KB | 中等 | 4 次内存访问 |
| 64KB | 64 KB | 较低 | 3 次内存访问 |
性能优化建议: 对于数据库、HPC 等大内存工作负载,考虑使用 64KB 页面粒度以减少 TLB 缺失。对于嵌入式或内存受限系统,4KB 页面粒度提供更精细的控制,减少内部碎片。
4.7 本章小结
本章详细介绍了 ARM64 页表配置的核心概念:
- 页面粒度 决定了页表层级和 TLB 覆盖范围,需要在灵活性和性能之间权衡。
- 页表层级 可以是 3 级、4 级或 5 级,取决于页面粒度和虚拟地址宽度。
- 虚拟地址空间 通过
TCR_EL1寄存器划分为用户空间和内核空间,支持对称和非对称配置。 - 页表配置 直接影响 TLB 的命中率和系统性能,是内核内存管理调优的关键参数。