2. ARM64架构基础:AArch64运行模式、异常级别(EL0-EL3)、MMU使能流程
ARMv8-A架构引入了两种执行状态:AArch64(64位)和AArch32(32位)。在Linux内核页表机制中,我们主要关注AArch64状态,因为它提供了64位虚拟地址空间、更大的物理地址范围以及全新的页表格式。本章将深入剖析AArch64的运行模式、异常级别模型以及MMU的初始化使能流程,为后续理解页表遍历和地址转换奠定基础。
2.1 AArch64运行模式与寄存器模型
AArch64运行模式摒弃了传统ARM的“处理器模式”(如SVC、IRQ、FIQ等),转而采用基于异常级别(Exception Levels, EL)的层次化权限模型。每个异常级别拥有独立的栈指针、页表基地址寄存器以及系统控制寄存器。
SP_ELx(栈指针)和TTBRx_ELx(页表基地址)都是每个异常级别私有的,这为虚拟化安全和隔离提供了硬件级支持。
2.1.1 异常级别(EL0 - EL3)
ARM64定义了4个异常级别,数字越大,特权越高:
| 异常级别 | 名称 | 典型用途 | 页表选择 |
|---|---|---|---|
| EL0 | 用户态(User) | 运行普通应用程序 | TTBR0_EL0(用户页表) |
| EL1 | 内核态(Kernel) | 运行操作系统内核 | TTBR0_EL1 / TTBR1_EL1 |
| EL2 | 虚拟机监视器(Hypervisor) | 运行Type-1/Type-2 Hypervisor(如KVM) | TTBR0_EL2 |
| EL3 | 安全监视器(Secure Monitor) | 运行安全固件(如ATF、TrustZone) | TTBR0_EL3 |
2.1.2 异常级别切换与栈指针
异常级别之间的切换通过异常(Exception)或中断触发。当从低级别(如EL0)进入高级别(如EL1)时,硬件自动保存返回地址和PSTATE到高级别的SPSR_ELx和ELR_ELx寄存器。每个异常级别可以选择使用独立的栈指针(SP_ELx)或共享当前栈指针(SP_EL0)。
// 示例:从EL0进入EL1时的硬件自动行为(伪代码)
// 1. 保存EL0的返回地址到 ELR_EL1
// 2. 保存EL0的PSTATE到 SPSR_EL1
// 3. 自动切换到 SP_EL1(如果配置了使用独立栈)
// 4. 跳转到异常向量表中的对应入口
2.2 MMU使能流程:从复位到页表激活
ARM64 MMU的使能并非简单的“打开/关闭”开关,而是一个严谨的、分步骤的初始化过程。错误的使能顺序会导致系统立即崩溃(如页表未就绪就开启MMU)。
2.2.1 使能前的硬件准备
在设置SCTLR_EL1.M(MMU使能位)之前,必须完成以下关键配置:
- 建立页表:在内存中分配并填充页表(至少包含一级页表)。
- 设置页表基地址:将页表物理地址写入
TTBR0_EL1(或TTBR1_EL1)。 - 配置翻译控制寄存器:设置
TCR_EL1,包括页粒度(4K/16K/64K)、虚拟地址宽度、缓存属性等。 - 配置内存属性:通过
MAIR_EL1定义内存类型(如Normal、Device)的索引。 - 执行ISB指令:确保上述配置在流水线中已提交。
2.2.2 使能流程步骤
以下是一个典型的ARM64 MMU使能序列(以EL1为例):
// 伪代码:ARM64 MMU使能流程
1. 初始化页表(在内存中构建页表结构)
2. 设置 TTBR0_EL1 = 页表基地址(物理地址)
3. 设置 TCR_EL1 = 配置值(如:4K页、48位虚拟地址、ASID启用)
4. 设置 MAIR_EL1 = 内存属性索引(如:0x44 表示 Normal Memory)
5. 执行 ISB(指令同步屏障)
6. 读取 SCTLR_EL1,设置 M 位(MMU使能)和 C 位(数据缓存使能)
7. 写入 SCTLR_EL1
8. 执行 ISB
9. (可选)执行 DSB(数据同步屏障)
10. 此时MMU已激活,后续所有地址访问均经过页表翻译
2.2.3 使能过程中的地址转换状态
下图展示了MMU使能前后,CPU访问地址的路径变化:
2.3 关键系统寄存器详解
MMU使能流程中涉及的核心寄存器及其作用如下:
| 寄存器 | 全称 | 关键字段/作用 |
|---|---|---|
SCTLR_EL1 |
系统控制寄存器 | M(MMU使能)、C(数据缓存使能)、I(指令缓存使能)、WXN(写不可执行) |
TCR_EL1 |
翻译控制寄存器 | T0SZ(TTBR0地址空间大小)、TG0(页粒度)、IPS(中间物理地址大小)、SH0(可共享性) |
TTBR0_EL1 |
页表基地址寄存器0 | 存放用户空间(低地址)页表的物理基地址;支持ASID(地址空间标识符) |
TTBR1_EL1 |
页表基地址寄存器1 | 存放内核空间(高地址)页表的物理基地址 |
MAIR_EL1 |
内存属性间接寄存器 | 定义8个内存属性索引(如:0x44=Normal, 0x00=Device-nGnRnE) |
2.4 使能后的页表切换与TLB管理
MMU使能后,内核在运行时可能需要切换页表(例如进程上下文切换)。此时需要遵循严格的TLB失效协议:
- 全局页表切换(如内核页表更新):执行
TLBI VMALLE1(失效所有EL1的TLB条目)。 - 进程切换(ASID机制):写入新进程的ASID到
TTBR0_EL1,然后执行TLBI ASIDE1(失效非全局条目)。 - 单页失效:使用
TLBI VAE1+ 虚拟地址,精确失效特定页的TLB。
2.5 本章小结
ARM64的AArch64运行模式通过异常级别(EL0-EL3)实现了严格的权限分层,每个级别拥有独立的页表配置。MMU使能是一个多步骤的硬件初始化过程,必须在页表就绪、寄存器配置正确、屏障指令执行完毕后才能安全开启。理解这些基础是后续学习四级页表遍历、页表缓存(TLB)以及虚拟化地址翻译的必备前提。