[mips*] Fix PR_SET_FPMODE issues with multi-threaded programs.
This commit is contained in:
parent
9f2cb7b094
commit
b101f08c76
|
@ -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 <aurel32@debian.org> Tue, 10 May 2016 23:58:07 +0200
|
||||||
|
|
||||||
linux (4.5.3-2) unstable; urgency=medium
|
linux (4.5.3-2) unstable; urgency=medium
|
||||||
|
|
||||||
* [s390x] PCI: Ignore zpci ABI changes; these functions are not used by
|
* [s390x] PCI: Ignore zpci ABI changes; these functions are not used by
|
||||||
|
|
42
debian/patches/bugfix/mips/MIPS-Disable-preemption-during-prctl-PR_SET_FP_MODE.patch
vendored
Normal file
42
debian/patches/bugfix/mips/MIPS-Disable-preemption-during-prctl-PR_SET_FP_MODE.patch
vendored
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
From: Paul Burton <paul.burton@imgtec.com>
|
||||||
|
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 <paul.burton@imgtec.com>
|
||||||
|
Fixes: 9791554b45a2 ("MIPS,prctl: add PR_[GS]ET_FP_MODE prctl options for MIPS")
|
||||||
|
Cc: stable <stable@vger.kernel.org> # 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
|
||||||
|
|
104
debian/patches/bugfix/mips/MIPS-Force-CPUs-to-lose-FP-context-during-mode-switc.patch
vendored
Normal file
104
debian/patches/bugfix/mips/MIPS-Force-CPUs-to-lose-FP-context-during-mode-switc.patch
vendored
Normal file
|
@ -0,0 +1,104 @@
|
||||||
|
From: Paul Burton <paul.burton@imgtec.com>
|
||||||
|
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 <paul.burton@imgtec.com>
|
||||||
|
Fixes: 9791554b45a2 ("MIPS,prctl: add PR_[GS]ET_FP_MODE prctl options for MIPS")
|
||||||
|
Cc: stable <stable@vger.kernel.org> # 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
|
||||||
|
|
|
@ -46,6 +46,8 @@ bugfix/x86/viafb-autoload-on-olpc-xo1.5-only.patch
|
||||||
|
|
||||||
# Arch bug fixes
|
# Arch bug fixes
|
||||||
bugfix/mips/MIPS-Allow-emulation-for-unaligned-LSDXC1-instructions.patch
|
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/vmxnet3-fix-lock-imbalance-in-vmxnet3_tq_xmit.patch
|
||||||
bugfix/x86/acpi-processor-request-native-thermal-interrupt-hand.patch
|
bugfix/x86/acpi-processor-request-native-thermal-interrupt-hand.patch
|
||||||
bugfix/arm/arm-dts-kirkwood-fix-sd-slot-default-configuration-f.patch
|
bugfix/arm/arm-dts-kirkwood-fix-sd-slot-default-configuration-f.patch
|
||||||
|
|
Loading…
Reference in New Issue