diff options
Diffstat (limited to 'arch/mips/kernel/traps.c')
-rw-r--r-- | arch/mips/kernel/traps.c | 73 |
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, ¤t->thread.fpu, 1); | 627 | sig = fpu_emulator_cop1Handler (regs, ¤t->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 | ¤t->thread.fpu, 0); | 786 | ¤t->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 | */ |
1262 | asmlinkage int (*save_fp_context)(struct sigcontext *sc); | 1237 | asmlinkage int (*save_fp_context)(struct sigcontext __user *sc); |
1263 | asmlinkage int (*restore_fp_context)(struct sigcontext *sc); | 1238 | asmlinkage int (*restore_fp_context)(struct sigcontext __user *sc); |
1264 | 1239 | ||
1265 | extern asmlinkage int _save_fp_context(struct sigcontext *sc); | 1240 | extern asmlinkage int _save_fp_context(struct sigcontext __user *sc); |
1266 | extern asmlinkage int _restore_fp_context(struct sigcontext *sc); | 1241 | extern asmlinkage int _restore_fp_context(struct sigcontext __user *sc); |
1267 | 1242 | ||
1268 | extern asmlinkage int fpu_emulator_save_context(struct sigcontext *sc); | 1243 | extern asmlinkage int fpu_emulator_save_context(struct sigcontext __user *sc); |
1269 | extern asmlinkage int fpu_emulator_restore_context(struct sigcontext *sc); | 1244 | extern asmlinkage int fpu_emulator_restore_context(struct sigcontext __user *sc); |
1270 | 1245 | ||
1271 | #ifdef CONFIG_SMP | 1246 | #ifdef CONFIG_SMP |
1272 | static int smp_save_fp_context(struct sigcontext *sc) | 1247 | static 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 | ||
1279 | static int smp_restore_fp_context(struct sigcontext *sc) | 1254 | static 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 | */ |
1309 | asmlinkage int (*save_fp_context32)(struct sigcontext32 *sc); | 1284 | asmlinkage int (*save_fp_context32)(struct sigcontext32 __user *sc); |
1310 | asmlinkage int (*restore_fp_context32)(struct sigcontext32 *sc); | 1285 | asmlinkage int (*restore_fp_context32)(struct sigcontext32 __user *sc); |
1311 | 1286 | ||
1312 | extern asmlinkage int _save_fp_context32(struct sigcontext32 *sc); | 1287 | extern asmlinkage int _save_fp_context32(struct sigcontext32 __user *sc); |
1313 | extern asmlinkage int _restore_fp_context32(struct sigcontext32 *sc); | 1288 | extern asmlinkage int _restore_fp_context32(struct sigcontext32 __user *sc); |
1314 | 1289 | ||
1315 | extern asmlinkage int fpu_emulator_save_context32(struct sigcontext32 *sc); | 1290 | extern asmlinkage int fpu_emulator_save_context32(struct sigcontext32 __user *sc); |
1316 | extern asmlinkage int fpu_emulator_restore_context32(struct sigcontext32 *sc); | 1291 | extern asmlinkage int fpu_emulator_restore_context32(struct sigcontext32 __user *sc); |
1317 | 1292 | ||
1318 | static inline void signal32_init(void) | 1293 | static inline void signal32_init(void) |
1319 | { | 1294 | { |