4. 页表层级与粒度

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 页面)的地址转换流程:

ARM64 4级页表地址转换流程 (4KB页面) 虚拟地址 (VA) [47:0] L0索引 [47:39] L1索引 [38:30] L2索引 [29:21] L3索引 [20:12] 页内偏移 [11:0] L0 页表 L1 页表 L2 页表 L3 页表 L0 描述符 L1 描述符 L2 描述符 L3 描述符 物理地址 (PA) = L3描述符[基址] + 页内偏移 说明 • 每级页表包含 512 个条目 • 每个条目 8 字节 • 页表大小 = 512 * 8 = 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 的命中率和系统性能,是内核内存管理调优的关键参数。