ARM64 Linux内核MMU页表配置与TLB管理 - 第2节

2.1 虚拟地址与物理地址

在 ARM64 架构中,CPU 执行指令时使用的地址是 虚拟地址(Virtual Address, VA),而实际访问 DRAM 或外设寄存器时使用的地址是 物理地址(Physical Address, PA)。MMU(Memory Management Unit)负责在指令执行流水线的地址阶段,将 VA 实时转换为 PA。

2.1.1 地址空间对比

属性虚拟地址(VA)物理地址(PA)
使用者CPU 指令、load/store、PC内存控制器、总线、DMA
空间大小48 位(经典页表)或 52 位(LVA 扩展)48 位(最大 256 TiB)
连续性每个进程拥有独立连续空间物理内存可能碎片化
保护粒度页级(4KB/16KB/64KB)无直接保护
映射关系多对一(多个 VA 映射到同一 PA)一对一(PA 唯一对应物理位置)
关键理解: 虚拟地址是“假地址”,物理地址是“真地址”。MMU 是连接两者的桥梁。没有 MMU,CPU 只能直接使用物理地址,无法实现进程隔离和虚拟内存。

2.1.2 ARM64 用户空间与内核空间划分

ARM64 Linux 内核采用 高低端划分 策略:

  • 用户空间(EL0): 低地址区域,VA 范围 0x0000_0000_0000_0000 ~ 0x0000_FFFF_FFFF_FFFF(48 位)。
  • 内核空间(EL1): 高地址区域,VA 范围 0xFFFF_0000_0000_0000 ~ 0xFFFF_FFFF_FFFF_FFFF(48 位)。
  • TTBR0_EL1 指向用户页表基址,TTBR1_EL1 指向内核页表基址。
ARM64 虚拟地址空间划分(48位) 用户空间 (EL0) 0x0000_0000_0000_0000 ~ 0x0000_FFFF_FFFF_FFFF 内核空间 (EL1) 0xFFFF_0000_0000_0000 ~ 0xFFFF_FFFF_FFFF_FFFF TTBR0_EL1 → 用户页表   |   TTBR1_EL1 → 内核页表 用户态无法访问内核地址,内核态可通过 copy_from_user 安全访问用户地址

2.2 地址转换原理

ARM64 地址转换的核心是 多级页表遍历(Page Table Walk)。当 CPU 发出一个 VA,MMU 硬件自动执行以下步骤:

  1. 确定页表基址: 根据 VA 的最高有效位选择 TTBR0_EL1(用户)或 TTBR1_EL1(内核)。
  2. 逐级索引: 将 VA 划分为多个位段,每段作为索引查找对应级别的页表项(PTE)。
  3. 检查权限与属性: 每个 PTE 包含物理地址高位、访问权限、内存类型、脏位、有效位等。
  4. 获取物理地址: 最后一级 PTE 提供物理页帧号(PFN),与 VA 的页内偏移拼接得到完整 PA。
  5. 缓存结果: 转换结果存入 TLB,加速后续相同 VA 的访问。

2.2.1 4KB 页 4 级页表地址拆分

VA 位段位宽作用页表级别
VA[47:39]9 bitsL0 索引(PGD)Level 0
VA[38:30]9 bitsL1 索引(PUD)Level 1
VA[29:21]9 bitsL2 索引(PMD)Level 2
VA[20:12]9 bitsL3 索引(PTE)Level 3
VA[11:0]12 bits页内偏移—
硬件加速: ARM64 的 Table Walk 完全由 MMU 硬件完成,无需软件介入。Linux 内核只需维护页表数据结构,MMU 自动读取内存中的页表项进行转换。
ARM64 4级页表地址转换流程(4KB页) L0索引 L1索引 L2索引 L3索引 页内偏移 VA[47:39]   VA[38:30]   VA[29:21]   VA[20:12]   VA[11:0] L0 PGD L1 PUD L2 PMD L3 PTE PA 每级页表项占用 8 字节,每级页表包含 512 个表项(9位索引)

2.3 页表的作用

页表(Page Table)是 MMU 地址转换的“字典”,存储在系统内存中。每个进程拥有独立的用户页表,内核页表全局共享。页表的核心作用包括:

  • 地址映射: 将虚拟页号(VPN)映射到物理页帧号(PFN)。
  • 权限控制: 通过 PTE 中的 AP(Access Permission)位控制读/写/执行权限。
  • 内存属性: 设置缓存策略(Normal/Device)、共享属性(Inner/Outer Shareable)、非安全访问等。
  • 页表项状态: 有效位(Valid)、脏位(Dirty)、访问位(Access Flag)用于页面回收和写回。
  • 大页支持: 在 L1/L2 级别设置块映射(Block Mapping),支持 2MB/1GB 大页,减少 TLB 压力。

2.3.1 ARM64 PTE 关键字段

位段位宽名称说明
[63:48]16 bitsPBHA页表属性扩展(硬件辅助)
[47:12]36 bitsPFN物理页帧号(4KB 页粒度)
[11]1 bitnG非全局位(0=全局,1=进程私有)
[10]1 bitAF访问标志(Access Flag)
[9:8]2 bitsSH共享属性(00=非共享,01=保留,10=外共享,11=内共享)
[7:6]2 bitsAP访问权限(00=EL1 R/W,01=EL1 R/W EL0 无,10=EL1 R/O,11=EL1 R/O EL0 无)
[5]1 bitNS非安全位(安全世界/非安全世界)
[4]1 bitAttrIndx内存属性索引(指向 MAIR_EL1)
[2:1]2 bitsAttr页表属性(00=故障,01=页,10=保留,11=块)
[0]1 bitValid有效位(1=有效,0=无效)
注意: 页表项中的 PFN 字段宽度取决于物理地址大小。ARM64 支持最大 48 位物理地址,因此 PFN 占用 36 位(48-12)。如果启用 52 位物理地址扩展,PFN 位段会相应扩展。

2.3.2 页表与 TLB 的协作

页表存储在内存中,MMU 每次地址转换都需要读取内存中的页表项。为了加速这一过程,MMU 内部维护了一个 转换后备缓冲器(TLB),缓存最近使用的 VA→PA 映射。当 TLB 命中时,MMU 直接返回 PA,无需访问内存页表;当 TLB 缺失时,MMU 执行硬件 Table Walk,填充 TLB 后返回结果。

页表与 TLB 协作流程 CPU 发出 VA TLB 缓存查找 命中? 物理地址 返回 PA Table Walk 读取内存页表 TLB 命中:ns 级延迟   |   TLB 缺失:需 4 次内存访问(4级页表),延迟数十 ns
性能关键: 页表遍历是内存访问中最频繁的操作之一。ARM64 通过 TLB、多级页表缓存(如 PTE 缓存)、以及硬件预取机制来降低 Table Walk 的开销。Linux 内核通过 flush_tlb_mm、flush_tlb_page 等接口管理 TLB 一致性。