From 59903e2934199043ebc97a19d43813acaa3848da Mon Sep 17 00:00:00 2001 From: Katsuhiro Suzuki Date: Mon, 1 Feb 2021 15:16:53 +0900 Subject: [PATCH] kernel: arch: introduce k_float_enable() This patch introduce new API to enable FPU of thread. This is pair of existed k_float_disable() API. And also add empty arch_float_enable() into each architectures that have arch_float_disable(). The arc and riscv already implemented arch_float_enable() so I do not touch these implementations. Motivation: Current Zephyr implementation does not allow to use FPU on main and other system threads like as work queue. Users need to create an other thread with K_FP_REGS for floating point programs. Users can use FPU more easily if they can enable FPU on running threads. Signed-off-by: Katsuhiro Suzuki --- arch/arc/core/thread.c | 2 +- arch/arm/core/aarch32/thread.c | 6 ++++ arch/riscv/core/thread.c | 2 +- arch/sparc/core/thread.c | 5 ++++ arch/x86/core/ia32/float.c | 2 +- arch/x86/core/ia32/thread.c | 11 +++++++ include/arch/x86/ia32/arch.h | 31 -------------------- include/kernel.h | 40 ++++++++++++++++++++++++++ kernel/include/kernel_arch_interface.h | 19 ++++++++++++ kernel/thread.c | 9 ++++++ 10 files changed, 93 insertions(+), 34 deletions(-) diff --git a/arch/arc/core/thread.c b/arch/arc/core/thread.c index 669624cf071..0cf26ffae39 100644 --- a/arch/arc/core/thread.c +++ b/arch/arc/core/thread.c @@ -232,7 +232,7 @@ int arch_float_disable(struct k_thread *thread) } -int arch_float_enable(struct k_thread *thread) +int arch_float_enable(struct k_thread *thread, unsigned int options) { unsigned int key; diff --git a/arch/arm/core/aarch32/thread.c b/arch/arm/core/aarch32/thread.c index 509a86b1929..6978b8bd0bc 100644 --- a/arch/arm/core/aarch32/thread.c +++ b/arch/arm/core/aarch32/thread.c @@ -458,6 +458,12 @@ int arch_float_disable(struct k_thread *thread) return 0; } + +int arch_float_enable(struct k_thread *thread, unsigned int options) +{ + /* This is not supported in Cortex-M and Cortex-R does not have FPU */ + return -ENOTSUP; +} #endif /* CONFIG_FPU && CONFIG_FPU_SHARING */ /* Internal function for Cortex-M initialization, diff --git a/arch/riscv/core/thread.c b/arch/riscv/core/thread.c index 0513b070301..77d7b01a436 100644 --- a/arch/riscv/core/thread.c +++ b/arch/riscv/core/thread.c @@ -152,7 +152,7 @@ int arch_float_disable(struct k_thread *thread) } -int arch_float_enable(struct k_thread *thread) +int arch_float_enable(struct k_thread *thread, unsigned int options) { unsigned int key; diff --git a/arch/sparc/core/thread.c b/arch/sparc/core/thread.c index ee7e4e9b638..2d5df753615 100644 --- a/arch/sparc/core/thread.c +++ b/arch/sparc/core/thread.c @@ -78,4 +78,9 @@ int arch_float_disable(struct k_thread *thread) { return -ENOSYS; } + +int arch_float_enable(struct k_thread *thread, unsigned int options) +{ + return -ENOTSUP; +} #endif /* CONFIG_FPU_SHARING */ diff --git a/arch/x86/core/ia32/float.c b/arch/x86/core/ia32/float.c index 3f522320419..a4f78687e63 100644 --- a/arch/x86/core/ia32/float.c +++ b/arch/x86/core/ia32/float.c @@ -179,7 +179,7 @@ static inline void FpCtxInit(struct k_thread *thread) * The locking isn't really needed when the routine is called by a cooperative * thread (since context switching can't occur), but it is harmless. */ -void k_float_enable(struct k_thread *thread, unsigned int options) +void z_float_enable(struct k_thread *thread, unsigned int options) { unsigned int imask; struct k_thread *fp_owner; diff --git a/arch/x86/core/ia32/thread.c b/arch/x86/core/ia32/thread.c index dc46958ea8e..cff38e92f88 100644 --- a/arch/x86/core/ia32/thread.c +++ b/arch/x86/core/ia32/thread.c @@ -59,6 +59,17 @@ int arch_float_disable(struct k_thread *thread) return -ENOSYS; #endif /* CONFIG_LAZY_FPU_SHARING */ } + +extern int z_float_enable(struct k_thread *thread, unsigned int options); + +int arch_float_enable(struct k_thread *thread, unsigned int options) +{ +#if defined(CONFIG_LAZY_FPU_SHARING) + return z_float_enable(thread, options); +#else + return -ENOTSUP; +#endif /* CONFIG_LAZY_FPU_SHARING */ +} #endif /* CONFIG_FPU && CONFIG_FPU_SHARING */ void arch_new_thread(struct k_thread *thread, k_thread_stack_t *stack, diff --git a/include/arch/x86/ia32/arch.h b/include/arch/x86/ia32/arch.h index 5058cc7ecaa..11457b8f443 100644 --- a/include/arch/x86/ia32/arch.h +++ b/include/arch/x86/ia32/arch.h @@ -396,37 +396,6 @@ static ALWAYS_INLINE unsigned int arch_irq_lock(void) struct k_thread; -/** - * @brief Enable preservation of floating point context information. - * - * This routine informs the kernel that the specified thread (which may be - * the current thread) will be using the floating point registers. - * The @a options parameter indicates which floating point register sets - * will be used by the specified thread: - * - * - K_FP_REGS indicates x87 FPU and MMX registers only - * - K_SSE_REGS indicates SSE registers (and also x87 FPU and MMX registers) - * - * Invoking this routine initializes the thread's floating point context info - * to that of an FPU that has been reset. The next time the thread is scheduled - * by z_swap() it will either inherit an FPU that is guaranteed to be in a "sane" - * state (if the most recent user of the FPU was cooperatively swapped out) - * or the thread's own floating point context will be loaded (if the most - * recent user of the FPU was preempted, or if this thread is the first user - * of the FPU). Thereafter, the kernel will protect the thread's FP context - * so that it is not altered during a preemptive context switch. - * - * @warning - * This routine should only be used to enable floating point support for a - * thread that does not currently have such support enabled already. - * - * @param thread ID of thread. - * @param options Registers to be preserved (K_FP_REGS or K_SSE_REGS). - * - * @return N/A - */ -extern void k_float_enable(struct k_thread *thread, unsigned int options); - /** * @} */ diff --git a/include/kernel.h b/include/kernel.h index ee7aa34504e..66c56b80a4f 100644 --- a/include/kernel.h +++ b/include/kernel.h @@ -5544,6 +5544,46 @@ __syscall void k_str_out(char *c, size_t n); */ __syscall int k_float_disable(struct k_thread *thread); +/** + * @brief Enable preservation of floating point context information. + * + * This routine informs the kernel that the specified thread + * will use the floating point registers. + + * Invoking this routine initializes the thread's floating point context info + * to that of an FPU that has been reset. The next time the thread is scheduled + * by z_swap() it will either inherit an FPU that is guaranteed to be in a + * "sane" state (if the most recent user of the FPU was cooperatively swapped + * out) or the thread's own floating point context will be loaded (if the most + * recent user of the FPU was preempted, or if this thread is the first user + * of the FPU). Thereafter, the kernel will protect the thread's FP context + * so that it is not altered during a preemptive context switch. + * + * The @a options parameter indicates which floating point register sets will + * be used by the specified thread. + * + * For x86 options: + * + * - K_FP_REGS indicates x87 FPU and MMX registers only + * - K_SSE_REGS indicates SSE registers (and also x87 FPU and MMX registers) + * + * @warning + * Some architectures apply restrictions on how the enabling of floating + * point preservation may be requested, see arch_float_enable. + * + * @warning + * This routine should only be used to enable floating point support for + * a thread that currently has such support enabled. + * + * @param thread ID of thread. + * @param options architecture dependent options + * + * @retval 0 On success. + * @retval -ENOTSUP If the floating point enabling is not implemented. + * -EINVAL If the floating point enabling could not be performed. + */ +__syscall int k_float_enable(struct k_thread *thread, unsigned int options); + #ifdef CONFIG_THREAD_RUNTIME_STATS /** diff --git a/kernel/include/kernel_arch_interface.h b/kernel/include/kernel_arch_interface.h index 796e8f02380..eb0e853600a 100644 --- a/kernel/include/kernel_arch_interface.h +++ b/kernel/include/kernel_arch_interface.h @@ -185,6 +185,25 @@ void arch_switch_to_main_thread(struct k_thread *main_thread, char *stack_ptr, * @retval -EINVAL If the floating point disabling could not be performed. */ int arch_float_disable(struct k_thread *thread); + +/** + * @brief Enable floating point context preservation + * + * The function is used to enable the preservation of floating + * point context information for a particular thread. + * This API depends on each architecture implimentation. If the architecture + * does not support enableing, this API will always be failed. + * + * The @a options parameter indicates which floating point register sets will + * be used by the specified thread. Currently it is used by x86 only. + * + * @param thread ID of thread. + * @param options architecture dependent options + * + * @retval 0 On success. + * @retval -EINVAL If the floating point enabling could not be performed. + */ +int arch_float_enable(struct k_thread *thread, unsigned int options); #endif /* CONFIG_FPU && CONFIG_FPU_SHARING */ /** @} */ diff --git a/kernel/thread.c b/kernel/thread.c index d91db4960e9..d479b46b2f7 100644 --- a/kernel/thread.c +++ b/kernel/thread.c @@ -884,6 +884,15 @@ int z_impl_k_float_disable(struct k_thread *thread) #endif /* CONFIG_FPU && CONFIG_FPU_SHARING */ } +int z_impl_k_float_enable(struct k_thread *thread, unsigned int options) +{ +#if defined(CONFIG_FPU) && defined(CONFIG_FPU_SHARING) + return arch_float_enable(thread, options); +#else + return -ENOTSUP; +#endif /* CONFIG_FPU && CONFIG_FPU_SHARING */ +} + #ifdef CONFIG_USERSPACE static inline int z_vrfy_k_float_disable(struct k_thread *thread) {