一般在修读 Operating System 时,都会学习到 Interrupt
的概念,此外,电脑在运作时也会碰到大大小小的问题。你可曾好奇电脑是如何排除这些问题的呢?
在本篇文章中,笔者会向大家介绍 RISC-V 处理器是如何处理中断以及异常问题的。
RISC-V 拥有不同的特权模式,供不同层级的程序运作在对应的平台上,如:
Machine Mode
、User Mode
、Supervisor Mode
等等。而本系列文只会专注在具有完整硬体存取权限的Machine Mode
上,如果读者对特权模式有兴趣,可以参考 RISC-V 的官方文件: riscv-privileged-v1.10。
RISC-V 架构定义了许多暂存器,部分暂存器被定义为控制和状态暂存器,也就是标题所指出的 CSR (Control and status registers),它被用於配置或是纪录处理器的运作状况。
笔者先将 RISC-V 架构中 (Machine Mode) 与中断、异常有关的暂存器都列出来,方便待会儿进行解说:
我们都知道,处理器是藉由接收指令进行运作的,若处理器在执行指令流的时候遇到无法预期的情况,便称之为异常
。
其实异常与中断非常相似,最主要的差别是异常发生於硬体、程序上的故障。
异常主要分成两大类型:
要判断异常属於同步或是异步最简单的方式是: 在同样的程序以及环境执行 n 次都能将同样的异常状态重现,该异常就可以被归类到同步异常。常见状况有:
异步异常又能在被细分为两种状态: 精确的异步异常
以及不精确的异步异常
。
由於简体文字书籍对於精确/非精确异步异常的介绍相当模糊。因此,笔者直接整理下表方便大家厘清:
异常 | 描述 |
---|---|
精确的异步异常 | 外部中断 |
不精确的异步异常 | 读写内存时出错 |
!读写内存时出错说明:
常见在当处理器将资料写进快取後,等到该资料在快取中被替换(存回外部记忆体)时才发现错误,此时处理器已经又处理了上百万条指令。在这个状况中,我们很难找出罪魁祸首(出错的指令)是谁。因此,该状况被归类在不精确的异步异常
。
当异常发生时,处理器会停止手边的工作,再将 Program counter 的位址指向 mtvec 所指的位址并开始执行。这样的行为就好像是主动跳入陷阱一样,因此,在 RISC-V 的架构中将这个动作定义为 Trap。
补充: mtvec 是一个可读可写的暂存器,开发者可以透过软件修改其值。
- 当 MODE 为 0 时,转跳至 BASE 值表示的位址。
- 当 MODE 为 1 时(同步异常),会将 PC 的位址指向:
BASE + 4 X CAUSE
!这边的 CAUSE 值等同於 mcause register 所表示的值。
在 RISC-V 架构中有定义:
当进入异常时硬体会更新 mcause register 的值,开发者可以透过软件去读取 mcause 以分析造成异常的具体原因。
mcause 的最高位 (MSB) 用来记录是否为 interrupt,其余 31 位都用来表示异常编号。
mepc register 被用来存放跳入 Trap 前 PC 指向的指令位址,待异常处理结束後,PC 会将 mepc 存放的指令位址读入并开始执行。
需要注意的是,mepc 在中断和异常发生时会有不同的行为:
关於 ecall 以及 ebreak,请参考 RV32I 指令集。
补充: mepc register 也是一个可读可写的暂存器。因此,我们同样可以利用软件修改它的值。
mtval register 又称为 mbadaddr register,在 RISC-V 的规格书有定义:
当进入异常时,硬体会自动更新 mtval register 的值,以纪录造成异常发生的暂存器访问地址或是指令编码。
从上面的叙述就可以知道,mtval 会有两种写入的 Case,分别是:
暂存器访问造成的异常
包括如硬件断点、存取指令、储存器读写时造成的异常。这时,硬体会将储存器访问的地址记录到 mtval 当中。
非法指令造成的异常
除了 RVC 指令集外,其他合法 RISC-V 指令集的 OPCODE 末两码都是 11。
在这个情况中,硬体会将非法的指令编码记录到 mtval 当中。
mstatus 纪载了大量的资料,根据 RISC-V 架构的规定:
当进入异常时,硬体会自动更新 mstatus 的某些域值。
简单来说,就是决定处理器要不要受理中断请求。
MPIE
MPIE 用来存放异常发生前 MIE 域的值。当异常结束後就可以利用 MPIE 还原 MIE 的值。
MPP
纪录异常发生前的工作模式,在 RISC-V 规格书中,有以下几种模式:
Level | Encoding | Name | Abbreviation | |
---|---|---|---|---|
0 | 00 | User/Application | U | |
1 | 01 | Supervisor | S | |
2 | 10 | Reserved | - | |
3 | 11 | Machine | M |
当异常处理完成後,需要从异常服务退出。在 RISC-V 架构中定义了一组用於退出异常的指令 (Trap-Return Instruction),包括:
分别对应了 Machine Mode, Supervisor Mode 以及 User Mode。
使用 MRET 指令退出异常後,硬体会做两件事情:
从 mepc 指向的指令位址开始执行
更新 mstatus register
同样以 Machine Mode 为例:
需要注意的是: MIE 域仅是反映中断是否接受处理,其控制权仍取决於 MIE register 中的 MEIE 域。
在先前导读过的 rv32emu-next 专案中,也包含了异常的处理,如果有兴趣可以在自行阅读原始码。经过上面的介绍後,就能轻松的看懂这个 RISC-V 的 Emulator 是如何运作的了(吗?)
>>: 【7】Dataset 的三个API : Shuffle Batch Repeat 如果使用顺序不同会产生的影响
上次说到了在特徵子集 Q 之下 被特徵子集 P 细分的程度 如果是 1 则表示 P 可以完全分类 Q...
tags: OC 30 day 获取网路数据的两种方式: 方式一:NSData 方法: 获取JSON...
快速排序法(Quick Sort)又称分割交换排序法,是目前公认效率极佳的演算法,使用了分治法(Di...
上篇介绍了PHP的阵列宣告、印出方式,这篇想和大家介绍PHP常用的阵列函数有哪些 1.in_arra...
SharedPreference常被使用於资料储存,很适合做一些简单的资料存取 先配置按钮-因为是要...