diff options
Diffstat (limited to 'debian/patches-rt/0212-arm64-fpsimd-use-preemp_disable-in-addition-to-local.patch')
-rw-r--r-- | debian/patches-rt/0212-arm64-fpsimd-use-preemp_disable-in-addition-to-local.patch | 171 |
1 files changed, 171 insertions, 0 deletions
diff --git a/debian/patches-rt/0212-arm64-fpsimd-use-preemp_disable-in-addition-to-local.patch b/debian/patches-rt/0212-arm64-fpsimd-use-preemp_disable-in-addition-to-local.patch new file mode 100644 index 000000000..5ac88e5fe --- /dev/null +++ b/debian/patches-rt/0212-arm64-fpsimd-use-preemp_disable-in-addition-to-local.patch @@ -0,0 +1,171 @@ +From e6eac38976a1eebb792eb6a02fd95ed0868576fc Mon Sep 17 00:00:00 2001 +From: Sebastian Andrzej Siewior <bigeasy@linutronix.de> +Date: Wed, 25 Jul 2018 14:02:38 +0200 +Subject: [PATCH 212/347] arm64: fpsimd: use preemp_disable in addition to + local_bh_disable() +Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/4.19/older/patches-4.19.246-rt110.tar.xz + +In v4.16-RT I noticed a number of warnings from task_fpsimd_load(). The +code disables BH and expects that it is not preemptible. On -RT the +task remains preemptible but remains the same CPU. This may corrupt the +content of the SIMD registers if the task is preempted during +saving/restoring those registers. + +Add preempt_disable()/enable() to enfore the required semantic on -RT. + +Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> +--- + arch/arm64/kernel/fpsimd.c | 31 +++++++++++++++++++++++++++++-- + 1 file changed, 29 insertions(+), 2 deletions(-) + +diff --git a/arch/arm64/kernel/fpsimd.c b/arch/arm64/kernel/fpsimd.c +index 89ab68cb35bb..481793a5adc1 100644 +--- a/arch/arm64/kernel/fpsimd.c ++++ b/arch/arm64/kernel/fpsimd.c +@@ -159,6 +159,16 @@ static void sve_free(struct task_struct *task) + __sve_free(task); + } + ++static void *sve_free_atomic(struct task_struct *task) ++{ ++ void *sve_state = task->thread.sve_state; ++ ++ WARN_ON(test_tsk_thread_flag(task, TIF_SVE)); ++ ++ task->thread.sve_state = NULL; ++ return sve_state; ++} ++ + /* + * TIF_SVE controls whether a task can use SVE without trapping while + * in userspace, and also the way a task's FPSIMD/SVE state is stored +@@ -549,6 +559,7 @@ int sve_set_vector_length(struct task_struct *task, + * non-SVE thread. + */ + if (task == current) { ++ preempt_disable(); + local_bh_disable(); + + fpsimd_save(); +@@ -559,8 +570,10 @@ int sve_set_vector_length(struct task_struct *task, + if (test_and_clear_tsk_thread_flag(task, TIF_SVE)) + sve_to_fpsimd(task); + +- if (task == current) ++ if (task == current) { + local_bh_enable(); ++ preempt_enable(); ++ } + + /* + * Force reallocation of task SVE state to the correct size +@@ -815,6 +828,7 @@ asmlinkage void do_sve_acc(unsigned int esr, struct pt_regs *regs) + + sve_alloc(current); + ++ preempt_disable(); + local_bh_disable(); + + fpsimd_save(); +@@ -828,6 +842,7 @@ asmlinkage void do_sve_acc(unsigned int esr, struct pt_regs *regs) + WARN_ON(1); /* SVE access shouldn't have trapped */ + + local_bh_enable(); ++ preempt_enable(); + } + + /* +@@ -894,10 +909,12 @@ void fpsimd_thread_switch(struct task_struct *next) + void fpsimd_flush_thread(void) + { + int vl, supported_vl; ++ void *mem = NULL; + + if (!system_supports_fpsimd()) + return; + ++ preempt_disable(); + local_bh_disable(); + + memset(¤t->thread.uw.fpsimd_state, 0, +@@ -906,7 +923,7 @@ void fpsimd_flush_thread(void) + + if (system_supports_sve()) { + clear_thread_flag(TIF_SVE); +- sve_free(current); ++ mem = sve_free_atomic(current); + + /* + * Reset the task vector length as required. +@@ -942,6 +959,8 @@ void fpsimd_flush_thread(void) + set_thread_flag(TIF_FOREIGN_FPSTATE); + + local_bh_enable(); ++ preempt_enable(); ++ kfree(mem); + } + + /* +@@ -953,9 +972,11 @@ void fpsimd_preserve_current_state(void) + if (!system_supports_fpsimd()) + return; + ++ preempt_disable(); + local_bh_disable(); + fpsimd_save(); + local_bh_enable(); ++ preempt_enable(); + } + + /* +@@ -1026,6 +1047,7 @@ void fpsimd_restore_current_state(void) + return; + } + ++ preempt_disable(); + local_bh_disable(); + + if (test_and_clear_thread_flag(TIF_FOREIGN_FPSTATE)) { +@@ -1034,6 +1056,7 @@ void fpsimd_restore_current_state(void) + } + + local_bh_enable(); ++ preempt_enable(); + } + + /* +@@ -1046,6 +1069,7 @@ void fpsimd_update_current_state(struct user_fpsimd_state const *state) + if (WARN_ON(!system_supports_fpsimd())) + return; + ++ preempt_disable(); + local_bh_disable(); + + current->thread.uw.fpsimd_state = *state; +@@ -1058,6 +1082,7 @@ void fpsimd_update_current_state(struct user_fpsimd_state const *state) + clear_thread_flag(TIF_FOREIGN_FPSTATE); + + local_bh_enable(); ++ preempt_enable(); + } + + /* +@@ -1104,6 +1129,7 @@ void kernel_neon_begin(void) + + BUG_ON(!may_use_simd()); + ++ preempt_disable(); + local_bh_disable(); + + __this_cpu_write(kernel_neon_busy, true); +@@ -1117,6 +1143,7 @@ void kernel_neon_begin(void) + preempt_disable(); + + local_bh_enable(); ++ preempt_enable(); + } + EXPORT_SYMBOL(kernel_neon_begin); + +-- +2.36.1 + |