riscv: Adds support for returning from exception handler

This commit is contained in:
Alexey Gerenkov
2022-02-02 22:25:13 +03:00
parent 300d67411a
commit 46a98fb8d1

View File

@@ -23,37 +23,41 @@
.equ panic_from_exception, xt_unhandled_exception .equ panic_from_exception, xt_unhandled_exception
.equ panic_from_isr, panicHandler .equ panic_from_isr, panicHandler
.macro save_regs /* Macro which first allocates space on the stack to save general
addi sp, sp, -CONTEXT_SIZE * purpose registers, and then save them. GP register is excluded.
sw ra, RV_STK_RA(sp) * The default size allocated on the stack is CONTEXT_SIZE, but it
sw tp, RV_STK_TP(sp) * can be overridden. */
sw t0, RV_STK_T0(sp) .macro save_general_regs cxt_size=CONTEXT_SIZE
sw t1, RV_STK_T1(sp) addi sp, sp, -\cxt_size
sw t2, RV_STK_T2(sp) sw ra, RV_STK_RA(sp)
sw s0, RV_STK_S0(sp) sw tp, RV_STK_TP(sp)
sw s1, RV_STK_S1(sp) sw t0, RV_STK_T0(sp)
sw a0, RV_STK_A0(sp) sw t1, RV_STK_T1(sp)
sw a1, RV_STK_A1(sp) sw t2, RV_STK_T2(sp)
sw a2, RV_STK_A2(sp) sw s0, RV_STK_S0(sp)
sw a3, RV_STK_A3(sp) sw s1, RV_STK_S1(sp)
sw a4, RV_STK_A4(sp) sw a0, RV_STK_A0(sp)
sw a5, RV_STK_A5(sp) sw a1, RV_STK_A1(sp)
sw a6, RV_STK_A6(sp) sw a2, RV_STK_A2(sp)
sw a7, RV_STK_A7(sp) sw a3, RV_STK_A3(sp)
sw s2, RV_STK_S2(sp) sw a4, RV_STK_A4(sp)
sw s3, RV_STK_S3(sp) sw a5, RV_STK_A5(sp)
sw s4, RV_STK_S4(sp) sw a6, RV_STK_A6(sp)
sw s5, RV_STK_S5(sp) sw a7, RV_STK_A7(sp)
sw s6, RV_STK_S6(sp) sw s2, RV_STK_S2(sp)
sw s7, RV_STK_S7(sp) sw s3, RV_STK_S3(sp)
sw s8, RV_STK_S8(sp) sw s4, RV_STK_S4(sp)
sw s9, RV_STK_S9(sp) sw s5, RV_STK_S5(sp)
sw s10, RV_STK_S10(sp) sw s6, RV_STK_S6(sp)
sw s11, RV_STK_S11(sp) sw s7, RV_STK_S7(sp)
sw t3, RV_STK_T3(sp) sw s8, RV_STK_S8(sp)
sw t4, RV_STK_T4(sp) sw s9, RV_STK_S9(sp)
sw t5, RV_STK_T5(sp) sw s10, RV_STK_S10(sp)
sw t6, RV_STK_T6(sp) sw s11, RV_STK_S11(sp)
sw t3, RV_STK_T3(sp)
sw t4, RV_STK_T4(sp)
sw t5, RV_STK_T5(sp)
sw t6, RV_STK_T6(sp)
.endm .endm
.macro save_mepc .macro save_mepc
@@ -61,37 +65,40 @@
sw t0, RV_STK_MEPC(sp) sw t0, RV_STK_MEPC(sp)
.endm .endm
.macro restore_regs /* Restore the general purpose registers (excluding gp) from the context on
lw ra, RV_STK_RA(sp) * the stack. The context is then deallocated. The default size is CONTEXT_SIZE
lw tp, RV_STK_TP(sp) * but it can be overriden. */
lw t0, RV_STK_T0(sp) .macro restore_general_regs cxt_size=CONTEXT_SIZE
lw t1, RV_STK_T1(sp) lw ra, RV_STK_RA(sp)
lw t2, RV_STK_T2(sp) lw tp, RV_STK_TP(sp)
lw s0, RV_STK_S0(sp) lw t0, RV_STK_T0(sp)
lw s1, RV_STK_S1(sp) lw t1, RV_STK_T1(sp)
lw a0, RV_STK_A0(sp) lw t2, RV_STK_T2(sp)
lw a1, RV_STK_A1(sp) lw s0, RV_STK_S0(sp)
lw a2, RV_STK_A2(sp) lw s1, RV_STK_S1(sp)
lw a3, RV_STK_A3(sp) lw a0, RV_STK_A0(sp)
lw a4, RV_STK_A4(sp) lw a1, RV_STK_A1(sp)
lw a5, RV_STK_A5(sp) lw a2, RV_STK_A2(sp)
lw a6, RV_STK_A6(sp) lw a3, RV_STK_A3(sp)
lw a7, RV_STK_A7(sp) lw a4, RV_STK_A4(sp)
lw s2, RV_STK_S2(sp) lw a5, RV_STK_A5(sp)
lw s3, RV_STK_S3(sp) lw a6, RV_STK_A6(sp)
lw s4, RV_STK_S4(sp) lw a7, RV_STK_A7(sp)
lw s5, RV_STK_S5(sp) lw s2, RV_STK_S2(sp)
lw s6, RV_STK_S6(sp) lw s3, RV_STK_S3(sp)
lw s7, RV_STK_S7(sp) lw s4, RV_STK_S4(sp)
lw s8, RV_STK_S8(sp) lw s5, RV_STK_S5(sp)
lw s9, RV_STK_S9(sp) lw s6, RV_STK_S6(sp)
lw s10, RV_STK_S10(sp) lw s7, RV_STK_S7(sp)
lw s11, RV_STK_S11(sp) lw s8, RV_STK_S8(sp)
lw t3, RV_STK_T3(sp) lw s9, RV_STK_S9(sp)
lw t4, RV_STK_T4(sp) lw s10, RV_STK_S10(sp)
lw t5, RV_STK_T5(sp) lw s11, RV_STK_S11(sp)
lw t6, RV_STK_T6(sp) lw t3, RV_STK_T3(sp)
addi sp, sp, CONTEXT_SIZE lw t4, RV_STK_T4(sp)
lw t5, RV_STK_T5(sp)
lw t6, RV_STK_T6(sp)
addi sp,sp, \cxt_size
.endm .endm
.macro restore_mepc .macro restore_mepc
@@ -141,40 +148,17 @@ _vector_table:
/* Exception handler.*/ /* Exception handler.*/
.type _panic_handler, @function .type _panic_handler, @function
_panic_handler: _panic_handler:
addi sp, sp, -RV_STK_FRMSZ /* allocate space on stack to store necessary registers */ /* Allocate space on the stack and store general purpose registers */
/* save general registers */ save_general_regs RV_STK_FRMSZ
sw ra, RV_STK_RA(sp)
sw gp, RV_STK_GP(sp) /* As gp register is not saved by the macro, save it here */
sw tp, RV_STK_TP(sp) sw gp, RV_STK_GP(sp)
sw t0, RV_STK_T0(sp)
sw t1, RV_STK_T1(sp) /* Same goes for the SP value before trapping */
sw t2, RV_STK_T2(sp)
sw s0, RV_STK_S0(sp)
sw s1, RV_STK_S1(sp)
sw a0, RV_STK_A0(sp)
sw a1, RV_STK_A1(sp)
sw a2, RV_STK_A2(sp)
sw a3, RV_STK_A3(sp)
sw a4, RV_STK_A4(sp)
sw a5, RV_STK_A5(sp)
sw a6, RV_STK_A6(sp)
sw a7, RV_STK_A7(sp)
sw s2, RV_STK_S2(sp)
sw s3, RV_STK_S3(sp)
sw s4, RV_STK_S4(sp)
sw s5, RV_STK_S5(sp)
sw s6, RV_STK_S6(sp)
sw s7, RV_STK_S7(sp)
sw s8, RV_STK_S8(sp)
sw s9, RV_STK_S9(sp)
sw s10, RV_STK_S10(sp)
sw s11, RV_STK_S11(sp)
sw t3, RV_STK_T3(sp)
sw t4, RV_STK_T4(sp)
sw t5, RV_STK_T5(sp)
sw t6, RV_STK_T6(sp)
addi t0, sp, RV_STK_FRMSZ /* restore sp with the value when trap happened */ addi t0, sp, RV_STK_FRMSZ /* restore sp with the value when trap happened */
sw t0, RV_STK_SP(sp) sw t0, RV_STK_SP(sp)
/* Save CSRs */
csrr t0, mepc csrr t0, mepc
sw t0, RV_STK_MEPC(sp) sw t0, RV_STK_MEPC(sp)
csrr t0, mstatus csrr t0, mstatus
@@ -198,17 +182,31 @@ _panic_handler:
li t0, 0x80000000 li t0, 0x80000000
bgeu a1, t0, _call_panic_handler bgeu a1, t0, _call_panic_handler
sw a1, RV_STK_MCAUSE(sp) sw a1, RV_STK_MCAUSE(sp)
/* exception_from_panic never returns */ jal panic_from_exception
j panic_from_exception /* We arrive here if the exception handler has returned. */
j _return_from_exception
_call_panic_handler: _call_panic_handler:
/* Remove highest bit from mcause (a1) register and save it in the /* Remove highest bit from mcause (a1) register and save it in the
* structure */ * structure */
not t0, t0 not t0, t0
and a1, a1, t0 and a1, a1, t0
sw a1, RV_STK_MCAUSE(sp) sw a1, RV_STK_MCAUSE(sp)
/* exception_from_isr never returns */ jal panic_from_isr
j panic_from_isr
.size panic_from_isr, .-panic_from_isr /* We arrive here if the exception handler has returned. This means that
* the exception was handled, and the execution flow should resume.
* Restore the registers and return from the exception.
*/
_return_from_exception:
restore_mepc
/* MTVEC and SP are assumed to be unmodified.
* MSTATUS, MHARTID, MTVAL are read-only and not restored.
*/
lw gp, RV_STK_GP(sp)
restore_general_regs RV_STK_FRMSZ
mret
.size _panic_handler, .-_panic_handler
/* This is the interrupt handler. /* This is the interrupt handler.
* It saves the registers on the stack, * It saves the registers on the stack,
@@ -220,7 +218,7 @@ _call_panic_handler:
.type _interrupt_handler, @function .type _interrupt_handler, @function
_interrupt_handler: _interrupt_handler:
/* entry */ /* entry */
save_regs save_general_regs
save_mepc save_mepc
/* Though it is not necessary we save GP and SP here. /* Though it is not necessary we save GP and SP here.
@@ -306,7 +304,7 @@ _interrupt_handler:
csrw mcause, s1 csrw mcause, s1
csrw mstatus, s2 csrw mstatus, s2
restore_mepc restore_mepc
restore_regs restore_general_regs
/* exit, this will also re-enable the interrupts */ /* exit, this will also re-enable the interrupts */
mret mret