aboutsummaryrefslogtreecommitdiffstats
path: root/arch/mips/kernel/traps.c
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>2005-04-28 09:39:10 -0400
committerRalf Baechle <ralf@linux-mips.org>2005-10-29 14:31:12 -0400
commitcd21dfcfbb5c43de54f6be795dde07397da2bc2f (patch)
treeed3a6c46fd6aabac95c99b1e816493fcb5f788f8 /arch/mips/kernel/traps.c
parent63b2d2f4d2073ac3452ce977d27cc81eabaa61a3 (diff)
Fix preemption and SMP problems in the FP emulator code.
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
Diffstat (limited to 'arch/mips/kernel/traps.c')
-rw-r--r--arch/mips/kernel/traps.c19
1 files changed, 17 insertions, 2 deletions
diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c
index 15fed0202154..b3ecd02757cb 100644
--- a/arch/mips/kernel/traps.c
+++ b/arch/mips/kernel/traps.c
@@ -551,6 +551,14 @@ asmlinkage void do_fpe(struct pt_regs *regs, unsigned long fcr31)
551 551
552 preempt_disable(); 552 preempt_disable();
553 553
554#ifdef CONFIG_PREEMPT
555 if (!is_fpu_owner()) {
556 /* We might lose fpu before disabling preempt... */
557 own_fpu();
558 BUG_ON(!used_math());
559 restore_fp(current);
560 }
561#endif
554 /* 562 /*
555 * Unimplemented operation exception. If we've got the full 563 * Unimplemented operation exception. If we've got the full
556 * software emulator on-board, let's use it... 564 * software emulator on-board, let's use it...
@@ -562,11 +570,18 @@ asmlinkage void do_fpe(struct pt_regs *regs, unsigned long fcr31)
562 * a bit extreme for what should be an infrequent event. 570 * a bit extreme for what should be an infrequent event.
563 */ 571 */
564 save_fp(current); 572 save_fp(current);
573 /* Ensure 'resume' not overwrite saved fp context again. */
574 lose_fpu();
575
576 preempt_enable();
565 577
566 /* Run the emulator */ 578 /* Run the emulator */
567 sig = fpu_emulator_cop1Handler (0, regs, 579 sig = fpu_emulator_cop1Handler (0, regs,
568 &current->thread.fpu.soft); 580 &current->thread.fpu.soft);
569 581
582 preempt_disable();
583
584 own_fpu(); /* Using the FPU again. */
570 /* 585 /*
571 * We can't allow the emulated instruction to leave any of 586 * We can't allow the emulated instruction to leave any of
572 * the cause bit set in $fcr31. 587 * the cause bit set in $fcr31.
@@ -712,6 +727,8 @@ asmlinkage void do_cpu(struct pt_regs *regs)
712 set_used_math(); 727 set_used_math();
713 } 728 }
714 729
730 preempt_enable();
731
715 if (!cpu_has_fpu) { 732 if (!cpu_has_fpu) {
716 int sig = fpu_emulator_cop1Handler(0, regs, 733 int sig = fpu_emulator_cop1Handler(0, regs,
717 &current->thread.fpu.soft); 734 &current->thread.fpu.soft);
@@ -719,8 +736,6 @@ asmlinkage void do_cpu(struct pt_regs *regs)
719 force_sig(sig, current); 736 force_sig(sig, current);
720 } 737 }
721 738
722 preempt_enable();
723
724 return; 739 return;
725 740
726 case 2: 741 case 2: