- ECALL
ecall 指令以前叫做 scall,用于执行环境的变更,它会根据当前所处模式触发不同的执行环境切换异常, 用来执行需要更高权限才能执行的功能;
简单来说,ecall 指令将权限提升到内核模式并将程序跳转到指定的地址。操作系统内核和应用程序其实都是相同格式的文件,最关键的区别就是程序执行的特权级别不同。所以 Syscall 的本质其实就是提升特权权限到内核模式,并跳转到操作系统指定的用于处理 Syscall 的代码地址。
Syscall 场景下是在 U-mode(用户模式)下执行 ecall 指令,主要会触发如下变更:
- 处理器特权级别由 User-mode(用户模式)提升为 Supervisor-mode(内核模式)
- 当前指令地址保存到
sepc
特权寄存器 - 设置
scause
特权寄存器 - 跳转到
stvec
特权寄存器指向的指令地址
-
EBREAK
环境操作指令,会导致自陷(self trap),PC会跳转到mtvec寄存器里的地址处。
用来中断程序的运作,让系统可以把使用权转交给 Debugger;
其实 Debugger 的 Break Point 就是用这个指令实现的,只是偷偷把指定位置的指令换掉了不跟使用者讲而已;
在RISC-V中,MRET
、SRET
和URET
分别用于从Machine、Supervisor和User模式中的trap返回,返回之后的特权等级即分别为MPP、SPP和UPP中记录的值;
- MRET
当异常程序处理完成后,最终要从异常服务程序中退出,并返回主程序。riscv中定义了一组退出指令mret,sret,和uret,对于机器模式,对应mret。
注意高等级的特权模式可以执行低等级的xRET指令,即M模式可以执行MRET,SRET和URET;
在机器模式下退出异常时候,软件必须使用mret。
riscv架构规定,处理器执行完mret指令后,硬件行为如下:
- 停止执行当前程序流,转而从csr寄存器mepc定义的pc地址开始执行。
- 硬件更新csr寄存器机器模式状态寄存器mstatus。mstatus寄存器MIE域被更新为当前MPIE的值。MPIE 域的值则更新为1。
- SRET
S模式下使用sret指令返回原先指令的下一条指令;
在执行sret之前,需要准备好sepc,sstatus寄存器,这一部分寄存器应当在恢复上下文时完成,需要特别关注sstatus的SPIE位以及SPP位,这为初始化PCB时的设计给出了提示。具体实现可通过阅读手册中对于sret指令的说明得到一些提示。
- URET
指令 URET 用于从用户态陷入状态中返回。URET 将 UPIE 复制回 UIE,然后将 UPIE 置位,最后将 uepc
拷贝至 pc
。
在 UPIE/UIE 栈弹出后置位 UPIE 是为了启用中断,以及帮助发现代码中的错误。
- WFI
WFI (Wait For Interrupt)指令是 RISC-V 架构定义的专门用于休眠的指令。
当处理器执行到 WFI 指令之后,将会停止执行当前的指令流,进入一种空闲状态。
这种空闲状态可以被称为“休眠”状态,直到处理器接收到中断(中断局部开关必须被打开,由 mie 寄存器控制),处理器便被唤醒 。
处理器被唤醒后,如果中断被全局打开 (mstatus 寄存器的MIE域控制),则进入中断异常服务程序开始执行;如果中断被全局关闭,则继续顺序执行之前停止的指令流。
wfi 通知处理器目前没有任何有用的工作,所有它应该进入低功耗模式, 直到任何使能有效的中断等待处理,即mie&mip ≠ 0。RISC-V 处理器以多种方式实现 该指令,包括到中断待处理之前都停止时钟。有的时候只把这条指令当作 nop 来执 行。因此,wfi 通常在循环内使用。
补充说明:wfi 不论全局中断使能有效与否都有用 如果在全局中断使能有效(mstatus.MIE = 1)时执行 wfi,然后有一个使能有效的中断等 待执行,则处理器跳转到异常处理程序。另一方面,如果在全局禁用中断时执行 wfi,接着 一个使能有效的中断等待执行,那么处理器继续执行 wfi 之后的代码。这些代码通常会检 查控制状态寄存器 mip,以决定下一步该做什么。与跳转到异常处理程序相比,这个策略可 以减少中断延迟,因为不需要保存和恢复整数寄存器;
- SFENCE.VMA
处理器用地址转换缓存(通常称为 TLB,全称为 Translation Lookaside Buffer)来提高虚拟地址与物理地址转换性能。
为了 降低 TLB 缓存本身的开销,大多数处理器不会让它时刻与页表保持一致。这意味着如果操作系统修改了页表,那么这个缓存会变得陈旧而不可用。
RISC-V 的 S 模式添加了另一条 sfence.vma 指令来解决这个问题。这条指令会通知处理器,软件可能已经修改了页表,于是处理器可以相应地刷新 TLB 缓存。
它需要两个可选的参数,这样可以缩小缓存刷新的范围。一个位于 rs1,它指示了页表哪个虚址对应的转换被修改了;另一个位于 rs2,它给出了被修改页表的进程的地址空间标识符(ASID)。如果两者都是 x0,便会刷新整个转换缓存。
补充说明: 多处理器中的地址转换缓存一致性 sfence.vma 仅影响执行当前指令的 hart 的地址转换硬件。当 hart 更改了另一个 hart 正在使 用的页表时,前一个 hart 必须用处理器间中断来通知后一个 hart,他应该执行 sfence.vma 指令。这个过程通常被称为 TLB 击落;
- FENCEI
- FENCE