arm64/sve: Delay freeing memory in fpsimd_flush_thread()
authorSebastian Andrzej Siewior <bigeasy@linutronix.de>
Thu, 5 May 2022 16:32:05 +0000 (18:32 +0200)
committerCatalin Marinas <catalin.marinas@arm.com>
Mon, 16 May 2022 18:15:45 +0000 (19:15 +0100)
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>
Reviewed-by: Mark Brown <broonie@kernel.org>
Link: https://lore.kernel.org/r/20220505163207.85751-2-bigeasy@linutronix.de
Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
arch/arm64/kernel/fpsimd.c

index 64431bc..6e53bad 100644 (file)
@@ -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);
 }
 
 /*