RISC-V异常处理流程概述(2):异常处理机制
RISC-V异常处理流程概述(2):异常处理机制
- 一、异常处理流程和异常委托
- 1.1 异常处理流程
- 1.2 异常委托
- 二、RISC-V异常处理中软件相关内容
- 2.1 异常处理准备工作
- 2.2 异常处理函数
- 2.3 Opensbi系统调用的注册
一、异常处理流程和异常委托
1.1 异常处理流程
发生异常时,首先需要执行 trap 流程:
- 切换到对应的特权模式以处理该 trap。检查 medeleg 寄存器中的相应位,以判断是直接 trap 进 S 模式还是 M 模式。
- 设置 [m/s]status 中的 xPP,xPIE,xIE 等字段。
并设置相关 CSR 的值:
- 将 [m/s]epc 设为导致异常的指令对应的 PC 值。
- 在 [m/s]tval 中存储有关的信息。
- 设置 [m/s]cause寄存器的值。 随后读出 [m/s]tvec 中的值,并根据这个值跳转到 trap 处理程序。

这里不过多分析异常处理过程中硬件寄存器的变化,需要注意的是,在执行异常处理程序时,会进行上下文环境的切换和保存,在执行完异常处理程序后,会通过【m/s】ret指令来退出异常处理程序,接下来会进行恢复异常前程序流的相关操作,最终会跳转到【m/s】pec中保存的地址执行。
1.2 异常委托
在默认的情况下,无论在什么模式下发生异常,都会将控制权交到M模式的异常处理程序,但是Linux系统多数异常都在S模式下进行系统调用。此时,会将M 模式的异常处理程序可以将异常重新导向 S 模式,但这些额外的操作会减慢大多数异常的处理速度。因此,RISC-V 提供了一种异常委托机制。通过该机制可以选择性地将异常交给 S 模式处理,而完全绕过 M 模式。
这种委托机制的实现主要通过:medeleg(Machine Exception Delegation,机器同步异常委托)和 mideleg(Machine Interrupt Delegation,机器中断委托)分别控制将哪些同步异常和中断委托给 S 模式,mret 指令则将 trap 交给其它特权模式处理。
委托给 S 模式的任何异常都可以被 S 模式屏蔽。sie(Supervisor Interrupt Enable,监管者中断使能)和 sip(Supervisor Interrupt Pending,监管者中断待处理)是 S 模式的控制状态寄存器,它们是 mie 和 mip 的子集。它们有着和 M 模式下相同的布局,但在 sie 和 sip 中只有由 mideleg 委托的中断对应的位才能读写,那些没有被委派的中断对应的位始终为 0。
注:发生异常时控制权都不会移交给权限更低的模式。在 M 模式下发生的异常总是在 M 模式下处理。在 S 模式下发生的异常,根据具体的委派设置,可能由 M 模式或 S 模式处理,但永远不会由 U 模式处理。
二、RISC-V异常处理中软件相关内容
2.1 异常处理准备工作
这里需要特殊强调的是异常处理构建的相关内容:
这里会将a4寄存器中的值存储到CSR_MTVEC这个状态寄存器,也就是异常处理程序的的入口;如果遇到异常、中断时,硬件会自动找到_trap_handler
/* Setup trap handler */la a4, _trap_handler
#if __riscv_xlen == 32csrr a5, CSR_MISAsrli a5, a5, ('H' - 'A')andi a5, a5, 0x1beq a5, zero, _skip_trap_handler_rv32_hypla a4, _trap_handler_rv32_hyp
#endifcsrw CSR_MTVEC, a4.section .entry, "ax", %progbits.align 3.globl _trap_handler
_trap_handler:TRAP_SAVE_AND_SETUP_SP_T0TRAP_SAVE_MEPC_MSTATUS 0TRAP_SAVE_GENERAL_REGS_EXCEPT_SP_T0TRAP_CALL_C_ROUTINETRAP_RESTORE_GENERAL_REGS_EXCEPT_SP_T0TRAP_RESTORE_MEPC_MSTATUS 0TRAP_RESTORE_SP_T0mret
建立excption_stack空间,如所示M模式下的异常,则从SP指针开始构建;若不是M模式进入异常,则需要从TP指针开始构建,TP的值为MSCRARCH(这个寄存器会在非M模式下记录M模式下栈帧地址)
.macro TRAP_SAVE_AND_SETUP_SP_T0/* Swap TP and MSCRATCH */csrrw tp, CSR_MSCRATCH, tp/* Save T0 in scratch space */REG_S t0, SBI_SCRATCH_TMP0_OFFSET(tp)/** Set T0 to appropriate exception stack** Came_From_M_Mode = ((MSTATUS.MPP < PRV_M) ? 1 : 0) - 1;* Exception_Stack = TP ^ (Came_From_M_Mode & (SP ^ TP))** Came_From_M_Mode = 0 ==> Exception_Stack = TP* Came_From_M_Mode = -1 ==> Exception_Stack = SP*/csrr t0, CSR_MSTATUSsrl t0, t0, MSTATUS_MPP_SHIFTand t0, t0, PRV_Mslti t0, t0, PRV_Madd t0, t0, -1xor sp, sp, tpand t0, t0, spxor sp, sp, tpxor t0, tp, t0/* Save original SP on exception stack */REG_S sp, (SBI_TRAP_REGS_OFFSET(sp) - SBI_TRAP_REGS_SIZE)(t0)/* Set SP to exception stack and make room for trap registers */add sp, t0, -(SBI_TRAP_REGS_SIZE)/* Restore T0 from scratch space */REG_L t0, SBI_SCRATCH_TMP0_OFFSET(tp)/* Save T0 on stack */REG_S t0, SBI_TRAP_REGS_OFFSET(t0)(sp)/* Swap TP and MSCRATCH */csrrw tp, CSR_MSCRATCH, tp
.endm
TRAP_CALL_C_ROUTINE前面的宏流程用于状态的保存,TRAP_CALL_C_ROUTINE则会调用到C阶段,进入真正的异常处理程序:
.macro TRAP_CALL_C_ROUTINE/* Call C routine */add a0, sp, zerocall sbi_trap_handler
.endm
下面将调用到sbi_trap_handler进行真正的异常处理函数。
2.2 异常处理函数
当Linux中发起ecall调用后,OpenSBI相关服务出发过程如下,主要分为以下几个阶段
- 上一节中讲到,在fw_base.S汇编阶段注册了M mode的trap handler,也就是sbi_trap_handler
- 在sbi_trap_handler中处理各种mcause,首先判断中断原因是否为外部设备中断(timer,ipi),若不是则会根据不同的异常类型比如illegal instructions,Misaligned load & store,S and M mode ecall等等
//lib/sbi_trap.c
/*** Handle trap/interrupt** This function is called by firmware linked to OpenSBI* library for handling trap/interrupt. It expects the* following:* 1. The 'mscratch' CSR is pointing to sbi_scratch of current HART* 2. The 'mcause' CSR is having exception/interrupt cause* 3. The 'mtval' CSR is having additional trap information* 4. The 'mtval2' CSR is having additional trap information* 5. The 'mtinst' CSR is having decoded trap instruction* 6. Stack pointer (SP) is setup for current HART* 7. Interrupts are disabled in MSTATUS CSR** @param regs pointer to register state*/
void sbi_trap_handler(struct sbi_trap_regs *regs)
{int rc = SBI_ENOTSUPP;const char *msg = "trap handler failed";ulong mcause = csr_read(CSR_MCAUSE);ulong mtval = csr_read(CSR_MTVAL), mtval2 = 0, mtinst = 0;struct sbi_trap_info trap;if (misa_extension('H')) {mtval2 = csr_read(CSR_MTVAL2);mtinst = csr_read(CSR_MTINST);}if (mcause & (1UL << (__riscv_xlen - 1))) {mcause &= ~(1UL << (__riscv_xlen - 1));switch (mcause) {case IRQ_M_TIMER:sbi_timer_process();break;case IRQ_M_SOFT:sbi_ipi_process();break;default:msg = "unhandled external interrupt";goto trap_error;};return;}switch (mcause) {case CAUSE_ILLEGAL_INSTRUCTION:rc = sbi_illegal_insn_handler(mtval, regs);msg = "illegal instruction handler failed";break;case CAUSE_MISALIGNED_LOAD:rc = sbi_misaligned_load_handler(mtval, mtval2, mtinst, regs)相关文章:
RISC-V异常处理流程概述(2):异常处理机制
RISC-V异常处理流程概述(2):异常处理机制 一、异常处理流程和异常委托1.1 异常处理流程1.2 异常委托二、RISC-V异常处理中软件相关内容2.1 异常处理准备工作2.2 异常处理函数2.3 Opensbi系统调用的注册一、异常处理流程和异常委托 1.1 异常处理流程 发生异常时,首先需要执…...
Unity3D中如何降低游戏的Drawcall详解
在Unity3D游戏开发中,Drawcall是一个至关重要的性能指标,它指的是CPU通知GPU绘制一个物体的命令次数。过多的Drawcall会导致游戏性能下降,因此优化Drawcall的数量是提高游戏性能的关键。本文将详细介绍Unity3D中降低Drawcall的几种主要方法&a…...
小程序-设置环境变量
在实际开发中,不同的开发环境,调用的接口地址是不一样的 例如:开发环境需要调用开发版的接口地址,生产环境需要正式版的接口地址 这时候,我们就可以使用小程序提供了 wx.getAccountInfoSync() 接口,用来获取…...
【RabbitMQ】一文详解消息可靠性
目录: 1.前言 2.生产者 3.数据持久化 4.消费者 5.死信队列 1.前言 RabbitMQ 是一款高性能、高可靠性的消息中间件,广泛应用于分布式系统中。它允许系统中的各个模块进行异步通信,提供了高度的灵活性和可伸缩性。然而,这种通…...
RuntimeError: Unexpected error from cudaGetDeviceCount
RuntimeError: Unexpected error from cudaGetDeviceCount 0. 引言1. 临时解决方法 0. 引言 使用 vllm-0.4.2 部署时,多卡正常运行。升级到 vllm-0.5.1 时,报错如下: (VllmWorkerProcess pid30692) WARNING 07-12 08:16:22 utils.py:562] U…...
uboot学习:(一)基础认知
目录 uboot是一个裸机程序(bootloader) 作用 要运行linux系统时,如何从外置的flash拷贝到DDR中,才能启动 uboot使用步骤 步骤1中的命令例子 注意 uboot源码获取方法 uboot是一个裸机程序(bootloader)…...
每天一个数据分析题(四百二十六)- 总体方差
为了比较两个总体方差,我们通常检验两个总体的() A. 方差差 B. 方差比 C. 方差乘积 D. 方差和 数据分析认证考试介绍:点击进入 题目来源于CDA模拟题库 点击此处获取答案 数据分析专项练习题库 内容涵盖Python,SQL,统计学&a…...
【C++】设计一套基于C++与C#的视频播放软件
在开发一款集视频播放与丰富交互功能于一体的软件时,结合C的高性能与C#在界面开发上的便捷性,是一个高效且实用的选择。以下,我们将概述这样一个系统的架构设计、关键技术点以及各功能模块的详细实现思路。 一、系统架构设计 1. 架构概览 …...
数学建模中的辅助变量、中间变量、指示变量
在数学建模中,除了决策变量外,还有一些其他类型的变量,如中间变量、辅助变量和指示变量。每种变量在模型中都有特定的用途和意义。以下是对这些变量的详细解释: 1. 决策变量(Decision Variables) 定义&am…...
python的seek()和tell()
seek() seek() 是用来在文件中移动指针位置的方法。它的作用是将文件内部的当前位置设置为指定的位置。 seek(offset, whence) 参数说明 offset: 这是一个整数值,表示相对于起始位置的偏移量。如果是正数,表示向文件末尾方向移动;如果是负…...
Go泛型详解
引子 如果我们要写一个函数分别比较2个整数和浮点数的大小,我们就要写2个函数。如下: func Min(x, y float64) float64 {if x < y {return x}return y }func MinInt(x, y int) int {if x < y {return x}return y }2个函数,除了数据类…...
【每日一练】python之sum()求和函数实例讲解
在Python中, sum()是一个内置函数,用于计算可迭代对象(如列表、元组等)中所有元素的总和。如下实例: """ 收入支出统计小程序 知识点:用户输入获取列表元素添加sum()函数,统计作用 "&…...
打造智慧校园德育管理,提升学生操行基础分
智慧校园的德育管理系统内嵌的操行基础分功能,是对学生日常行为规范和道德素养进行量化评估的一个创新实践。该功能通过将抽象的道德品质转化为具体可量化的指标,如遵守纪律、尊师重道、团结协作、爱护环境及参与集体活动的积极性等,为每个学…...
自定义函数---随机数系列函数
大家有没有发现平常在写随机数的时候,需要引入很多的头文件,然后还需要用一些复杂的函数,大家可能不太习惯,于是我就制作了一个头文件 // random_number.h #ifndef RANDOM_NUMBER_H // 预处理指令,防止头文件被重复包含…...
一文了解5G新通话技术演进与业务模型
5G新通话简介 5G新通话,也被称为VoNR,是基于R16及后续协议产生的一种增强型语音通话业务。 它在IMS网络里新增数据通道(Data Channel),承载通话时的文本、图片、涂鸦、菜单等信息。它能在传统话音业务基础上提供更多服…...
视频使用操作说明书-T80002系列视频编码器如何对接海康NVR硬盘录像机,包括T80002系列高清HDMI编码器、4K超高清HDMI编码器
视频使用操作说明书-T80002系列视频编码器如何对接海康NVR硬盘录像机,包括T80002系列高清HDMI编码器、4K超高清HDMI编码器。 视频使用操作说明书-T80002系列视频编码器如何对接海康NVR硬盘录像机,包括T80002系列高清HDMI编码器、4K超高清HDMI编码器 同三…...
el-input-number计数器change事件校验数据,改变绑定数据值后change方法失效问题的原因及解决方法
在change事件中如果对el-input-number绑定的数据进行更改,会出现change事件失效的问题 试过:this.$set()及赋值等方法,都无法解决 解决方法:用$nextTick函数对绑定值进行更改( this.$nextTick(() > { this.绑定…...
将vue项目整合到springboot项目中并在阿里云上运行
第一步,使用springboot中的thymeleaf模板引擎 导入依赖 <!-- thymeleaf 模板 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-thymeleaf</artifactId></dependency> 在r…...
AC修炼计划(AtCoder Regular Contest 179)A~C
A - Partition A题传送门 这道题不难发现,如果数字最终的和大于等于K,我们可以把这个原数列从大到小排序,得到最终答案。 如果和小于K,则从小到大排序,同时验证是否符合要求。 #pragma GCC optimize(3) //O2优化开启…...
开发编码规范笔记
前言 (1)该博客仅用于个人笔记 格式转换 (1)查看是 LF 行尾还是CRLF 行尾。 # 单个文件,\n 表示 LF 行尾。\r\n 表示 CRLF 行尾。 hexdump -c <yourfile> # 单个文件,$ 表示 LF 行尾。^M$ 表示 CRLF …...
Golang dig框架与GraphQL的完美结合
将 Go 的 Dig 依赖注入框架与 GraphQL 结合使用,可以显著提升应用程序的可维护性、可测试性以及灵活性。 Dig 是一个强大的依赖注入容器,能够帮助开发者更好地管理复杂的依赖关系,而 GraphQL 则是一种用于 API 的查询语言,能够提…...
cf2117E
原题链接:https://codeforces.com/contest/2117/problem/E 题目背景: 给定两个数组a,b,可以执行多次以下操作:选择 i (1 < i < n - 1),并设置 或,也可以在执行上述操作前执行一次删除任意 和 。求…...
【Go】3、Go语言进阶与依赖管理
前言 本系列文章参考自稀土掘金上的 【字节内部课】公开课,做自我学习总结整理。 Go语言并发编程 Go语言原生支持并发编程,它的核心机制是 Goroutine 协程、Channel 通道,并基于CSP(Communicating Sequential Processes࿰…...
2023赣州旅游投资集团
单选题 1.“不登高山,不知天之高也;不临深溪,不知地之厚也。”这句话说明_____。 A、人的意识具有创造性 B、人的认识是独立于实践之外的 C、实践在认识过程中具有决定作用 D、人的一切知识都是从直接经验中获得的 参考答案: C 本题解…...
推荐 github 项目:GeminiImageApp(图片生成方向,可以做一定的素材)
推荐 github 项目:GeminiImageApp(图片生成方向,可以做一定的素材) 这个项目能干嘛? 使用 gemini 2.0 的 api 和 google 其他的 api 来做衍生处理 简化和优化了文生图和图生图的行为(我的最主要) 并且有一些目标检测和切割(我用不到) 视频和 imagefx 因为没 a…...
LabVIEW双光子成像系统技术
双光子成像技术的核心特性 双光子成像通过双低能量光子协同激发机制,展现出显著的技术优势: 深层组织穿透能力:适用于活体组织深度成像 高分辨率观测性能:满足微观结构的精细研究需求 低光毒性特点:减少对样本的损伤…...
LOOI机器人的技术实现解析:从手势识别到边缘检测
LOOI机器人作为一款创新的AI硬件产品,通过将智能手机转变为具有情感交互能力的桌面机器人,展示了前沿AI技术与传统硬件设计的完美结合。作为AI与玩具领域的专家,我将全面解析LOOI的技术实现架构,特别是其手势识别、物体识别和环境…...
Qt 事件处理中 return 的深入解析
Qt 事件处理中 return 的深入解析 在 Qt 事件处理中,return 语句的使用是另一个关键概念,它与 event->accept()/event->ignore() 密切相关但作用不同。让我们详细分析一下它们之间的关系和工作原理。 核心区别:不同层级的事件处理 方…...
Python 训练营打卡 Day 47
注意力热力图可视化 在day 46代码的基础上,对比不同卷积层热力图可视化的结果 import torch import torch.nn as nn import torch.optim as optim from torchvision import datasets, transforms from torch.utils.data import DataLoader import matplotlib.pypl…...
Docker拉取MySQL后数据库连接失败的解决方案
在使用Docker部署MySQL时,拉取并启动容器后,有时可能会遇到数据库连接失败的问题。这种问题可能由多种原因导致,包括配置错误、网络设置问题、权限问题等。本文将分析可能的原因,并提供解决方案。 一、确认MySQL容器的运行状态 …...
