管理员模式下不触发外部中断

External interrupt does not trigger when in Supervisor mode

我正在编写一个玩具内核来学习操作系统。我的目标是 RISC-V 机器(virt in qemu)。我尝试将中断委托给主管模式,但我不知道为什么它不起作用。

根据我在特权架构手册中读到的内容,我需要在 mie CSR 中为主管启用例外,并在 midelegmedeleg 企业社会责任。但是这样做不会在有外部中断挂起时引发任何异常。

软件中断工作,它们在 S 模式下被触发和获取,但外部中断甚至不触发(甚至在 M 模式下也不)。

为了了解发生了什么,我尝试使用 gdb 并观察 mip 寄存器的变化。 我用机器的 UART0 端口触发中断(通过按键盘上的一个键),这就是发生的事情。

按下一个键会在 mip 中设置一个暂停执行的位。这是相关 CSR 的状态:

(gdb) p /x $sip
 = 0x200
(gdb) p /x $sie
 = 0x222
(gdb) p /x $mstatus
 = 0xaa
(gdb) p /x $mideleg
 = 0x666
(gdb) p /x $medeleg
 = 0xb0bfff
(gdb) p /x $scause
 = 0x0
(gdb) p /x $stval
 = 0x0

因此设置了 SEIP(管理程序外部中断挂起)位,但没有触发。如果我继续执行,我最终会触发页面错误或非法指令,因为这些是软件中断并被采用。

如果我在管理员模式下尝试运行一条wfi指令,同样的事情会发生,因此机器会卡在wfi指令处。

是我做错了什么还是virt? 如果这个问题缺少细节,请告诉我,我会修改它。

编辑:似乎 virt 机器所基于的电路板有一个用于 Hart 0 的 SiFive E51 处理器,它根本不支持管理模式,当然我正在使用这个 hart 作为我的引导加载程序。

但是,为什么模拟器允许在此 hart 上使用主管模式,即使文档明确告诉它仅实现 M 和 U 模式?为什么同步异常仍然委托给 S 模式?

谢谢

关于 virt RISC-V 机器的精度

从 Hart 0 更改为 Hart 1 作为我的主要核心并没有改变问题。

通过打印 misamimp CSR,我现在可以看出 virt 机器的所有核心都具有相同的 misa 并实施主管模式。所以本机并没有基于FU53平台架构,只是用了一个PLIC同种全局中断系统。

但是PLIC内存映射与FU53不同,FU53没有Hart 0的S模式全局中断内存映射寄存器。因此,我用来启用S模式全局中断的地址不是不错的。

在此文件中:qemu/virt.h at master · qemu/qemu您可以找到用于计算正确 PLIC 地址的常量,以便在设置时使用。

我仍然不完全理解为什么 mip 中的挂起位被设置,但现在它起作用了。

tl;博士

这是进入 S 模式时使其工作的状态。 PLIC 地址是罪魁祸首。

mstatus: MPIE = 1, SIE = 1, MPP = 01
mie    : MEIE = MTIE = MSIE = SEIE = STIE = SSIE = 1 (mie=0xaaa)
mideleg: 0x222
medeleg: 0xb0bfff (which is set when writing 0xffffffff to it)

PLIC:
  - *0x0C00_2080 (Hart 0 S-mode enable) = 0x400 (enable UART0)
  - *0x0C00_0028 (Interrupt number 10 priority) = 1
  - *0x0C20_1000 (Hart 0 S-mode threshold) = 0