Commit bdef750d authored by Paul Mackerras's avatar Paul Mackerras Committed by Linus Torvalds

[PATCH] PPC/PPC64: Fix FP state corruption on UP

Unfortunately the patch Ben sent last week to fix a bug in the saving and
restoring of floating-point and altivec context across signal handlers
introduced another bug, which tends to corrupt the FP and altivec contexts
of other tasks.  This patch fixes the problem for both ppc32 and ppc64. 
Signed-off-by: default avatarPaul Mackerras <paulus@samba.org>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 5a67930c
......@@ -290,7 +290,7 @@ restore_user_regs(struct pt_regs *regs, struct mcontext __user *sr, int sig)
/* force the process to reload the FP registers from
current->thread when it next does FP instructions */
regs->msr &= ~MSR_FP;
regs->msr &= ~(MSR_FP | MSR_FE0 | MSR_FE1);
if (__copy_from_user(current->thread.fpr, &sr->mc_fregs,
sizeof(sr->mc_fregs)))
return 1;
......@@ -330,9 +330,14 @@ restore_user_regs(struct pt_regs *regs, struct mcontext __user *sr, int sig)
#endif /* CONFIG_SPE */
#ifndef CONFIG_SMP
last_task_used_math = NULL;
last_task_used_altivec = NULL;
last_task_used_spe = NULL;
preempt_disable();
if (last_task_used_math == current)
last_task_used_math = NULL;
if (last_task_used_altivec == current)
last_task_used_altivec = NULL;
if (last_task_used_spe == current)
last_task_used_spe = NULL;
preempt_enable();
#endif
return 0;
}
......
......@@ -224,8 +224,12 @@ static long restore_sigcontext(struct pt_regs *regs, sigset_t *set, int sig,
#endif /* CONFIG_ALTIVEC */
#ifndef CONFIG_SMP
last_task_used_math = NULL;
last_task_used_altivec = NULL;
preempt_disable();
if (last_task_used_math == current)
last_task_used_math = NULL;
if (last_task_used_altivec == current)
last_task_used_altivec = NULL;
preempt_enable();
#endif
/* Force reload of FP/VEC */
regs->msr &= ~(MSR_FP | MSR_FE0 | MSR_FE1 | MSR_VEC);
......
......@@ -235,8 +235,12 @@ static long restore_user_regs(struct pt_regs *regs,
#endif /* CONFIG_ALTIVEC */
#ifndef CONFIG_SMP
last_task_used_math = NULL;
last_task_used_altivec = NULL;
preempt_disable();
if (last_task_used_math == current)
last_task_used_math = NULL;
if (last_task_used_altivec == current)
last_task_used_altivec = NULL;
preempt_enable();
#endif
return 0;
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment