管理员模式下不触发外部中断
External interrupt does not trigger when in Supervisor mode
我正在编写一个玩具内核来学习操作系统。我的目标是 RISC-V 机器(virt
in qemu
)。我尝试将中断委托给主管模式,但我不知道为什么它不起作用。
根据我在特权架构手册中读到的内容,我需要在 mie
CSR 中为主管启用例外,并在 mideleg
和 medeleg
企业社会责任。但是这样做不会在有外部中断挂起时引发任何异常。
软件中断工作,它们在 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 作为我的主要核心并没有改变问题。
通过打印 misa
和 mimp
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
我正在编写一个玩具内核来学习操作系统。我的目标是 RISC-V 机器(virt
in qemu
)。我尝试将中断委托给主管模式,但我不知道为什么它不起作用。
根据我在特权架构手册中读到的内容,我需要在 mie
CSR 中为主管启用例外,并在 mideleg
和 medeleg
企业社会责任。但是这样做不会在有外部中断挂起时引发任何异常。
软件中断工作,它们在 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 作为我的主要核心并没有改变问题。
通过打印 misa
和 mimp
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