diff --git a/arch/arc/core/thread.c b/arch/arc/core/thread.c index 4b1d836103e..387f983780b 100644 --- a/arch/arc/core/thread.c +++ b/arch/arc/core/thread.c @@ -276,6 +276,15 @@ int arch_float_enable(struct k_thread *thread, unsigned int options) } #endif /* CONFIG_FPU && CONFIG_FPU_SHARING */ +int arch_coprocessors_disable(struct k_thread *thread) +{ +#if defined(CONFIG_FPU) && defined(CONFIG_FPU_SHARING) + return arch_float_disable(thread); +#else + return -ENOTSUP; +#endif +} + #if !defined(CONFIG_MULTITHREADING) K_KERNEL_STACK_ARRAY_DECLARE(z_interrupt_stacks, CONFIG_MP_MAX_NUM_CPUS, CONFIG_ISR_STACK_SIZE); diff --git a/arch/arm/core/cortex_a_r/thread.c b/arch/arm/core/cortex_a_r/thread.c index 14f6d3f7de9..96d32b8f58d 100644 --- a/arch/arm/core/cortex_a_r/thread.c +++ b/arch/arm/core/cortex_a_r/thread.c @@ -415,3 +415,12 @@ int arch_float_enable(struct k_thread *thread, unsigned int options) return -ENOTSUP; } #endif /* CONFIG_FPU && CONFIG_FPU_SHARING */ + +int arch_coprocessors_disable(struct k_thread *thread) +{ +#if defined(CONFIG_FPU) && defined(CONFIG_FPU_SHARING) + return arch_float_disable(thread); +#else + return -ENOTSUP; +#endif +} diff --git a/arch/arm/core/cortex_m/thread.c b/arch/arm/core/cortex_m/thread.c index 733b4b8637f..edbff466a33 100644 --- a/arch/arm/core/cortex_m/thread.c +++ b/arch/arm/core/cortex_m/thread.c @@ -462,6 +462,15 @@ int arch_float_enable(struct k_thread *thread, unsigned int options) } #endif /* CONFIG_FPU && CONFIG_FPU_SHARING */ +int arch_coprocessors_disable(struct k_thread *thread) +{ +#if defined(CONFIG_FPU) && defined(CONFIG_FPU_SHARING) + return arch_float_disable(thread); +#else + return -ENOTSUP; +#endif +} + /* Internal function for Cortex-M initialization, * applicable to either case of running Zephyr * with or without multi-threading support. diff --git a/arch/arm64/core/thread.c b/arch/arm64/core/thread.c index c48672a5f07..3d93eb4b824 100644 --- a/arch/arm64/core/thread.c +++ b/arch/arm64/core/thread.c @@ -199,3 +199,12 @@ FUNC_NORETURN void arch_user_mode_enter(k_thread_entry_t user_entry, CODE_UNREACHABLE; } #endif + +int arch_coprocessors_disable(struct k_thread *thread) +{ +#if defined(CONFIG_FPU_SHARING) + return arch_float_disable(thread); +#else + return -ENOTSUP; +#endif +} diff --git a/arch/mips/core/thread.c b/arch/mips/core/thread.c index 7966ff462f5..1f2be889c23 100644 --- a/arch/mips/core/thread.c +++ b/arch/mips/core/thread.c @@ -39,3 +39,8 @@ void arch_new_thread(struct k_thread *thread, k_thread_stack_t *stack, thread->callee_saved.sp = (unsigned long)stack_init; } + +int arch_coprocessors_disable(struct k_thread *thread) +{ + return -ENOTSUP; +} diff --git a/arch/posix/core/thread.c b/arch/posix/core/thread.c index 050d075fe57..2b0d8d9d850 100644 --- a/arch/posix/core/thread.c +++ b/arch/posix/core/thread.c @@ -115,6 +115,12 @@ int arch_float_enable(struct k_thread *thread, unsigned int options) } #endif /* CONFIG_FPU && CONFIG_FPU_SHARING */ +int arch_coprocessors_disable(struct k_thread *thread) +{ + /* Posix does not support coprocessors */ + return -ENOTSUP; +} + #if defined(CONFIG_ARCH_HAS_THREAD_ABORT) void z_impl_k_thread_abort(k_tid_t thread) { diff --git a/arch/riscv/core/thread.c b/arch/riscv/core/thread.c index ab2cbfe0036..4ee23303f1a 100644 --- a/arch/riscv/core/thread.c +++ b/arch/riscv/core/thread.c @@ -255,3 +255,12 @@ FUNC_NORETURN void z_riscv_switch_to_main_no_multithreading(k_thread_entry_t mai CODE_UNREACHABLE; /* LCOV_EXCL_LINE */ } #endif /* !CONFIG_MULTITHREADING */ + +int arch_coprocessors_disable(struct k_thread *thread) +{ +#ifdef CONFIG_FPU_SHARING + return arch_float_disable(thread); +#else + return -ENOTSUP; +#endif +} diff --git a/arch/rx/core/thread.c b/arch/rx/core/thread.c index 88670bf75da..5855dac3526 100644 --- a/arch/rx/core/thread.c +++ b/arch/rx/core/thread.c @@ -51,3 +51,8 @@ void arch_new_thread(struct k_thread *thread, k_thread_stack_t *stack, char *sta thread->switch_handle = (void *)iframe; } + +int arch_coprocessors_disable(struct k_thread *thread) +{ + return -ENOTSUP; +} diff --git a/arch/sparc/core/thread.c b/arch/sparc/core/thread.c index e56d9f827c9..e706f35c3a4 100644 --- a/arch/sparc/core/thread.c +++ b/arch/sparc/core/thread.c @@ -77,3 +77,8 @@ int arch_float_enable(struct k_thread *thread, unsigned int options) return -ENOTSUP; } #endif /* CONFIG_FPU_SHARING */ + +int arch_coprocessors_disable(struct k_thread *thread) +{ + return -ENOTSUP; +} diff --git a/arch/x86/core/ia32/thread.c b/arch/x86/core/ia32/thread.c index b639bb59fdf..21d03ca2160 100644 --- a/arch/x86/core/ia32/thread.c +++ b/arch/x86/core/ia32/thread.c @@ -72,6 +72,15 @@ int arch_float_enable(struct k_thread *thread, unsigned int options) } #endif /* CONFIG_FPU && CONFIG_FPU_SHARING */ +int arch_coprocessors_disable(struct k_thread *thread) +{ +#if defined(CONFIG_FPU) && defined(CONFIG_FPU_SHARING) + return arch_float_disable(thread); +#else + return -ENOTSUP; +#endif +} + void arch_new_thread(struct k_thread *thread, k_thread_stack_t *stack, char *stack_ptr, k_thread_entry_t entry, void *p1, void *p2, void *p3) diff --git a/arch/x86/core/intel64/thread.c b/arch/x86/core/intel64/thread.c index 49cb58ec9c6..bc326b2b170 100644 --- a/arch/x86/core/intel64/thread.c +++ b/arch/x86/core/intel64/thread.c @@ -83,3 +83,11 @@ int arch_float_enable(struct k_thread *thread, unsigned int options) return 0; } + +int arch_coprocessors_disable(struct k_thread *thread) +{ + /* x86-64 always has FP/SSE enabled so cannot be disabled */ + ARG_UNUSED(thread); + + return -ENOTSUP; +} diff --git a/arch/xtensa/core/thread.c b/arch/xtensa/core/thread.c index 80ddf16363c..d5a5abac11c 100644 --- a/arch/xtensa/core/thread.c +++ b/arch/xtensa/core/thread.c @@ -145,6 +145,51 @@ int arch_float_enable(struct k_thread *thread, unsigned int options) } #endif /* CONFIG_FPU && CONFIG_FPU_SHARING */ + +#if defined(CONFIG_XTENSA_LAZY_HIFI_SHARING) +void xtensa_hifi_disown(struct k_thread *thread) +{ + unsigned int cpu_id = 0; + struct k_thread *owner; + +#if CONFIG_MP_MAX_NUM_CPUS > 1 + cpu_id = thread->base.cpu; +#endif + + owner = atomic_ptr_get(&_kernel.cpus[cpu_id].arch.hifi_owner); + + if (owner == thread) { + atomic_ptr_set(&_kernel.cpus[cpu_id].arch.hifi_owner, NULL); + } +} +#endif + +int arch_coprocessors_disable(struct k_thread *thread) +{ + bool enotsup = true; + +#if defined(CONFIG_FPU) && defined(CONFIG_FPU_SHARING) + arch_float_disable(thread); + enotsup = false; +#endif + +#if defined(CONFIG_XTENSA_LAZY_HIFI_SHARING) + xtensa_hifi_disown(thread); + + /* + * This routine is only called when aborting a thread and we + * deliberately do not disable the HiFi coprocessor here. + * 1. Such disabling can only be done for the current CPU, and we do + * not have control over which CPU the thread is running on. + * 2. If the thread (being deleted) is a currently executing thread, + * there will be a context switch to another thread and that CPU + * will automatically disable the HiFi coprocessor upon the switch. + */ + enotsup = false; +#endif + return enotsup ? -ENOTSUP : 0; +} + #ifdef CONFIG_USERSPACE FUNC_NORETURN void arch_user_mode_enter(k_thread_entry_t user_entry, void *p1, void *p2, void *p3) diff --git a/kernel/include/kernel_arch_interface.h b/kernel/include/kernel_arch_interface.h index 956856a2ffc..e9b946d234a 100644 --- a/kernel/include/kernel_arch_interface.h +++ b/kernel/include/kernel_arch_interface.h @@ -212,6 +212,14 @@ int arch_float_disable(struct k_thread *thread); int arch_float_enable(struct k_thread *thread, unsigned int options); #endif /* CONFIG_FPU && CONFIG_FPU_SHARING */ +/** + * @brief Disable coprocessor context preservation + * + * This function serves as a catchall for disabling the preservation of + * coprocessor context information when aborting a thread. + */ +int arch_coprocessors_disable(struct k_thread *thread); + #if defined(CONFIG_USERSPACE) && defined(CONFIG_ARCH_HAS_THREAD_PRIV_STACK_SPACE_GET) /** * @brief Obtain privileged stack usage information for the specified thread diff --git a/kernel/sched.c b/kernel/sched.c index fce7fc40fe9..7ed11942107 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -1281,9 +1281,7 @@ static ALWAYS_INLINE void halt_thread(struct k_thread *thread, uint8_t new_state return; } -#if defined(CONFIG_FPU) && defined(CONFIG_FPU_SHARING) - arch_float_disable(thread); -#endif /* CONFIG_FPU && CONFIG_FPU_SHARING */ + arch_coprocessors_disable(thread); SYS_PORT_TRACING_FUNC(k_thread, sched_abort, thread);