I am writing a toy kernel to learn about operating systems. I am targeting a RISC-V machine (virt in qemu). I try to delegate interrupts to Supervisor mode, but I don't know why it does not work.
From what I read in the privileged architecture manual, I need to enable exceptions for supervisor in the mie CSR, and set bits from the exceptions I want to delegate in the mideleg and medeleg CSRs. But doing so does not raise any exception when having an external interrupt pending.
Software interrupts work, they are triggered and taken in S-mode, but External interrupts are not even triggering (not even in M-mode).
To understand what happens, I tried using gdb and watch for the mip register to change.
I trigger the interrupt with the UART0 port of the machine (by pressing a key on my keyboard) and here is what happen.
Pressing a key sets a bit in mip which pauses the execution. And here is the state of the relevant CSR:
(gdb) p /x $sip
$3 = 0x200
(gdb) p /x $sie
$4 = 0x222
(gdb) p /x $mstatus
$5 = 0xaa
(gdb) p /x $mideleg
$6 = 0x666
(gdb) p /x $medeleg
$7 = 0xb0bfff
(gdb) p /x $scause
$8 = 0x0
(gdb) p /x $stval
$9 = 0x0
So the SEIP (supervisor external interrupt pending) bit is set, but nothing triggers. If I then continue execution I eventually trigger a Page Fault or an Illegal Instruction as these are software interrupts and are taken.
If I try to run a wfi instruction in supervisor mode, the same thing happens, and thuss the machine will be stuck at the wfi instruction.
Am I doing something wrong or is it virt ?
If this question lacks details, please tell me, I will modify it.
Edit: it seems like the board on which the virt machine is based has for Hart 0 a SiFive E51 processor which does not support supervisor mode at all and of course I was using this hart for my bootloader.
But still, why does the simulator allow supervisor mode on this hart even though the documentation explicitely tells it implements only M and U modes ? And why are the synchronous exceptions still delegated into S-mode ?
Thank you