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

1.1 AArch64 执行状态

ARMv8 架构引入了两种执行状态:AArch32 和 AArch64。本课程聚焦于 AArch64 状态,它是 64 位 ARM 架构的核心执行环境,也是 Linux 内核运行的基础。

1.1.1 AArch64 关键特性

  • 64 位虚拟地址空间:支持 48 位(经典)或 52 位(扩展)虚拟地址,最大可寻址 4PB(48 位)或 16EB(52 位)。
  • 31 个通用寄存器:X0-X30,每个均为 64 位宽。X30 用作链接寄存器(LR)。
  • 栈指针寄存器:SP_EL0 和 SP_ELx(x=1,2,3),每个异常等级拥有独立的栈指针。
  • 程序计数器:PC,64 位宽,不可直接写入。
  • 异常链接寄存器:ELR_ELx,用于保存异常返回地址。
  • 保存的状态寄存器:SPSR_ELx,保存异常发生时的处理器状态。
关键区别:与 AArch32 相比,AArch64 取消了 CPSR 的直接访问模式,改用 SPSR_ELx 保存异常上下文;通用寄存器数量从 15 个(R0-R14)扩展到 31 个(X0-X30),显著减少了栈帧保存/恢复的开销。

1.1.2 寄存器模型对比

特性 AArch32 AArch64
通用寄存器 15 个(R0-R14) 31 个(X0-X30)
PC 可写性 可直接写入(如 MOV PC, LR) 不可直接写入
栈指针 R13(SP) SP_EL0 / SP_ELx
异常返回 SUBS PC, LR ERET
虚拟地址宽度 32 位 48/52 位
AArch64 寄存器模型 通用寄存器 X0-X30 X0-X7:参数/返回值寄存器 X8:间接结果寄存器 X9-X15:临时寄存器(调用者保存) X16-X17:IP0/IP1(内部过程调用) X18:平台寄存器 X19-X28:被调用者保存寄存器 X29:帧指针(FP) X30:链接寄存器(LR) 特殊寄存器 SP_EL0:EL0 栈指针 SP_EL1:EL1 栈指针 SP_EL2:EL2 栈指针 SP_EL3:EL3 栈指针 PC:程序计数器(只读) ELR_ELx:异常链接寄存器 SPSR_ELx:保存的状态寄存器 TPIDR_ELx:线程 ID 寄存器

1.2 异常等级(Exception Levels)

ARMv8-A 架构定义了四个异常等级(EL0-EL3),用于实现不同特权级别的软件隔离。这是操作系统内核安全隔离的硬件基础。

1.2.1 异常等级定义

异常等级 名称 运行软件 特权级别
EL0 用户态 应用程序 最低
EL1 内核态 操作系统内核 中等
EL2 虚拟机监控器 Hypervisor 高
EL3 安全监控器 Secure Monitor 最高

1.2.2 异常等级切换规则

  • 异常捕获:低等级向高等级切换(如 EL0 → EL1),通过同步异常(SVC、HVC、SMC)或异步异常(IRQ、FIQ、SError)触发。
  • 异常返回:高等级向低等级切换(如 EL1 → EL0),通过 ERET 指令实现。
  • 等级提升:只能逐级或跨级向更高等级切换(如 EL0 → EL1 或 EL0 → EL2)。
  • 等级降低:只能向更低等级切换,不能直接跳转到同级或更高级。
重要约束:EL0 无法直接访问页表基地址寄存器 TTBR0_EL1/TTBR1_EL1,也无法执行 DSB/ISB 等屏障指令。所有页表操作必须由 EL1 及以上等级完成。
ARMv8-A 异常等级模型 EL3:安全监控器 Secure Monitor / ATF / TEE EL2:虚拟机监控器 Hypervisor / KVM / Xen EL1:内核态 Linux Kernel / 设备驱动 EL0:用户态 应用程序 / 用户空间库 ERET 返回 ERET 返回 SMC 指令 HVC 指令 SVC 指令

1.3 内存模型基础

ARMv8-A 内存模型定义了处理器如何访问内存、缓存一致性、内存排序以及设备内存的访问规则。理解内存模型是正确配置 MMU 和页表的前提。

1.3.1 内存类型

内存类型 属性 典型用途 缓存策略
Normal 可缓存、可合并、可重排 DRAM、内核代码、用户数据 Write-Back / Write-Through
Device 不可缓存、严格排序 MMIO 寄存器、外设内存 Non-Cacheable
Strongly Ordered 严格排序、完全同步 中断控制器、系统控制寄存器 Non-Cacheable

1.3.2 内存属性与页表描述符

在页表描述符中,通过 AttrIndx 字段(位[4:2])索引 MAIR_EL1 寄存器中的属性编码。MAIR_EL1 包含 8 个属性字段,每个字段 8 位,定义内存类型和缓存策略。

// MAIR_EL1 寄存器格式(8 个属性字段,每个 8 位)
// 位 [63:56] Attr7 | [55:48] Attr6 | [47:40] Attr5 | [39:32] Attr4
// 位 [31:24] Attr3 | [23:16] Attr2 | [15:8]  Attr1 | [7:0]   Attr0

// Linux 内核典型配置
#define MAIR_ATTR_NORMAL_WB      0xFF  // Normal Write-Back 可缓存
#define MAIR_ATTR_NORMAL_WT      0xBB  // Normal Write-Through 可缓存
#define MAIR_ATTR_DEVICE_nGnRnE  0x00  // Device 非缓存非聚集非重排
#define MAIR_ATTR_NORMAL_NC      0x44  // Normal Non-Cacheable

1.3.3 内存排序模型

ARMv8 采用弱排序(Weakly Ordered)内存模型,允许处理器和编译器对内存访问进行重排,以提高性能。但对外设访问和多核同步场景,必须使用内存屏障指令保证顺序。

屏障指令 作用 使用场景
DMB 数据内存屏障 保证屏障前后的数据访问顺序
DSB 数据同步屏障 等待所有内存访问完成后再执行后续指令
ISB 指令同步屏障 刷新流水线,保证后续指令从缓存/内存重新读取
页表切换关键点:修改 TTBR0_EL1/TTBR1_EL1 后,必须依次执行 DSB(确保页表写入完成)和 ISB(刷新流水线),否则处理器可能使用过期的 TLB 条目。
ARMv8 内存模型与页表属性映射 MAIR_EL1 寄存器(8 × 8 位属性字段) Attr7 | Attr6 | Attr5 | Attr4 | Attr3 | Attr2 | Attr1 | Attr0 Attr0: 0xFF Normal WB Attr1: 0x44 Normal NC Attr2: 0x00 Device 页表描述符 AttrIndx 字段(位[4:2]) AttrIndx = 0 → MAIR_EL1 Attr0 | AttrIndx = 1 → Attr1 | AttrIndx = 2 → Attr2 Normal 内存 可缓存、可合并 Write-Back/Write-Through Device 内存 不可缓存 严格排序(nGnRnE) Strongly Ordered 完全同步 无缓存、无重排

1.4 本章小结

  • AArch64 执行状态:提供 31 个 64 位通用寄存器、独立的栈指针和异常链接寄存器,是 Linux 内核运行的基础硬件环境。
  • 异常等级(EL0-EL3):实现从用户态到安全监控器的四级特权隔离,页表配置和 TLB 管理主要在 EL1(内核态)完成。
  • 内存模型:区分 Normal/Device/Strongly Ordered 三种内存类型,通过 MAIR_EL1 和页表描述符 AttrIndx 字段协同配置内存属性。
  • 内存屏障:DMB/DSB/ISB 是保证页表切换正确性的关键指令,任何 TTBR 寄存器的修改都必须配合屏障指令使用。