当前位置:网站首页>【RISC-V】Trap和Exception
【RISC-V】Trap和Exception
2022-08-04 11:28:00 【佳大先生】
文章目录
控制流 (Control Flow)和Trap
- 控制流(Control Flow)
- branch(条件分支指令), jump (无条件跳转指令),由程序正常自主控制的流程
- 异常控制流 (Exceptional Control Flow,简称 ECP, 又称Trap)
- 不在程序的控制范围之内
- exception
- interrupt
RISC-V Trap处理中涉及的寄存器
八个控制状态寄存器(CSR)是机器模式下异常处理的必要部分:
- mtvec(Machine Trap Vector)它保存发生异常时处理器需要跳转到的地址。
- mepc(Machine Exception PC)它指向发生异常的指令。
- mcause(Machine Exception Cause)它指示发生异常的种类。
- mie(Machine Interrupt Enable)它指出处理器目前能处理和必须忽略的中断。
- mip(Machine Interrupt Pending)它列出目前正准备处理的中断。
- mtval(Machine Trap Value)它保存了陷入(trap)的附加信息:地址例外中出错
- 的地址、发生非法指令例外的指令本身,对于其他异常,它的值为 0。
- mscratch(Machine Scratch)它暂时存放一个字大小的数据。
- mstatus(Machine Status)它保存全局中断使能,以及许多其他的状态,如图
mtvec (Machine Trap-Vector Base-Address)
- BASE: trap入口函数的及地址,必须保证四字节对其
- MODE: 进一步用于控制入口函数的地址配置方式
- Direct: 所有的exception和interrupt发生后pc都跳转到BASE指定的地址处。其实就是一个中断处理函数。
- Vectored: exception处理方式同Direct;但interrupt的入口地址以数组方式排列。其实就是多向量指向不同的中断处理函数。
mepc (Machine Exception Program Counter)
- 当trap发生时,pc会被替换为mtvec设定的地址,同时hart会设置mepc为当前指令或者下一条指令的地址(如果是异常则设置当前指令,如果是中断则设置下一条指令的地址),当我们需要退出trap时可以调用特殊的mret指令,该指令会将mepc中的值恢复到pc中(实现返回的效果)。
- 在处理trap的程序中我们可以修改mepc的值达到改变mret返回地址的目的。
mcause (Machine Cause)
- 当trap发生时,hart会设置该寄存器通知我们trap发生的原因。
- 最高位Interrupt为1时标识了当前trap为interrupt,否则是exception。通过此标识能快速分辨发生了中断还是异常。
- 剩余的Exception Code用于标识具体的interrupt或者exception的种类。
- WLRL(Write/Read Only Legal Values)
mstatus (Machine Status)
- MIE: 分别用于打开(1)或者关闭(0) M/S/U模式下的全局中断。当trap发生时,hart会自动将MIE设置为0。
- MPIE: 当trap发生时用于保存trap发生之前的MIE值。
- MPP: 当trap发生时用于保存trap发生之前的权限级别值。M/S/U三种模式用两个bit表示。
中断与异常含义
RISC-V Trap处理流程
Trap初始化(设置入口地址等)-> Trap的Top Half(硬件处理过程)-> Trap的Bottom Half(软件逻辑部分)-> 从Trap返回
Top Half(Trap发生时,Hart自动执行流)
- 先把 mstatus 的MIE值复制到MPIE中,清除 mstatus 中的MIE标志位,效果是中断被禁止。(这就是硬件上不支持中断嵌套,但可以手动将中断再次打开实现中断嵌套)
- 设置 mepc,同时PC被设置为 mtvec。(需要注意的是,对于 exception, mepc 指向导致异常的指令;对于 interrupt,它指向被中断的指令的下一条指令。)
- 根据 trap 的种类设置 mcausem,并根据需要为 mtval 设置附加信息。
- 将 trap发生之前的权限模式保存在 mstatus 的 MPP 域中,再把 hart 权限模式更改为M(也就是说无论在任何 Level 下触发 trap, hart首先切换到 Machine 模式)
Bottom Half(软件需要做的事情)
- 保存(save) 当前控制流的上下文信息,是指保存x1~x31寄存器的值。(利用 mscratch)
- 调用C语言的trap handler
- 中断C程序执行完毕之后从trap handler函数返回,mepc的值可能需要调整。
- 恢复 (restore)上下文的信息。
- 执行 MRET指令返回到trap之前的状态。
退出 trap:编程调用 MRET 指令
- 针对不同权限级别下有各自退出trap的返回指令xRET (x=M/S/U)
- 以在M模式下指令mret指令为例,会执行开中断(mstatus.MIE = mstatus.MPIE; mstatus.MPIE = 1),然后返回进入trap之前的指令,如果是中断的话返回进入trap之前的下一条指令。(pc = mepc)
portASM.S
/*-----------------------------------------------------------*/
.section .text.freertos_risc_v_trap_handler
.align 8
freertos_risc_v_trap_handler:
portcontextSAVE_CONTEXT_INTERNAL
csrr a0, mcause
csrr a1, mepc
bge a0, x0, synchronous_exception
asynchronous_interrupt:
store_x a1, 0( sp ) /* Asynchronous interrupt so save unmodified exception return address. */
load_x sp, xISRStackTop /* Switch to ISR stack. */
j handle_interrupt
synchronous_exception:
addi a1, a1, 4 /* Synchronous so update exception return address to the instruction after the instruction that generated the exeption. */
store_x a1, 0( sp ) /* Save updated exception return address. */
load_x sp, xISRStackTop /* Switch to ISR stack. */
j handle_exception
handle_interrupt:
#if( portasmHAS_MTIME != 0 )
test_if_mtimer: /* If there is a CLINT then the mtimer is used to generate the tick interrupt. */
addi t0, x0, 1
slli t0, t0, __riscv_xlen - 1 /* LSB is already set, shift into MSB. Shift 31 on 32-bit or 63 on 64-bit cores. */
addi t1, t0, 7 /* 0x8000[]0007 == machine timer interrupt. */
bne a0, t1, application_interrupt_handler
portUPDATE_MTIMER_COMPARE_REGISTER
call xTaskIncrementTick
beqz a0, processed_source /* Don't switch context if incrementing tick didn't unblock a task. */
call vTaskSwitchContext
j processed_source
#endif /* portasmHAS_MTIME */
application_interrupt_handler:
call freertos_risc_v_application_interrupt_handler
j processed_source
handle_exception:
/* a0 contains mcause. */
li t0, 11 /* 11 == environment call. */
bne a0, t0, application_exception_handler /* Not an M environment call, so some other exception. */
call vTaskSwitchContext
j processed_source
application_exception_handler:
call freertos_risc_v_application_exception_handler
j processed_source /* No other exceptions handled yet. */
processed_source:
portcontextRESTORE_CONTEXT
/*-----------------------------------------------------------*/
边栏推荐
- cat /proc/kallsyms found that the kernel symbol table values are all 0
- 数据库对象
- 什么是 DevOps?看这一篇就够了!
- winform 在Datatable插入一笔数据
- Leetcode brush - structure binary tree (105. Once upon a time sequence and the sequence structure binary tree traversal sequence, 106. From the sequence with the sequence structure binary tree travers
- 【LeetCode】899.有序队列
- MySQL 45 讲 | 10 MySQL为什么有时候会选错索引?
- *iframe*
- 使用.NET简单实现一个Redis的高性能克隆版(二)
- 小程序实战(三) - head组件的封装与使用
猜你喜欢
Leetcode刷题——二叉搜索树相关题目(98. 验证二叉搜索树、235. 二叉搜索树的最近公共祖先、1038. 从二叉搜索树到更大和树、538. 把二叉搜索树转换为累加树)
[Flight Control Development Advanced Course 7] Crazy Shell Open Source Formation UAV - Formation Flight
什么是 DevOps?看这一篇就够了!
Leetcode brush questions - 543. Diameter of binary trees, 617. Merging binary trees (recursive solution)
Camunda overall architecture and related concepts
Redis查询缓存
中介者模式(Mediator)
What is the principle of thermal imaging temperature measurement?Do you know?
剑指长城炮? 长安全新皮卡官方谍照
数据库对象
随机推荐
秒云成功入选《2022爱分析 · 银行数字化厂商全景报告》,智能运维能力获认可
WPF 截图控件之画笔(八)「仿微信」
bitset的基本用法
ECCV 2022 | 清华&腾讯AI Lab提出REALY: 重新思考3D人脸重建的评估方法
技术干货 | 用零信任保护代码安全
ESP8266-Arduino编程实例-APDS-9930环境光和趋近感器驱动
剑指offer专项突击版第19天
【黄啊码】MySQL入门—1、SQL 的执行流程
MySQL 45 讲 | 11 怎么给字符串字段加索引?
Leetcode刷题——路径总和
剑指长城炮? 长安全新皮卡官方谍照
Disc burning steps
HyperLynx仿真(一)LineSim简单介绍
你值得拥有的登录注册页面(附赠源码)
datax oracle to oracle增量同步
cat /proc/kallsyms found that the kernel symbol table values are all 0
Zikko上市同时搭载HDMI2.1和2.5GbE新款雷电4扩展坞
DB2查看执行过长的SQL
vscode插件设置——Golang开发环境配置
Oracle中对临时表空间执行shrink操作