arch: riscv32: Move MEPC increment in irq_wrapper

Move the MEPC increment logic in __irq_wrapper such that the saved MEPC
is only incremented on a syscall (ecall instruction).

Signed-off-by: Nathaniel Graff <nathaniel.graff@sifive.com>
This commit is contained in:
Nathaniel Graff 2018-08-02 10:38:57 -07:00 committed by Kumar Gala
commit 970cfdb88b
2 changed files with 33 additions and 34 deletions

View file

@ -96,7 +96,7 @@ FUNC_NORETURN void _NanoFatalErrorHandler(unsigned int reason,
" a2: 0x%x a3: 0x%x a4: 0x%x a5: 0x%x\n"
" a6: 0x%x a7: 0x%x\n",
k_current_get(),
(esf->mepc == 0xdeadbaad) ? 0xdeadbaad : esf->mepc - 4,
(esf->mepc == 0xdeadbaad) ? 0xdeadbaad : esf->mepc,
esf->ra, esf->gp, esf->tp, esf->t0,
esf->t1, esf->t2, esf->t3, esf->t4,
esf->t5, esf->t6, esf->a0, esf->a1,

View file

@ -129,16 +129,6 @@ SECTION_FUNC(exception.entry, __irq_wrapper)
addi t1, x0, 0
bnez a0, is_interrupt
/*
* If exception is not an interrupt, MEPC will contain
* the instruction address, which has caused the exception.
* Increment saved MEPC by 4 to prevent running into the
* exception again, upon exiting the ISR.
*/
lw t0, __NANO_ESF_mepc_OFFSET(sp)
addi t0, t0, 4
sw t0, __NANO_ESF_mepc_OFFSET(sp)
/*
* If the exception is the result of an ECALL, check whether to
* perform a context-switch or an IRQ offload. Otherwise call _Fault
@ -153,29 +143,7 @@ SECTION_FUNC(exception.entry, __irq_wrapper)
* If mcause == SOC_MCAUSE_ECALL_EXP, handle system call,
* otherwise handle fault
*/
#ifdef CONFIG_IRQ_OFFLOAD
/* If not system call, jump to is_fault */
bne t0, t1, is_fault
/*
* Determine if the system call is the result of an IRQ offloading.
* Done by checking if _offload_routine is not pointing to NULL.
* If NULL, jump to reschedule to perform a context-switch, otherwise,
* jump to is_interrupt to handle the IRQ offload.
*/
la t0, _offload_routine
lw t1, 0x00(t0)
beqz t1, reschedule
bnez t1, is_interrupt
is_fault:
#else
/*
* Go to reschedule to handle context-switch if system call,
* otherwise call _Fault to handle exception
*/
beq t0, t1, reschedule
#endif
beq t0, t1, is_syscall
/*
* Call _Fault to handle exception.
@ -188,6 +156,37 @@ is_fault:
la ra, no_reschedule
tail _Fault
is_syscall:
/*
* A syscall is the result of an ecall instruction, in which case the
* MEPC will contain the address of the ecall instruction.
* Increment saved MEPC by 4 to prevent triggering the same ecall
* again upon exiting the ISR.
*
* It's safe to always increment by 4, even with compressed
* instructions, because the ecall instruction is always 4 bytes.
*/
lw t0, __NANO_ESF_mepc_OFFSET(sp)
addi t0, t0, 4
sw t0, __NANO_ESF_mepc_OFFSET(sp)
#ifdef CONFIG_IRQ_OFFLOAD
/*
* Determine if the system call is the result of an IRQ offloading.
* Done by checking if _offload_routine is not pointing to NULL.
* If NULL, jump to reschedule to perform a context-switch, otherwise,
* jump to is_interrupt to handle the IRQ offload.
*/
la t0, _offload_routine
lw t1, 0x00(t0)
bnez t1, is_interrupt
#endif
/*
* Go to reschedule to handle context-switch
*/
j reschedule
is_interrupt:
/*
* Save current thread stack pointer and switch