RISC-V 特权指令结构


机器模式

机器模式(缩写为 M 模式,M-mode)是 RISC-V 中 hart(hardware thread,硬件线 程)可以执行的最高权限模式。在 M 模式下运行的 hart 对内存,I/O 和一些对于启动和配 置系统来说必要的底层功能有着完全的使用权。因此它是唯一所有标准 RISC-V 处理器都 必须实现的权限模式。实际上简单的 RISC-V 微控制器仅支持 M 模式。

hart 是 硬 件 线 程 (hardware thread)的缩略 形式。 我们用该术语将 它们与大多数程序员熟 悉的软件线程区分开 来。软件线程在 harts 上 进行分时复用。 大多数 处理器核都只有一个 hart。
CSR:控制状态寄存器

机器模式最重要的特性是拦截和处理异常(不寻常的运行时事件)的能力。
RISC-V 将 异常分为两类。

  • 同步异常:这类异常在指令执行期间产生
    • 如访问了无效的存储器地址
    • 执行了具有无效操作码的指令
  • 中断:它是与指令流异步的外部事件,比如键盘输入。

为了方便表述与区分,本文接下来的表述按照如下规则

  • 异常:异常分两类,其中的同步异常
  • 中断:异常分两类,其中的中断

RISC-V 异常和中断的原因
image

中断时mcause的最高有效位被设置成1,异常时置为0,剩下的位标识了中断或者异常的具体原因。

中断类型(来源)

  1. 软件中断:软件中断通过向内存映射寄存器中存数来触发,并通常用于由一个 hart 中断另一个 hart(在其他架构中称为处理器间中断机制)。
  2. 时钟中断:当 hart 的时间比较器(一个名为 mtimecmp 的内存映射寄存器)大于实时计数器mtime 时,会触发时钟中断。
  3. 外部中断: 有平台级中断控制器(大多数外部设备连接到这个中断控制器)引发。

机器模式下的异常、中断处理
八个控制状态寄存器(CSR)是机器模式下异常、中断处理的必要部分

  • mtvec(Machine Trap Vector)它保存发生异常/中断时处理器需要跳转到的地址。
    • RISC-V 还支持向量中断,其中处理器跳转到各类异常/中断各自对应的地址,而不是一个统一的入口点。这种寻址消除 了读取和解码 mcause 的需要,加快了中断处理速度。 将 mtval [0]设 置为 1 可启用此功能; 然后根据异常/中断原因 xPC 设置为(mtval-1 + 4x ), 而 不 是 通 常 的 mtvec
  • mepc(Machine Exception PC)它指向发生异常/中断的指令。
  • mcause(Machine Exception Cause)它指示发生异常/中断的原因(类型)。
  • mie(Machine Interrupt Enable)它指出处理器当前屏蔽了哪些中断。
  • mip(Machine Interrupt Pending)它列出目前正准备处理的中断(已经到来的中断)。
  • mtval(Machine Trap Value)它保存了陷入(trap)的附加信息:page fault中出错的地址、发生非法指令例外的指令本身,对于其他异常,它的值为 0。
  • mscratch(Machine Scratch)它暂时存放一个字大小的数据。
  • mstatus(Machine Status)它保存全局中断使能,以及许多其他的状态

mstatus
image

mstatus.MIE 置 1 时才会产生中断。
mstatus.PMIE 它在异常/中断发生后保存 MIE 的旧值

mie
每个中断在控制状态寄存器 mie 中都有自己的使能位。这些位在 mie 中的位置对应于图[[RISC-V 异常和中断的原因.png]]。例如,mie[7]=1 对应于 M 模式中的时钟中断打开。
注意:中断可以被屏蔽,但是异常不能被屏蔽

mip
mie 有着相同的布局,并且指示当前待处理的中断。

三者相互配合

  • mstatus.MIE=1 打开接收中断的总开关 = 1
  • mie[7] = 1 接收时钟中断
  • mip[7] = 1 当前待处理的中断刚好有时钟中断
    则可以处理机器的时钟中断。mstatus[MIE] & mie[7] & mip[7] ≠ 0

当一个hart 发生异常、中断时

硬件会自动经历如下的状态转换:

  • 异常指令的PC被保存在mepc中,PC被设置为mtvec
    • 对于同步异常:pepc指向导致异常的指令。
    • 对于中断:它指向中断处理后应该恢复执行的位置。(这个由软件设置)
  • 根据异常/中断源来设置mcause寄存器。
  • mtval设置为出错的地址或者其他适用于特定异常的信息。
  • mstatus中的MIE位置置零以禁用中断,并把先前的MIE值保留到MPIE中。
  • 发生异常之前的权限模式保留在mstatusMPP域中,再把权限模式更改为M。(如果处理器仅实现 M 模式,则有效地跳过这个步骤)。

处理中

为避免覆盖整数寄存器中的内容,异常/中断处理程序先在最开始用 mscratch 和整数寄存器(例如 a0)中的值交换。通常,软件会让 mscratch 包含指向附加临时内存空间的指针,处理程序用该指针来保存其主体中将会用到的整数寄存器。在主体执行之 后,中断程序会恢复它保存到内存中的寄存器,然后再次使用 mscratcha0 交换, 将两个寄存器恢复到它们在发生异常之前的值。

返回

  • 使用 mret 指令返回,mretPC设置为mepc
  • mstatusMPIE 域复制到 MIE 来恢复之前的中断使能设置
  • 并将权限模式设置为 mstatusMPP 域中的值

委托

默认情况下,发生所有异常(不论在什么权限模式下)的时候,控制权都会被移交到 M 模式的异常处理程序。但是 Unix 系统中的大多数例外都应该进行 S 模式下的系统调 用。M 模式的异常处理程序可以将异常重新导向 S 模式,但这些额外的操作会减慢大多数 异常的处理速度。因此,RISC-V 提供了一种异常委托机制。通过该机制可以选择性地将中断和同步异常交给 S 模式处理,而完全绕过 M 模式。

委托中断
mideleg(Machine Interrupt Delegation,机器中断委托)CSR控制将哪些中断委托给 S模式

mipmie 一样,mideleg 中的每个位对应于”异常/中断原因图“相同的中断。例如, mideleg[5]对应于 S 模式的时钟中断,如果把它置位,S 模式的时钟中断将会移交 S 模式 的异常处理程序,而不是 M 模式的异常处理程序。

屏蔽委托的中断
委托给 S 模式的任何中断都可以被 S 模式的sieCSR屏蔽。
sie(Supervisor Interrupt Enable,监管者中断使能)和 sip(Supervisor Interrupt Pending,监管者中断待处理)CSR 是 S 模式的控制状态寄存器,他们是 miemip 的子集。它们有着和 M 模式下相同的布局,但在 siesip 中只有与由 mideleg 委托的中断对应的位才能读写。那些没有被委派 的中断对应的位始终为零。

委托异常
M 模式还可以通过 medeleg CSR 将同步异常委托给 S 模式
medeleg[15]便会把 store page fault(store 过程中出现的缺页)委托给 S 模式。

基于页面的虚拟内存
S 模式提供了一种传统的虚拟内存系统,它将内存划分为固定大小的页来进行地址转 换和对内存内容的保护。启用分页的时候,大多数地址(包括 load 和 store 的有效地址和 PC 中的地址)都是虚拟地址。要访问物理内存,它们必须被转换为真正的物理地址,这通 过遍历一种称为页表的多叉树实现。 RISC-V 的分页方案以 SvX 的模式命名,其中 X 是以位为单位的虚拟地址的长度。RV64 支持多种分页方案,但我们只介绍最受欢迎的一种,Sv39。
image

标志位 说明
V 决定了该页表项的其余部分是否有效(V = 1 时有效) 。若 V = 0,则任何遍历到此页表项的虚址转换操作都会导致页错误。
R、W 和 X 位分别表示此页是否可以读取、写入和执行。如果这三个位都是 0,V=1 那么这个页表项是指向下一级页表的指针,否则它是页表树的一个叶节点。
U 位表示该页是否是用户页面。若 U = 0,则 U 模式不能访问此页面,但 S 模式 可以。若 U = 1,则 U 模式下能访问这个页面 。
G 表示这个映射是否对所有虚址空间有效,硬件可以用这个信息来提高地址转换的性能。这一位通常只用于属于操作系统的页面
A 位表示自从上次 A 位被清除以来,该页面是否被访问过。
D 位表示自从上次清除 D 位以来页面是否被弄脏(例如被写入)。
RSW 域留给操作系统使用,它会被硬件忽略。
PNN PPN 域包含物理页号,这是物理地址的一部分。若这个页表项是一个叶节点,那 么 PPN 是转换后物理地址的一部分。否则 PPN 给出下一节页表的地址。

操作系统依赖于 A 位和 D 位来决定将哪些页面 交换到辅存。定期清除 A 位有助于 OS 判断哪 些页面是最近最少使用 的。 置上 D 位表示换 出该页面的成本更高, 因为它必须写回辅存。

一个叫 satp(Supervisor Address Translation and Protection,监管者地址转换和保护) 的 S 模式控制状态寄存器控制了分页系统。satp 有三个域。Mode域可以开启分页并选择页表级数。ASID(Address Space Identifier, 地址空间标识符)域是可选的,它可以用来降低上下文切换的开销。最后,PPN 字段保存 了根页表的物理地址,它以 4 KiB 的页面大小为单位。通常 M 模式的程序在第一次进入 S 模式之前会把零写入 satp 以禁用分页,然后 S 模式的程序在初始化页表以后会再次进行 satp 寄存器的写操
image

清除TLB缓存
所有现代的处理器都用地 址转换缓存(通常称为 TLB,全称为 Translation Lookaside Buffer)来减少这种开销。为了 降低这个缓存本身的开销,大多数处理器不会让它时刻与页表保持一致。这意味着如果操 作系统修改了页表,那么这个缓存会变得陈旧而不可用。S 模式添加了另一条指令来解决 这个问题。这条sfence.vma 会通知处理器,软件可能已经修改了页表,于是处理器可以 相应地刷新转换缓存。它需要两个可选的参数,这样可以缩小缓存刷新的范围。一个位于 rs1,它指示了页表哪个虚址对应的转换被修改了;另一个位于 rs2,它给出了被修改页表 的进程的地址空间标识符(ASID)。如果两者都是 x0,便会刷新整个转换缓存。

特权指令

  1. mret: machine-mode trap return
  2. sret: supervisor-mode trap return
  3. sfence.vma: supervisor-mode fence.virtual memory addreee
  4. wfi: wait for interrupt
  5. csrr,读取一个 CSR 的值到通用寄存器。如:csrr t0, mstatus,读取 mstatus 的值到 t0 中。
  6. csrw,把一个通用寄存器中的值写入 CSR 中。如:csrw mstatus, t0,将 t0 的值写入 mstatus
  7. csrs,把 CSR 中指定的 bit 置 1。如:csrsi mstatus, (1 << 2),将 mstatus 的右起第 3 位置 1。
  8. csrc,把 CSR 中指定的 bit 置 0。如:csrci mstatus, (1 << 2),将 mstatus 的右起第 3 位置 0。
  9. csrrw,读取一个 CSR 的值到通用寄存器,然后把另一个值写入该 CSR。如:csrrw t0, mstatus, t0,将 mstatus 的值与 t0 的值交换。
  10. csrrs,读取一个 CSR 的值到通用寄存器,然后把该 CSR 中指定的 bit 置 1。
  11. csrrc,读取一个 CSR 的值到通用寄存器,然后把该 CSR 中指定的 bit 置 0。