ARM向量表

发布于:2025-03-31 ⋅ 阅读:(24) ⋅ 点赞:(0)
向量表 作用 说明
RVBAR 在 AArch64 中,重置向量不再是异常向量表的一部分。 有复位向量的专用配置输入引脚和寄存器。 在 AArch64 中,处理器从 IMPLEMENTAION‑DEFINED 地址开始执行, 该地址由硬件输入引 脚RVBARADDR定义, 可以通过 RVBAR_EL3 寄存器读取。 您必须在此地址放置引导代码。
VBAR_EL1 AArch64 模式下的向量表包含 16 个条目, 每个 条目大小为 128B,最多包含 32 条指令。
VBAR_EL2 AArch64 模式下的向量表包含 16 个条目, 每个 条目大小为 128B,最多包含 32 条指令。
VBAR_EL3 AArch64 模式下的向量表包含 16 个条目, 每个 条目大小为 128B,最多包含 32 条指令。

向量表必须放置在 2KB 对⻬的地址。

通过初始化 VBAR_ELn 寄存器来指定地址。

向量表结构

下图显示了向量表的结构。

初始化向量表

展示了如何在复位后初始化 VBAR_EL3、VBAR_EL2 和 VBAR_EL1。

向量表

显示了 AArch64 中异常的典型向量表。

更新SPSR_ELn(其中n是获取异常的Exception级别),以存储在异常结束时正确返回所需的PSTATE信息。

PSTATE被更新以反映新的处理器状态(这可能意味着抛出Exception级别,也可能保持不变)。

在异常末尾要返回的地址存储在ELR_ELn中。寄存器名称上的_ELn后缀表示在不同的Exception级别上存在这些寄存器的多个副本。例如,这意味着SPSR_EL1与SPSR_EL2是不同的物理寄存器。

而我们在异常处理中,又会调用下一级的函数来干活,图形也就如下所示:

当异常处理完成后,processor由高级别返回低级别时,使用ERET指令返回

每个异常级别都有自己的一套向量表,这些表的基地址分别写在VBAR_EL3, VBAR_EL2 and VBAR_EL1系统寄存器中. 向量表中的每个条目有16 instructions long(0x80字节)(在ARMv7-A和AArch32中,每个条目只有4个字节)。这意味着在AArch64中顶层处理程序可以直接在向量中,而不是跳转到其它地址处执行.

VBAR_ELn执行的每个table中,定义了16个entries,具体走哪一个entry是由下面几个因素决定的: • The type of exception (SError, FIQ, IRQ, or Synchronous) 异常类型(SError, FIQ, IRQ,或Synchronous) • If the exception is being taken at the same Exception level, the stack pointer to be used (SP0 or SPn).如果异常是在相同的exception级别获取的,则使用的堆栈指针(SP0或SPn)。

• If the exception is being taken at a lower Exception level, the Execution state of the next lower level (AArch64 or AArch32).如果在较低的exception级别获取异常,则下一个较低级别(AArch64或AArch32)的执行状态。

一张经典的向量表,如下所示:

举一个超级简单的例子: kernel code执行在EL1,这时来了一个IRQ,该中断没有配置到hypervisor和secure environment中,所以它的处理仅仅是在kernel中完成,程序跳转到VBAR_EL1+0x280,栈使用sp_el1(将SPSel设置程sp_el1)

异常返回

软件必须告诉处理器何时从异常中返回。这是通过代码完成的使用ERET指令。这将从SPSR_ELn中恢复异常前的PSTATE并返回通过从ELR_ELn恢复PC,将程序执行返回到原始位置。 在A64指令集中,使用寄存器X30(与RET指令一起)返回子例程

ELR_ELn寄存器用于存储来自异常的返回地址。它的价值寄存器是自动写入的入口异常,并被写入到PC作为其中之一执行用于从异常中返回的ERET指令的效果。

除了SPSR和ELR寄存器之外,每个异常级别都有自己专用的堆栈指针登记。它们是SP_EL0、SP_EL1、SP_EL2和SP_EL3。这些寄存器用来指向专用的栈。堆栈可以,例如,用来存储寄存器被损坏异常处理程序,使它们可以在返回之前恢复到原来的值原始代码

处理程序代码可以从使用SP_ELn切换到使用SP_EL0。例如,SP_EL1可能指向存储小堆栈的内存块,内核可以始终保证该小堆栈是有效的。SP_EL0可能指向较大的内核任务堆栈. 但不能保证不发生溢出。这切换通过写入SPSel寄存器来控制。

PSTATE

当前processor的状态保存在PSTATE,当异常到来时,PSTATE的值会自动保存在SPSR中。 aarch64中由三个SPSR : SPSR_EL3, SPSR_EL2, and SPSR_EL1 例如,如果发生了一个异常target到EL1,那么当前处理器的状态会自动保存到SPSR_EL1中;

中断的处理流程

同步中断触发方式

异常后的处理

异常综合寄存器(ESR_ELn)故障地址寄存器(FAR_ELn)是为异常处理程序提供关于同EL步异常原因的信息。

ESR_ELn保存了异常原因,而FAR_ELn保存了所有同步指令和数据中止以及对齐故障的故障虚拟地址。

异常链接寄存器(ELR_ELn)也保存了导致中止数据访问的指令的地址(对于数据中止)。这些在内存故障后被更新,但在其他情况下也会被设置,例如,通过分支到错位的地址。如果一个异常从AArch32中的异常级别进入使用AArch64的异常级别,并且该异常写入了与目标异常级别相关的故障地址寄存器,FAR_ELn的前32位都被设置为0。

异常综合寄存器,ESR_ELn,包含了允许异常处理程序确定异常原因的信息。它只对同步异常和SError进行更新。它不对IRQ或FIQ进行更新,因为这些中断处理程序通常从通用中断控制器(GIC)的寄存器中获取状态信息。

Bit[31:26](ESR_ELn.EC)表示异常类别,它使处理程序能够区分各种可能的异常原因(如未分配的指令,从MCR或MRC到CP15的异常,FP操作的异常,SVC、HVC或SMC的执行,数据中止,以及对齐异常)。例如,EC=101111是一个SError中断。

Bit[25](ESR_ELn.IL)表示被困指令的长度(16位指令为0,32位指令为1),并对某些异常类别进行设置。

Bit[24:0] (ESR_ELn.ISS)构成指令特定综合症(ISS)字段,包含该异常类型的特定信息。例如,当一个系统调用指令(SVC、HVC或SMC)被执行时,该字段包含与操作码相关的即时值,如SVC为0x123456。