diff options
author | Sebastian Andrzej Siewior <bigeasy@linutronix.de> | 2022-05-05 18:32:05 +0200 |
---|---|---|
committer | Catalin Marinas <catalin.marinas@arm.com> | 2022-05-16 19:15:45 +0100 |
commit | a1259dd807192917eb98603f8bc7b43f70cea5b9 (patch) | |
tree | 780ca2f8950d839bd188b920a72781a6baa433e4 /arch/arm64 | |
parent | d158a0608eb85f29f98357b97d01b80250636613 (diff) | |
download | linux-a1259dd807192917eb98603f8bc7b43f70cea5b9.tar.gz |
arm64/sve: Delay freeing memory in fpsimd_flush_thread()
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>
Diffstat (limited to 'arch/arm64')
-rw-r--r-- | arch/arm64/kernel/fpsimd.c | 17 |
1 files changed, 15 insertions, 2 deletions
diff --git a/arch/arm64/kernel/fpsimd.c b/arch/arm64/kernel/fpsimd.c index 64431bc62472..6e53badff8a6 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); } /* |