# 中断与异常


## 相关寄存器

除了32个通用寄存器之外，RISCV架构还有大量的 控制状态寄存器 Control and Status Registers(CSRs)。其中有几个重要的寄存器和中断机制有关。

+ stvec：中断向量表地址寄存器 
+ sepc(supervisor exception program counter)，它会记录触发中断的那条指令的地址；
+ scause，它会记录中断发生的原因，还会记录该中断是不是一个外部中断；
+ stval，它会记录一些中断处理所需要的辅助信息，比如指令获取(instruction fetch)、访存、缺页异常，它会把发生问题的目标地址或者出错的指令记录下来，这样我们在中断处理程序中就知道处理目标了。

## 中断向量表

RISCV有两种中断异常实现方式，一种是给一个中断向量表基址，CPU会根据当前中断产生的原因，偏移对应的偏移量，选择对应的中断处理函数。另一种是给定唯一的中断处理程序的地址，无论什么原因引发的中断都调用这个函数。为了开发的方便，我们使用了第二种方法。我们写了一个trap函数用于处理中断，为了保存一些寄存器的值，我们写了trapEntry.s，这个汇编文件的内容是将所有的寄存器的值保存，跳转到trap函数，然后再恢复刚刚保存的寄存器值。

## 原因判断

我们使用了一个函数处理所有的中断，那就要在trap函数中判断中断产生的原因,我们只需要读取scause寄存器的中断类型，该寄存器的值对应的原因我们可以再riscv标准里找到。

![](https://cdn.jsdelivr.net/gh/li1553770945/images/scause2.jpg)

## 处理方法

对于不同的中断异常，我们目前使用如下处理方法：

+ 系统调用：调用系统调用处理函数
+ 缺页异常：调用缺页处理函数
+ 时钟中断：交给调度器处理
+ 其他：我们抛出异常，打印出中断原因代码，当前pc，epc等，然后直接进入KernelMonitor

## KernelMonitor

我们设计中kernelmonitor是内核发生panic之后进入的地方，它可以做一些简单的处理，当然我们目前只写了一种处理方式——输入shutdown,kernelmonitor会关机。







-----------------

By：PeaceSheep

2022.06.05