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"
|
" a2: 0x%x a3: 0x%x a4: 0x%x a5: 0x%x\n"
|
||||||
" a6: 0x%x a7: 0x%x\n",
|
" a6: 0x%x a7: 0x%x\n",
|
||||||
k_current_get(),
|
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->ra, esf->gp, esf->tp, esf->t0,
|
||||||
esf->t1, esf->t2, esf->t3, esf->t4,
|
esf->t1, esf->t2, esf->t3, esf->t4,
|
||||||
esf->t5, esf->t6, esf->a0, esf->a1,
|
esf->t5, esf->t6, esf->a0, esf->a1,
|
||||||
|
|
|
@ -129,16 +129,6 @@ SECTION_FUNC(exception.entry, __irq_wrapper)
|
||||||
addi t1, x0, 0
|
addi t1, x0, 0
|
||||||
bnez a0, is_interrupt
|
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
|
* If the exception is the result of an ECALL, check whether to
|
||||||
* perform a context-switch or an IRQ offload. Otherwise call _Fault
|
* 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,
|
* If mcause == SOC_MCAUSE_ECALL_EXP, handle system call,
|
||||||
* otherwise handle fault
|
* otherwise handle fault
|
||||||
*/
|
*/
|
||||||
#ifdef CONFIG_IRQ_OFFLOAD
|
beq t0, t1, is_syscall
|
||||||
/* 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
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Call _Fault to handle exception.
|
* Call _Fault to handle exception.
|
||||||
|
@ -188,6 +156,37 @@ is_fault:
|
||||||
la ra, no_reschedule
|
la ra, no_reschedule
|
||||||
tail _Fault
|
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:
|
is_interrupt:
|
||||||
/*
|
/*
|
||||||
* Save current thread stack pointer and switch
|
* Save current thread stack pointer and switch
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue