aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm64/kernel/fpsimd.c
diff options
context:
space:
mode:
authorSebastian Andrzej Siewior <bigeasy@linutronix.de>2022-05-05 18:32:05 +0200
committerCatalin Marinas <catalin.marinas@arm.com>2022-05-16 19:15:45 +0100
commita1259dd807192917eb98603f8bc7b43f70cea5b9 (patch)
tree780ca2f8950d839bd188b920a72781a6baa433e4 /arch/arm64/kernel/fpsimd.c
parentarm64/sme: More sensibly define the size for the ZA register set (diff)
downloadlinux-dev-a1259dd807192917eb98603f8bc7b43f70cea5b9.tar.xz
linux-dev-a1259dd807192917eb98603f8bc7b43f70cea5b9.zip
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/kernel/fpsimd.c')
-rw-r--r--arch/arm64/kernel/fpsimd.c17
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);
}
/*