riscv: isr.S: optimize FP regs save/restore decision

Rely on mstatus rather than thread->base.user_options since it is always
up to date (updated by z_riscv_switch) to simplify the code and be SMP
proof. Also carry over SF_INIT to the mstatus being restored in case
it was changed in the mean time.

Signed-off-by: Nicolas Pitre <npitre@baylibre.com>
This commit is contained in:
Nicolas Pitre 2022-03-07 17:31:13 -05:00 committed by Anas Nashif
parent ce8dabfe9e
commit 69d06a901c
1 changed files with 30 additions and 28 deletions

View File

@ -135,14 +135,6 @@ SECTION_FUNC(exception.entry, __irq_wrapper)
addi sp, sp, -__z_arch_esf_t_SIZEOF
DO_CALLER_SAVED(sr) ;
/* Save MEPC register */
csrr t0, mepc
sr t0, __z_arch_esf_t_mepc_OFFSET(sp)
/* Save MSTATUS register */
csrr t0, mstatus
sr t0, __z_arch_esf_t_mstatus_OFFSET(sp)
#ifdef CONFIG_USERSPACE
/*
* The scratch register now contains either the user mode stack
@ -163,12 +155,18 @@ SECTION_FUNC(exception.entry, __irq_wrapper)
sw zero, 0(t0)
#endif
/* Save MEPC register */
csrr t0, mepc
sr t0, __z_arch_esf_t_mepc_OFFSET(sp)
/* Save MSTATUS register */
csrr t4, mstatus
sr t4, __z_arch_esf_t_mstatus_OFFSET(sp)
#if defined(CONFIG_FPU) && defined(CONFIG_FPU_SHARING)
/* Assess whether floating-point registers need to be saved. */
la t0, _kernel
lr t0, _kernel_offset_to_current(t0)
lb t0, _thread_offset_to_user_options(t0)
andi t0, t0, K_FP_REGS
li t1, MSTATUS_FS_INIT
and t0, t4, t1
beqz t0, skip_store_fp_caller_saved
DO_FP_CALLER_SAVED(fsr, sp)
skip_store_fp_caller_saved:
@ -457,28 +455,32 @@ no_reschedule:
jal ra, __soc_restore_context
#endif /* CONFIG_RISCV_SOC_CONTEXT_SAVE */
#if defined(CONFIG_FPU) && defined(CONFIG_FPU_SHARING)
/*
* Determine if we need to restore floating-point registers. This needs
* to happen before restoring integer registers to avoid stomping on
* t0.
*/
la t0, _kernel
lr t0, _kernel_offset_to_current(t0)
lb t0, _thread_offset_to_user_options(t0)
andi t0, t0, K_FP_REGS
beqz t0, skip_load_fp_caller_saved
DO_FP_CALLER_SAVED(flr, sp)
skip_load_fp_caller_saved:
#endif /* CONFIG_FPU && CONFIG_FPU_SHARING */
/* Restore MEPC register */
lr t0, __z_arch_esf_t_mepc_OFFSET(sp)
csrw mepc, t0
/* Restore MSTATUS register */
lr t4, __z_arch_esf_t_mstatus_OFFSET(sp)
csrw mstatus, t4
csrrw t5, mstatus, t4
#if defined(CONFIG_FPU) && defined(CONFIG_FPU_SHARING)
/*
* Determine if we need to restore FP regs based on the previous
* (before the csr above) mstatus value available in t5.
*/
li t1, MSTATUS_FS_INIT
and t0, t5, t1
beqz t0, no_fp
/* make sure FP is enabled in the restored mstatus */
csrs mstatus, t1
DO_FP_CALLER_SAVED(flr, sp)
j 1f
no_fp: /* make sure this is reflected in the restored mstatus */
csrc mstatus, t1
1:
#endif /* CONFIG_FPU && CONFIG_FPU_SHARING */
#ifdef CONFIG_USERSPACE
/*