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:
parent
8cf8db3a73
commit
970cfdb88b
2 changed files with 33 additions and 34 deletions
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue