Konstantin Demin
c3d09a3e94
imported from https://salsa.debian.org/kernel-team/linux.git commit 9d5cc9d9d6501d7f1dd7e194d4b245bd0b6c6a22 version 6.11.4-1
76 lines
2.4 KiB
Diff
76 lines
2.4 KiB
Diff
From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
|
|
Date: Fri, 19 May 2023 16:57:29 +0200
|
|
Subject: [PATCH 1/4] ARM: vfp: Provide vfp_lock() for VFP locking.
|
|
Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.11/older/patches-6.11-rt7.tar.xz
|
|
|
|
kernel_neon_begin() uses local_bh_disable() to ensure exclusive access
|
|
to the VFP unit. This is broken on PREEMPT_RT because a BH disabled
|
|
section remains preemptible on PREEMPT_RT.
|
|
|
|
Introduce vfp_lock() which uses local_bh_disable() and preempt_disable()
|
|
on PREEMPT_RT. Since softirqs are processed always in thread context,
|
|
disabling preemption is enough to ensure that the current context won't
|
|
get interrupted by something that is using the VFP. Use it in
|
|
kernel_neon_begin().
|
|
|
|
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
|
|
---
|
|
arch/arm/vfp/vfpmodule.c | 32 ++++++++++++++++++++++++++++++--
|
|
1 file changed, 30 insertions(+), 2 deletions(-)
|
|
|
|
--- a/arch/arm/vfp/vfpmodule.c
|
|
+++ b/arch/arm/vfp/vfpmodule.c
|
|
@@ -56,6 +56,34 @@ extern unsigned int VFP_arch_feroceon __
|
|
union vfp_state *vfp_current_hw_state[NR_CPUS];
|
|
|
|
/*
|
|
+ * Claim ownership of the VFP unit.
|
|
+ *
|
|
+ * The caller may change VFP registers until vfp_unlock() is called.
|
|
+ *
|
|
+ * local_bh_disable() is used to disable preemption and to disable VFP
|
|
+ * processing in softirq context. On PREEMPT_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.
|
|
+ */
|
|
+static void vfp_lock(void)
|
|
+{
|
|
+ if (!IS_ENABLED(CONFIG_PREEMPT_RT))
|
|
+ local_bh_disable();
|
|
+ else
|
|
+ preempt_disable();
|
|
+}
|
|
+
|
|
+static void vfp_unlock(void)
|
|
+{
|
|
+ if (!IS_ENABLED(CONFIG_PREEMPT_RT))
|
|
+ local_bh_enable();
|
|
+ else
|
|
+ preempt_enable();
|
|
+}
|
|
+
|
|
+/*
|
|
* Is 'thread's most up to date state stored in this CPUs hardware?
|
|
* Must be called from non-preemptible context.
|
|
*/
|
|
@@ -837,7 +865,7 @@ void kernel_neon_begin(void)
|
|
unsigned int cpu;
|
|
u32 fpexc;
|
|
|
|
- local_bh_disable();
|
|
+ vfp_lock();
|
|
|
|
/*
|
|
* Kernel mode NEON is only allowed outside of hardirq context with
|
|
@@ -868,7 +896,7 @@ void kernel_neon_end(void)
|
|
{
|
|
/* Disable the NEON/VFP unit. */
|
|
fmxr(FPEXC, fmrx(FPEXC) & ~FPEXC_EN);
|
|
- local_bh_enable();
|
|
+ vfp_unlock();
|
|
}
|
|
EXPORT_SYMBOL(kernel_neon_end);
|
|
|