3. MMU 基础:页表、TLB、转换粒度、页表遍历

内存管理单元(MMU)是 CPU 与系统内存之间的地址转换引擎。在 ARM 体系中,MMU 负责将 CPU 发出的虚拟地址(VA)转换为物理地址(PA),同时提供访问权限检查和内存属性控制。理解页表、TLB、转换粒度与页表遍历是掌握 SMMU 与 IOMMU 的基石。

3.1 页表(Page Table)

页表是一种多级查找数据结构,用于描述虚拟地址到物理地址的映射关系。ARMv8-A 架构支持 4KB、16KB 和 64KB 三种页面粒度,并采用 4 级或 3 级页表(取决于配置)。

关键概念:页表项(PTE)不仅包含物理页帧号(PFN),还包含访问权限(AP)、可缓存性(Attr)、执行权限(XN/PXN)等控制位。

3.1.1 页表层级结构

以 4KB 页面、4 级页表(Stage 1)为例,各级页表的作用如下:

级别 名称 粒度 覆盖范围 描述
L0 PGD(页全局目录) 512GB 512 × 1GB 顶级页表,每个表项指向一个 L1 表
L1 PUD(页上级目录) 1GB 512 × 2MB 可映射 1GB 块或指向 L2 表
L2 PMD(页中间目录) 2MB 512 × 4KB 可映射 2MB 块或指向 L3 表
L3 PTE(页表项) 4KB 512 × 4KB 最终页表,映射 4KB 物理页面
ARM 特色:ARMv8-A 支持 块映射(Block Mapping),在 L1 或 L2 级可以直接映射大块(1GB 或 2MB),跳过后续级别,减少页表遍历深度。

3.1.2 页表项格式

一个典型的 ARMv8-A Stage 1 页表项(L3 描述符)包含以下关键字段:

  • 位 [47:12]:输出物理地址(PA[47:12]),即物理页帧号
  • 位 [11:10]:访问权限(AP),控制读/写权限
  • 位 [7:6]:属性索引(AttrIndx),指向 MAIR 寄存器定义的缓存策略
  • 位 [54]:不可执行(XN),禁止在该页执行代码
  • 位 [0]:有效位(Valid),标记该表项是否可用
// ARMv8-A L3 页表项结构(简化)
struct arm64_pte {
    unsigned long valid      : 1;   // 位 0: 有效位
    unsigned long type       : 1;   // 位 1: 页/块类型
    unsigned long attr_index : 3;   // 位 4:2: 属性索引
    unsigned long ns         : 1;   // 位 5: 非安全
    unsigned long ap         : 2;   // 位 7:6: 访问权限
    unsigned long sh         : 2;   // 位 9:8: 可共享性
    unsigned long af         : 1;   // 位 10: 访问标志
    unsigned long nG         : 1;   // 位 11: 非全局
    unsigned long pfn        : 36;  // 位 47:12: 物理页帧号
    unsigned long reserved   : 15;  // 位 62:48: 保留
    unsigned long pxn        : 1;   // 位 63: 特权不可执行
};

3.2 TLB(转换后备缓冲器)

TLB 是 MMU 内部的高速缓存,用于缓存最近使用的虚拟地址到物理地址的转换结果。每次页表遍历都需要访问内存,TLB 可以显著减少地址转换的延迟。

3.2.1 TLB 结构

ARM 处理器通常包含多级 TLB:

  • L1 TLB(微 TLB):容量小(通常 32-64 项),访问延迟 1-2 个周期,用于快速路径
  • L2 TLB(主 TLB):容量大(通常 512-1024 项),访问延迟 5-10 个周期,作为 L1 的后备
  • 统一 TLB:某些实现中 L2 TLB 同时缓存指令和数据转换
TLB 一致性:当页表被软件修改后,必须执行 TLB 失效操作(如 tlbi vmalle1),否则 MMU 可能使用过时的 TLB 项,导致地址转换错误。

3.2.2 TLB 项格式

每个 TLB 项通常包含:

字段 说明
虚拟地址(VA) 转换的输入地址(或 ASID + VA 组合)
物理地址(PA) 转换后的输出地址
ASID 地址空间标识符,区分不同进程的 TLB 项
属性 缓存策略、访问权限、可执行性等
粒度 映射的页面大小(4KB/16KB/64KB/2MB/1GB)

3.3 转换粒度

ARMv8-A 支持多种转换粒度,不同粒度影响页表深度、TLB 覆盖范围和内存利用率。

粒度 页表级数 最大地址空间 TLB 覆盖 适用场景
4KB 4 级(L0-L3) 48 位 VA 较小 通用操作系统,细粒度内存管理
16KB 4 级(L0-L3) 48 位 VA 中等 特定嵌入式场景
64KB 3 级(L0-L2) 48 位 VA 较大 高性能计算,大页需求
2MB(块) L2 块映射 48 位 VA 大 内核映射,大块连续内存
1GB(块) L1 块映射 48 位 VA 极大 设备内存映射,IOMMU 大页
SMMU 中的大页:在 SMMU 中,使用 2MB 或 1GB 大页可以减少页表级数,降低 TLB 压力,对高带宽 DMA 设备(如 GPU、网络控制器)尤为重要。

3.4 页表遍历(Page Table Walk)

页表遍历是 MMU 根据虚拟地址逐级查找页表的过程。ARMv8-A 的硬件页表遍历器(Hardware Page Table Walker)自动完成此操作,无需软件干预。

3.4.1 遍历流程

  1. TLB 查找:MMU 首先在 TLB 中查找虚拟地址。如果命中(TLB hit),直接返回物理地址。
  2. TLB 未命中:如果 TLB 未命中(TLB miss),硬件页表遍历器启动。
  3. 读取根页表基址:从 TTBR0_EL1(用户空间)或 TTBR1_EL1(内核空间)寄存器获取 L0 页表基址。
  4. 逐级索引:从虚拟地址中提取各级索引(L0-L3),依次读取页表项。
  5. 检查块映射:如果在 L1 或 L2 级遇到块映射描述符,遍历提前终止。
  6. 最终 PTE:到达 L3 级后,读取最终的页表项,获取物理地址和属性。
  7. TLB 填充:将转换结果写入 TLB,供后续访问使用。
性能影响:一次完整的 4 级页表遍历需要 4 次内存访问(L0-L3),每次访问可能产生缓存未命中。TLB 命中率是 MMU 性能的关键指标。

3.4.2 页表遍历 SVG 图

ARMv8-A 页表遍历流程(4KB 页面,4 级页表) 虚拟地址 (VA) TLB 查找 未命中 L0 页表 (PGD) TTBR0/1 基址 + VA[47:39] L1 页表 (PUD) VA[38:30] 索引 L2 页表 (PMD) VA[29:21] 索引 L3 页表 (PTE) VA[20:12] 索引 物理地址 (PA) 填充 TLB 项 块映射优化 L1/L2 可提前终止遍历

3.5 地址空间隔离与 ASID

ARM MMU 通过 ASID(地址空间标识符) 实现进程间的 TLB 隔离。每个进程分配唯一的 ASID,TLB 项中记录 ASID,不同进程的相同虚拟地址不会冲突。

  • ASID 大小:ARMv8-A 支持 8 位(256 个)或 16 位(65536 个)ASID
  • 全局页:nG 位为 0 的页表项标记为全局,所有 ASID 共享(通常用于内核空间)
  • 非全局页:nG 位为 1 的页表项与 ASID 绑定,仅对特定进程可见
上下文切换开销:传统做法在进程切换时刷新整个 TLB,导致性能损失。使用 ASID 后,只需切换 TTBR0_EL1 中的 ASID,TLB 项可保留,大幅降低切换开销。

3.6 本章小结

组件 核心作用 关键参数
页表 存储 VA→PA 映射关系 级数(3/4)、粒度(4K/16K/64K)
TLB 缓存地址转换结果 容量、关联度、ASID 支持
转换粒度 决定映射的最小内存单元 4KB/2MB/1GB 等
页表遍历 硬件自动查找页表的过程 遍历深度、块映射优化