floating point register corruption

From: Paolo Galtieri
Date: Tue Nov 29 2005 - 14:23:49 EST


Folks,
I recently discovered a bug on PPC which causes the floating
point registers to get corrupted when CONFIG_PREEMPT=y.

The problem occurred while running a multi threaded Java application
that does floating point. The problem could be reproduced in
anywhere from 2 to 6 hours. With the patch I have included below
it ran for over a week without failure.

Paolo

Signed-off-by: pgaltieri@xxxxxxxxxx

--- linux-2.6.15-rc3/arch/ppc/kernel/process.c 2005-11-29
07:01:55.000000000 -0700
+++ new-linux-2.6.15-rc3/arch/ppc/kernel/process.c 2005-11-29
07:20:37.000000000 -0700
@@ -417,6 +417,7 @@

void exit_thread(void)
{
+ preempt_disable();
if (last_task_used_math == current)
last_task_used_math = NULL;
if (last_task_used_altivec == current)
@@ -425,10 +426,12 @@
if (last_task_used_spe == current)
last_task_used_spe = NULL;
#endif
+ preempt_enable();
}

void flush_thread(void)
{
+ preempt_disable();
if (last_task_used_math == current)
last_task_used_math = NULL;
if (last_task_used_altivec == current)
@@ -437,6 +440,7 @@
if (last_task_used_spe == current)
last_task_used_spe = NULL;
#endif
+ preempt_enable();
}

void
@@ -535,6 +539,7 @@
regs->nip = nip;
regs->gpr[1] = sp;
regs->msr = MSR_USER;
+ preempt_disable();
if (last_task_used_math == current)
last_task_used_math = NULL;
if (last_task_used_altivec == current)
@@ -543,6 +548,7 @@
if (last_task_used_spe == current)
last_task_used_spe = NULL;
#endif
+ preempt_enable();
memset(current->thread.fpr, 0, sizeof(current->thread.fpr));
current->thread.fpscr.val = 0;
#ifdef CONFIG_ALTIVEC


-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/