diff options
| author | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-04-21 01:57:51 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-04-21 01:57:51 -0400 |
| commit | ea8df8c5e609a53f4d03d133baea9561412f4303 (patch) | |
| tree | 1451390f27ffad89c11671eb3e61d66f48dca00b | |
| parent | 241c39b9ac4bf847013aa06cce6d4d61426a2006 (diff) | |
| parent | 1d464c26b5625215c4b35fb336c8f3c57d248c2e (diff) | |
Merge branch 'upstream' of git://ftp.linux-mips.org/pub/scm/upstream-linus
* 'upstream' of git://ftp.linux-mips.org/pub/scm/upstream-linus:
[MIPS] Fix wrong checksum for split TCP packets on 64-bit MIPS
[MIPS] Fix BUG(), BUG_ON() handling
[MIPS] Retry {save,restore}_fp_context if failed in atomic context.
[MIPS] Disallow CpU exception in kernel again.
[MIPS] Add missing silicon revisions for BCM112x
| -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-common.h | 9 | ||||
| -rw-r--r-- | arch/mips/kernel/signal.c | 52 | ||||
| -rw-r--r-- | arch/mips/kernel/signal32.c | 52 | ||||
| -rw-r--r-- | arch/mips/kernel/traps.c | 25 | ||||
| -rw-r--r-- | arch/mips/sibyte/sb1250/setup.c | 12 | ||||
| -rw-r--r-- | include/asm-mips/bug.h | 3 | ||||
| -rw-r--r-- | include/asm-mips/checksum.h | 2 | ||||
| -rw-r--r-- | include/asm-mips/fpu.h | 25 | ||||
| -rw-r--r-- | include/asm-mips/sibyte/sb1250_scd.h | 1 | ||||
| -rw-r--r-- | include/asm-mips/thread_info.h | 1 |
12 files changed, 131 insertions, 71 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-common.h b/arch/mips/kernel/signal-common.h index 297dfcb97524..c0faabd52010 100644 --- a/arch/mips/kernel/signal-common.h +++ b/arch/mips/kernel/signal-common.h | |||
| @@ -34,4 +34,13 @@ extern int install_sigtramp(unsigned int __user *tramp, unsigned int syscall); | |||
| 34 | /* Check and clear pending FPU exceptions in saved CSR */ | 34 | /* Check and clear pending FPU exceptions in saved CSR */ |
| 35 | extern int fpcsr_pending(unsigned int __user *fpcsr); | 35 | extern int fpcsr_pending(unsigned int __user *fpcsr); |
| 36 | 36 | ||
| 37 | /* Make sure we will not lose FPU ownership */ | ||
| 38 | #ifdef CONFIG_PREEMPT | ||
| 39 | #define lock_fpu_owner() preempt_disable() | ||
| 40 | #define unlock_fpu_owner() preempt_enable() | ||
| 41 | #else | ||
| 42 | #define lock_fpu_owner() pagefault_disable() | ||
| 43 | #define unlock_fpu_owner() pagefault_enable() | ||
| 44 | #endif | ||
| 45 | |||
| 37 | #endif /* __SIGNAL_COMMON_H */ | 46 | #endif /* __SIGNAL_COMMON_H */ |
diff --git a/arch/mips/kernel/signal.c b/arch/mips/kernel/signal.c index 8c3c5a5789b0..07d67309451a 100644 --- a/arch/mips/kernel/signal.c +++ b/arch/mips/kernel/signal.c | |||
| @@ -20,6 +20,7 @@ | |||
| 20 | #include <linux/ptrace.h> | 20 | #include <linux/ptrace.h> |
| 21 | #include <linux/unistd.h> | 21 | #include <linux/unistd.h> |
| 22 | #include <linux/compiler.h> | 22 | #include <linux/compiler.h> |
| 23 | #include <linux/uaccess.h> | ||
| 23 | 24 | ||
| 24 | #include <asm/abi.h> | 25 | #include <asm/abi.h> |
| 25 | #include <asm/asm.h> | 26 | #include <asm/asm.h> |
| @@ -27,7 +28,6 @@ | |||
| 27 | #include <asm/cacheflush.h> | 28 | #include <asm/cacheflush.h> |
| 28 | #include <asm/fpu.h> | 29 | #include <asm/fpu.h> |
| 29 | #include <asm/sim.h> | 30 | #include <asm/sim.h> |
| 30 | #include <asm/uaccess.h> | ||
| 31 | #include <asm/ucontext.h> | 31 | #include <asm/ucontext.h> |
| 32 | #include <asm/cpu-features.h> | 32 | #include <asm/cpu-features.h> |
| 33 | #include <asm/war.h> | 33 | #include <asm/war.h> |
| @@ -78,6 +78,46 @@ struct rt_sigframe { | |||
| 78 | /* | 78 | /* |
| 79 | * Helper routines | 79 | * Helper routines |
| 80 | */ | 80 | */ |
| 81 | static int protected_save_fp_context(struct sigcontext __user *sc) | ||
| 82 | { | ||
| 83 | int err; | ||
| 84 | while (1) { | ||
| 85 | lock_fpu_owner(); | ||
| 86 | own_fpu_inatomic(1); | ||
| 87 | err = save_fp_context(sc); /* this might fail */ | ||
| 88 | unlock_fpu_owner(); | ||
| 89 | if (likely(!err)) | ||
| 90 | break; | ||
| 91 | /* touch the sigcontext and try again */ | ||
| 92 | err = __put_user(0, &sc->sc_fpregs[0]) | | ||
| 93 | __put_user(0, &sc->sc_fpregs[31]) | | ||
| 94 | __put_user(0, &sc->sc_fpc_csr); | ||
| 95 | if (err) | ||
| 96 | break; /* really bad sigcontext */ | ||
| 97 | } | ||
| 98 | return err; | ||
| 99 | } | ||
| 100 | |||
| 101 | static int protected_restore_fp_context(struct sigcontext __user *sc) | ||
| 102 | { | ||
| 103 | int err, tmp; | ||
| 104 | while (1) { | ||
| 105 | lock_fpu_owner(); | ||
| 106 | own_fpu_inatomic(0); | ||
| 107 | err = restore_fp_context(sc); /* this might fail */ | ||
| 108 | unlock_fpu_owner(); | ||
| 109 | if (likely(!err)) | ||
| 110 | break; | ||
| 111 | /* touch the sigcontext and try again */ | ||
| 112 | err = __get_user(tmp, &sc->sc_fpregs[0]) | | ||
| 113 | __get_user(tmp, &sc->sc_fpregs[31]) | | ||
| 114 | __get_user(tmp, &sc->sc_fpc_csr); | ||
| 115 | if (err) | ||
| 116 | break; /* really bad sigcontext */ | ||
| 117 | } | ||
| 118 | return err; | ||
| 119 | } | ||
| 120 | |||
| 81 | int setup_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc) | 121 | int setup_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc) |
| 82 | { | 122 | { |
| 83 | int err = 0; | 123 | int err = 0; |
| @@ -113,10 +153,7 @@ int setup_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc) | |||
| 113 | * Save FPU state to signal context. Signal handler | 153 | * Save FPU state to signal context. Signal handler |
| 114 | * will "inherit" current FPU state. | 154 | * will "inherit" current FPU state. |
| 115 | */ | 155 | */ |
| 116 | own_fpu(1); | 156 | err |= protected_save_fp_context(sc); |
| 117 | enable_fp_in_kernel(); | ||
| 118 | err |= save_fp_context(sc); | ||
| 119 | disable_fp_in_kernel(); | ||
| 120 | } | 157 | } |
| 121 | return err; | 158 | return err; |
| 122 | } | 159 | } |
| @@ -148,7 +185,7 @@ check_and_restore_fp_context(struct sigcontext __user *sc) | |||
| 148 | err = sig = fpcsr_pending(&sc->sc_fpc_csr); | 185 | err = sig = fpcsr_pending(&sc->sc_fpc_csr); |
| 149 | if (err > 0) | 186 | if (err > 0) |
| 150 | err = 0; | 187 | err = 0; |
| 151 | err |= restore_fp_context(sc); | 188 | err |= protected_restore_fp_context(sc); |
| 152 | return err ?: sig; | 189 | return err ?: sig; |
| 153 | } | 190 | } |
| 154 | 191 | ||
| @@ -187,11 +224,8 @@ int restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc) | |||
| 187 | 224 | ||
| 188 | if (used_math) { | 225 | if (used_math) { |
| 189 | /* restore fpu context if we have used it before */ | 226 | /* restore fpu context if we have used it before */ |
| 190 | own_fpu(0); | ||
| 191 | enable_fp_in_kernel(); | ||
| 192 | if (!err) | 227 | if (!err) |
| 193 | err = check_and_restore_fp_context(sc); | 228 | err = check_and_restore_fp_context(sc); |
| 194 | disable_fp_in_kernel(); | ||
| 195 | } else { | 229 | } else { |
| 196 | /* signal handler may have used FPU. Give it up. */ | 230 | /* signal handler may have used FPU. Give it up. */ |
| 197 | lose_fpu(0); | 231 | lose_fpu(0); |
diff --git a/arch/mips/kernel/signal32.c b/arch/mips/kernel/signal32.c index 151fd2f0893a..b9a014411f83 100644 --- a/arch/mips/kernel/signal32.c +++ b/arch/mips/kernel/signal32.c | |||
| @@ -22,6 +22,7 @@ | |||
| 22 | #include <linux/compat.h> | 22 | #include <linux/compat.h> |
| 23 | #include <linux/suspend.h> | 23 | #include <linux/suspend.h> |
| 24 | #include <linux/compiler.h> | 24 | #include <linux/compiler.h> |
| 25 | #include <linux/uaccess.h> | ||
| 25 | 26 | ||
| 26 | #include <asm/abi.h> | 27 | #include <asm/abi.h> |
| 27 | #include <asm/asm.h> | 28 | #include <asm/asm.h> |
| @@ -29,7 +30,6 @@ | |||
| 29 | #include <linux/bitops.h> | 30 | #include <linux/bitops.h> |
| 30 | #include <asm/cacheflush.h> | 31 | #include <asm/cacheflush.h> |
| 31 | #include <asm/sim.h> | 32 | #include <asm/sim.h> |
| 32 | #include <asm/uaccess.h> | ||
| 33 | #include <asm/ucontext.h> | 33 | #include <asm/ucontext.h> |
| 34 | #include <asm/system.h> | 34 | #include <asm/system.h> |
| 35 | #include <asm/fpu.h> | 35 | #include <asm/fpu.h> |
| @@ -176,6 +176,46 @@ struct rt_sigframe32 { | |||
| 176 | /* | 176 | /* |
| 177 | * sigcontext handlers | 177 | * sigcontext handlers |
| 178 | */ | 178 | */ |
| 179 | static int protected_save_fp_context32(struct sigcontext32 __user *sc) | ||
| 180 | { | ||
| 181 | int err; | ||
| 182 | while (1) { | ||
| 183 | lock_fpu_owner(); | ||
| 184 | own_fpu_inatomic(1); | ||
| 185 | err = save_fp_context32(sc); /* this might fail */ | ||
| 186 | unlock_fpu_owner(); | ||
| 187 | if (likely(!err)) | ||
| 188 | break; | ||
| 189 | /* touch the sigcontext and try again */ | ||
| 190 | err = __put_user(0, &sc->sc_fpregs[0]) | | ||
| 191 | __put_user(0, &sc->sc_fpregs[31]) | | ||
| 192 | __put_user(0, &sc->sc_fpc_csr); | ||
| 193 | if (err) | ||
| 194 | break; /* really bad sigcontext */ | ||
| 195 | } | ||
| 196 | return err; | ||
| 197 | } | ||
| 198 | |||
| 199 | static int protected_restore_fp_context32(struct sigcontext32 __user *sc) | ||
| 200 | { | ||
| 201 | int err, tmp; | ||
| 202 | while (1) { | ||
| 203 | lock_fpu_owner(); | ||
| 204 | own_fpu_inatomic(0); | ||
| 205 | err = restore_fp_context32(sc); /* this might fail */ | ||
| 206 | unlock_fpu_owner(); | ||
| 207 | if (likely(!err)) | ||
| 208 | break; | ||
| 209 | /* touch the sigcontext and try again */ | ||
| 210 | err = __get_user(tmp, &sc->sc_fpregs[0]) | | ||
| 211 | __get_user(tmp, &sc->sc_fpregs[31]) | | ||
| 212 | __get_user(tmp, &sc->sc_fpc_csr); | ||
| 213 | if (err) | ||
| 214 | break; /* really bad sigcontext */ | ||
| 215 | } | ||
| 216 | return err; | ||
| 217 | } | ||
| 218 | |||
| 179 | static int setup_sigcontext32(struct pt_regs *regs, | 219 | static int setup_sigcontext32(struct pt_regs *regs, |
| 180 | struct sigcontext32 __user *sc) | 220 | struct sigcontext32 __user *sc) |
| 181 | { | 221 | { |
| @@ -209,10 +249,7 @@ static int setup_sigcontext32(struct pt_regs *regs, | |||
| 209 | * Save FPU state to signal context. Signal handler | 249 | * Save FPU state to signal context. Signal handler |
| 210 | * will "inherit" current FPU state. | 250 | * will "inherit" current FPU state. |
| 211 | */ | 251 | */ |
| 212 | own_fpu(1); | 252 | err |= protected_save_fp_context32(sc); |
| 213 | enable_fp_in_kernel(); | ||
| 214 | err |= save_fp_context32(sc); | ||
| 215 | disable_fp_in_kernel(); | ||
| 216 | } | 253 | } |
| 217 | return err; | 254 | return err; |
| 218 | } | 255 | } |
| @@ -225,7 +262,7 @@ check_and_restore_fp_context32(struct sigcontext32 __user *sc) | |||
| 225 | err = sig = fpcsr_pending(&sc->sc_fpc_csr); | 262 | err = sig = fpcsr_pending(&sc->sc_fpc_csr); |
| 226 | if (err > 0) | 263 | if (err > 0) |
| 227 | err = 0; | 264 | err = 0; |
| 228 | err |= restore_fp_context32(sc); | 265 | err |= protected_restore_fp_context32(sc); |
| 229 | return err ?: sig; | 266 | return err ?: sig; |
| 230 | } | 267 | } |
| 231 | 268 | ||
| @@ -261,11 +298,8 @@ static int restore_sigcontext32(struct pt_regs *regs, | |||
| 261 | 298 | ||
| 262 | if (used_math) { | 299 | if (used_math) { |
| 263 | /* restore fpu context if we have used it before */ | 300 | /* restore fpu context if we have used it before */ |
| 264 | own_fpu(0); | ||
| 265 | enable_fp_in_kernel(); | ||
| 266 | if (!err) | 301 | if (!err) |
| 267 | err = check_and_restore_fp_context32(sc); | 302 | err = check_and_restore_fp_context32(sc); |
| 268 | disable_fp_in_kernel(); | ||
| 269 | } else { | 303 | } else { |
| 270 | /* signal handler may have used FPU. Give it up. */ | 304 | /* signal handler may have used FPU. Give it up. */ |
| 271 | lose_fpu(0); | 305 | lose_fpu(0); |
diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c index 7d76a85422b2..493cb29b8a42 100644 --- a/arch/mips/kernel/traps.c +++ b/arch/mips/kernel/traps.c | |||
| @@ -650,7 +650,7 @@ asmlinkage void do_bp(struct pt_regs *regs) | |||
| 650 | unsigned int opcode, bcode; | 650 | unsigned int opcode, bcode; |
| 651 | siginfo_t info; | 651 | siginfo_t info; |
| 652 | 652 | ||
| 653 | if (get_user(opcode, (unsigned int __user *) exception_epc(regs))) | 653 | if (__get_user(opcode, (unsigned int __user *) exception_epc(regs))) |
| 654 | goto out_sigsegv; | 654 | goto out_sigsegv; |
| 655 | 655 | ||
| 656 | /* | 656 | /* |
| @@ -700,7 +700,7 @@ asmlinkage void do_tr(struct pt_regs *regs) | |||
| 700 | unsigned int opcode, tcode = 0; | 700 | unsigned int opcode, tcode = 0; |
| 701 | siginfo_t info; | 701 | siginfo_t info; |
| 702 | 702 | ||
| 703 | if (get_user(opcode, (unsigned int __user *) exception_epc(regs))) | 703 | if (__get_user(opcode, (unsigned int __user *) exception_epc(regs))) |
| 704 | goto out_sigsegv; | 704 | goto out_sigsegv; |
| 705 | 705 | ||
| 706 | /* Immediate versions don't provide a code. */ | 706 | /* Immediate versions don't provide a code. */ |
| @@ -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/arch/mips/sibyte/sb1250/setup.c b/arch/mips/sibyte/sb1250/setup.c index 87188f0f6fbe..f4a6169aa0a4 100644 --- a/arch/mips/sibyte/sb1250/setup.c +++ b/arch/mips/sibyte/sb1250/setup.c | |||
| @@ -141,6 +141,18 @@ static int __init setup_bcm112x(void) | |||
| 141 | periph_rev = 3; | 141 | periph_rev = 3; |
| 142 | pass_str = "A2"; | 142 | pass_str = "A2"; |
| 143 | break; | 143 | break; |
| 144 | case K_SYS_REVISION_BCM112x_A3: | ||
| 145 | periph_rev = 3; | ||
| 146 | pass_str = "A3"; | ||
| 147 | break; | ||
| 148 | case K_SYS_REVISION_BCM112x_A4: | ||
| 149 | periph_rev = 3; | ||
| 150 | pass_str = "A4"; | ||
| 151 | break; | ||
| 152 | case K_SYS_REVISION_BCM112x_B0: | ||
| 153 | periph_rev = 3; | ||
| 154 | pass_str = "B0"; | ||
| 155 | break; | ||
| 144 | default: | 156 | default: |
| 145 | printk("Unknown %s rev %x\n", soc_str, soc_pass); | 157 | printk("Unknown %s rev %x\n", soc_str, soc_pass); |
| 146 | ret = 1; | 158 | ret = 1; |
diff --git a/include/asm-mips/bug.h b/include/asm-mips/bug.h index 4d560a533940..7eb63de808bc 100644 --- a/include/asm-mips/bug.h +++ b/include/asm-mips/bug.h | |||
| @@ -18,7 +18,8 @@ do { \ | |||
| 18 | 18 | ||
| 19 | #define BUG_ON(condition) \ | 19 | #define BUG_ON(condition) \ |
| 20 | do { \ | 20 | do { \ |
| 21 | __asm__ __volatile__("tne $0, %0" : : "r" (condition)); \ | 21 | __asm__ __volatile__("tne $0, %0, %1" \ |
| 22 | : : "r" (condition), "i" (BRK_BUG)); \ | ||
| 22 | } while (0) | 23 | } while (0) |
| 23 | 24 | ||
| 24 | #define HAVE_ARCH_BUG_ON | 25 | #define HAVE_ARCH_BUG_ON |
diff --git a/include/asm-mips/checksum.h b/include/asm-mips/checksum.h index 20a81e1548f5..290485ac5407 100644 --- a/include/asm-mips/checksum.h +++ b/include/asm-mips/checksum.h | |||
| @@ -166,7 +166,7 @@ static inline __wsum csum_tcpudp_nofold(__be32 saddr, | |||
| 166 | #else | 166 | #else |
| 167 | "r" (proto + len), | 167 | "r" (proto + len), |
| 168 | #endif | 168 | #endif |
| 169 | "r" (sum)); | 169 | "r" ((__force unsigned long)sum)); |
| 170 | 170 | ||
| 171 | return sum; | 171 | return sum; |
| 172 | } | 172 | } |
diff --git a/include/asm-mips/fpu.h b/include/asm-mips/fpu.h index 4e12d1f9534f..b414a7d9db43 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) \ |
| @@ -102,14 +100,19 @@ static inline void __own_fpu(void) | |||
| 102 | set_thread_flag(TIF_USEDFPU); | 100 | set_thread_flag(TIF_USEDFPU); |
| 103 | } | 101 | } |
| 104 | 102 | ||
| 105 | static inline void own_fpu(int restore) | 103 | static inline void own_fpu_inatomic(int restore) |
| 106 | { | 104 | { |
| 107 | preempt_disable(); | ||
| 108 | if (cpu_has_fpu && !__is_fpu_owner()) { | 105 | if (cpu_has_fpu && !__is_fpu_owner()) { |
| 109 | __own_fpu(); | 106 | __own_fpu(); |
| 110 | if (restore) | 107 | if (restore) |
| 111 | _restore_fp(current); | 108 | _restore_fp(current); |
| 112 | } | 109 | } |
| 110 | } | ||
| 111 | |||
| 112 | static inline void own_fpu(int restore) | ||
| 113 | { | ||
| 114 | preempt_disable(); | ||
| 115 | own_fpu_inatomic(restore); | ||
| 113 | preempt_enable(); | 116 | preempt_enable(); |
| 114 | } | 117 | } |
| 115 | 118 | ||
| @@ -162,18 +165,4 @@ static inline fpureg_t *get_fpu_regs(struct task_struct *tsk) | |||
| 162 | return tsk->thread.fpu.fpr; | 165 | return tsk->thread.fpu.fpr; |
| 163 | } | 166 | } |
| 164 | 167 | ||
| 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 */ | 168 | #endif /* _ASM_FPU_H */ |
diff --git a/include/asm-mips/sibyte/sb1250_scd.h b/include/asm-mips/sibyte/sb1250_scd.h index 7ed0bb611e56..b6a7d8f6ced5 100644 --- a/include/asm-mips/sibyte/sb1250_scd.h +++ b/include/asm-mips/sibyte/sb1250_scd.h | |||
| @@ -84,6 +84,7 @@ | |||
| 84 | #define K_SYS_REVISION_BCM112x_A2 0x21 | 84 | #define K_SYS_REVISION_BCM112x_A2 0x21 |
| 85 | #define K_SYS_REVISION_BCM112x_A3 0x22 | 85 | #define K_SYS_REVISION_BCM112x_A3 0x22 |
| 86 | #define K_SYS_REVISION_BCM112x_A4 0x23 | 86 | #define K_SYS_REVISION_BCM112x_A4 0x23 |
| 87 | #define K_SYS_REVISION_BCM112x_B0 0x30 | ||
| 87 | 88 | ||
| 88 | #define K_SYS_REVISION_BCM1480_S0 0x01 | 89 | #define K_SYS_REVISION_BCM1480_S0 0x01 |
| 89 | #define K_SYS_REVISION_BCM1480_A1 0x02 | 90 | #define K_SYS_REVISION_BCM1480_A1 0x02 |
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) |
