1. ARM体系结构基础:处理器模式、寄存器组、异常向量表、MMU与Cache基础概念
1.1 ARM处理器模式
ARM处理器支持多种运行模式,每种模式对应不同的权限级别和寄存器视图。理解这些模式是分析内核启动流程的前提,因为Linux内核在启动过程中会经历多次模式切换。
| 处理器模式 | 缩写 | 权限等级 | 典型用途 |
|---|---|---|---|
| 用户模式 | USR | 非特权(PL0) | 运行应用程序 |
| 快速中断模式 | FIQ | 特权(PL1) | 高速数据传输 |
| 普通中断模式 | IRQ | 特权(PL1) | 通用中断处理 |
| 管理模式 | SVC | 特权(PL1) | 操作系统内核(复位后默认模式) |
| 中止模式 | ABT | 特权(PL1) | 数据/指令访问异常 |
| 未定义模式 | UND | 特权(PL1) | 未定义指令异常 |
| 系统模式 | SYS | 特权(PL1) | 运行特权任务(共享用户模式寄存器) |
| 安全监视器模式 | MON | 最高特权(PL2/EL3) | 安全世界与非安全世界切换(TrustZone) |
| 虚拟机监视器模式 | HYP | 虚拟化特权(PL2/EL2) | 虚拟化扩展(Cortex-A15+) |
启动关键点:ARM处理器在上电或复位后默认进入SVC模式(管理模式),这是Linux内核启动的初始模式。内核在完成初始化后,会通过系统调用切换到USR模式运行用户空间进程。
1.2 寄存器组
ARM处理器共有37个寄存器(ARMv7-A架构),包括31个通用寄存器和6个状态寄存器。不同模式下,部分寄存器是物理独立的(banked),这是实现快速上下文切换的硬件基础。
通用寄存器(R0-R15)
- R0-R12:通用数据寄存器,用于算术运算、地址计算等。
- R13(SP):栈指针寄存器,每种特权模式拥有独立的SP。
- R14(LR):链接寄存器,保存子程序返回地址或异常返回地址。
- R15(PC):程序计数器,指向当前指令地址+8(ARM状态)或+4(Thumb状态)。
状态寄存器(CPSR/SPSR)
- CPSR:当前程序状态寄存器,保存条件标志、中断屏蔽位、处理器模式等。
- SPSR:保存的程序状态寄存器,用于异常发生时保存CPSR副本。
调试要点:在分析内核启动异常时,检查SPSR可以还原异常发生前的处理器模式、中断状态和条件标志。例如,SPSR的M[4:0]字段指示了之前的处理器模式。
1.3 异常向量表
异常向量表是ARM处理器响应异常事件的入口地址表。当异常发生时,处理器强制跳转到向量表中对应的地址执行。向量表的基地址由系统控制协处理器CP15的VBAR寄存器决定。
| 向量偏移 | 异常类型 | 优先级 | 进入模式 | 典型触发条件 |
|---|---|---|---|---|
| 0x00 | 复位 | 1(最高) | SVC | 上电或复位信号 |
| 0x04 | 未定义指令 | 6 | UND | 执行未定义指令 |
| 0x08 | 软件中断(SWI/SVC) | 6 | SVC | 执行SVC指令(系统调用) |
| 0x0C | 预取中止 | 5 | ABT | 指令预取地址无效 |
| 0x10 | 数据中止 | 2 | ABT | 数据访问地址无效或权限错误 |
| 0x14 | 保留 | — | — | — |
| 0x18 | 普通中断(IRQ) | 4 | IRQ | IRQ中断请求 |
| 0x1C | 快速中断(FIQ) | 3 | FIQ | FIQ中断请求 |
常见调试陷阱:在启动早期(MMU未开启时),向量表必须位于低地址(0x00000000)或由硬件配置的高地址(0xFFFF0000)。如果VBAR配置错误,任何异常都会导致处理器跳转到错误地址,表现为系统“死机”或反复复位。
1.4 MMU与Cache基础概念
MMU(内存管理单元)和Cache是ARM处理器实现虚拟内存和高效数据访问的核心硬件模块。在Linux内核启动过程中,MMU和Cache的初始化顺序直接影响启动速度和稳定性。
MMU核心功能
- 虚拟地址到物理地址转换:通过页表(Page Table)实现地址映射。
- 内存访问权限控制:设置读/写/执行权限,实现进程隔离。
- 内存属性管理:配置缓存策略、共享属性、执行权限等。
Cache层次结构
| Cache类型 | 存储内容 | 典型大小 | 行大小 | 关联度 |
|---|---|---|---|---|
| L1 I-Cache | 指令 | 16KB - 64KB | 32B / 64B | 2路 / 4路 |
| L1 D-Cache | 数据 | 16KB - 64KB | 32B / 64B | 2路 / 4路 |
| L2 Cache | 指令+数据(统一) | 256KB - 2MB | 64B | 8路 / 16路 |
启动阶段MMU/Cache操作策略
- 复位后:MMU和Cache默认关闭,所有地址访问直接映射到物理地址。
- 启动早期:保持MMU关闭,使用物理地址访问。此时可以开启I-Cache加速指令预取(需确认硬件支持)。
- 页表建立:内核在启动汇编阶段建立初始页表(通常使用段映射,1MB粒度)。
- MMU使能:设置CP15的SCTLR寄存器中的M位,开启MMU。此时需确保代码和栈位于映射后的虚拟地址空间。
- Cache使能:MMU稳定后,依次使能L1 D-Cache和L2 Cache。
调试技巧:当内核启动过程中出现“跳转后跑飞”或“访问地址异常”时,应优先检查:
1. MMU使能时PC是否已位于映射后的虚拟地址空间。
2. 页表项中的缓存属性(C/B bit)是否与硬件设计匹配。
3. TLB是否在页表更新后执行了失效操作(TLB flush)。
1. MMU使能时PC是否已位于映射后的虚拟地址空间。
2. 页表项中的缓存属性(C/B bit)是否与硬件设计匹配。
3. TLB是否在页表更新后执行了失效操作(TLB flush)。
1.5 本章小结
- ARM处理器提供多种特权模式,Linux内核主要使用SVC模式运行,通过异常机制实现系统调用和中断处理。
- 寄存器组中banked寄存器是实现快速异常切换的硬件基础,调试时SPSR是还原异常现场的关键。
- 异常向量表是异常处理的入口,内核启动时必须正确设置VBAR寄存器。
- MMU负责虚拟地址到物理地址的转换和权限控制,Cache用于加速内存访问,两者必须在启动阶段按正确顺序初始化。