diff mbox series

[1/3] arm64/sve: Delay freeing memory in fpsimd_flush_thread()

Message ID 20220505163207.85751-2-bigeasy@linutronix.de (mailing list archive)
State New, archived
Headers show
Series arm64 related PREEMPT_RT patches. | expand

Commit Message

Sebastian Andrzej Siewior May 5, 2022, 4:32 p.m. UTC
fpsimd_flush_thread() invokes kfree() via sve_free()+sme_free() within a
preempt disabled section which is not working on -RT.

Delay freeing of memory until preemption is enabled again.

Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
---
 arch/arm64/kernel/fpsimd.c | 17 +++++++++++++++--
 1 file changed, 15 insertions(+), 2 deletions(-)

Comments

Mark Brown May 10, 2022, 6:31 p.m. UTC | #1
On Thu, May 05, 2022 at 06:32:05PM +0200, Sebastian Andrzej Siewior wrote:
> fpsimd_flush_thread() invokes kfree() via sve_free()+sme_free() within a
> preempt disabled section which is not working on -RT.

Reviewed-by: Mark Brown <broonie@kernel.org>

It'd be better to copy people actively working on the specific code
you're patching as well as the architecture maintainers, it helps things
get noticed for review.
diff mbox series

Patch

diff --git a/arch/arm64/kernel/fpsimd.c b/arch/arm64/kernel/fpsimd.c
index 95a733d3b2538..475939beb0167 100644
--- a/arch/arm64/kernel/fpsimd.c
+++ b/arch/arm64/kernel/fpsimd.c
@@ -1562,6 +1562,9 @@  static void fpsimd_flush_thread_vl(enum vec_type type)
 
 void fpsimd_flush_thread(void)
 {
+	void *sve_state = NULL;
+	void *za_state = NULL;
+
 	if (!system_supports_fpsimd())
 		return;
 
@@ -1573,18 +1576,28 @@  void fpsimd_flush_thread(void)
 
 	if (system_supports_sve()) {
 		clear_thread_flag(TIF_SVE);
-		sve_free(current);
+
+		/* Defer kfree() while in atomic context */
+		sve_state = current->thread.sve_state;
+		current->thread.sve_state = NULL;
+
 		fpsimd_flush_thread_vl(ARM64_VEC_SVE);
 	}
 
 	if (system_supports_sme()) {
 		clear_thread_flag(TIF_SME);
-		sme_free(current);
+
+		/* Defer kfree() while in atomic context */
+		za_state = current->thread.za_state;
+		current->thread.za_state = NULL;
+
 		fpsimd_flush_thread_vl(ARM64_VEC_SME);
 		current->thread.svcr = 0;
 	}
 
 	put_cpu_fpsimd_context();
+	kfree(sve_state);
+	kfree(za_state);
 }
 
 /*