机器模式(machine-mode)
机器模式(缩写为 M 模式,M-mode)是 RISC-V 中 hart(hardware thread,硬件线程)可以执行的最高权限模式。在 M 模式下运行的 hart 对内存,I/O 和一些对于启动和配置系统来说必要的底层功能有着完全的使用权。
机器模式可以拦截并处理异常,异常被分为两类。一类是同步异常,指执行了无效操作码的指令,或者访问了无效的内存地址。另一类即是中断(软件中断硬件中断)。
机器模式下的异常处理
八个控制状态寄存器(CSR)是机器模式下异常处理的必要部分:
mtvec(Machine Trap Vector)
它保存发生异常时处理器需要跳转到的地址。mepc(Machine Exception PC)
它指向发生异常的指令。mcause(Machine Exception Cause)
它指示发生异常的种类。mie(Machine Interrupt Enable)
它指出目前哪些中断可以被处理。mip(Machine Interrupt Pending)
保存目前待处理的中断。mtval(Machine Trap Value)
它保存了陷入(trap)的附加信息:地址例外中出错的地址、发生非法指令例外的指令本身,对于其他异常,它的值为 0。mscratch(Machine Scratch)
它暂时存放一个字大小的数据。mstatus(Machine Status)
它保存全局中断开关,以及许多其他的状态,其中包括当前以哪种模式运行
处理器在 M 模式下运行时,只有在全局中断开关 mstatus.MIE=1
时才会产生中断.此外,每种类型中断在CSRmie
中都有自己的开关。举个例子,xv6在最开始运行时,会在start.c中完成对时钟中断器的初始化。
1 | /** |
如果timerinit()
初始化完成后,发生了时钟中断,那么此时寄存器mip
的MTIE
会置为1,那么此时就会发生中断。
中断什么时候发生?当CPU执行一条指令前,他会去检查一下对应的中断寄存器,对应时钟中断,当检查到mip.MTIE = 1,即此时有一条时钟中断,且对应的mstatus.mie = 1 && mie.MTIE = 1,那么此时就会发生时钟中断。
在机器模式下,当CPU发生发生异常时,硬件会自动做出以下动作:
- 发生异常指令的PC保存到CSR
mepc
中,并将PC设置为CSRmtvec
的值 - 根据异常来源设置CSR
mcause
,将mtval设置为设置为出错的地址或者其他特定的异常信息。 - 将
mstatus.MIE
置为0,禁用全局中断,并将mstatus.MIE
的值保存到mstatus.MPIE
中 - 将异常前的运行模式保存到
mstatus.MPP
中,并将运行模式切换到M模式。
此时跳转到mtvec保存的地址中去执行,当返回时,需要依赖mret
指令,执行mret执行将会执行上述步骤的逆操作,返回到原先发生异常的状态。
用户模式 (user-mode)
对于简单的嵌入式系统来说,机器模式就够了,而对于操作系统来说,上面运行这很多用户程序,需要保证用户程序间的内存相互隔离,以保证安全性,同时要禁止用户程序使用一些机器特权指令,例如mret等等。防止用户程序越界。
用户代码必须被限制只能访问自己那部分内存。实现了 M 和 U 模式的处理器具有一个叫做物理内存保护(PMP,Physical Memory Protection)的功能,允许 M 模式指定 U 模式可以访问的内存地址。PMP 包括几个地址寄存器(通常为 8 到 16 个)和相应的配置寄存器。这些配置寄存器可以授予或拒绝读、写和执行权限。当处于 U 模式的处理器尝试取指或执行 load 或 store 操作时,将地址和所有的 PMP 地址寄存器比较。如果地址大于等于 PMP 地址 i,但小于 PMP 地址 i+1,则 PMP i+1 的配置寄存器决定该访问是否可以继续,如果不能将会引发访问异常。
管理模式(supervisor-mode)
上一节中描述的 PMP 方案对嵌入式系统的实现很有吸引力,因为它以相对较低的成本提供了内存保护,但它的一些缺点限制了它在通用计算中的使用。由于 PMP 仅支持固定数量的内存区域,因此无法对它进行扩展从而适应复杂的应用程序。而且由于这些区域必须在物理存储中连续,因此系统可能产生存储碎片化的问题。另外,PMP 不能有效地支持对辅存的分页。
更复杂的 RISC-V 处理器用和几乎所有通用架构相同的方式处理这些问题:使用基于页面的虚拟内存。这个功能构成了监管者模式(S 模式)的核心,这是一种可选的权限模式,旨在支持现代类 Unix 操作系统,如 Linux,FreeBSD 和 Windows。S 模式比 U 模式权
限更高,但比 M 模式低。与 U 模式一样,S 模式下运行的软件不能使用 M 模式的 CSR 和指令,并且受到 PMP 的限制。本届介绍 S 模式的中断和异常,下一节将详细介绍 S 模式下的虚拟内存系统。
默认情况下,发生所有异常(不论在什么权限模式下)的时候,控制权都会被移交到M 模式的异常处理程序。但是 Unix 系统中的大多数例外都应该进行 S 模式下的系统调用。M 模式的异常处理程序可以将异常重新导向 S 模式,但这些额外的操作会减慢大多数
异常的处理速度。因此,RISC-V 提供了一种异常委托机制。通过该机制可以选择性地将中断和同步异常交给 S 模式处理,而完全绕过 M 模式。
mideleg(Machine Interrupt Delegation,机器中断委托)CSR 控制将哪些中断委托给 S模式。例如,mideleg[5]对应于 S 模式的时钟中断,如果把它置位,S 模式的时钟中断将会移交 S 模式的异常处理程序,而不是 M 模式的异常处理程序。
sie
和sip
在S模式下的作用等同于mie
和mip
在M模式下的作用。
同样的,处理中断委托外,还有同步异常委托CSR medeleg(Machine Execption Delegation)。
请注意,无论委派设置是怎样的,发生异常时控制权都不会移交给权限更低的模式。在 M 模式下发生的异常总是在 M 模式下处理。在 S 模式下发生的异常,根据具体的委派设置,可能由 M 模式或 S 模式处理,但永远不会由 U 模式处理。
S 模式有几个异常处理 CSR:sepc、stvec、scause、sscratch、stval 和 sstatus,它们 M 模式 CSR 相同的功能。监管者异常返回指令 sret 与 mret 的行为相同,但它作用于 S 模式的异常处理 CSR,而不是 M 模式的 CSR。
在管理模式下,当CPU发生发生异常时,硬件会自动做出以下动作:
- 发生异常指令的PC保存到CSR
sepc
中,并将PC设置为CSRstvec
的值 - 根据异常来源设置CSR
scause
,将mtval设置为设置为出错的地址或者其他特定的异常信息。 - 将
mstatus.SIE
置为0,禁用全局中断,并将mstatus.SIE
的值保存到mstatus.SPIE
中 - 将异常前的运行模式保存到
mstatus.SPP
中,并将运行模式切换到S模式。