RV特权架构小记
参考链接
note:文章仅用于自己记忆,下面的内容手册里都会有并且更加完善
异常和中断#
用户模式(U)所能提供的可以看成只能完成计算和访存等功能,我们需要更多现代的特性的时候,就必须进入最高特权的机器模式(M)或提供给操作系统的监管者模式(S),并且需要csr(控制状态寄存器)来帮助完成这样的扩展。
机器模式是唯一所有标准 RISC-V 处理器都必须实现的权限模式,该模式是hart(硬件线程)可以执行的最高权限模式。
我们熟悉的计算和访存等功能都在用户模式下完成,而这个模式的最重要功能之一则是负责处理拦截和处理异常。
rv将异常分为两种:
- 同步异常(指令执行期间产生,比如访问无效地址、执行无效命令)
- 中断(与指令流异步的外部事件,比如鼠标单击)
其中第一种同步异常又分为以下五种:
- 访问错误异常:例如尝试写入rom
- 断点异常:例如ebreak
- 环境调用异常:ecall
- 非法指令异常:译码阶段发现无效操作码
- 非对齐地址异常
下面这张图显示了各个类型的异常/中断如何表示,并存储在mcause寄存器中
rvbook第二章说过可以支持非对齐访存,但为什么有instruction address misaligned异常呢。是因为原子访存操作必须要对齐,其次,一些处理器设计者采取将非对齐访存通过软件模拟的方式来实现,而不在硬件层面提供支持。当然,如果需要性能更好的处理器,完全可以在硬件层面提供非对齐访存的支持
机器模式#
csr#
如果你翻看rv的规格手册你会发现有很多不明觉厉的csr,然而此处支持m-mode下异常处理的必要csr只有八个:
csr | 保存的内容 |
---|---|
mtvec | 发生异常时需要跳转的地址 |
mepc | 发生异常的指令地址 |
mcause | 发生异常的种类 |
mie | 目前能处理和必须忽略的中断 |
mip | 目前正准备处理的中断 |
mtval | trap的附加信息:比如访存异常的出错地址、非法指令异常的指令本身 |
mscratch | 暂存字大小数据 |
mstatus | 许多状态 |
前面几个寄存器相对好理解,看一下最后一个mstatus:
mstatus也有一个MIE域,与mie寄存器不同,MIE域控制全局中断使能,mie寄存器控制每种类型中断的使能,比如mie[7]对应m-mode下的时钟中断。显然,只有MIE=1时,mie才有效。
中断处理流程举例#
用m-mode时钟中断举例,当MIE=1(全局中断使能有效),mie[7]=1(时钟中断使能有效),mip[7]=1(时钟中断到来),此时处理器处理该时钟中断:
- pc保存到mepc,pc设置为mtvec
- 根据mcause设置mtval
- MIE保存到MPIE,并将MIE设置为0禁用中断
- 权限模式保存到MPP,并将权限模式设置为m-mode(如果只实现m-mode,不需要这个步骤)
中断对于正常程序来说属于另一个例程,因此还需要将中断处理程序用到的整数寄存器保存到“栈”中,具体做法是软件让mscratch包含指向附加临时内存空间的指针,中断处理程序通过该指针保存整数寄存器到内存中,并且在结束时恢复。(关于这里我在写pa的nanos-lite中断处理的时候发现处理程序并没有使用mscratch,而是像普通的函数一样使用sp来入栈和出栈,可能是为了简化实现)
最后用mret退出异常处理程序时,处理器将MIE恢复为MPIE,并将MPIE设1;根据MPV和MPP恢复权限,并将MPV和MPP设0,pc恢复为mepc。
中断嵌套#
遇到中断嵌套的时候,上述的mepc,mcause等寄存器还需要保存到内存中的栈中,可抢 占的中断处理程序可以在启用中断之前把这些寄存器保存到内存中的栈,然后在退出之前,禁用中断并从栈中恢复寄存器。
还有一个特殊的指令:wfi(wait for interrupt),它通知处理处理器目前不用干活,应该进入低功耗模式,直到mie&mip≠0,具体取决于处理器的实现,可以停止时钟,或者仅仅当nop来执行。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律