ARMv8架构概述:AArch64与AArch32执行状态、异常等级模型、寄存器组概览

各位好,欢迎来到《ARMv8性能调优与安全扩展调试实战》的第一章。咱们今天不绕弯子,直接聊聊ARMv8最核心的几个概念。说实话,我刚开始接触ARMv8的时候,也被那一堆新名词搞得有点晕。但后来发现,只要把执行状态、异常等级和寄存器组这三块吃透了,后面看什么都顺眼。

1.1 两种执行状态:AArch64与AArch32

ARMv8最大的变化,就是引入了AArch64执行状态。这不是简单的"32位升级到64位",而是整个架构的重新设计。

特性 AArch64 AArch32
寄存器宽度 64位通用寄存器 32位通用寄存器
指令集 A64(固定32位长度) A32/T32(32位/16位混合)
异常等级 EL0~EL3,共4级 PL0~PL3,共4级(但映射方式不同)
地址空间 最大48位虚拟地址 最大32位虚拟地址
兼容性 不向后兼容AArch32 兼容ARMv7及之前

关键点:AArch64和AArch32是两种互斥的执行状态。处理器在复位时可以选择进入哪一种,但运行时不能在同一异常等级下混用。不过,不同异常等级可以运行不同的执行状态——比如EL3跑AArch64,EL0跑AArch32,这是完全允许的。

我个人习惯把AArch64看作一个"全新的起点"。它抛弃了ARMv7时代很多历史包袱,比如条件执行(除了分支指令)、LDM/STM这种批量加载存储指令,都砍掉了。为什么?为了简化硬件设计,提高频率。你想想看,一个指令里带4个条件位,解码器得多复杂。

1.2 异常等级模型:EL0到EL3

ARMv8的异常等级模型,说白了就是给软件划分了四个"权限层级"。

  • EL0:用户态。跑应用程序,权限最低。不能直接操作硬件,不能配置MMU,连中断都碰不到。
  • EL1:操作系统内核态。Linux内核、RTOS都跑在这里。可以管理MMU、处理中断、调度任务。
  • EL2:虚拟机监视器(Hypervisor)。虚拟化场景下,Host VM跑在这里。我做过一个项目,需要在EL2拦截Guest OS对定时器的访问,那叫一个折腾。
  • EL3:安全监视器(Secure Monitor)。这是最高权限等级,负责安全世界和普通世界的切换。ARM TrustZone的根就在EL3。

避坑指南:我曾经在调试一个安全启动方案时,发现EL3的代码里不小心访问了EL2的寄存器,结果直接触发SError异常。记住:高等级可以访问低等级的资源,反过来不行。EL3能看EL2的配置,但EL2想读EL3的寄存器?门都没有。

异常等级之间通过异常来切换。比如应用程序(EL0)调用系统调用(SVC指令),就会触发一个同步异常,处理器提升到EL1,跳转到内核的异常向量表。这个过程涉及栈切换、寄存器保存、异常返回地址记录——嗯,细节后面章节会展开。

1.3 寄存器组概览

AArch64的寄存器组,比AArch32规整得多。咱们先看通用寄存器。

1.3.1 通用寄存器:X0~X30

AArch64有31个通用寄存器,X0到X30。每个都是64位宽。访问低32位时,用W0~W30。比如:

// 64位操作
ADD X0, X1, X2      // X0 = X1 + X2

// 32位操作(高位自动清零)
ADD W0, W1, W2      // W0 = W1 + W2,X0的高32位清零

这里有个细节:X30是链接寄存器(LR),保存函数调用的返回地址。X29是帧指针(FP),用于栈回溯。X18是平台寄存器,一般不用,留给平台固件用。

注意:X0~X7用于传递参数和返回值。函数调用时,前8个参数放X0~X7,多余的压栈。返回值放X0。这是ARM64的调用约定(AAPCS64),写汇编时千万别搞混。

1.3.2 特殊寄存器

除了通用寄存器,还有一堆特殊寄存器。我挑几个最常用的说说:

  • SP_ELx:栈指针。每个异常等级有自己的栈指针。EL1用SP_EL1,EL2用SP_EL2,EL3用SP_EL3。EL0的栈指针是SP_EL0。
  • ELR_ELx:异常返回地址寄存器。发生异常时,处理器把返回地址存到这里。ERET指令就从这里恢复执行。
  • SPSR_ELx:保存的程序状态寄存器。异常发生时,PSTATE(处理器状态)被保存到这里。包括条件标志位、异常掩码、执行状态等。
  • VBAR_ELx:异常向量基地址寄存器。指向异常向量表的起始地址。每个异常等级有自己的向量表。

1.3.3 系统寄存器访问

访问系统寄存器,必须用MSR和MRS指令。不能像通用寄存器那样直接MOV。

// 读取当前异常等级
MRS X0, CurrentEL

// 设置VBAR_EL1
LDR X0, =my_vector_table
MSR VBAR_EL1, X0

// 写SPSR_EL1
MSR SPSR_EL1, X0

我记得刚学ARMv8时,总想用STR写系统寄存器,结果编译直接报错。后来养成了习惯:看到"系统寄存器"四个字,脑子里自动弹出MSR/MRS。

1.4 知识结构图:ARMv8核心概念关系

下面这张图,把执行状态、异常等级和寄存器组的关系串起来了。建议保存下来,后面章节会反复用到。

ARMv8核心概念关系图 ARMv8核心概念关系图 执行状态 AArch64 AArch32 异常等级 EL0(用户态) EL1(内核态) EL2(Hypervisor) EL3(Secure Monitor) 寄存器组 X0~X30 SP/ELR/SPSR VBAR/CurrentEL 决定 拥有 说明: 1. 执行状态决定指令集和寄存器宽度。 2. 异常等级决定软件权限和资源访问能力。 3. 寄存器组是软件操作硬件的接口。 4. 三者共同构成ARMv8的编程模型基础。 5. 不同异常等级可以运行不同的执行状态。

1.5 本章小结

这一章我们覆盖了三个核心概念:

  • AArch64 vs AArch32:两种执行状态,互斥但可共存于不同异常等级。
  • EL0~EL3:四个异常等级,从用户态到安全监视器,权限逐级递增。
  • 寄存器组:31个通用寄存器(X0~X30)加一堆特殊寄存器,用MSR/MRS访问。