参考:
《ARM Architecture Reference Manual ARMv7-A and ARMv7-R edition》
《ARM Cortex™-A Series Version: 4.0 Programmer’s Guide》

ARMv7-A 系列其他文章:
深入理解 ARMv7-A|异常/中断处理

ARMv7-A 是一款多模式架构(modal architecture)处理器。理解它的处理器模式与寄存器模型,是后续学习异常处理、MMU、Cache、虚拟化以及安全扩展等高级主题的基础。本文将从处理器模式核心寄存器两个维度,系统梳理 ARMv7-A 的编程模型。

1、ARM Processor Modes

  ARMv7-A 在引入安全扩展(Security Extensions)之前,共有七种处理器模式(具体总结见表 3-1)。这七种模式由六种特权模式(privileged modes)和一种非特权用户模式(non-privileged user mode)组成。

  所谓"特权",指的是能够执行用户模式下受限的系统操作——例如 MMU 配置、Cache 维护、修改 CPSR 控制位等直接影响系统全局状态的行为。模式的切换通常由异常触发,也可由特权软件通过写 CPSR.M 显式执行。

在这里插入图片描述
  引入 TrustZone 安全扩展后新增 Monitor 模式,引入虚拟化扩展后新增 Hyp 模式,共计可达到九种模式。全部模式编码如下:

在这里插入图片描述


  虚拟化扩展引入后,Non-secure 状态下新增了特权等级 PL2,形成三个层级:

在这里插入图片描述

  如果实现了虚拟化扩展,将会出现一种区别于以往架构的特权模型。在 Non-secure 状态下,可以存在三个特权等级(Privilege Levels):PL0、PL1 和 PL2。

  • PL0:应用软件运行的特权等级,运行于 User 模式。在 User 模式下执行的软件被称为非特权软件(unprivileged software)。这类软件无法访问架构的某些特定功能,尤其是无法修改许多系统配置设置。运行在 PL0 的软件只能进行非特权内存访问。
  • PL1:除 User 模式和 Hyp 模式之外,所有其他模式下的软件执行均处于 PL1。通常,操作系统软件在 PL1 上运行。PL1 模式涵盖了除 User 模式和 Hyp 模式之外的所有模式。一个操作系统通常被期望跨越所有的 PL1 模式运行,而其应用程序则运行在 PL0(User 模式)下。
  • PL2:Hyp 模式通常由 hypervisor(虚拟机管理程序)使用,用于控制并切换那些运行在 PL1 上的 Guest Operating Systems(客户操作系统)。如果实现了虚拟化扩展,hypervisor 将运行在 PL2(Hyp 模式)。Hypervisor 将控制并实现多个操作系统在同一个处理器系统上的共存与执行。

需要注意的是,这些特权等级(Privilege Levels)与 TrustZone 的 Secure 和 Normal (Non-secure) 设置是相互独立的

图3-3展示了不同安全状态下可用的处理器模式:

在这里插入图片描述
  特定处理器模式和状态的存在取决于处理器是否实现了相关的架构扩展

  像 Linux 这类通用操作系统及其应用程序,默认运行在 Non-secure 状态。Secure 状态则留给固件(如 ATF/BL31)或高安全敏感软件使用。

  处理器当前的模式和执行状态,统一保存在 CPSR(Current Program Status Register) 的 M[4:0] 和 T/J 位中。

1.1 TrustZone 安全扩展

  TrustZone 安全扩展引入了两套独立于特权等级的硬件隔离安全状态(Secure / Non-secure),同时新增了 Monitor 模式作为它们的切换网关。原有的每种处理器模式,在两个安全世界中各自独立存在一份实例。

在这里插入图片描述
  TrustZone 的核心思想是将系统资源一分为二:一部分属于 Secure world,其余属于 Normal(Non-secure)world。当处理器处于 Non-secure 状态时,无法访问分配给 Secure 状态的内存和外设。 Monitor 模式下运行的软件负责两个世界之间的上下文保存、恢复与状态切换。


1.1.1 检测 TrustZone 是否已实现

通过读取 CP15 的 ID_PFR1 寄存器(Processor Feature Register 1)的 Security 字段:

// C代码中(内核态)读取 ID_PFR1 寄存器:
unsigned int pfr1;
asm volatile ("mrc p15, 0, %0, c0, c1, 1" : "=r" (pfr1));
unsigned int security = (pfr1 >> 4) & 0xF;
// security == 0: 未实现 TrustZone
// security == 1: 已实现 TrustZone

在这里插入图片描述
在这里插入图片描述

1.1.2 安全状态切换

通过操作 SCR(Secure Configuration Register)的 NS 位完成,SCR 寄存器仅在 Secure 特权模式下可写

在这里插入图片描述
在这里插入图片描述

关键约束:Secure ↔ Non-secure 的切换必须在 Monitor 模式下进行

在这里插入图片描述

✅ 示例:启动后从 Secure World 跳转到 Linux 内核(NS)

// 假设当前在 Monitor 模式
ldr     r0, =0x13         // SVC mode, ARM state
msr     spsr_cxsf, r0     // 设置返回目标模式(SVC, ARM)
ldr     lr, =0x80008000   // Linux 内核入口地址

// 设置 SCR.NS = 1,进入 Non-Secure World
mrc     p15, 0, r1, c1, c1, 0
orr     r1, r1, #1
mcr     p15, 0, r1, c1, c1, 0

eret    // 跳转到 NS World 中执行

Non-secure → Secure 的切换同理,也需要经 Monitor 模式中转。

1.2 Monitor 模式与 SMC 调用

  Monitor 模式如何进入?它的代码入口在哪里——在 Linux 内核中吗?

进入方式:执行 SMC(Secure Monitor Call)指令。硬件执行后会产生异常,跳转到 Monitor 模式异常向量表中 0x08 偏移处,执行 Secure Monitor Call 异常处理函数。

在这里插入图片描述

SMC<c> #<imm4>
  • < c >:表示条件码。例如 SMC + 条件码可以为:SMCNESMCEQ
  • imm4:4 位立即数。ARMv7-A 架构未定义其语义(通常置 0),实际参数通过寄存器传递

代码入口:Monitor 模式的代码实现位于 BL31 固件中(通常遵循 ARM Trusted Firmware, ATF 标准),而非 Linux 内核。ATF 的启动流程大致为:

BL1 (Boot ROM) → BL2 (Trusted Boot Firmware)
    → BL31 (Monitor 模式运行时服务) + BL32 (Secure OS, 如 OP-TEE)
    → BL33 (Normal World: U-Boot → Linux)

  其中 BL31 是 Monitor 模式的核心——它在系统启动后常驻运行,负责分发 SMC 调用到对应的运行时服务(PSCI 电源管理、Secure OS 调度、SiP/OEM 服务等)。关于安全启动和 ATF 的详细内容留到后续章节展开。

  简而言之:SMC → 异常 → BL31 分发器 → 对应服务处理函数,通过寄存器的参数组合(遵循 SMC Calling Convention, SMCCC)决定具体的服务类型。


拓展——Linux 内核中的 SMC 典型应用:
Linux 内核中最常见的 SMC 调用是多核启动(PSCI):

// 启动 CPU#1
arm_smccc_smc(PSCI_CPU_ON, 			  // Function ID
              0x101,                  // 目标 CPU MPIDR
              0x80080000,             // 次核启动地址
              0, 0, 0, 0, 0, 		  // 其它参数
              &res);

2、ARM core registers

  ARMv7-A 提供 16 个 32 位通用寄存器(R0-R15),外加 CPSR 和每种异常模式私有的 SPSR(Saved Program Status Register)。

在这里插入图片描述

2.1 寄存器分组(Banking)

  同名寄存器在不同处理器模式下可能映射到不同物理存储位置,这称为 Banking。下图中带阴影的即为 Banked Registers——它们物理上独立,仅当处理器处于对应模式时才能被访问。

在这里插入图片描述
  访问哪个 Banked 实例由当前处理器模式隐式决定:User 模式下访问 R13 得到 R13_usr,SVC 模式下访问则得到 R13_svc。

FIQ 的独特优势:FIQ 是唯一拥有私有 R8-R12 的模式。这意味着 FIQ 处理程序可以无需压栈就直接使用 R8-R12,省去了保存/恢复上下文的开销,因此 FIQ 的响应速度比 IRQ 更快。

  • R0-R12:通用数据存储。R0 常作累加器或函数返回值;R7 存储系统调用号(详见 ARM-Linux 系统调用);R11(FP)指向栈帧基址(详见 ARM 栈和函数调用);函数的前四个参数由 R0-R3 传递(AAPCS 约定)。
  • R13(SP):各模式的独立栈指针。Boot Code 必须在使能栈操作之前,为将要使用的每种模式分别初始化 SP。无栈操作时可用作通用寄存器。
  • R14(LR):链接寄存器,保存 BL 指令的返回地址。异常模式的 R14(如 R14_irq、R14_svc)保存异常返回地址;在异常处理函数内部执行 BL 时同样作为 LR 使用。
  • R15 (PC):程序计数器。由于 ARM1 三级流水线的历史遗留,ARM 状态下 PC 指向当前指令 +8 字节,Thumb 状态下指向 +4 字节。ARM 状态下 [1:0] 位读回恒为 0,Thumb 状态下 [0] 位读回恒为 0。显式写入 R15 会直接改变程序执行流。

  ARM 体系结构过程调用标准(AAPCS)和 ARM 嵌入式 ABI(AEABI)规定了通用寄存器的使用规范,以保证不同工具链和编程语言之间的互操作性。

2.2 Hypervisor 模式寄存器

  实现虚拟化扩展的处理器中,Hyp 模式(PL2)拥有私有寄存器:R13 (SP_hyp)SPSR_hyp。它复用 User 模式的 LR 来保存函数返回地址,并使用专用寄存器 ELR_hyp 保存异常返回地址。Hyp 模式仅在 Normal world 中存在,提供专门用于虚拟化的控制功能,这些功能仅在 PL2 下可访问。

2.3 Program Status Registers

  程序状态寄存器(PSR)构成另一类 Banked Registers。每种异常模式都拥有自己的 SPSR,用于在异常进入时由硬件自动保存 CPSR 的副本。User 和 System 模式下没有 SPSR,访问 SPSR 行为不可预测。

  User 模式下只能访问 CPSR 的受限视图——APSR(Application Program Status Register),仅暴露 N、Z、C、V、Q 和 GE[3:0] 位。这些位通常由设置条件码的指令自动置位,由条件执行指令进行测试,应用程序员很少需要直接操作它们。

例如,CMP R0, R1 会在两值相等时将 Z 标志位置位。

2.3.1 CPSR 位域详解

在这里插入图片描述

  • N – 表示 ALU(算术逻辑单元)运算结果为负(Negative)。
  • Z – 表示 ALU 运算结果为零(Zero)。
  • C – 表示 ALU 运算产生了进位或借位(Carry out)。
  • V – 表示 ALU 运算发生了溢出(oVerflow)。
  • Q – 表示累积饱和标志(cumulative saturation),也被称为“粘性”标志(sticky)。
  • J – 指示处理器内核当前是否处于 Jazelle 状态。
  • GE[3:0] – 供部分 SIMD(单指令多数据)指令使用。
  • IT[7:2] – 用于 Thumb-2 指令组的 If-Then 条件执行。
  • E 位 – 控制加载/存储指令的字节序(Endianness)。
    • 0 Little-endian operation.
    • 1 Big-endian operation.
  • A 位 – 禁用异步中止(asynchronous aborts)。
    • Asynchronous Abort 是一种硬件异常。它主要由外部硬件错误(如总线错误、内存 ECC 校验失败)触发
  • I 位 – 禁用 IRQ(普通中断)。
    • 1 表示屏蔽
  • F 位 – 禁用 FIQ(快速中断)。
    • 1 表示屏蔽
  • T 位 – 指示处理器内核当前是否处于 Thumb 状态。
    • 0 = ARM 态,1 = Thumb 态
  • M[4:0] – 指定当前的处理器模式(如 FIQ、IRQ 等),见上文模式表。
    在这里插入图片描述
2.3.2 MSR / MRS 指令

对状态寄存器的读写通过以下两条指令,仅在特权模式下可用:

MRS <Rd>, <system_register>        ; 将 CPSR/SPSR 的值读到通用寄存器
MSR <system_register>, <Rn>        ; 将通用寄存器的值写入 CPSR/SPSR

MSR 支持按字段写入:cpsr_c(控制域,[7:0])、cpsr_x(扩展域,[15:8])、cpsr_s(状态域,[23:16])、cpsr_f(标志域,[31:24])。例如 MSR cpsr_c, r0 仅修改 CPSR 的低 8 位(含 M[4:0]、I、F、T),不影响标志位。

2.3.3 异常进入时 CPSR 的变化

  在 ARMv7 手册的 B1.8.5 Processor state on exception entry 章节,详细的介绍了,在进入异常时,该寄存器的一个变化。

  • CPSR.M 被硬件自动设置为目标异常模式对应的编码。
  • CPSR.{A, I, F} 是否自动置 1(屏蔽中断)取决于目标模式和当前安全状态,具体规则见手册 Table B1-10。若表中该位无定义,则保持不变。
  • Thumb 状态位(T)和字节序位(E)会根据异常向量表和 SCTLR 的配置自动设置。
    在这里插入图片描述
2.3.4 SPSR 的作用

The purpose of an SPSR is to record the pre-exception value of the CPSR. On taking an exception, the CPSR is copied to the SPSR of the mode to which the exception is taken.

SPSR 的核心价值在于:

  1. 异常返回恢复:异常返回时,硬件(或软件配合)可将 SPSR 的值恢复到 CPSR,使处理器回到异常发生前的状态。
  2. 现场回溯诊断:允许异常处理程序检查异常发生时的指令集状态(ARM/Thumb)和特权级别。例如,判断触发"未定义指令异常"的那条指令是在 ARM 还是 Thumb 状态下执行的。

2.4 Coprocessor 15

  CP15,即系统控制协处理器(System Control Coprocessor),是 ARMv7-A 系统架构功能的核心控制接口。它最多包含 16 个 32 位主寄存器(c0-c15),访问受特权级控制,并非所有寄存器都能在 User 模式下访问。

  指令中通过 Op1、Op2 和 CRm 字段来精确选择目标寄存器或操作,从而极大地扩展了实际可寻址的物理寄存器数量。
在这里插入图片描述

关键 CP15 寄存器速览

寄存器组 典型寄存器 功能
c0 MIDR, CTR, MPIDR, ID_PFRx 处理器与功能特性识别
c1 SCTLR, SCR, ACTLR, CPACR 系统控制与配置(MMU/Cache/分支预测开关)
c2 TTBR0, TTBR1, TTBCR 页表基址寄存器(用户/内核页表)
c3 DACR 域访问控制(ARMv7 中逐渐被淘汰)
c5/c6 DFSR, IFSR, DFAR, IFAR 内存异常状态与地址记录
c7 Cache 与分支预测器维护操作
c8 TLB 维护操作
c12 VBAR, MVBAR 异常向量表基址(普通/Monitor 模式)
c13 CONTEXTIDR, TPIDRx 进程/线程上下文 ID 与 ASID

在这里插入图片描述
讲两个比较常见的案例:

MIDR(Main ID Register, c0):

只读寄存器,记录处理器身份信息:

MRC p15, 0, r1, c0, c0, 0    ; 将 MIDR 读入 r1

SCTLR(System Control Register, c1):

系统控制寄存器是最重要的系统配置寄存器之一,控制 MMU、Cache 等全局开关:

MRC p15, 0, r1, c1, c0, 0    ; 读 SCTLR
MCR p15, 0, r1, c1, c0, 0    ; 写 SCTLR

3、小结

  本文从处理器模式和安全状态两个维度梳理了 ARMv7-A 的架构模型(9 种模式、3 个特权等级、2 套安全状态),并详述了通用寄存器分组(Banking)机制、CPSR/SPSR 状态寄存器的位域定义与异常行为,以及 CP15 协处理器的核心寄存器布局。掌握这些内容后,再理解 ARMv7-A 的异常处理、MMU/Cache 控制以及安全启动流程就会更加得心应手。

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐