I need to implement a machine mode trap handler on a bare-metal RISC-V system. The trap handler should be using a separate stack region from the main program. I understand the basic flow for that if implementing in assembly:
- enter the trap handler
- write
spwith the trap stack pointer (saved inmscratchfor example) - save the context on the stack (registers x1-x31)
- do stuff
- restore the context from the stack
- write sp with the original stack pointer
- return with
mret
Now, I am trying to minimize the use of assembly code, and looking at the GCC's RISC-V specific function attribute:
void f (void) __attribute__ ((interrupt ("machine")));
It looks like it is capable of doing all of the steps above automagically except steps 2 and 6 - that is swapping stacks. The question - is there a way/trick in GCC to make a function, that is an interrupt handler - for context saving or a general function for stack frame allocation to use a different stack?
(Note: I am aware of the naked attribute, but the idea here is to benefit from the automatic generation of prologue/epilogue the interrupt attribute is providing)
UPD: I have actually found that in recent SiFive specific GCC they have introduced the extra attribute options:
void f (void) __attribute__ ((interrupt ("SiFive-CLIC-stack-swap")));
as can be seen in their GitHub repo But it looks like it is only done for machine traps. I am looking for a solution that would work similarly for supervisor traps as well.