本文声明内容来源于网络进行整合/再创作部分内容由AI辅助生成。AArch64 异常调用指令在AArch64中某些指令的执行会产生异常。通常会执行以下指令以从运行于更高异常级别的软件中请求服务。指令类型助记符异常级别核心用途16 位有效载荷 (#uimm16)发起异常SVC管理调用EL1系统最常用。应用程序用户模式EL0请求操作系统内核态EL1服务如读写文件、退出程序。告诉内核 “具体要做什么”。例如 #0 代表退出。HVC系统管理程序调用EL2虚拟化虚拟机客户操作系统通常运行在 EL1请求虚拟机监控器HypervisorEL2服务虚拟机向宿主机传递的具体功能编号。SMC安全监视调用EL3安全正常状态EL1/EL2请求安全状态EL3的安全服务如指纹识别、硬件加密向安全监控器传递的具体功能编号。异常返回ERET返回原级别通用。处理器在异常处理完成后返回到原地址继续执行程序。无。当前异常级别的SPSR_ELn寄存器重新构造处理器状态并自动分支到 LR_ELn中的地址。AArch64 异常表异常向量表发生异常时处理器必须执行与异常对应的处理程序。不同异常处理程序在内存中的入口点集合就构成了异常向量表。在ARMv8-A架构的AArch64执行状态下每个异常级别EL3、EL2、EL1都拥有自己独立的异常向量表。这一点非常重要因为不同级别如安全监控器、虚拟机监视器、操作系统内核负责处理不同性质的异常。向量基址寄存器VBAR每个异常级别对应的向量表在内存中的基地址由该级别下的一个系统寄存器——向量基址寄存器Vector Based Address Register 来设定。具体来说EL1使用 VBAR_EL1EL2使用 VBAR_EL2EL3使用 VBAR_EL3向量表的内容、结构与布局AArch64的向量表里存放的是可以直接执行的指令而不是单纯的内存地址。这意味着当异常发生时处理器直接从向量表的相应入口开始取指执行。表的大小与条目每个异常级别的向量表总共包含16个条目。条目的大小每个条目占据连续的128字节。由于AArch64指令固定为4字节因此每个条目可以容纳最多32条指令。这种设计给了开发者足够的空间在入口处直接实现一些简单的处理逻辑而不必立即进行跳转例如顶级异常处理程序可以直接写在向量表中。如何找到正确的异常处理入口向量表的偏移量和向量表的基地址上表是其中一个向量表。基地址由VBAR_ELn提供然后每个条目从这个基地址定义一个偏移量。当异常发生时处理器会根据以下三个关键因素动态计算并跳转到正确的向量表条目计算公式为VBAR_ELn 偏移量1、异常的类型Exception Type这是触发向量的根本原因分为四大类同步异常Synchronous、IRQ普通中断、FIQ快速中断和SError系统错误。2、异常发生时正在使用的堆栈指针Stack Pointer当异常在同一异常级别内部产生时例如EL1的代码触发了EL1级别的异常处理器的响应取决于其当前配置的堆栈指针如果使用的是 SP_EL0通常用于用户态应用则视为一种错误或特殊场景。如果使用的是 SP_EL1/2/3即当前级别的专用堆栈指针则为正常的内核态异常。3、异常来源的异常级别当异常来自比当前级别更低的异常级别时例如EL0的用户态应用执行了SVC指令陷入EL1的内核处理器会考虑目标低级别执行时的指令集状态较低异常级别运行在AArch64状态。较低异常级别运行在AArch32状态。实例分析假设一个最常见的场景在EL1如Linux内核上执行代码时收到了一个普通的IRQ中断。异常来源由于中断发生时处理器正在EL1执行这属于“在同一异常级别内部产生”的异常。堆栈指针内核代码通常会将SPSel位置1意味着它正在使用专用的SP_EL1作为堆栈指针。查找向量表根据表格我们需要看“同一异常级别使用SP_ELx”这一分组。异常类型是“IRQ”对应这一分组中的第二个条目偏移量 0x280。计算入口地址处理器会从 VBAR_EL1 寄存器中读取EL1向量表的基地址然后加上偏移量 0x280。从这个计算出的地址开始执行的就是内核为IRQ编写的顶级处理程序。