From 232b781c602a68cf7cd8dbe523ca4d88212a55a9 Mon Sep 17 00:00:00 2001 From: meganz009 Date: Mon, 5 Jun 2023 15:16:08 +0800 Subject: [PATCH 1/2] x86/fpu: Simplify fpregs_[un]lock() commit 721903d6208517a2e07f4b3a49562bad9d6e342a upstream. There is no point in disabling preemption and then disabling bottom halfs. Just disabling bottom halfs is sufficient as it implicitly disables preemption on !RT kernels. Signed-off-by: Thomas Gleixner Link: https://lore.kernel.org/r/20201027101349.455380473@linutronix.de Signed-off-by: Sebastian Andrzej Siewior --- arch/x86/include/asm/fpu/api.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/arch/x86/include/asm/fpu/api.h b/arch/x86/include/asm/fpu/api.h index 7c8f544f71f5..41e54c6a83a3 100644 --- a/arch/x86/include/asm/fpu/api.h +++ b/arch/x86/include/asm/fpu/api.h @@ -42,17 +42,18 @@ static inline void kernel_fpu_begin(void) * A context switch will (and softirq might) save CPU's FPU registers to * fpu->fpstate.regs and set TIF_NEED_FPU_LOAD leaving CPU's FPU registers in * a random state. + * + * local_bh_disable() protects against both preemption and soft interrupts + * on !RT kernels. */ static inline void fpregs_lock(void) { - preempt_disable(); local_bh_disable(); } static inline void fpregs_unlock(void) { local_bh_enable(); - preempt_enable(); } #ifdef CONFIG_X86_DEBUG_FPU -- Gitee From 5d47ea65f01f5b8af69e334635566598844befbf Mon Sep 17 00:00:00 2001 From: meganz009 Date: Mon, 5 Jun 2023 15:16:16 +0800 Subject: [PATCH 2/2] x86/fpu: Make kernel FPU protection RT friendly commit 9b19a3560b8d730c4d5c88effb46cd46450cffdf upstream. Non RT kernels need to protect FPU against preemption and bottom half processing. This is achieved by disabling bottom halfs via local_bh_disable() which implictly disables preemption. On RT kernels this protection mechanism is not sufficient because local_bh_disable() does not disable preemption. It serializes bottom half related processing via a CPU local lock. As bottom halfs are running always in thread context on RT kernels disabling preemption is the proper choice as it implicitly prevents bottom half processing. Signed-off-by: Thomas Gleixner Link: https://lore.kernel.org/r/20201027101349.588965083@linutronix.de Signed-off-by: Sebastian Andrzej Siewior --- arch/x86/include/asm/fpu/api.h | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/arch/x86/include/asm/fpu/api.h b/arch/x86/include/asm/fpu/api.h index 41e54c6a83a3..4c48f1b208c9 100644 --- a/arch/x86/include/asm/fpu/api.h +++ b/arch/x86/include/asm/fpu/api.h @@ -45,15 +45,29 @@ static inline void kernel_fpu_begin(void) * * local_bh_disable() protects against both preemption and soft interrupts * on !RT kernels. + * + * On RT kernels local_bh_disable() is not sufficient because it only + * serializes soft interrupt related sections via a local lock, but stays + * preemptible. Disabling preemption is the right choice here as bottom + * half processing is always in thread context on RT kernels so it + * implicitly prevents bottom half processing as well. + * + * Disabling preemption also serializes against kernel_fpu_begin(). */ static inline void fpregs_lock(void) { - local_bh_disable(); + if (!IS_ENABLED(CONFIG_PREEMPT_RT)) + local_bh_disable(); + else + preempt_disable(); } static inline void fpregs_unlock(void) { - local_bh_enable(); + if (!IS_ENABLED(CONFIG_PREEMPT_RT)) + local_bh_enable(); + else + preempt_enable(); } #ifdef CONFIG_X86_DEBUG_FPU -- Gitee