Skip to content

Commit 8117ce7

Browse files
Paolo Galtieripaulusmack
authored andcommitted
[PATCH] ppc: fix floating point register corruption
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. Signed-off-by: Paolo Galtieri <[email protected]> Cc: Kumar Gala <[email protected]> Cc: Matt Porter <[email protected]> Cc: Tom Rini <[email protected]> Cc: Benjamin Herrenschmidt <[email protected]> Signed-off-by: Andrew Morton <[email protected]> Signed-off-by: Paul Mackerras <[email protected]>
1 parent 12074a3 commit 8117ce7

File tree

1 file changed

+6
-0
lines changed

1 file changed

+6
-0
lines changed

arch/ppc/kernel/process.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -417,6 +417,7 @@ void show_regs(struct pt_regs * regs)
417417

418418
void exit_thread(void)
419419
{
420+
preempt_disable();
420421
if (last_task_used_math == current)
421422
last_task_used_math = NULL;
422423
if (last_task_used_altivec == current)
@@ -425,10 +426,12 @@ void exit_thread(void)
425426
if (last_task_used_spe == current)
426427
last_task_used_spe = NULL;
427428
#endif
429+
preempt_enable();
428430
}
429431

430432
void flush_thread(void)
431433
{
434+
preempt_disable();
432435
if (last_task_used_math == current)
433436
last_task_used_math = NULL;
434437
if (last_task_used_altivec == current)
@@ -437,6 +440,7 @@ void flush_thread(void)
437440
if (last_task_used_spe == current)
438441
last_task_used_spe = NULL;
439442
#endif
443+
preempt_enable();
440444
}
441445

442446
void
@@ -535,6 +539,7 @@ void start_thread(struct pt_regs *regs, unsigned long nip, unsigned long sp)
535539
regs->nip = nip;
536540
regs->gpr[1] = sp;
537541
regs->msr = MSR_USER;
542+
preempt_disable();
538543
if (last_task_used_math == current)
539544
last_task_used_math = NULL;
540545
if (last_task_used_altivec == current)
@@ -543,6 +548,7 @@ void start_thread(struct pt_regs *regs, unsigned long nip, unsigned long sp)
543548
if (last_task_used_spe == current)
544549
last_task_used_spe = NULL;
545550
#endif
551+
preempt_enable();
546552
memset(current->thread.fpr, 0, sizeof(current->thread.fpr));
547553
current->thread.fpscr.val = 0;
548554
#ifdef CONFIG_ALTIVEC

0 commit comments

Comments
 (0)