RISC V::中断与异常处理 -- 中断篇

你可曾想过现今的电脑是如何同时运行多个应用程序?
又或是单核心电脑如何做到多工?
为衔接之後的议题,我们需要先认识 RISC-V CPU 中的中断机制。

复习: CSR 暂存器

CSR 暂存器在昨天的文章内也有提到,放置在此篇仅是方便读者查阅。

RISC-V 架构定义了许多暂存器,部分暂存器被定义为控制和状态暂存器,也就是标题所指出的 CSR (Control and status registers),它被用於配置或是纪录处理器的运作状况。
笔者先将 RISC-V 架构中 (Machine Mode)与中断、异常有关的暂存器都列出来,方便待会儿进行解说:

  • CSR
    • mtvec
      当进入异常时, PC (Program counter) 会进入 mtvec 所指向的地址并继续运行。
    • mcause
      纪载异常的原因
    • mtval
      纪载异常讯息
    • mepc
      进入异常前 PC 所指向的地址。若异常处理完毕, Program counter 可以读取该位址并继续执行。
    • mstatus
      进入异常时,硬体会更新 mstatus 寄存器的某些域值。
    • mie
      决定中断是否被处理。
    • mip
      反映不同类型中断的等待状态。
  • Memory Address Mapped
    • mtime
      纪录计时器的值。
    • mtimecmp
      储存计时器的比较值。
    • msip
      产生或结束软件中断。
    • PLIC

中断

现今的作业系统都具备多工处理的能力,不管你的电脑是单核心、双核心甚至是以上,处理器都必须设计有中断的能力,让作业系统能指派不同的程序给处理器运行,达成所谓的多工

关於作业系统如何做到多工,笔者会在之後的作业系统系列提到。

在 RISC-V ISA 的定义中,中断主要分成以下四种,分别是:

  • External Interrupt
  • Timer Interrupt
  • Software Interrupt
  • Dubug Interrupt

RISC-V 其定义了多种模式,如: Machine ModeUser ModeSupervisor Mode 等等,由於笔者所阅读的技术书都是以 Machine Mode 去做介绍。因此,本篇章同样也会以 Machine Mode 为主。

External Interrupt

External Interrupt 是指源自处理器外部造成的中断,像是 UART、GPIO 等外部设备产生的中断。
通常,因为有多个外部设备,在处理器外面会有一个控制器先将外部的中断请求做预处理,等到处理完成後,若处理器没有关闭 Interrupt 的功能,处理器才会真正执行中断。这个外部控制器叫做: Programmable Interrupt Controller。此外,RISC-V 也定义了 Platform Level Interrupt,细节会在文章的後面补充。

补充:
RISC-V 架构对中断的定义保留了很大的空间,以 mcause register 为例,在 Interrupt 的定义上,Exception Code >= 12 都是被保留的,方便进行扩充。

mcause

Timer Interrupt

RISC-V 架构有规定,系统平台必须要有一个计时器。并且,该计时器必须具备两个 64-bit 的暂存器 mtime 以及 mtimecmp,前者用於纪录当前计数器的值,後者则是 mtime 的比较值,当 value of mtime > value of mtimecmp 时便会产生中断。

补充:
我们可以在 CSR Register 的介绍中看到,mtime 以及 mtimecmp 并没有被归类在 CSR 暂存器中而是被放在 Memory address mapped 类,这是因为 RISC-V 并没有定义这两个暂存器的 Memory mapped address,具体位址交给 SoC 的系统制造商决定。

Software Interrupt

软件触发的中断。

  • 软件中断是否被系统受理由 MIE Register 的 MSIE 域控制(1 为 Enable,0 为 Disable)。
  • 若硬体执行绪将 MSIP 写入 1 会触发 Machine Mode 的软件中断,当中断处理完毕後,必须再将 MSIP 归 0。

Debug Interrupt

该中断用於 Debugger 的实作。

中断屏蔽

异常不能被屏蔽,但是中断可以。

RISC-V 定义了 MIE Register,让它可以控制中断的屏蔽。

MIE

以 MEIE 为例,

  • 字首 M 代表 Machine Mode,字首若是 US 则代表 User ModeSupervisor Mode
  • 第二个字母 E 代表 External Interrupt,字母若是 TS 则代表 Timer Interrupt 以及 Software Interrupt
  • 第三个字母 I 代表 Interrupt
  • 第四个字母 E 代表 Enable

中断等待

RISC-V 定义了 MIP Register,可以用来查询中断的等待状态。

MIP

以 MEIP 为例,

  • 字首 M 代表 Machine Mode,字首若是 US 则代表 User ModeSupervisor Mode
  • 第二个字母 E 代表 External Interrupt,字母若是 TS 则代表 Timer Interrupt 以及 Software Interrupt
  • 第三个字母 I 代表 Interrupt
  • 第四个字母 P 代表 Pending

!补充->中断的优先级:
External > Software > Timer

巢状中断

中断嵌套的概念有点像是,进入中断 A 时又产生了中断 B,为了帮助读者理解,笔者在这边附上作业系统层的 Nested Interrupt 概念图:

不过,RISC-V 处理器在预设情况下并不支援中断嵌套,原因如下:

  • 进入异常时,mstatus 的 MIE 域会被更新为 0,代表中断被关闭,处理器直到中断退出前不会处理新的中断请求。

当然,如果真的有中断嵌套的需求,开发者也可以利用软件做到:

  • 将 msatus 的 MIE 域设为 1。
  • 考虑中断的优先级,将 MIE Register 相对应的域做设定。

CSR 指令

RISC-V 定义了一系列的指令让开发者能够对 CSR 暂存器进行操作:

  • csrs
    把 CSR 中指定的 bit 设为 1。
csrsi mstatus, (1 << 2)

上面的指令会将 mstatus 从 LSB 数起的第三个位置设成 1。

  • csrc
    把 CSR 中指定的 bit 设为 0。
csrsi mstatus, (1 << 2)

上面的指令会将 mstatus 从 LSB 数起的第三个位置设成 0。

  • csrr[c|s]
    将 CSR 的值读入通用暂存器。
csrr to, mscratch
  • csrw
    将通用暂存器的值写入 CSR。
csrw	mepc, a0
  • csrrw[i]
    将 csr 的值写入 rd 後,且将 rs1 的值写入 csr。
csrrw rd, csr, rs1/imm

换个角度思考:

csrrw t6, mscratch, t6

上面的操作可以让 t6 与 mscratch 的值互换。

这几个 CSR 指令需要开发者特别留意,之後在阅读甚至是撰写作业系统原始码时,在处理各类的 Interrupt 都必须使用这些操作。

总结

本篇与 RISC-V::中断与异常处理 – 异常篇完整的介绍了 RISC-V 的中断与异常处理,考虑到笔者的体力篇幅问题,PLIC 会用额外一篇文章做介绍。

Reference


<<:  8 稍微重构一下下,一点就好

>>:  Day 7 在 Linode 上购置一台 VPS 主机并安装 Docker

Day 13 Mailhog - 模拟 SMTP 邮件服务的开发利器

由於 Mautic 是一个自动化行销利器,那麽寄发电子邮件便是一个必须的功能。不过在开发时一再的利用...

DAY27 把这个Google maps 放在 APP 上(三)

写完第26天之後我思考了很久(大概一天),因为 Google maps 的功能也介绍的差不多了,但是...

Day 22: Recurrent Neural Network — 循环精神网路初探(上)

Recurrent Neural Network 循环精神网路 RNN是一种专门设计用以解决时间序列...

[Day 21] 资料关联

资料关联 一对一(One to One) 一对多(One to Many) 多对多(Many to ...

[DAY 05] 盐水豆签羹

盐水豆签羹 地点:台南市盐水区朝琴路19号 时间:14:00~19:00 这一家的照片忘了拍 但是还...