10

vesperW · 2022年05月31日

[ARM异常]-ARMV8-aarch64异常和中断处理概念详细介绍

1、异常和中断的概念

(AArch64 Exception and Interrupt Handling)
异常是指需要特权软件(an exception handler))采取某些操作,以确保系统的平稳运行

中断有时用作异常的同义词。但是对于ARM的术语来说,中断是异步异常,只是异常的一种;

异常是一个事件(而不是分支或跳转指令)导致指令的正常顺序执行被修改。
一个中断是一个异常,它不是由程序执行直接引起的。通常情况下,硬件外部到处理器核心信号中断,如一个按钮被按下

ARM-A架构异常分为两组,同步和异步的。
同步异常类型可以有很多原因,但是它们是以类似的方式处理。
异步异常类型被细分为三个中断:IRQ, FIQ和SError(系统错误)。

2、异常产生的方法:

(1)、Abort :
指令获取失败时生成中止(指令中止)
失败的数据访问(数据中止)
它们可以来自外部记忆系统在内存访问上给出错误响应(指示可能指定的地址与系统中的实际内存不对应)。或者,核心的内存管理单元(MMU)生成中止

在AArch64中,同步中止会导致同步异常。异步中止会导致SError中断异常

(2)、Reset
重置是一种特殊情况,因为它总是有自己的向量以最高的实现异常级别为目标
地址可以从重置向量基地址寄存器中读取RVBAR_ELn,其中n是实现的最高异常级别的数目。
所有的核心都有一个重置输入,并在它们被重置后接受重置异常重置。它是最高优先级的异常,不能被掩盖。这个异常是用来在内核上执行代码来初始化它,在系统通电后向上

(3)、同步异常
• The Supervisor Call (SVC) instruction enables User mode programs
to request an OS service.
• The Hypervisor Call (HVC) instruction enables the guest OS to
request hypervisor services.
• The Secure monitor Call (SMC) instruction enables the Normal

(4)、异步异常(中断)
中断有三种类型,IRQ, FIQ和SError。IRQ和FIQ是与SError相比,一般用途是与外部异步数据中止。所以通常,术语“中断”仅指到IRQ和FIQ。

3、同步异常和异步异常的处理

(1)、处理一个同步异常
Exception Syndrome Register (ESR_ELn)
Fault Address Register (FAR_ELn)
The Exception Link Register (ELR_ELn)

异常综合征寄存器(ESR_ELn)和错误地址寄存器(FAR_ELn)是提供用于向异常处理程序提供有关同步异常原因的信息
ESR_ELn提供异常原因的信息,而FAR\_ELn保存所有同步指令和数据中止和对齐错误的错误虚拟地址。

对于实现了EL2 (Hypervisor)或EL3(安全内核)的系统,同步异常通常在当前或更高的异常级别中获取。异步异常可以(如果)),将被路由到更高的异常级别,由Hypervisor或安全程序处理
内核。SCR_EL3寄存器指定哪些异常被路由到EL3,类似地,HCR_EL2指定将哪些异常路由到EL2。有一些单独的位允许独立控制IRQ, FIQ和SError的路由。

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

(3)、Unallocated instructions
Unallocated instructions cause a Synchronous Abort in AArch64. 该异常产生的原因:
• An instruction opcode that is not allocated.
• An instruction that requires a higher level of privilege than the current Exception level. //比如你在EL1中操作了SCR_EL3寄存器
• An instruction that has been disabled.
• Any instruction when the PSTATE.IL field is set.

(4)、System calls
1653976070(1).png

4、异常处理

ARMv8-A体系结构有四个异常级别:EL0、EL1、EL2和EL3。处理器执行
只能通过获取异常或从异常返回来在异常级别之间移动。

需要注意的是:

  • When the processor moves from a higher to a lower Exception level, the Execution state can stay the same, or it can switch from AArch64 to AArch32.
  • When moving from a lower to a higher Exception level, the Execution state can stay the same or switch from AArch32 to AArch64
    也就是说,如果高级别的level为aarch32,那么低级别的level一定得为aarch32
    如果高级别的level为aarch64,那么低级别的level一可以为aarch32或aarch64

当一个异常发生时, the processor自动执行了如下动作:

  1. The SPSR_ELn is updated (where n is the Exception level where the exception is taken), to store the PSTATE information that is required to correctly return at the end of the exception.
  2. PSTATE is updated to reflect the new processor status (and this can mean that the Exception level is raised, or it can stay the same).
  3. The address to return to at the end of the exception is stored in ELR_ELn.
    The _ELn suffix on register names denotes that there are multiple copies of these registers
    existing at different Exception levels. This means, for example, that SPSR_EL1 is a different
    physical register to SPSR_EL2.
    1653976214(1).png
    而我们在异常处理中,又会调用下一级的函数来干活,图形也就如下所示:
    1653976226(1).png
    当异常处理完成后,processor由高级别返回低级别时,使用ERET指令返回

5、异常向量表

每个异常级别都有自己的一套向量表,这些表的基地址分别写在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)
• If the exception is being taken at the same Exception level, the stack pointer to be used (SP0 or SPn).
• If the exception is being taken at a lower Exception level, the Execution state of the next lower level (AArch64 or AArch32).

一张经典的向量表,如下所示:
1653976260(1).png

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

6、异常返回

软件必须告诉处理器何时从异常中返回。这是通过代码完成的使用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寄存器来控制。

7、PSTATE

1653976324(1).png
当前processor的状态保存在PSTATE,当异常到来时,PSTATE的值会自动保存在SPSR中。 aarch64中由三个SPSR : SPSR_EL3, SPSR_EL2, and SPSR_EL1
例如,如果发生了一个异常target到EL1,那么当前处理器的状态会自动保存到SPSR_EL1中;
1653976339(1).png
7、中断的处理流程
1653976365(1).png

作者:代码改变世界ctw
文章来源: https://blog.csdn.net/weixin_42135087/article/details/109025760/

推荐阅读

欢迎大家点赞留言,更多Arm技术文章动态请关注极术社区Arm技术专栏欢迎添加极术小姐姐微信(id:aijishu20)加入技术交流群,请备注研究方向。
推荐阅读
关注数
23567
内容数
1018
Arm相关的技术博客,提供最新Arm技术干货,欢迎关注
目录
极术微信服务号
关注极术微信号
实时接收点赞提醒和评论通知
安谋科技学堂公众号
关注安谋科技学堂
实时获取安谋科技及 Arm 教学资源
安谋科技招聘公众号
关注安谋科技招聘
实时获取安谋科技中国职位信息