diff options
| -rw-r--r-- | arch/mips/kernel/r2300_switch.S | 10 | ||||
| -rw-r--r-- | arch/mips/kernel/r4k_switch.S | 10 | ||||
| -rw-r--r-- | arch/mips/kernel/signal.c | 10 | ||||
| -rw-r--r-- | arch/mips/kernel/signal32.c | 10 | ||||
| -rw-r--r-- | arch/mips/kernel/traps.c | 21 | ||||
| -rw-r--r-- | include/asm-mips/fpu.h | 16 | ||||
| -rw-r--r-- | include/asm-mips/thread_info.h | 1 |
7 files changed, 21 insertions, 57 deletions
diff --git a/arch/mips/kernel/r2300_switch.S b/arch/mips/kernel/r2300_switch.S index 28c2e2e6af73..656bde2e11b1 100644 --- a/arch/mips/kernel/r2300_switch.S +++ b/arch/mips/kernel/r2300_switch.S | |||
| @@ -49,7 +49,8 @@ LEAF(resume) | |||
| 49 | #ifndef CONFIG_CPU_HAS_LLSC | 49 | #ifndef CONFIG_CPU_HAS_LLSC |
| 50 | sw zero, ll_bit | 50 | sw zero, ll_bit |
| 51 | #endif | 51 | #endif |
| 52 | mfc0 t2, CP0_STATUS | 52 | mfc0 t1, CP0_STATUS |
| 53 | sw t1, THREAD_STATUS(a0) | ||
| 53 | cpu_save_nonscratch a0 | 54 | cpu_save_nonscratch a0 |
| 54 | sw ra, THREAD_REG31(a0) | 55 | sw ra, THREAD_REG31(a0) |
| 55 | 56 | ||
| @@ -59,8 +60,8 @@ LEAF(resume) | |||
| 59 | lw t3, TASK_THREAD_INFO(a0) | 60 | lw t3, TASK_THREAD_INFO(a0) |
| 60 | lw t0, TI_FLAGS(t3) | 61 | lw t0, TI_FLAGS(t3) |
| 61 | li t1, _TIF_USEDFPU | 62 | li t1, _TIF_USEDFPU |
| 62 | and t1, t0 | 63 | and t2, t0, t1 |
| 63 | beqz t1, 1f | 64 | beqz t2, 1f |
| 64 | nor t1, zero, t1 | 65 | nor t1, zero, t1 |
| 65 | 66 | ||
| 66 | and t0, t0, t1 | 67 | and t0, t0, t1 |
| @@ -73,13 +74,10 @@ LEAF(resume) | |||
| 73 | li t1, ~ST0_CU1 | 74 | li t1, ~ST0_CU1 |
| 74 | and t0, t0, t1 | 75 | and t0, t0, t1 |
| 75 | sw t0, ST_OFF(t3) | 76 | sw t0, ST_OFF(t3) |
| 76 | /* clear thread_struct CU1 bit */ | ||
| 77 | and t2, t1 | ||
| 78 | 77 | ||
| 79 | fpu_save_single a0, t0 # clobbers t0 | 78 | fpu_save_single a0, t0 # clobbers t0 |
| 80 | 79 | ||
| 81 | 1: | 80 | 1: |
| 82 | sw t2, THREAD_STATUS(a0) | ||
| 83 | /* | 81 | /* |
| 84 | * The order of restoring the registers takes care of the race | 82 | * The order of restoring the registers takes care of the race |
| 85 | * updating $28, $29 and kernelsp without disabling ints. | 83 | * updating $28, $29 and kernelsp without disabling ints. |
diff --git a/arch/mips/kernel/r4k_switch.S b/arch/mips/kernel/r4k_switch.S index c7698fd9955c..cc566cf12246 100644 --- a/arch/mips/kernel/r4k_switch.S +++ b/arch/mips/kernel/r4k_switch.S | |||
| @@ -48,7 +48,8 @@ | |||
| 48 | #ifndef CONFIG_CPU_HAS_LLSC | 48 | #ifndef CONFIG_CPU_HAS_LLSC |
| 49 | sw zero, ll_bit | 49 | sw zero, ll_bit |
| 50 | #endif | 50 | #endif |
| 51 | mfc0 t2, CP0_STATUS | 51 | mfc0 t1, CP0_STATUS |
| 52 | LONG_S t1, THREAD_STATUS(a0) | ||
| 52 | cpu_save_nonscratch a0 | 53 | cpu_save_nonscratch a0 |
| 53 | LONG_S ra, THREAD_REG31(a0) | 54 | LONG_S ra, THREAD_REG31(a0) |
| 54 | 55 | ||
| @@ -58,8 +59,8 @@ | |||
| 58 | PTR_L t3, TASK_THREAD_INFO(a0) | 59 | PTR_L t3, TASK_THREAD_INFO(a0) |
| 59 | LONG_L t0, TI_FLAGS(t3) | 60 | LONG_L t0, TI_FLAGS(t3) |
| 60 | li t1, _TIF_USEDFPU | 61 | li t1, _TIF_USEDFPU |
| 61 | and t1, t0 | 62 | and t2, t0, t1 |
| 62 | beqz t1, 1f | 63 | beqz t2, 1f |
| 63 | nor t1, zero, t1 | 64 | nor t1, zero, t1 |
| 64 | 65 | ||
| 65 | and t0, t0, t1 | 66 | and t0, t0, t1 |
| @@ -72,13 +73,10 @@ | |||
| 72 | li t1, ~ST0_CU1 | 73 | li t1, ~ST0_CU1 |
| 73 | and t0, t0, t1 | 74 | and t0, t0, t1 |
| 74 | LONG_S t0, ST_OFF(t3) | 75 | LONG_S t0, ST_OFF(t3) |
| 75 | /* clear thread_struct CU1 bit */ | ||
| 76 | and t2, t1 | ||
| 77 | 76 | ||
| 78 | fpu_save_double a0 t0 t1 # c0_status passed in t0 | 77 | fpu_save_double a0 t0 t1 # c0_status passed in t0 |
| 79 | # clobbers t1 | 78 | # clobbers t1 |
| 80 | 1: | 79 | 1: |
| 81 | LONG_S t2, THREAD_STATUS(a0) | ||
| 82 | 80 | ||
| 83 | /* | 81 | /* |
| 84 | * The order of restoring the registers takes care of the race | 82 | * The order of restoring the registers takes care of the race |
diff --git a/arch/mips/kernel/signal.c b/arch/mips/kernel/signal.c index 8c3c5a5789b0..fa581192de21 100644 --- a/arch/mips/kernel/signal.c +++ b/arch/mips/kernel/signal.c | |||
| @@ -113,10 +113,10 @@ int setup_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc) | |||
| 113 | * Save FPU state to signal context. Signal handler | 113 | * Save FPU state to signal context. Signal handler |
| 114 | * will "inherit" current FPU state. | 114 | * will "inherit" current FPU state. |
| 115 | */ | 115 | */ |
| 116 | preempt_disable(); | ||
| 116 | own_fpu(1); | 117 | own_fpu(1); |
| 117 | enable_fp_in_kernel(); | ||
| 118 | err |= save_fp_context(sc); | 118 | err |= save_fp_context(sc); |
| 119 | disable_fp_in_kernel(); | 119 | preempt_enable(); |
| 120 | } | 120 | } |
| 121 | return err; | 121 | return err; |
| 122 | } | 122 | } |
| @@ -148,7 +148,10 @@ check_and_restore_fp_context(struct sigcontext __user *sc) | |||
| 148 | err = sig = fpcsr_pending(&sc->sc_fpc_csr); | 148 | err = sig = fpcsr_pending(&sc->sc_fpc_csr); |
| 149 | if (err > 0) | 149 | if (err > 0) |
| 150 | err = 0; | 150 | err = 0; |
| 151 | preempt_disable(); | ||
| 152 | own_fpu(0); | ||
| 151 | err |= restore_fp_context(sc); | 153 | err |= restore_fp_context(sc); |
| 154 | preempt_enable(); | ||
| 152 | return err ?: sig; | 155 | return err ?: sig; |
| 153 | } | 156 | } |
| 154 | 157 | ||
| @@ -187,11 +190,8 @@ int restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc) | |||
| 187 | 190 | ||
| 188 | if (used_math) { | 191 | if (used_math) { |
| 189 | /* restore fpu context if we have used it before */ | 192 | /* restore fpu context if we have used it before */ |
| 190 | own_fpu(0); | ||
| 191 | enable_fp_in_kernel(); | ||
| 192 | if (!err) | 193 | if (!err) |
| 193 | err = check_and_restore_fp_context(sc); | 194 | err = check_and_restore_fp_context(sc); |
| 194 | disable_fp_in_kernel(); | ||
| 195 | } else { | 195 | } else { |
| 196 | /* signal handler may have used FPU. Give it up. */ | 196 | /* signal handler may have used FPU. Give it up. */ |
| 197 | lose_fpu(0); | 197 | lose_fpu(0); |
diff --git a/arch/mips/kernel/signal32.c b/arch/mips/kernel/signal32.c index 151fd2f0893a..53a337cfeb66 100644 --- a/arch/mips/kernel/signal32.c +++ b/arch/mips/kernel/signal32.c | |||
| @@ -209,10 +209,10 @@ static int setup_sigcontext32(struct pt_regs *regs, | |||
| 209 | * Save FPU state to signal context. Signal handler | 209 | * Save FPU state to signal context. Signal handler |
| 210 | * will "inherit" current FPU state. | 210 | * will "inherit" current FPU state. |
| 211 | */ | 211 | */ |
| 212 | preempt_disable(); | ||
| 212 | own_fpu(1); | 213 | own_fpu(1); |
| 213 | enable_fp_in_kernel(); | ||
| 214 | err |= save_fp_context32(sc); | 214 | err |= save_fp_context32(sc); |
| 215 | disable_fp_in_kernel(); | 215 | preempt_enable(); |
| 216 | } | 216 | } |
| 217 | return err; | 217 | return err; |
| 218 | } | 218 | } |
| @@ -225,7 +225,10 @@ check_and_restore_fp_context32(struct sigcontext32 __user *sc) | |||
| 225 | err = sig = fpcsr_pending(&sc->sc_fpc_csr); | 225 | err = sig = fpcsr_pending(&sc->sc_fpc_csr); |
| 226 | if (err > 0) | 226 | if (err > 0) |
| 227 | err = 0; | 227 | err = 0; |
| 228 | preempt_disable(); | ||
| 229 | own_fpu(0); | ||
| 228 | err |= restore_fp_context32(sc); | 230 | err |= restore_fp_context32(sc); |
| 231 | preempt_enable(); | ||
| 229 | return err ?: sig; | 232 | return err ?: sig; |
| 230 | } | 233 | } |
| 231 | 234 | ||
| @@ -261,11 +264,8 @@ static int restore_sigcontext32(struct pt_regs *regs, | |||
| 261 | 264 | ||
| 262 | if (used_math) { | 265 | if (used_math) { |
| 263 | /* restore fpu context if we have used it before */ | 266 | /* restore fpu context if we have used it before */ |
| 264 | own_fpu(0); | ||
| 265 | enable_fp_in_kernel(); | ||
| 266 | if (!err) | 267 | if (!err) |
| 267 | err = check_and_restore_fp_context32(sc); | 268 | err = check_and_restore_fp_context32(sc); |
| 268 | disable_fp_in_kernel(); | ||
| 269 | } else { | 269 | } else { |
| 270 | /* signal handler may have used FPU. Give it up. */ | 270 | /* signal handler may have used FPU. Give it up. */ |
| 271 | lose_fpu(0); | 271 | lose_fpu(0); |
diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c index 7d76a85422b2..6b356f62289e 100644 --- a/arch/mips/kernel/traps.c +++ b/arch/mips/kernel/traps.c | |||
| @@ -757,11 +757,12 @@ asmlinkage void do_cpu(struct pt_regs *regs) | |||
| 757 | { | 757 | { |
| 758 | unsigned int cpid; | 758 | unsigned int cpid; |
| 759 | 759 | ||
| 760 | die_if_kernel("do_cpu invoked from kernel context!", regs); | ||
| 761 | |||
| 760 | cpid = (regs->cp0_cause >> CAUSEB_CE) & 3; | 762 | cpid = (regs->cp0_cause >> CAUSEB_CE) & 3; |
| 761 | 763 | ||
| 762 | switch (cpid) { | 764 | switch (cpid) { |
| 763 | case 0: | 765 | case 0: |
| 764 | die_if_kernel("do_cpu invoked from kernel context!", regs); | ||
| 765 | if (!cpu_has_llsc) | 766 | if (!cpu_has_llsc) |
| 766 | if (!simulate_llsc(regs)) | 767 | if (!simulate_llsc(regs)) |
| 767 | return; | 768 | return; |
| @@ -772,9 +773,6 @@ asmlinkage void do_cpu(struct pt_regs *regs) | |||
| 772 | break; | 773 | break; |
| 773 | 774 | ||
| 774 | case 1: | 775 | case 1: |
| 775 | if (!test_thread_flag(TIF_ALLOW_FP_IN_KERNEL)) | ||
| 776 | die_if_kernel("do_cpu invoked from kernel context!", | ||
| 777 | regs); | ||
| 778 | if (used_math()) /* Using the FPU again. */ | 776 | if (used_math()) /* Using the FPU again. */ |
| 779 | own_fpu(1); | 777 | own_fpu(1); |
| 780 | else { /* First time FPU user. */ | 778 | else { /* First time FPU user. */ |
| @@ -782,19 +780,7 @@ asmlinkage void do_cpu(struct pt_regs *regs) | |||
| 782 | set_used_math(); | 780 | set_used_math(); |
| 783 | } | 781 | } |
| 784 | 782 | ||
| 785 | if (raw_cpu_has_fpu) { | 783 | if (!raw_cpu_has_fpu) { |
| 786 | if (test_thread_flag(TIF_ALLOW_FP_IN_KERNEL)) { | ||
| 787 | local_irq_disable(); | ||
| 788 | if (cpu_has_fpu) | ||
| 789 | regs->cp0_status |= ST0_CU1; | ||
| 790 | /* | ||
| 791 | * We must return without enabling | ||
| 792 | * interrupts to ensure keep FPU | ||
| 793 | * ownership until resume. | ||
| 794 | */ | ||
| 795 | return; | ||
| 796 | } | ||
| 797 | } else { | ||
| 798 | int sig; | 784 | int sig; |
| 799 | sig = fpu_emulator_cop1Handler(regs, | 785 | sig = fpu_emulator_cop1Handler(regs, |
| 800 | ¤t->thread.fpu, 0); | 786 | ¤t->thread.fpu, 0); |
| @@ -836,7 +822,6 @@ asmlinkage void do_cpu(struct pt_regs *regs) | |||
| 836 | 822 | ||
| 837 | case 2: | 823 | case 2: |
| 838 | case 3: | 824 | case 3: |
| 839 | die_if_kernel("do_cpu invoked from kernel context!", regs); | ||
| 840 | break; | 825 | break; |
| 841 | } | 826 | } |
| 842 | 827 | ||
diff --git a/include/asm-mips/fpu.h b/include/asm-mips/fpu.h index 4e12d1f9534f..71436f90203f 100644 --- a/include/asm-mips/fpu.h +++ b/include/asm-mips/fpu.h | |||
| @@ -68,8 +68,6 @@ do { \ | |||
| 68 | /* We don't care about the c0 hazard here */ \ | 68 | /* We don't care about the c0 hazard here */ \ |
| 69 | } while (0) | 69 | } while (0) |
| 70 | 70 | ||
| 71 | #define __fpu_enabled() (read_c0_status() & ST0_CU1) | ||
| 72 | |||
| 73 | #define enable_fpu() \ | 71 | #define enable_fpu() \ |
| 74 | do { \ | 72 | do { \ |
| 75 | if (cpu_has_fpu) \ | 73 | if (cpu_has_fpu) \ |
| @@ -162,18 +160,4 @@ static inline fpureg_t *get_fpu_regs(struct task_struct *tsk) | |||
| 162 | return tsk->thread.fpu.fpr; | 160 | return tsk->thread.fpu.fpr; |
| 163 | } | 161 | } |
| 164 | 162 | ||
| 165 | static inline void enable_fp_in_kernel(void) | ||
| 166 | { | ||
| 167 | set_thread_flag(TIF_ALLOW_FP_IN_KERNEL); | ||
| 168 | /* make sure CU1 and FPU ownership are consistent */ | ||
| 169 | if (!__is_fpu_owner() && __fpu_enabled()) | ||
| 170 | __disable_fpu(); | ||
| 171 | } | ||
| 172 | |||
| 173 | static inline void disable_fp_in_kernel(void) | ||
| 174 | { | ||
| 175 | BUG_ON(!__is_fpu_owner() && __fpu_enabled()); | ||
| 176 | clear_thread_flag(TIF_ALLOW_FP_IN_KERNEL); | ||
| 177 | } | ||
| 178 | |||
| 179 | #endif /* _ASM_FPU_H */ | 163 | #endif /* _ASM_FPU_H */ |
diff --git a/include/asm-mips/thread_info.h b/include/asm-mips/thread_info.h index 6cf05f4a4e7e..fbcda8204473 100644 --- a/include/asm-mips/thread_info.h +++ b/include/asm-mips/thread_info.h | |||
| @@ -119,7 +119,6 @@ register struct thread_info *__current_thread_info __asm__("$28"); | |||
| 119 | #define TIF_POLLING_NRFLAG 17 /* true if poll_idle() is polling TIF_NEED_RESCHED */ | 119 | #define TIF_POLLING_NRFLAG 17 /* true if poll_idle() is polling TIF_NEED_RESCHED */ |
| 120 | #define TIF_MEMDIE 18 | 120 | #define TIF_MEMDIE 18 |
| 121 | #define TIF_FREEZE 19 | 121 | #define TIF_FREEZE 19 |
| 122 | #define TIF_ALLOW_FP_IN_KERNEL 20 | ||
| 123 | #define TIF_SYSCALL_TRACE 31 /* syscall trace active */ | 122 | #define TIF_SYSCALL_TRACE 31 /* syscall trace active */ |
| 124 | 123 | ||
| 125 | #define _TIF_SYSCALL_TRACE (1<<TIF_SYSCALL_TRACE) | 124 | #define _TIF_SYSCALL_TRACE (1<<TIF_SYSCALL_TRACE) |
