aboutsummaryrefslogtreecommitdiffstats
path: root/arch/mips/kernel/traps.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/mips/kernel/traps.c')
-rw-r--r--arch/mips/kernel/traps.c73
1 files changed, 24 insertions, 49 deletions
diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c
index 18f56a9dbcfa..493cb29b8a42 100644
--- a/arch/mips/kernel/traps.c
+++ b/arch/mips/kernel/traps.c
@@ -610,16 +610,6 @@ asmlinkage void do_fpe(struct pt_regs *regs, unsigned long fcr31)
610 if (fcr31 & FPU_CSR_UNI_X) { 610 if (fcr31 & FPU_CSR_UNI_X) {
611 int sig; 611 int sig;
612 612
613 preempt_disable();
614
615#ifdef CONFIG_PREEMPT
616 if (!is_fpu_owner()) {
617 /* We might lose fpu before disabling preempt... */
618 own_fpu();
619 BUG_ON(!used_math());
620 restore_fp(current);
621 }
622#endif
623 /* 613 /*
624 * Unimplemented operation exception. If we've got the full 614 * Unimplemented operation exception. If we've got the full
625 * software emulator on-board, let's use it... 615 * software emulator on-board, let's use it...
@@ -630,18 +620,12 @@ asmlinkage void do_fpe(struct pt_regs *regs, unsigned long fcr31)
630 * register operands before invoking the emulator, which seems 620 * register operands before invoking the emulator, which seems
631 * a bit extreme for what should be an infrequent event. 621 * a bit extreme for what should be an infrequent event.
632 */ 622 */
633 save_fp(current);
634 /* Ensure 'resume' not overwrite saved fp context again. */ 623 /* Ensure 'resume' not overwrite saved fp context again. */
635 lose_fpu(); 624 lose_fpu(1);
636
637 preempt_enable();
638 625
639 /* Run the emulator */ 626 /* Run the emulator */
640 sig = fpu_emulator_cop1Handler (regs, &current->thread.fpu, 1); 627 sig = fpu_emulator_cop1Handler (regs, &current->thread.fpu, 1);
641 628
642 preempt_disable();
643
644 own_fpu(); /* Using the FPU again. */
645 /* 629 /*
646 * We can't allow the emulated instruction to leave any of 630 * We can't allow the emulated instruction to leave any of
647 * the cause bit set in $fcr31. 631 * the cause bit set in $fcr31.
@@ -649,9 +633,7 @@ asmlinkage void do_fpe(struct pt_regs *regs, unsigned long fcr31)
649 current->thread.fpu.fcr31 &= ~FPU_CSR_ALL_X; 633 current->thread.fpu.fcr31 &= ~FPU_CSR_ALL_X;
650 634
651 /* Restore the hardware register state */ 635 /* Restore the hardware register state */
652 restore_fp(current); 636 own_fpu(1); /* Using the FPU again. */
653
654 preempt_enable();
655 637
656 /* If something went wrong, signal */ 638 /* If something went wrong, signal */
657 if (sig) 639 if (sig)
@@ -668,7 +650,7 @@ asmlinkage void do_bp(struct pt_regs *regs)
668 unsigned int opcode, bcode; 650 unsigned int opcode, bcode;
669 siginfo_t info; 651 siginfo_t info;
670 652
671 if (get_user(opcode, (unsigned int __user *) exception_epc(regs))) 653 if (__get_user(opcode, (unsigned int __user *) exception_epc(regs)))
672 goto out_sigsegv; 654 goto out_sigsegv;
673 655
674 /* 656 /*
@@ -718,7 +700,7 @@ asmlinkage void do_tr(struct pt_regs *regs)
718 unsigned int opcode, tcode = 0; 700 unsigned int opcode, tcode = 0;
719 siginfo_t info; 701 siginfo_t info;
720 702
721 if (get_user(opcode, (unsigned int __user *) exception_epc(regs))) 703 if (__get_user(opcode, (unsigned int __user *) exception_epc(regs)))
722 goto out_sigsegv; 704 goto out_sigsegv;
723 705
724 /* Immediate versions don't provide a code. */ 706 /* Immediate versions don't provide a code. */
@@ -791,21 +773,15 @@ asmlinkage void do_cpu(struct pt_regs *regs)
791 break; 773 break;
792 774
793 case 1: 775 case 1:
794 preempt_disable(); 776 if (used_math()) /* Using the FPU again. */
795 777 own_fpu(1);
796 own_fpu(); 778 else { /* First time FPU user. */
797 if (used_math()) { /* Using the FPU again. */
798 restore_fp(current);
799 } else { /* First time FPU user. */
800 init_fpu(); 779 init_fpu();
801 set_used_math(); 780 set_used_math();
802 } 781 }
803 782
804 if (cpu_has_fpu) { 783 if (!raw_cpu_has_fpu) {
805 preempt_enable();
806 } else {
807 int sig; 784 int sig;
808 preempt_enable();
809 sig = fpu_emulator_cop1Handler(regs, 785 sig = fpu_emulator_cop1Handler(regs,
810 &current->thread.fpu, 0); 786 &current->thread.fpu, 0);
811 if (sig) 787 if (sig)
@@ -846,7 +822,6 @@ asmlinkage void do_cpu(struct pt_regs *regs)
846 822
847 case 2: 823 case 2:
848 case 3: 824 case 3:
849 die_if_kernel("do_cpu invoked from kernel context!", regs);
850 break; 825 break;
851 } 826 }
852 827
@@ -1259,26 +1234,26 @@ static inline void mips_srs_init(void)
1259/* 1234/*
1260 * This is used by native signal handling 1235 * This is used by native signal handling
1261 */ 1236 */
1262asmlinkage int (*save_fp_context)(struct sigcontext *sc); 1237asmlinkage int (*save_fp_context)(struct sigcontext __user *sc);
1263asmlinkage int (*restore_fp_context)(struct sigcontext *sc); 1238asmlinkage int (*restore_fp_context)(struct sigcontext __user *sc);
1264 1239
1265extern asmlinkage int _save_fp_context(struct sigcontext *sc); 1240extern asmlinkage int _save_fp_context(struct sigcontext __user *sc);
1266extern asmlinkage int _restore_fp_context(struct sigcontext *sc); 1241extern asmlinkage int _restore_fp_context(struct sigcontext __user *sc);
1267 1242
1268extern asmlinkage int fpu_emulator_save_context(struct sigcontext *sc); 1243extern asmlinkage int fpu_emulator_save_context(struct sigcontext __user *sc);
1269extern asmlinkage int fpu_emulator_restore_context(struct sigcontext *sc); 1244extern asmlinkage int fpu_emulator_restore_context(struct sigcontext __user *sc);
1270 1245
1271#ifdef CONFIG_SMP 1246#ifdef CONFIG_SMP
1272static int smp_save_fp_context(struct sigcontext *sc) 1247static int smp_save_fp_context(struct sigcontext __user *sc)
1273{ 1248{
1274 return cpu_has_fpu 1249 return raw_cpu_has_fpu
1275 ? _save_fp_context(sc) 1250 ? _save_fp_context(sc)
1276 : fpu_emulator_save_context(sc); 1251 : fpu_emulator_save_context(sc);
1277} 1252}
1278 1253
1279static int smp_restore_fp_context(struct sigcontext *sc) 1254static int smp_restore_fp_context(struct sigcontext __user *sc)
1280{ 1255{
1281 return cpu_has_fpu 1256 return raw_cpu_has_fpu
1282 ? _restore_fp_context(sc) 1257 ? _restore_fp_context(sc)
1283 : fpu_emulator_restore_context(sc); 1258 : fpu_emulator_restore_context(sc);
1284} 1259}
@@ -1306,14 +1281,14 @@ static inline void signal_init(void)
1306/* 1281/*
1307 * This is used by 32-bit signal stuff on the 64-bit kernel 1282 * This is used by 32-bit signal stuff on the 64-bit kernel
1308 */ 1283 */
1309asmlinkage int (*save_fp_context32)(struct sigcontext32 *sc); 1284asmlinkage int (*save_fp_context32)(struct sigcontext32 __user *sc);
1310asmlinkage int (*restore_fp_context32)(struct sigcontext32 *sc); 1285asmlinkage int (*restore_fp_context32)(struct sigcontext32 __user *sc);
1311 1286
1312extern asmlinkage int _save_fp_context32(struct sigcontext32 *sc); 1287extern asmlinkage int _save_fp_context32(struct sigcontext32 __user *sc);
1313extern asmlinkage int _restore_fp_context32(struct sigcontext32 *sc); 1288extern asmlinkage int _restore_fp_context32(struct sigcontext32 __user *sc);
1314 1289
1315extern asmlinkage int fpu_emulator_save_context32(struct sigcontext32 *sc); 1290extern asmlinkage int fpu_emulator_save_context32(struct sigcontext32 __user *sc);
1316extern asmlinkage int fpu_emulator_restore_context32(struct sigcontext32 *sc); 1291extern asmlinkage int fpu_emulator_restore_context32(struct sigcontext32 __user *sc);
1317 1292
1318static inline void signal32_init(void) 1293static inline void signal32_init(void)
1319{ 1294{