4. MMU使能步骤:设置TTBR/MAIR/TCR寄存器、同步屏障、使能MMU位
MMU(内存管理单元)的使能是页表初始化完成后最关键的一步。该过程涉及对系统控制协处理器(如ARMv8-A架构中的系统寄存器)进行精确配置,并严格遵循“先配置、后同步、再使能”的顺序。任何步骤的缺失或顺序错误都可能导致系统崩溃或不可预测的行为。
4.1 核心寄存器配置
在使能MMU之前,必须正确设置以下三个关键寄存器组,它们共同定义了页表的基址、内存属性以及转换规则。
| 寄存器 | 全称 | 核心作用 | 关键字段示例 |
|---|---|---|---|
| TTBR0/1 | Translation Table Base Register | 存放一级页表的物理基地址(BA) | BADDR[47:0] |
| MAIR | Memory Attribute Indirection Register | 定义内存属性编码(如Cache策略、设备内存类型) | Attr0~Attr7 |
| TCR | Translation Control Register | 控制页表粒度、地址空间大小、页表格式 | T0SZ, TG0, SH0, ORGN0, IRGN0 |
性能提示: TTBR0与TTBR1分别用于用户空间(EL0)和内核空间(EL1)的地址转换。在裸机或RTOS环境中,通常只使用TTBR1并配置TCR使其覆盖整个地址空间,以减少TLB刷新开销。
4.2 配置步骤与同步屏障
配置过程必须严格遵循“写寄存器 → 数据同步屏障(DSB) → 指令同步屏障(ISB) → 使能MMU位”的流程。DSB确保所有内存访问(包括页表写入)完成,ISB确保后续指令使用最新的系统寄存器值。
- 步骤1:设置MAIR寄存器
/* 示例:设置MAIR,Attr0=0xFF (Normal Memory, Write-Back), Attr1=0x04 (Device-nGnRE) */ LDR x0, =0x000004FF MSR MAIR_EL1, x0 - 步骤2:设置TCR寄存器
/* 示例:4KB粒度,48位输入地址,Inner/Outer Write-Back Cache */ LDR x0, =((64-48) << 0) | (0 << 14) | (3 << 12) | (3 << 10) | (3 << 8) | (3 << 6) MSR TCR_EL1, x0 - 步骤3:设置TTBR0/1寄存器
/* 示例:将一级页表基地址(物理地址)写入TTBR1 */ LDR x0, =PAGE_TABLE_BASE_PA MSR TTBR1_EL1, x0 - 步骤4:插入同步屏障
DSB SY /* 确保所有页表写入和寄存器配置完成 */ ISB /* 清空流水线,确保后续指令读取最新寄存器值 */ - 步骤5:使能MMU位
MRS x0, SCTLR_EL1 ORR x0, x0, #1 /* 设置SCTLR_EL1的M位(MMU使能位) */ MSR SCTLR_EL1, x0 ISB /* 使能后立即插入ISB,确保后续指令在转换地址下执行 */
关键陷阱: 在使能MMU的瞬间,程序计数器(PC)指向的地址必须已经建立了有效的页表映射。通常的做法是在使能MMU之前,确保当前代码段所在的虚拟地址与物理地址是恒等映射(Identity Mapping),否则使能后CPU将立即取指失败。
4.3 MMU使能流程架构图
下图展示了从寄存器配置到MMU使能的完整数据流与同步屏障插入点。
4.4 性能优化要点
- 批量配置寄存器: 在使能MMU之前,将所有寄存器(MAIR、TCR、TTBR)的值准备好,使用连续的
MSR指令写入,减少指令开销。 - 最小化同步屏障开销: 只在配置完成后插入一次
DSB和一次ISB,而不是在每个寄存器写入后都插入屏障。现代处理器通常能保证对系统寄存器的写入顺序。 - 恒等映射区域优化: 确保使能MMU的代码段所在的页表项在初始化时已被填充,且映射属性(如可执行、可读)正确。避免使能后因缺页异常而陷入死循环。
- TLB预刷新: 在使能MMU之前,执行
TLBI VMALLE1(无效化所有TLB条目),确保使能后TLB中不存在旧的、无效的转换条目。
实践建议: 在调试MMU使能代码时,可以在使能MMU的指令前后放置调试灯或GPIO翻转操作。如果使能后灯不亮或系统挂起,通常表明恒等映射配置错误或同步屏障缺失。