MENU

Riscv 异常处理

August 26, 2022 • 阅读: 1372 • 笔记&折腾

简单描述 RISCV 处理器在发生异常时的处理过程。

异常与中断的关系。

中断和异常都为异常,分为:

同步异常:IO,illegal, page fault,miss_aligh 等来自处理器内部的发生的异常。
异步异常(中断):鼠标,键盘,Timer 等外部事件。

[tips category="explain"] 本文以下声明的异常如无特别注明,皆指同步异常。 [/tips]

riscv 三种 特权模式

Riscv 有三种特权模式,分别是 U-mode、S-mode、M-mode

U-mode : 用户模式。通常情况下用户编写的程序都在该模式下执行。
S-mode : 内核模式。 通常情况下,操作系统在此模式下执行。可以访问一些 s 模式下的寄存器。
M-mode:机器模式。最高权限,所有的 RISCV 处理器都应该实现的模式。几乎能够执行所有特权指令和读写所有的特权寄存器。通常情况下处理器发生中断和异常时在此模式下进行处理。

对于某些处理器, S-mode 可以不用实现。

当异常发生时模式的转换

当异常发生时,处理器的模式不会向更低等级的模式转换,只会向更高或者同级的模式转换。

当U模式下发生异常时,可以转换到 U/S/M 模式;
当S模式下发生异常时,可以转换到 S/M 模式;
当M模式下发生异常时,只能转换到 M 模式;

并且异常发生时,与异常相关的寄存器值也会随之发生改变。

与异常有关的寄存器

仅举例 M-mode 的 csr 寄存器,S -mode 在此忽略。

mtvec

Machine Trap-Vector Base-Address Register (mtvec)
机器模式异常入口基地址寄存器。
当程序发生异常时,处理器将会切换到 M-mode 并跳转到 mtvec 寄存器内的地址开始执行,并处理异常。

mcause

Machine Cause Register (mcause)
机器模式下异常原因寄存器。
当异常发生时,mcause 寄存器的对应位将会被置1,用于表明异常发生的原因。一些常见的异常类型如下图:

mcause-coding

例如,当异常发生后 mcause 寄存器的值为 2 时,表明这是因为程序中遇到了非法的指令导致的异常。

mepc

Machine Exception Program Counter (mepc)
机器模式异常程序计数器
记录了当异常发生的虚拟地址。
可用于异常处理结束后处理器返回用户程序继续执行。(mret 指令,回到 mepc 中的指令继续执行,并从机器模式返回异常发生时的处理器模式)

以 ebreak 指令为例。

ebreak 执行时,将会触发 BREAKPOINT 的异常。通常情况下,该异常与 debug 相关。在此处只用于举例异常发生过程。

Main:
….
0x80000100   addi x1, x1, 1
0x80000104   ebreak
0x80000108   addi x2, x2, 2
….

当处理器执行到 ebreak 这条指令时,将会触发异常,mepc 寄存器被写入 0x80000104 的值,即 ebreak 指令的地址。

通常情况下,最简单的异常处理是跳过异常发生的指令,只需要在异常处理中将 mepc +=4,然后再 mret ,处理器就会跳过 (0x80000104 ebreak)指令,执行(0x80000108 addi x2, x2, 2)指令。

mtval

Machine Trap Value Register (mtval)
机器模式异常值寄存器。
当异常发生时,该 寄存器将被写入异常的信息,用于辅助处理器更好地处理该异常。

mstatus

Machine Status Register (mstatus)
机器模式状态寄存器
该寄存器记录了 m 模式下的状态。
其中,MPP 记录了进入异常处理之前的模式,也是 mret 返回后要切换的模式,可以通过修改该位域改变接下来程序执行的模式。
FS域 是浮点状态和开关。
MIE为中断使能位。

当异常发生时

当异常发生时,处理器会做如下处理(用户模式下):

- 处理器停止执行当前的程序流,转而跳转 mtvec 寄存器定义的 PC 地址开始执行;
- 处理器切换到机器模式;
- 将异常原因记录到 mcause 寄存器中;
- 将发生异常的指令地址写入 mepc 寄存器中;
- 将异常发生时的存储器访问地址或者指令编码保存到 mtval 寄存器中;
- 更新 mstatus 状态寄存器;

异常处理

当异常发生后,处理器会做如下处理(机器模式下):

- 当处理器进入异常后,就会跳到 mtvec 寄存器定义的 PC 地址执行新的程序。
- 使用 mscratch 保存现场上下文。
- 使用 mcause 寄存器用于判断是那种异常类型。(其中包含了 12 种中断以及 16 种异常。)
- MEPC += 4。使返回时跳过发生异常的指令。
- 使用 mscratch 恢复现场上下文。
- mret。

异常处理后

当处理器处理完异常之后,软件上要执行 MRET 指令,然后处理器会做如下处理(机器模式下):

- 处理器停止执行当前的程序流,转而跳转 mepc 寄存器保存的 PC 地址开始执行。
- 处理器模式切换到 MSTATUS 的 MPP 位域中写入的模式。
- 更新 mstatus 状态寄存器。

Leave a Comment