-
Notifications
You must be signed in to change notification settings - Fork 49
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add optional support for hardware register save e.g. shadow register sets? #329
Comments
Regarding the e.g. in case of ch32v003 it would be a snippet from my Xteic spec:
|
It seems like this proposal could be standalone and apply to any interrupt controller (CLIC, CLINT, AIA)? Make a proposal to the SIG and see if they have it become a new task group? linking issue #108. |
FYI, official proposal for prestacked annottion is here: riscv-non-isa/riscv-c-api-doc#53 It allows CLIC to be extended with minimal set of shadow or stacked registers without the need for extra compiler attributes (except the |
We currently support two methods of writing interrupt handlers in C (etc):
assembly-language handler that saves
ra
,a0
-a7
,t0
-t6
then calls a standard ABI function that can freely use those registers (as usual) and savess0
-s11
if it uses them. When the C function returns all registers are restored beforemret
.direct call of C
__attribute__((interrupt))
function that saves only and exactly the registers it uses (if self-contained), and saves all volatile registers in the event that it must call a standard ABI function. The function restores all registers before usingmret
to return.I propose that we consider adding a third option which might or might not be implemented in any particular core but if it is present has standardised interface and functionality.
ra
,a0
-a7
,t0
-t6
), hopefully more quickly than software can, calls a standard ABI handler function, and when it returns the hardware quickly restores the saved registers.In many cases the hardware save/restore might be an instantaneous (single cycle, maybe in parallel with fetching the interrupt vector) swapping of register sets. In other cases it might save registers to the stack and might not be any faster than normal store/load instructions, other than in not having to do instruction fetches (which might be cache misses, if there is an icache). Or it might be able to use a wider interface to dcache/RAM than normal stores&loads would.
As with Zcmp and Zcmt, this is more likely to be considered a desirable feature by the microcontroller community.
In particular, it matches the interrupt handling on ARMv7-M. Cortex-M{0+,3,4,7} save volatile registers to the stack and put a "fake" return address into
LR
... 0xFFFFFFEn or 0xFFFFFFFn depending on whether FP registers have or have not been saved and depending on the exact interrupt return behaviour desired. The core then calls a standard ABI C function. A normalret
instruction (or any instruction that loads such a value into PC) then results in interrupt return.RISC-V vendor WCH already implement a similar feature in their increasingly popular cores, which they call HPE (Hardware Prologue/Epilog). Their hardware saves the volatile registers then calls the handler, which is a normal ABI function except that it must end with
mret
notret
. They provide a special compiler that implements a special__attribute__((interrupt"WCH-Interrupt-fast")))
.This is a bit inconvenient, especially for people who want to use a standard toolchain. The correct work-around is to make a standard ABI function
void my_handler()
and also__attribute__((naked)) void my_handler_hpe(){asm("call my_handler; mret");}
.I have suggested to WCH that they also allow a function ending with
ret
to work (i.e. a completely standard C function), and a possible mechanism to achieve this: ifret
opcode is encountered AND in_interrupt_handler ANDsp
==sp_on_entry_to_handler
THEN executemret
. They seem interested in this idea for future core revs.The Cortex-M technique of putting a distinguished value in
ra
(different ones formret
,sret
,uret
) would be simpler, if it is not patented.Anyway, I think it is essential that if a hardware save/restore feature is standardised then it should be designed to call a completely standard ABI function, no special attributes needed.
Note that the lowest-end WCH chip, the CH32V003 (the "10c RISC-V" chip) pushes the 10 saved registers (it is an RV32E core) to a 48 byte stack frame, while the higher end WCH cores have multiple sets of shadow registers in the core. The same program code works with either implementation.
Once again, this is a feature more likely to be desired by users of microcontrollers.
A sequencer to save registers is a little additional hardware (possibly already present for Zcmp) in a simple core, but a PITA in an OoO core. Multiple extra register sets is a significant hardware investment that might well be more profitably used for other purposes (or simply avoided).
So it is not for everyone. But some of the market wants it, at least one major vendor is already implementing it and others may well follow.
Therefore, it is best if it is standardized.
The text was updated successfully, but these errors were encountered: