riscv: integrate the new FPU context switching support
FPU context switching is always performed on demand through the FPU access exception handler. Actual task switching only grants or denies FPU access depending on the current FPU owner. Because RISC-V doesn't have a dedicated FPU access exception, we must catch the Illegal Instruction exception and look for actual FP opcodes. There is no longer a need to allocate FPU storage on the stack for every exception making esf smaller and stack overflows less likely. Signed-off-by: Nicolas Pitre <npitre@baylibre.com>
This commit is contained in:
parent
cb4c0f6c94
commit
ff07da6ff1
12 changed files with 204 additions and 344 deletions
|
@ -65,12 +65,9 @@ void arch_new_thread(struct k_thread *thread, k_thread_stack_t *stack,
|
|||
*/
|
||||
stack_init->mstatus = MSTATUS_DEF_RESTORE;
|
||||
|
||||
#if defined(CONFIG_FPU) && defined(CONFIG_FPU_SHARING)
|
||||
/* Shared FP mode: enable FPU of threads with K_FP_REGS. */
|
||||
if ((thread->base.user_options & K_FP_REGS) != 0) {
|
||||
stack_init->mstatus |= MSTATUS_FS_INIT;
|
||||
}
|
||||
thread->callee_saved.fcsr = 0;
|
||||
#if defined(CONFIG_FPU_SHARING)
|
||||
/* thread birth happens through the exception return path */
|
||||
thread->arch.exception_depth = 1;
|
||||
#elif defined(CONFIG_FPU)
|
||||
/* Unshared FP mode: enable FPU of each thread. */
|
||||
stack_init->mstatus |= MSTATUS_FS_INIT;
|
||||
|
@ -118,72 +115,6 @@ void arch_new_thread(struct k_thread *thread, k_thread_stack_t *stack,
|
|||
thread->switch_handle = thread;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_FPU) && defined(CONFIG_FPU_SHARING)
|
||||
int arch_float_disable(struct k_thread *thread)
|
||||
{
|
||||
unsigned int key;
|
||||
|
||||
if (thread != _current) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (arch_is_in_isr()) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Ensure a preemptive context switch does not occur */
|
||||
key = irq_lock();
|
||||
|
||||
/* Disable all floating point capabilities for the thread */
|
||||
thread->base.user_options &= ~K_FP_REGS;
|
||||
|
||||
/* Clear the FS bits to disable the FPU. */
|
||||
__asm__ volatile (
|
||||
"mv t0, %0\n"
|
||||
"csrrc x0, mstatus, t0\n"
|
||||
:
|
||||
: "r" (MSTATUS_FS_MASK)
|
||||
);
|
||||
|
||||
irq_unlock(key);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int arch_float_enable(struct k_thread *thread, unsigned int options)
|
||||
{
|
||||
unsigned int key;
|
||||
|
||||
if (thread != _current) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (arch_is_in_isr()) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Ensure a preemptive context switch does not occur */
|
||||
key = irq_lock();
|
||||
|
||||
/* Enable all floating point capabilities for the thread. */
|
||||
thread->base.user_options |= K_FP_REGS;
|
||||
|
||||
/* Set the FS bits to Initial and clear the fcsr to enable the FPU. */
|
||||
__asm__ volatile (
|
||||
"mv t0, %0\n"
|
||||
"csrrs x0, mstatus, t0\n"
|
||||
"fscsr x0, x0\n"
|
||||
:
|
||||
: "r" (MSTATUS_FS_INIT)
|
||||
);
|
||||
|
||||
irq_unlock(key);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif /* CONFIG_FPU && CONFIG_FPU_SHARING */
|
||||
|
||||
#ifdef CONFIG_USERSPACE
|
||||
|
||||
/*
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue