1. ARM64 架构概述:AArch64 执行状态、异常等级与内存模型

ARMv8-A 架构引入了 AArch64 执行状态,这是 64 位 ARM 处理器的核心运行模式。与传统的 32 位 AArch32 状态相比,AArch64 提供了更大的虚拟地址空间、更多的通用寄存器以及全新的异常模型。理解 AArch64 的执行状态、异常等级(Exception Levels)和内存模型,是深入掌握 MMU 页表机制与 TLB 缓存刷新的基石。

1.1 AArch64 执行状态与寄存器模型

AArch64 执行状态专为 64 位操作系统设计,其寄存器模型与 AArch32 有显著差异:

特性 AArch64 AArch32
通用寄存器 31 个 64 位寄存器(X0-X30),其中 X30 为链接寄存器(LR) 16 个 32 位寄存器(R0-R15)
栈指针 每个异常等级拥有独立的 SP_ELx 共享 SP,或使用 SPSR 切换
程序状态寄存器 PSTATE(NZCV、DAIF、CurrentEL 等) CPSR
虚拟地址宽度 支持 48 位或 52 位(取决于页表配置) 最大 32 位
异常返回 ERET 指令,从 ELR_ELx 恢复 PC MOVS PC, LR 或 SUBS PC, LR
关键点:在 AArch64 中,所有异常处理都使用专用的异常链接寄存器(ELR_ELx)和保存的状态寄存器(SPSR_ELx),这简化了嵌套异常的处理逻辑,并提高了安全性。

1.2 异常等级(Exception Levels)

ARMv8-A 定义了四个异常等级(EL0-EL3),每个等级对应不同的特权级别和资源访问权限。这种分层设计是 ARM 安全模型和虚拟化支持的基础。

ARM64 异常等级(Exception Levels)架构图 EL3:安全监控器(Secure Monitor) 最高特权级,管理安全世界与非安全世界的切换 EL2:虚拟机监控器(Hypervisor) 虚拟化扩展,管理虚拟机(VM)的隔离与切换 EL1:操作系统内核(OS Kernel) 运行 Linux 内核,管理 MMU 页表和系统资源 EL0:用户态应用程序(User Apps) 最低特权级,运行用户进程,受 MMU 保护 说明:异常等级从 EL0(最低)到 EL3(最高)。Linux 内核通常运行在 EL1,KVM 虚拟化使用 EL2,TrustZone 安全固件使用 EL3。

1.3 异常等级之间的切换

异常等级之间的切换通过 异常(Exception) 和 异常返回(ERET) 机制实现。当低等级代码触发异常时,处理器会提升到更高的异常等级执行异常处理程序。

  • 同步异常:指令执行直接导致,如系统调用(SVC)、页故障(Page Fault)、未定义指令。
  • 异步异常:外部事件触发,如中断(IRQ/FIQ)、SError(系统错误)。
  • 异常向量表:每个异常等级都有独立的向量表基址寄存器(VBAR_ELx),指向该等级异常处理入口。
MMU 关联:当发生页故障异常时,处理器会从当前异常等级(通常是 EL0 或 EL1)陷入到 EL1 的异常向量表,Linux 内核的缺页异常处理程序(do_page_fault)会解析故障地址并更新页表。

1.4 ARM64 内存模型简介

ARM64 的内存模型定义了处理器如何访问内存、缓存一致性以及内存排序规则。对于 MMU 和 TLB 而言,最重要的概念是 内存类型(Memory Type) 和 共享属性(Shareability)。

内存类型 描述 典型用途
Normal 普通内存,允许缓存、合并和推测访问 DRAM、栈、堆、代码段
Device 设备内存,严格排序,禁止推测访问 MMIO 寄存器、外设内存
Strongly Ordered 强排序内存,所有访问按程序顺序执行 某些系统控制寄存器
共享属性 描述 对 TLB 的影响
Non-shareable 仅当前处理器核访问 TLB 条目仅对当前 PE 有效,无需广播
Inner Shareable 同一集群内的多个核共享 TLB 维护操作需要广播到 Inner Shareable 域
Outer Shareable 跨集群的多个核共享 TLB 维护操作需要广播到 Outer Shareable 域
Full System 整个系统中的所有核共享 TLB 维护操作需要广播到所有 PE

1.5 内存模型与页表的关系

在 ARM64 的页表描述符中,每个页表条目(PTE)都包含 内存类型 和 共享属性 字段。MMU 在遍历页表时,会将这些属性缓存到 TLB 中,后续访问直接使用 TLB 中的属性信息,无需再次遍历页表。

页表描述符中的内存属性字段 页表条目(PTE)64 位结构 [63:52] 保留 / 52 位地址扩展 | [51:12] 物理地址 PFN | [11:2] 属性位 | [1:0] 描述符类型 属性位详解(Bits [11:2]) Bit[11:10] AP(访问权限) | Bit[7:6] SH(共享属性) | Bit[5:4] AttrIndx(内存类型索引) MMU 页表遍历与属性缓存流程 1. CPU 发出虚拟地址 VA → 2. MMU 遍历页表(多级查询)→ 3. 读取 PTE 中的 PFN + 属性 4. 将 VA→PA 映射 + 内存类型/共享属性 缓存到 TLB → 5. 后续访问直接命中 TLB

1.6 内存模型对 TLB 缓存刷新的影响

由于 TLB 中缓存了内存类型和共享属性,当操作系统修改页表(例如更改内存类型或权限)时,必须执行 TLB 维护操作,以确保所有处理器核看到一致的映射和属性。

常见陷阱:只刷新 TLB 条目而不考虑共享域(Shareability Domain)可能导致缓存一致性问题。例如,在 Inner Shareable 域中修改页表后,必须使用 TLBI VMALLE1IS(Inner Shareable 域广播失效)而非 TLBI VMALLE1(仅本地失效),否则其他核可能仍使用过时的 TLB 条目。

1.7 本章小结

  • AArch64 提供了 64 位寄存器模型和更大的虚拟地址空间,是 Linux 内核运行的基础。
  • 异常等级(EL0-EL3) 实现了特权级分离,EL1 是内核运行的主要场所,MMU 和 TLB 操作在此等级完成。
  • 内存模型 定义了 Normal/Device 内存类型和共享属性,这些属性直接嵌入页表描述符,并被 TLB 缓存。
  • 理解异常等级切换和内存属性传播,是后续学习页表遍历、TLB 失效策略和性能优化的前提。