From b101f08c765a1c1c91afc4bb79d8a7375ce88021 Mon Sep 17 00:00:00 2001 From: Aurelien Jarno Date: Wed, 11 May 2016 00:15:41 +0200 Subject: [PATCH] [mips*] Fix PR_SET_FPMODE issues with multi-threaded programs. --- debian/changelog | 7 ++ ...eemption-during-prctl-PR_SET_FP_MODE.patch | 42 +++++++ ...to-lose-FP-context-during-mode-switc.patch | 104 ++++++++++++++++++ debian/patches/series | 2 + 4 files changed, 155 insertions(+) create mode 100644 debian/patches/bugfix/mips/MIPS-Disable-preemption-during-prctl-PR_SET_FP_MODE.patch create mode 100644 debian/patches/bugfix/mips/MIPS-Force-CPUs-to-lose-FP-context-during-mode-switc.patch diff --git a/debian/changelog b/debian/changelog index f01683d77..76dd3feed 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,10 @@ +linux (4.5.3-3) UNRELEASED; urgency=medium + + [ Aurelien Jarno ] + * [mips*] Fix PR_SET_FPMODE issues with multi-threaded programs. + + -- Aurelien Jarno Tue, 10 May 2016 23:58:07 +0200 + linux (4.5.3-2) unstable; urgency=medium * [s390x] PCI: Ignore zpci ABI changes; these functions are not used by diff --git a/debian/patches/bugfix/mips/MIPS-Disable-preemption-during-prctl-PR_SET_FP_MODE.patch b/debian/patches/bugfix/mips/MIPS-Disable-preemption-during-prctl-PR_SET_FP_MODE.patch new file mode 100644 index 000000000..4aac015c3 --- /dev/null +++ b/debian/patches/bugfix/mips/MIPS-Disable-preemption-during-prctl-PR_SET_FP_MODE.patch @@ -0,0 +1,42 @@ +From: Paul Burton +Date: Thu, 21 Apr 2016 12:43:57 +0100 +Subject: [1/2] MIPS: Disable preemption during prctl(PR_SET_FP_MODE, ...) +Origin: https://patchwork.linux-mips.org/patch/13144/ + +Whilst a PR_SET_FP_MODE prctl is performed there are decisions made +based upon whether the task is executing on the current CPU. This may +change if we're preempted, so disable preemption to avoid such changes +for the lifetime of the mode switch. + +Signed-off-by: Paul Burton +Fixes: 9791554b45a2 ("MIPS,prctl: add PR_[GS]ET_FP_MODE prctl options for MIPS") +Cc: stable # v4.0+ +--- + arch/mips/kernel/process.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/arch/mips/kernel/process.c b/arch/mips/kernel/process.c +index 92880ce..ce55ea0 100644 +--- a/arch/mips/kernel/process.c ++++ b/arch/mips/kernel/process.c +@@ -601,6 +601,9 @@ int mips_set_process_fp_mode(struct task_struct *task, unsigned int value) + if (!(value & PR_FP_MODE_FR) && cpu_has_fpu && cpu_has_mips_r6) + return -EOPNOTSUPP; + ++ /* Proceed with the mode switch */ ++ preempt_disable(); ++ + /* Save FP & vector context, then disable FPU & MSA */ + if (task->signal == current->signal) + lose_fpu(1); +@@ -659,6 +662,7 @@ int mips_set_process_fp_mode(struct task_struct *task, unsigned int value) + + /* Allow threads to use FP again */ + atomic_set(&task->mm->context.fp_mode_switching, 0); ++ preempt_enable(); + + return 0; + } +-- +2.8.1 + diff --git a/debian/patches/bugfix/mips/MIPS-Force-CPUs-to-lose-FP-context-during-mode-switc.patch b/debian/patches/bugfix/mips/MIPS-Force-CPUs-to-lose-FP-context-during-mode-switc.patch new file mode 100644 index 000000000..9619c587e --- /dev/null +++ b/debian/patches/bugfix/mips/MIPS-Force-CPUs-to-lose-FP-context-during-mode-switc.patch @@ -0,0 +1,104 @@ +From: Paul Burton +Date: Thu, 21 Apr 2016 12:43:58 +0100 +Subject: [2/2] MIPS: Force CPUs to lose FP context during mode switches +Origin: https://patchwork.linux-mips.org/patch/13145/ + +Commit 9791554b45a2 ("MIPS,prctl: add PR_[GS]ET_FP_MODE prctl options +for MIPS") added support for the PR_SET_FP_MODE prctl, which allows a +userland program to modify its FP mode at runtime. This is most notably +required if dynamic linking leads to the FP mode requirement changing at +runtime from that indicated in the initial executable's ELF header. In +order to avoid overhead in the general FP context restore code, it aimed +to have threads in the process become unable to enable the FPU during a +mode switch & have the thread calling the prctl syscall wait for all +other threads in the process to be context switched at least once. Once +that happens we can know that no thread in the process whose mode will +be switched has live FP context, and it's safe to perform the mode +switch. However in the (rare) case of modeswitches occurring in +multithreaded programs this can lead to indeterminate delays for the +thread invoking the prctl syscall, and the code monitoring for those +context switches was woefully inadequate for all but the simplest cases. + +Fix this by broadcasting an IPI if other CPUs may have live FP context +for an affected thread, with a handler causing those CPUs to relinquish +their FPU ownership. Threads will then be allowed to continue running +but will stall on the wait_on_atomic_t in enable_restore_fp_context if +they attempt to use FP again whilst the mode switch is still in +progress. The end result is less fragile poking at scheduler context +switch counts & a more expedient completion of the mode switch. + +Signed-off-by: Paul Burton +Fixes: 9791554b45a2 ("MIPS,prctl: add PR_[GS]ET_FP_MODE prctl options for MIPS") +Cc: stable # v4.0+ +--- + arch/mips/kernel/process.c | 40 +++++++++++++++++----------------------- + 1 file changed, 17 insertions(+), 23 deletions(-) + +diff --git a/arch/mips/kernel/process.c b/arch/mips/kernel/process.c +index ce55ea0..e1b36a4 100644 +--- a/arch/mips/kernel/process.c ++++ b/arch/mips/kernel/process.c +@@ -580,11 +580,19 @@ int mips_get_process_fp_mode(struct task_struct *task) + return value; + } + ++static void prepare_for_fp_mode_switch(void *info) ++{ ++ struct mm_struct *mm = info; ++ ++ if (current->mm == mm) ++ lose_fpu(1); ++} ++ + int mips_set_process_fp_mode(struct task_struct *task, unsigned int value) + { + const unsigned int known_bits = PR_FP_MODE_FR | PR_FP_MODE_FRE; +- unsigned long switch_count; + struct task_struct *t; ++ int max_users; + + /* Check the value is valid */ + if (value & ~known_bits) +@@ -613,31 +621,17 @@ int mips_set_process_fp_mode(struct task_struct *task, unsigned int value) + smp_mb__after_atomic(); + + /* +- * If there are multiple online CPUs then wait until all threads whose +- * FP mode is about to change have been context switched. This approach +- * allows us to only worry about whether an FP mode switch is in +- * progress when FP is first used in a tasks time slice. Pretty much all +- * of the mode switch overhead can thus be confined to cases where mode +- * switches are actually occuring. That is, to here. However for the +- * thread performing the mode switch it may take a while... ++ * If there are multiple online CPUs then force any which are running ++ * threads in this process to lose their FPU context, which they can't ++ * regain until fp_mode_switching is cleared later. + */ + if (num_online_cpus() > 1) { +- spin_lock_irq(&task->sighand->siglock); +- +- for_each_thread(task, t) { +- if (t == current) +- continue; +- +- switch_count = t->nvcsw + t->nivcsw; +- +- do { +- spin_unlock_irq(&task->sighand->siglock); +- cond_resched(); +- spin_lock_irq(&task->sighand->siglock); +- } while ((t->nvcsw + t->nivcsw) == switch_count); +- } ++ /* No need to send an IPI for the local CPU */ ++ max_users = (task->mm == current->mm) ? 1 : 0; + +- spin_unlock_irq(&task->sighand->siglock); ++ if (atomic_read(¤t->mm->mm_users) > max_users) ++ smp_call_function(prepare_for_fp_mode_switch, ++ (void *)current->mm, 1); + } + + /* +-- +2.8.1 + diff --git a/debian/patches/series b/debian/patches/series index d4fe6923d..7bacabe55 100644 --- a/debian/patches/series +++ b/debian/patches/series @@ -46,6 +46,8 @@ bugfix/x86/viafb-autoload-on-olpc-xo1.5-only.patch # Arch bug fixes bugfix/mips/MIPS-Allow-emulation-for-unaligned-LSDXC1-instructions.patch +bugfix/mips/MIPS-Disable-preemption-during-prctl-PR_SET_FP_MODE.patch +bugfix/mips/MIPS-Force-CPUs-to-lose-FP-context-during-mode-switc.patch bugfix/x86/vmxnet3-fix-lock-imbalance-in-vmxnet3_tq_xmit.patch bugfix/x86/acpi-processor-request-native-thermal-interrupt-hand.patch bugfix/arm/arm-dts-kirkwood-fix-sd-slot-default-configuration-f.patch