第二章 复位后的第一条指令(Reset Vector)
概念解释
处理器的复位(Reset)信号释放后,CPU 进入一个确定的状态:所有通用寄存器、控制寄存器恢复到默认值,程序计数器(PC)被硬件强制赋值为一个特定的值——这个值就是复位向量地址(Reset Vector Address)。在 AArch64(ARMv8‑A 64 位)架构中,复位向量地址固定为 0x00000000(物理地址),SoC 厂商通常会在该地址处放置一条无条件跳转指令,使 CPU 立即跳转到 BootROM 的实际入口代码。
AArch64 异常向量表(Exception Vector Table, EVT)是架构定义的一组固定偏移入口,用于处理同步异常(未定义指令、系统调用等)和异步异常(IRQ、FIQ、SError)。复位本身并不属于异常,但复位向量与异常向量表共享同一基地址区域——通常 EVT 以 2KB 对齐存放,复位条目正好位于基地址 + 0x000 处。每个向量条目占用 128 字节(32 条指令),足够存放跳转到具体处理函数的临时代码。
跳转逻辑的核心是一条无条件跳转指令(如 b redirect_to_bootrom),其编码在 ROM 中固化。CPU 从复位向量取出该指令,立即跳转到 BootROM 内初始化代码的入口地址。
原理图解
下图展示了复位后的引导路径:CPU 从复位向量地址(物理 0x0)执行跳转指令,经过异常向量表区域(仅使用复位条目),最终进入 BootROM 入口,开始初始化流程。
类比:目录索引与翻书
想象一本技术手册的目录页:复位向量就是手册封面上的“第一章”三个字,CPU 上电后自动翻到封面页。但是封面页只有一句话:“请翻到第 128 页”。这“一句话”就是跳转指令。异常向量表相当于手册的快速索引区域,每个可能遇到的问题(比如纸张破损、墨水模糊)都预留了一个小标签,标签上写着“遇到此类问题请翻到第 X 页”。复位,就是第一章的标签——CPU 什么都不问,直接按这个标签行动。
常见误区
- 误区一:复位向量就是 BootROM 入口函数。 实际上复位向量处放的只是一段非常简短的跳转代码(通常 2~4 条汇编),真正的初始化代码在跳转目标地址。如果直接把 BootROM 入口入口函数放在 0x0,会导致异常向量表无法正常对齐(占用首 2KB 空间),且不利于后续 MMU 映射。
- 误区二:AArch64 异常向量表大小是固定的 2KB。 架构规定每个向量占用 128 字节,共 16 个条目(4 类 × 4 种异常类型),总计 2KB。但 SoC 可以根据需求仅在实现中放置必要的条目,未使用的向量条目通常填充为
ERET或死循环。 - 误区三:所有 SoC 的复位向量地址都是 0x0。 虽然 AArch64 架构定义复位从 0x0 取指,但某些 SoC 会在复位前由外部硬件重映射 ROM 窗口,或者使用 CPU 的复位偏移寄存器(如 RVBAR),使实际入口地址不同。例如高通 8155 的 BootROM 实际入口需要通过复位后的第一段代码再映射后才到达。
练习题
- 当高通 8155 的 CPU 从复位状态释放后,它首先从哪个物理地址取指令?
A. 0x80000000
B. 0x00000000
C. 0x1A000000
D. 取决于当前异常级别
答案:B - AArch64 异常向量表中每个条目占用多少字节?
A. 32 字节
B. 64 字节
C. 128 字节
D. 256 字节
答案:C - 以下关于复位向量的描述中,错误的是:
A. 复位向量处必须存放一条可执行指令
B. 复位向量地址在 MMU 开启后才会被转换为虚拟地址
C. 复位向量跳转的目标通常是 BootROM 的初始化代码
D. 复位向量与异常向量表共用基地址
答案:B(复位后 MMU 关闭,使用物理地址)
应用边界
复位后的第一条指令设计直接受安全启动和多级启动架构影响:
- 安全启动 SoC:复位向量跳转的目标地址不是固定 ROM 区域,而是一个经过硬件哈希校验的小型引导块(称为 SBL‑1)。跳转逻辑中可能包含条件判断(如是否触发安全模式恢复)。
- 多级跳转:有些 SoC 在 0x0 地址放置的是一条间接跳转(通过寄存器或内存映射),第一次跳转后立即执行一个小型“加载器”,加载更大的 BootROM 段。例如,高通 8155 的 BootROM 分为几级:第一级硬件固定跳转到内部 ROM 的 PBL(Primary Boot Loader),再由 PBL 加载 SBL。
- 存储器类型:若 SoC 支持从多种非易失存储器启动(如 eMMC、UFS、NAND),复位向量本身不变,但跳转后进入的 BootROM 代码会立即检测启动介质选择逻辑,此时复位向量地址仅作为“入口触发器”,不直接映射启动策略。