ARMv8-AArch64 的异常处理模型详解之异常向量表vector tables

目录

一,AArch64 异常向量表

 二,栈指针以及SP寄存器的选择

三,从异常返回


 

一,AArch64 异常向量表

异常向量表(vector tables)是一组存放于普通内存(normal memory)空间的,用于处理不同类型异常的指令(exception handler)。

当异常发生时,处理器需要跳转到对应的异常处理器(exception handler)来处理异常。异常处理器充当调度代码,识别异常的原因,然后调用相关的处理程序代码(异常处理子程序)来处理异常。

  • exception vector:在内存中存储异常处理器(exception handler)的位置称为异常向量。
  • exception vector tables :异常向量统一存放的区域称为异常向量表。
每个异常级别都有它自己的向量表,其基地址由它自己的向量基地址寄存器(Vector Base Address Register) VBAR_EL<x>定义,其中<x>为1、2或3。需要注意的是,没有针对EL0的向量表,因为异常永远不会在EL0中被处理。VBAR的值需要由软件进行初始化,它们在reset后的值是未定义的。
所有的向量表都使用相同的格式,对不同的异常类型和异常来源,有着不同的异常处理器(异常向量) ,并且,针对每种异常类型,在距离向量基地址的固定偏移量处(0x80)都有一个异常向量。
异常向量的区分和选择取决于如下因素:
  • 异常的类型,比如有(SError, FIQ, IRQ以及同步异常)。
  • 当前异常等级以及目标异常等级(The Exception levels the exception is being taken from and to)。
  • 当前支持的执行状态(AArch32或者AArch64)
  • 所使用的栈指针寄存器(SP_EL0还是SP_ELx)

下表为AArch64的异常向量表格式:

Address

Exception type

Description

VBAR_ELn + 0x000

Synchronous

Current EL with SP0

+ 0x080

IRQ/vIRQ

+ 0x100

FIQ/vFIQ

+ 0x180

SError/vSError

+ 0x200

Synchronous

Current EL with SPx

+ 0x280

IRQ/vIRQ

+ 0x300

FIQ/vFIQ

+ 0x380

SError/vSError

+ 0x400

Synchronous

Lower EL using AArch64

+ 0x480

IRQ/vIRQ

+ 0x500

FIQ/vFIQ

+ 0x580

SError/vSError

+ 0x600

Synchronous

Lower EL using AArch32

+ 0x680

IRQ/vIRQ

+ 0x700

FIQ/vFIQ

+ 0x780

SError/vSError

从这张表我们可以知道,这些向量被分为两组,每一组又被分为两个子组: 

  • 异常等级有变化(准确来说是异常等级提高,从低等级进入到更高等级,Exception from Lower EL)
    • 低等级是AArch32状态
    • 低等级是AArch64状态
  • 异常等级无变化
    • 异常使用SP_ELx。
    • 异常使用SP_EL0。

在VBAR_ELn 的向量基地址已知的情况下,当发生异常时,处理器可以根据当前的状态以及异常的类型,找到对应的异常向量进行异常处理。

如下图所示,为一个简单的异常处理流程图,当异常发生时,处理器会跳到对应异常向量中,首先将易失寄存器,也就是当前处理器的寄存器上下文保存到栈中。然后调用针对当前异常类型的异常处理函数进行处理。在异常处理完之后,再将之前保存在栈中的寄存器上下文恢复。最后执行ERET指令,从异常中返回。

AArch64的异常向量有32 个word的空间(128 bytes),可以存放32条指令,可以用于栈操作(寄存器上下文的压栈以及出栈)、调用特定异常处理函数以及ERET指令。

 

 二,栈指针以及SP寄存器的选择

 在上节中提到过异常向量的选择因素中有一项所使用的栈指针寄存器(SP_EL0还是SP_ELx)。当处理器执行在AArch64状态下时,ARM架构允许软件为当前的异常等级选择栈指针寄存器:

  • SP_EL0(需要配置PSTATE的SP)。
  • SP_ELx,x为当前的异常等级(默认情况)。

比如处理器当前处于EL1,默认情况下是使用SP_EL1作为当前的SP寄存器,但是也可以配置成使用SP_EL0。基于此配置,异常向量也被多分成了两组(使用SP_EL0还是SP_ELx)。

当异常发生时,默认情况下,会自动使用目标异常等级的SP_ELx作为栈指针寄存器。但是栈指针寄存器的选择可以通过配置PSTATE来实现,另外必须遵守如下规则:

  • 如果当前处于EL0,则处理器使用EL0的栈指针寄存器:SP_EL0。
  • 如果处于EL1,EL2或者EL3时,处理器使用的栈指针寄存器受到PSTATE.SP位控制
    • ​​​​​​​​​​​​​​如果PSTATE.SP=0,则处理器使用SP_EL0。
    • 如果PSTATE.SP=1(默认情况下为1,在warm reset后,SP也为1),则处理器使用SP_ELx。

 为什么会有SP_EL0和SP_ELx的选择配置呢?

主要是因为EL0是应用层,一般的应用程序都在EL0上运行,因此给SP_EL0分配的栈空间一般都非常大。如果异常处理时有比较大的栈空间需求,SP_EL0是更好的选择,软件可以通过设置PSTATE.SP=0,让其他异常等级上的程序工作使用SP_EL0。

三,从异常返回

当异常处理完成后,处理器需要恢复到异常发生前的状态,需要:

  • 恢复所有的之前压入栈的寄存器上下文。
  • 执行ERET指令。

ERET指令主要干了两件事:

  • SPSR_EL<x>寄存器里的值恢复到PSTATE。
  • 将ELR_EL<x>里保存的地址恢复到PC寄存器,相当于处理器跳转到ELR_EL<x>中的地址。

SPSR_EL<x>和ELR_EL<x>的x是目标异常等级,也就是(taken to和returned from的异常等级),SPSR_EL<x>寄存器里也同样保存着执行状态控制bit,如果想要改变处理器的执行状态,其中一个方法就是在ERET指令之前,将想要的执行状态(AArch32或者AArch64)提前写入SPSR_ELx。需要注意的是,写入SPSR_ELx的执行状态需要和SCR_EL3.RW 或者HCR_EL2.RW配置相对应,不然会产生非法的异常返回。

ERET主要是将SPSR_EL<x>和ELR_EL<x>的值更新到PSTATE和PC寄存器,为了让处理器不会进入未定义的状态,这两个更新操作是原子性的(不会被打断),而且对处理器来说是不可见的。

下图是ERET指令的伪代码,通过对伪代码进行分析,可以知道,虽然ERET的两个更新操作是原子性的,但是也有先后顺序:先更新SPSR,再更新PC 。

 

 

 

 对于ELR的使用,有一点要特别注意:ELR中保存的地址与异常类型有关。

  • 对于同步的异常服务调用指令,比如SVC、HVC以及SMC。假设执行了SMC指令进入到EL3,ELR_EL3中保存的是SMC的下一条指令。
  • 对于其他的同步异常,ELR保存的是产生异常的那条指令的地址。
  • 对于异步异常,ELR中保存的是当异常发生时,第一条还没有被执行完成的指令的地址。

当然异常处理程序软件也可以再适当的时候修改ELR寄存器里的内容,确保处理器在ERET指令后能回到正确的程序流中。

下图是ARMv7的各类型异常的首选异常返回地址:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/701314.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【机器学习科学库】全md文档笔记:Jupyter Notebook和Matplotlib使用(已分享,附代码)

本系列文章md笔记&#xff08;已分享&#xff09;主要讨论人工智能相关知识。主要内容包括&#xff0c;了解机器学习定义以及应用场景&#xff0c;掌握机器学习基础环境的安装和使用&#xff0c;掌握利用常用的科学计算库对数据进行展示、分析&#xff0c;学会使用jupyter note…

vue从flask获取数据并显示

记录一个前后端分离遇到的问题&#xff0c;即vue前端从flask后端获取数据。具体描述如下&#xff1a;flask只负责连接数据库并获取数据库的数据&#xff0c;并返回给前端vue&#xff1b;vue则需要获取后端返回的数据并显示。 方法如下&#xff0c;分别用一个vue组件和一个flas…

【网站项目】488服装店销售管理系统

&#x1f64a;作者简介&#xff1a;拥有多年开发工作经验&#xff0c;分享技术代码帮助学生学习&#xff0c;独立完成自己的项目或者毕业设计。 代码可以私聊博主获取。&#x1f339;赠送计算机毕业设计600个选题excel文件&#xff0c;帮助大学选题。赠送开题报告模板&#xff…

迷你世界之建筑生成球体

local x0,y0,z00,30,0--起点坐标 local dx,dy,dz60,60,60--外切长方体横纵竖长度 local count,all0,dx*dy*dz--计数&#xff0c;总数 local m,k10000,0--单次生成方块数&#xff0c;无用循环值 local x,y,z0,0,0--当前坐标 local demath.random(2,19)/2 local id600--方块…

中兴通讯携吉林移动迈向5G-A新阶段,完成3CC技术应用

日前&#xff0c;中兴通讯携手中国移动吉林移动分公司&#xff0c;在5G-A领域取得新突破。具体来说&#xff0c;双方基于MTK芯片M80终端&#xff0c;完成了5G-A三载波聚合试点&#xff0c;实测下行速率达到理论峰值4.25Gbps&#xff0c;相比2.6G单载波速率提升2.5倍。如此成绩&…

C++面试题精选与解析

C面试题精选与解析 一、基础与语法 请问C中的指针和引用有什么区别&#xff1f; 指针是一个变量&#xff0c;存储的是另一个变量的内存地址。指针可以被重新赋值以指向另一个不同的对象。而引用是某个变量的别名&#xff0c;一旦引用被初始化为一个变量&#xff0c;就不能改变…

LLM权重量化

LLM权重量化 浮点表示的背景知识Nave 8位量化使用LLM.int8() 进行8位量化结论References 大型语言模型(llm)以其广泛的计算需求而闻名。通常&#xff0c;模型的大小是通过将**参数的数量(大小)乘以这些值的精度(数据类型)**来计算的。为了节省内存&#xff0c;可以通过称为量化…

cmake 项目。qt5升级 qt6 报错 error: “Qt requires a C++17 compiler 已解决

日常项目开发中。需要对qt5升级到qt6 做cmake兼容配置&#xff0c;在编译中发现&#xff0c;有c 编译环境 报错 2>C:\Qt\6.5.3\msvc2019_64\include\QtCore/qcompilerdetection.h(1226,1): fatal error C1189: #error: "Qt requires a C17 compiler, and a suitable …

了解 JavaScript 中的重放攻击和复现攻击

在网络安全领域&#xff0c;重放攻击&#xff08;Replay Attack&#xff09;和复现攻击&#xff08;Playback Attack&#xff09;是一些可能导致安全漏洞的攻击形式。这两种攻击类型涉及在通信过程中再次发送已经捕获的数据&#xff0c;以达到欺骗系统的目的。本文将介绍 JavaS…

企业微信怎么变更企业名称?

企业微信变更主体有什么作用&#xff1f;现在很多公司都用企业微信来加客户&#xff0c;有时候辛辛苦苦积累了很多客户&#xff0c;但是公司却因为各种各样的原因需要注销&#xff0c;那么就需要通过企业微信变更主体的方法&#xff0c;把企业微信绑定的公司更改为最新的。企业…

Qt Android sdk配置报错解决

使用的jdk8总是失败&#xff0c;报错command tools run以及platform sdk等问题。后来主要是设置jdk版本为17&#xff0c;就配置生效了。Android sdk路径可以选用Android Studio自带的&#xff0c;但是也要在Qt中点击“设置SDK”按钮做必要的下载更新等。 编译器这里会自动检测到…

linux中的权限

Linux 的权限 在了解Linux的权限之前&#xff0c;我们需要知道Linux的构成&#xff0c;Linux分为三个部分&#xff0c;内核、外部程序、以及用户。 内核&#xff1a; 内核一般是指Linux的操作系统&#xff0c;用来执行用户发送的指令 或者 拒绝执行用户发布指令时而发出的报…

大数据之Flink优化

文章目录 导言&#xff1a;Flink调优概览第1章 资源配置调优1.1 内存设置1.1.1 TaskManager 内存模型1.1.2 生产资源配置示例 1.2 合理利用 cpu 资源1.2.1 使用 DefaultResourceCalculator 策略1.2.2 使用 DominantResourceCalculator 策略1.2.3 使用DominantResourceCalculato…

YOLOv9来了,可编程梯度信息与广义高效层聚合网络 助力全新检测SOTA前沿

本文首发&#xff1a;AIWalker 欢迎关注AIWalker&#xff0c;近距离接触底层视觉与基础AI技术 摘要 当今的深度学习方法侧重于如何设计最合适的目标函数&#xff0c;以便模型的预测结果最接近真实情况&#xff1b;与此同时&#xff0c;必须设计一个适当的架构&#xff0c;以便…

[electron]官方示例解析

官方例子 github链接 main.js const { app, BrowserWindow } require(electron)说句实话这里的语法是有部分看不懂的。导入模块虽然electron有很多模块。但是这里只是用到了app 和 BrowserWindow function createWindow () {// Create the browser window.const mainWindo…

go语言的理解,看这一篇就够了

1.来源 Go语言是谷歌2009年发布的第二款开源编程语言 2.谷歌为什么要创建Go语言 计算机硬件技术更新频繁, 性能提高很快,默目前主流的编程语言发展明显落后于硬件,不能合理利用多核多CPU的优势提升软件系统性能软件系统复杂度越来越高,维护成本越来越高,目前缺乏一个简洁而高效…

SSM项目集成Spring Security 4.X版本 之 加入DWZ,J-UI框架实现登录和主页菜单显示

目录 前言 一、加入DWZ J-UI框架 二、实现登录页面 三、实现主页面菜单显示 前言 大家好&#xff01;写文章之前先列出几篇相关文章。本文内容也在其项目中接续实现。 一. SSM项目集成Spring Security 4.X版本&#xff08;使用spring-security.xml 配置文件方式&#xff…

eclipse中open Type 、 open type in Hierachy、open Resource的区别

目录 场景&#xff1a; open Type open Resource open type in Hierachy 场景&#xff1a; 在项目中想要研究底层代码&#xff0c;经常要用eclipse看依赖jar包的类&#xff0c;比如spring的源码中AbstractApplicationContext类CTLSHIFTT用的少&#xff0c;经常用的CTLSHIR…

YOLO系列论文阅读(v1--v3)

搞目标检测&#xff0c;绕不开的一个框架就是yolo&#xff0c;而且更糟糕的是&#xff0c;随着yolo的发展迭代&#xff0c;yolo网络可以做的事越来越多&#xff0c;语义分割&#xff0c;关键点检测&#xff0c;3D目标检测。。。这几天决定把YOLO系列彻底梳理一下&#xff0c;在…

leet hot 100-4 移动零

移动零 原题链接思路代码 原题链接 leet hot 100-4 283. 移动零 思路 遍历数组 将非0数字 移动到数组前端 数字0就会被移动到数组末端 时间复杂度O(n) 空间复杂度(n) 代码 class Solution { public:void moveZeroes(vector<int>& nums) {int start 0;int ind…