ARM64 Linux内核MMU页表机制与TLB缓存刷新 - 第2节

2.1 虚拟地址与物理地址

在ARM64 Linux系统中,CPU执行指令时使用的地址并非直接对应物理内存中的实际位置,而是通过MMU(Memory Management Unit)进行转换。这种设计引入了两个核心概念:虚拟地址(VA,Virtual Address)和物理地址(PA,Physical Address)。

  • 虚拟地址(VA):由CPU指令生成,是进程视角的地址空间。每个进程拥有独立的虚拟地址空间,大小由处理器位数决定(ARM64支持48位或52位虚拟地址)。
  • 物理地址(PA):实际访问内存硬件单元的地址,对应DRAM或MMIO(内存映射I/O)的真实位置。
关键理解:虚拟地址是“假地址”,物理地址是“真地址”。MMU负责将虚拟地址映射到物理地址,使得每个进程可以认为自己拥有从0到最大地址的连续内存空间,而实际上物理内存可能是不连续的、共享的,甚至部分数据在磁盘上(通过缺页异常换入)。

下表总结了虚拟地址与物理地址的核心差异:

特性 虚拟地址(VA) 物理地址(PA)
生成者 CPU指令(程序计数器PC) MMU转换后输出
空间大小 48位(256TB)或52位(4PB) 取决于物理内存容量(通常40~48位)
连续性 每个进程拥有连续的地址空间 物理内存可能碎片化、不连续
隔离性 进程间虚拟地址相互隔离 物理地址全局共享
权限控制 通过页表项设置读/写/执行权限 无直接权限属性
实战提示:在Linux内核中,虚拟地址空间被划分为用户空间(低地址)和内核空间(高地址)。ARM64架构下,典型的分界线是0x0000_0000_0000_0000 ~ 0x0000_FFFF_FFFF_FFFF为用户空间,0xFFFF_0000_0000_0000以上为内核空间。

2.2 地址转换:MMU的核心工作

MMU的地址转换过程本质上是查表操作。CPU发出的虚拟地址被分解为多个索引字段,每个字段用于在页表的某一级中查找对应的表项,最终得到物理地址。ARM64架构支持多级页表(通常为3级或4级),以适应大地址空间并节省页表内存。

地址转换的基本流程如下:

  1. TLB查找:MMU首先在TLB(Translation Lookaside Buffer)中查找虚拟地址对应的转换结果。如果命中(TLB hit),直接获得物理地址,无需访问页表。
  2. 页表遍历:如果TLB未命中(TLB miss),MMU硬件自动遍历页表。从TTBRx_EL1(Translation Table Base Register)寄存器指向的顶级页表开始,逐级索引。
  3. 权限检查:在每一级页表项中检查访问权限(读/写/执行)、异常等级检查(EL0/EL1/EL2/EL3)以及访问标志位(AF,Access Flag)。
  4. 物理地址生成:最后一级页表项(页表条目,PTE)中包含物理页帧号(PFN,Page Frame Number),与虚拟地址中的页内偏移组合,形成完整的物理地址。
注意:ARM64的地址转换是硬件自动完成的,软件(操作系统)只需维护页表结构和TTBRx_EL1寄存器。但页表的建立、修改和销毁由内核负责,这是内存管理子系统的核心任务。

下图展示了ARM64 4级页表的地址转换过程:

ARM64 4级页表地址转换流程 ARM64 4级页表地址转换流程 虚拟地址(VA)分解:63~48位保留 | 47~39位(L0索引) | 38~30位(L1索引) | 29~21位(L2索引) | 20~12位(L3索引) | 11~0位(页内偏移) TTBRx_EL1 → L0基地址 L0页表 → 找到L1表基址 L1页表 → 找到L2表基址 L2页表 → 找到L3表基址 L3页表 → 物理页帧号(PFN) 物理地址 = PFN + 页内偏移(11~0位)

2.3 页表的作用

页表是MMU进行地址转换的核心数据结构,本质是一个多级树形结构,存储在物理内存中。每个进程拥有独立的页表,由操作系统内核维护。页表的主要作用包括:

  • 地址映射:将虚拟页号(VPN,Virtual Page Number)映射到物理页帧号(PFN)。这是页表最基本的功能。
  • 权限控制:每个页表项(PTE)包含权限位,控制该页面的读(R)、写(W)、执行(X)权限,以及用户/内核空间访问权限(AP位)。
  • 属性管理:包括缓存策略(Cacheable/Non-cacheable)、共享属性(Shareable/Non-shareable)、访问标志(AF,Access Flag)和脏页标志(DBM,Dirty Bit Modifier)。
  • 内存隔离:不同进程的页表相互独立,确保进程A无法访问进程B的物理内存,实现进程间隔离。
  • 按需分配:页表可以只映射实际使用的虚拟地址范围,未使用的虚拟地址对应的页表项可以标记为无效(Invalid),节省页表内存。
页表项(PTE)关键字段:在ARM64中,一个标准的页表项(8字节)包含物理页帧号(PFN,高位)、访问权限位(AP[2:1])、可执行位(UXN/PXN)、访问标志位(AF)、脏页位(DBM)、连续块指示位(Contiguous)、以及类型位(Table/Page)等。

下表展示了ARM64页表项中关键字段的含义:

字段 位范围 描述
PFN [47:12](4KB页) 物理页帧号,指向物理内存中的4KB页
AP[2:1] [7:6] 访问权限:00=EL1读写,01=EL1/EL0读写,10=EL1只读,11=EL1/EL0只读
UXN [54] 用户不可执行(User Execute Never)
PXN [53] 特权不可执行(Privileged Execute Never)
AF [10] 访问标志:1表示该页已被访问,用于页面回收算法
DBM [51] 脏页标志:1表示该页已被写入,用于回写文件系统
Contiguous [52] 连续块指示:1表示该页属于一个连续块(16页或32页)
Type [1:0] 表项类型:00=无效,01=页表(指向下一级),10=保留,11=页(最后一级)

2.4 TLB的作用

TLB(Translation Lookaside Buffer)是MMU内部的一个高速缓存,专门用于缓存最近使用的虚拟地址到物理地址的转换结果。由于页表存储在物理内存中,每次地址转换都需要多次内存访问(多级页表遍历),TLB的存在极大地加速了这一过程。

TLB的核心作用包括:

  • 加速地址转换:TLB命中时,MMU可以在1~2个CPU周期内获得物理地址,而页表遍历可能需要数十甚至上百个周期。
  • 减少内存访问:避免重复访问页表,降低内存带宽消耗和延迟。
  • 支持进程切换:TLB通常包含ASID(Address Space ID)字段,用于区分不同进程的转换条目,减少进程切换时的TLB刷新开销。
性能关键:TLB的命中率直接影响系统性能。ARM64架构支持多种页面大小(4KB、16KB、64KB、2MB、1GB等),大页面可以减少页表级数并提高TLB覆盖范围,是性能优化的常用手段。

下图展示了TLB在地址转换流程中的位置和作用:

TLB在地址转换中的位置 TLB在地址转换中的位置 CPU 虚拟地址(VA) TLB 命中 物理地址 内存 未命中 页表遍历(硬件) 多级页表查找 写入TLB缓存 TLB命中:直接获得物理地址,延迟约1~2周期 TLB未命中:硬件遍历页表(数十周期),结果写入TLB后重试

2.5 页表与TLB的协同工作

页表和TLB共同构成了ARM64 MMU的地址转换体系。页表是慢速路径(软件维护、硬件遍历),TLB是快速路径(硬件缓存、自动管理)。两者的协同关系如下:

  • 页表是权威数据源:TLB中的所有条目都是从页表中获取的。如果页表被修改(例如解除映射、更改权限),对应的TLB条目必须被刷新(Invalidate),否则MMU可能使用过时的转换结果。
  • TLB是性能加速器:TLB的容量有限(通常几十到几百个条目),但命中率极高(通常超过99%)。TLB未命中时,硬件自动遍历页表并填充TLB。
  • ASID机制:ARM64的TLB支持ASID(Address Space ID),每个进程分配唯一的ASID。TLB条目中存储ASID,使得不同进程的转换条目可以共存于TLB中,进程切换时无需完全刷新TLB,只需切换TTBRx_EL1和ASID。
关键约束:当内核修改页表(如解除用户空间映射、更改页面权限)时,必须执行TLB刷新指令(如TLBI VMALLE1、TLBI ASIDE1等),确保后续访问使用最新的页表内容。TLB刷新是MMU一致性的核心保障,也是性能敏感的操作。

下表总结了页表与TLB的对比:

特性 页表(Page Table) TLB(Translation Lookaside Buffer)
存储位置 物理内存(DRAM) CPU内部(SRAM)
访问速度 数十~数百周期(多级遍历) 1~2周期
容量 大(每个进程独立,可占用MB级内存) 小(通常32~1024个条目)
维护者 操作系统内核(软件) MMU硬件(自动填充/淘汰)
一致性 权威数据源 页表的缓存副本,需软件刷新
进程切换 切换TTBRx_EL1指向新进程页表 通过ASID避免完全刷新
总结:虚拟地址提供进程隔离和抽象,物理地址对应真实硬件资源,页表是地址转换的“地图”,TLB是“地图缓存”。理解这四者的关系是掌握ARM64 Linux内核MMU机制的基础,也是后续学习页表创建、TLB刷新策略和性能优化的前提。