Loading arch/mips/kernel/r2300_switch.S +6 −4 Original line number Diff line number Diff line Loading @@ -49,8 +49,7 @@ LEAF(resume) #ifndef CONFIG_CPU_HAS_LLSC sw zero, ll_bit #endif mfc0 t1, CP0_STATUS sw t1, THREAD_STATUS(a0) mfc0 t2, CP0_STATUS cpu_save_nonscratch a0 sw ra, THREAD_REG31(a0) Loading @@ -60,8 +59,8 @@ LEAF(resume) lw t3, TASK_THREAD_INFO(a0) lw t0, TI_FLAGS(t3) li t1, _TIF_USEDFPU and t2, t0, t1 beqz t2, 1f and t1, t0 beqz t1, 1f nor t1, zero, t1 and t0, t0, t1 Loading @@ -74,10 +73,13 @@ LEAF(resume) li t1, ~ST0_CU1 and t0, t0, t1 sw t0, ST_OFF(t3) /* clear thread_struct CU1 bit */ and t2, t1 fpu_save_single a0, t0 # clobbers t0 1: sw t2, THREAD_STATUS(a0) /* * The order of restoring the registers takes care of the race * updating $28, $29 and kernelsp without disabling ints. Loading arch/mips/kernel/r4k_switch.S +6 −4 Original line number Diff line number Diff line Loading @@ -48,8 +48,7 @@ #ifndef CONFIG_CPU_HAS_LLSC sw zero, ll_bit #endif mfc0 t1, CP0_STATUS LONG_S t1, THREAD_STATUS(a0) mfc0 t2, CP0_STATUS cpu_save_nonscratch a0 LONG_S ra, THREAD_REG31(a0) Loading @@ -59,8 +58,8 @@ PTR_L t3, TASK_THREAD_INFO(a0) LONG_L t0, TI_FLAGS(t3) li t1, _TIF_USEDFPU and t2, t0, t1 beqz t2, 1f and t1, t0 beqz t1, 1f nor t1, zero, t1 and t0, t0, t1 Loading @@ -73,10 +72,13 @@ li t1, ~ST0_CU1 and t0, t0, t1 LONG_S t0, ST_OFF(t3) /* clear thread_struct CU1 bit */ and t2, t1 fpu_save_double a0 t0 t1 # c0_status passed in t0 # clobbers t1 1: LONG_S t2, THREAD_STATUS(a0) /* * The order of restoring the registers takes care of the race Loading arch/mips/kernel/signal.c +12 −17 Original line number Diff line number Diff line Loading @@ -82,6 +82,7 @@ int setup_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc) { int err = 0; int i; unsigned int used_math; err |= __put_user(regs->cp0_epc, &sc->sc_pc); Loading @@ -104,22 +105,18 @@ int setup_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc) err |= __put_user(rddsp(DSP_MASK), &sc->sc_dsp); } err |= __put_user(!!used_math(), &sc->sc_used_math); used_math = !!used_math(); err |= __put_user(used_math, &sc->sc_used_math); if (used_math()) { if (used_math) { /* * Save FPU state to signal context. Signal handler * will "inherit" current FPU state. */ preempt_disable(); if (!is_fpu_owner()) { own_fpu(); restore_fp(current); } own_fpu(1); enable_fp_in_kernel(); err |= save_fp_context(sc); preempt_enable(); disable_fp_in_kernel(); } return err; } Loading Loading @@ -188,20 +185,18 @@ int restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc) err |= __get_user(used_math, &sc->sc_used_math); conditional_used_math(used_math); preempt_disable(); if (used_math()) { if (used_math) { /* restore fpu context if we have used it before */ own_fpu(); own_fpu(0); enable_fp_in_kernel(); if (!err) err = check_and_restore_fp_context(sc); disable_fp_in_kernel(); } else { /* signal handler may have used FPU. Give it up. */ lose_fpu(); lose_fpu(0); } preempt_enable(); return err; } Loading arch/mips/kernel/signal32.c +12 −17 Original line number Diff line number Diff line Loading @@ -181,6 +181,7 @@ static int setup_sigcontext32(struct pt_regs *regs, { int err = 0; int i; u32 used_math; err |= __put_user(regs->cp0_epc, &sc->sc_pc); Loading @@ -200,22 +201,18 @@ static int setup_sigcontext32(struct pt_regs *regs, err |= __put_user(mflo3(), &sc->sc_lo3); } err |= __put_user(!!used_math(), &sc->sc_used_math); used_math = !!used_math(); err |= __put_user(used_math, &sc->sc_used_math); if (used_math()) { if (used_math) { /* * Save FPU state to signal context. Signal handler * will "inherit" current FPU state. */ preempt_disable(); if (!is_fpu_owner()) { own_fpu(); restore_fp(current); } own_fpu(1); enable_fp_in_kernel(); err |= save_fp_context32(sc); preempt_enable(); disable_fp_in_kernel(); } return err; } Loading Loading @@ -262,20 +259,18 @@ static int restore_sigcontext32(struct pt_regs *regs, err |= __get_user(used_math, &sc->sc_used_math); conditional_used_math(used_math); preempt_disable(); if (used_math()) { if (used_math) { /* restore fpu context if we have used it before */ own_fpu(); own_fpu(0); enable_fp_in_kernel(); if (!err) err = check_and_restore_fp_context32(sc); disable_fp_in_kernel(); } else { /* signal handler may have used FPU. Give it up. */ lose_fpu(); lose_fpu(0); } preempt_enable(); return err; } Loading arch/mips/kernel/traps.c +37 −47 Original line number Diff line number Diff line Loading @@ -610,16 +610,6 @@ asmlinkage void do_fpe(struct pt_regs *regs, unsigned long fcr31) if (fcr31 & FPU_CSR_UNI_X) { int sig; preempt_disable(); #ifdef CONFIG_PREEMPT if (!is_fpu_owner()) { /* We might lose fpu before disabling preempt... */ own_fpu(); BUG_ON(!used_math()); restore_fp(current); } #endif /* * Unimplemented operation exception. If we've got the full * software emulator on-board, let's use it... Loading @@ -630,18 +620,12 @@ asmlinkage void do_fpe(struct pt_regs *regs, unsigned long fcr31) * register operands before invoking the emulator, which seems * a bit extreme for what should be an infrequent event. */ save_fp(current); /* Ensure 'resume' not overwrite saved fp context again. */ lose_fpu(); preempt_enable(); lose_fpu(1); /* Run the emulator */ sig = fpu_emulator_cop1Handler (regs, ¤t->thread.fpu, 1); preempt_disable(); own_fpu(); /* Using the FPU again. */ /* * We can't allow the emulated instruction to leave any of * the cause bit set in $fcr31. Loading @@ -649,9 +633,7 @@ asmlinkage void do_fpe(struct pt_regs *regs, unsigned long fcr31) current->thread.fpu.fcr31 &= ~FPU_CSR_ALL_X; /* Restore the hardware register state */ restore_fp(current); preempt_enable(); own_fpu(1); /* Using the FPU again. */ /* If something went wrong, signal */ if (sig) Loading Loading @@ -775,12 +757,11 @@ asmlinkage void do_cpu(struct pt_regs *regs) { unsigned int cpid; die_if_kernel("do_cpu invoked from kernel context!", regs); cpid = (regs->cp0_cause >> CAUSEB_CE) & 3; switch (cpid) { case 0: die_if_kernel("do_cpu invoked from kernel context!", regs); if (!cpu_has_llsc) if (!simulate_llsc(regs)) return; Loading @@ -791,21 +772,30 @@ asmlinkage void do_cpu(struct pt_regs *regs) break; case 1: preempt_disable(); own_fpu(); if (used_math()) { /* Using the FPU again. */ restore_fp(current); } else { /* First time FPU user. */ if (!test_thread_flag(TIF_ALLOW_FP_IN_KERNEL)) die_if_kernel("do_cpu invoked from kernel context!", regs); if (used_math()) /* Using the FPU again. */ own_fpu(1); else { /* First time FPU user. */ init_fpu(); set_used_math(); } if (cpu_has_fpu) { preempt_enable(); if (raw_cpu_has_fpu) { if (test_thread_flag(TIF_ALLOW_FP_IN_KERNEL)) { local_irq_disable(); if (cpu_has_fpu) regs->cp0_status |= ST0_CU1; /* * We must return without enabling * interrupts to ensure keep FPU * ownership until resume. */ return; } } else { int sig; preempt_enable(); sig = fpu_emulator_cop1Handler(regs, ¤t->thread.fpu, 0); if (sig) Loading Loading @@ -1259,26 +1249,26 @@ static inline void mips_srs_init(void) /* * This is used by native signal handling */ asmlinkage int (*save_fp_context)(struct sigcontext *sc); asmlinkage int (*restore_fp_context)(struct sigcontext *sc); asmlinkage int (*save_fp_context)(struct sigcontext __user *sc); asmlinkage int (*restore_fp_context)(struct sigcontext __user *sc); extern asmlinkage int _save_fp_context(struct sigcontext *sc); extern asmlinkage int _restore_fp_context(struct sigcontext *sc); extern asmlinkage int _save_fp_context(struct sigcontext __user *sc); extern asmlinkage int _restore_fp_context(struct sigcontext __user *sc); extern asmlinkage int fpu_emulator_save_context(struct sigcontext *sc); extern asmlinkage int fpu_emulator_restore_context(struct sigcontext *sc); extern asmlinkage int fpu_emulator_save_context(struct sigcontext __user *sc); extern asmlinkage int fpu_emulator_restore_context(struct sigcontext __user *sc); #ifdef CONFIG_SMP static int smp_save_fp_context(struct sigcontext *sc) static int smp_save_fp_context(struct sigcontext __user *sc) { return cpu_has_fpu return raw_cpu_has_fpu ? _save_fp_context(sc) : fpu_emulator_save_context(sc); } static int smp_restore_fp_context(struct sigcontext *sc) static int smp_restore_fp_context(struct sigcontext __user *sc) { return cpu_has_fpu return raw_cpu_has_fpu ? _restore_fp_context(sc) : fpu_emulator_restore_context(sc); } Loading Loading @@ -1306,14 +1296,14 @@ static inline void signal_init(void) /* * This is used by 32-bit signal stuff on the 64-bit kernel */ asmlinkage int (*save_fp_context32)(struct sigcontext32 *sc); asmlinkage int (*restore_fp_context32)(struct sigcontext32 *sc); asmlinkage int (*save_fp_context32)(struct sigcontext32 __user *sc); asmlinkage int (*restore_fp_context32)(struct sigcontext32 __user *sc); extern asmlinkage int _save_fp_context32(struct sigcontext32 *sc); extern asmlinkage int _restore_fp_context32(struct sigcontext32 *sc); extern asmlinkage int _save_fp_context32(struct sigcontext32 __user *sc); extern asmlinkage int _restore_fp_context32(struct sigcontext32 __user *sc); extern asmlinkage int fpu_emulator_save_context32(struct sigcontext32 *sc); extern asmlinkage int fpu_emulator_restore_context32(struct sigcontext32 *sc); extern asmlinkage int fpu_emulator_save_context32(struct sigcontext32 __user *sc); extern asmlinkage int fpu_emulator_restore_context32(struct sigcontext32 __user *sc); static inline void signal32_init(void) { Loading Loading
arch/mips/kernel/r2300_switch.S +6 −4 Original line number Diff line number Diff line Loading @@ -49,8 +49,7 @@ LEAF(resume) #ifndef CONFIG_CPU_HAS_LLSC sw zero, ll_bit #endif mfc0 t1, CP0_STATUS sw t1, THREAD_STATUS(a0) mfc0 t2, CP0_STATUS cpu_save_nonscratch a0 sw ra, THREAD_REG31(a0) Loading @@ -60,8 +59,8 @@ LEAF(resume) lw t3, TASK_THREAD_INFO(a0) lw t0, TI_FLAGS(t3) li t1, _TIF_USEDFPU and t2, t0, t1 beqz t2, 1f and t1, t0 beqz t1, 1f nor t1, zero, t1 and t0, t0, t1 Loading @@ -74,10 +73,13 @@ LEAF(resume) li t1, ~ST0_CU1 and t0, t0, t1 sw t0, ST_OFF(t3) /* clear thread_struct CU1 bit */ and t2, t1 fpu_save_single a0, t0 # clobbers t0 1: sw t2, THREAD_STATUS(a0) /* * The order of restoring the registers takes care of the race * updating $28, $29 and kernelsp without disabling ints. Loading
arch/mips/kernel/r4k_switch.S +6 −4 Original line number Diff line number Diff line Loading @@ -48,8 +48,7 @@ #ifndef CONFIG_CPU_HAS_LLSC sw zero, ll_bit #endif mfc0 t1, CP0_STATUS LONG_S t1, THREAD_STATUS(a0) mfc0 t2, CP0_STATUS cpu_save_nonscratch a0 LONG_S ra, THREAD_REG31(a0) Loading @@ -59,8 +58,8 @@ PTR_L t3, TASK_THREAD_INFO(a0) LONG_L t0, TI_FLAGS(t3) li t1, _TIF_USEDFPU and t2, t0, t1 beqz t2, 1f and t1, t0 beqz t1, 1f nor t1, zero, t1 and t0, t0, t1 Loading @@ -73,10 +72,13 @@ li t1, ~ST0_CU1 and t0, t0, t1 LONG_S t0, ST_OFF(t3) /* clear thread_struct CU1 bit */ and t2, t1 fpu_save_double a0 t0 t1 # c0_status passed in t0 # clobbers t1 1: LONG_S t2, THREAD_STATUS(a0) /* * The order of restoring the registers takes care of the race Loading
arch/mips/kernel/signal.c +12 −17 Original line number Diff line number Diff line Loading @@ -82,6 +82,7 @@ int setup_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc) { int err = 0; int i; unsigned int used_math; err |= __put_user(regs->cp0_epc, &sc->sc_pc); Loading @@ -104,22 +105,18 @@ int setup_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc) err |= __put_user(rddsp(DSP_MASK), &sc->sc_dsp); } err |= __put_user(!!used_math(), &sc->sc_used_math); used_math = !!used_math(); err |= __put_user(used_math, &sc->sc_used_math); if (used_math()) { if (used_math) { /* * Save FPU state to signal context. Signal handler * will "inherit" current FPU state. */ preempt_disable(); if (!is_fpu_owner()) { own_fpu(); restore_fp(current); } own_fpu(1); enable_fp_in_kernel(); err |= save_fp_context(sc); preempt_enable(); disable_fp_in_kernel(); } return err; } Loading Loading @@ -188,20 +185,18 @@ int restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc) err |= __get_user(used_math, &sc->sc_used_math); conditional_used_math(used_math); preempt_disable(); if (used_math()) { if (used_math) { /* restore fpu context if we have used it before */ own_fpu(); own_fpu(0); enable_fp_in_kernel(); if (!err) err = check_and_restore_fp_context(sc); disable_fp_in_kernel(); } else { /* signal handler may have used FPU. Give it up. */ lose_fpu(); lose_fpu(0); } preempt_enable(); return err; } Loading
arch/mips/kernel/signal32.c +12 −17 Original line number Diff line number Diff line Loading @@ -181,6 +181,7 @@ static int setup_sigcontext32(struct pt_regs *regs, { int err = 0; int i; u32 used_math; err |= __put_user(regs->cp0_epc, &sc->sc_pc); Loading @@ -200,22 +201,18 @@ static int setup_sigcontext32(struct pt_regs *regs, err |= __put_user(mflo3(), &sc->sc_lo3); } err |= __put_user(!!used_math(), &sc->sc_used_math); used_math = !!used_math(); err |= __put_user(used_math, &sc->sc_used_math); if (used_math()) { if (used_math) { /* * Save FPU state to signal context. Signal handler * will "inherit" current FPU state. */ preempt_disable(); if (!is_fpu_owner()) { own_fpu(); restore_fp(current); } own_fpu(1); enable_fp_in_kernel(); err |= save_fp_context32(sc); preempt_enable(); disable_fp_in_kernel(); } return err; } Loading Loading @@ -262,20 +259,18 @@ static int restore_sigcontext32(struct pt_regs *regs, err |= __get_user(used_math, &sc->sc_used_math); conditional_used_math(used_math); preempt_disable(); if (used_math()) { if (used_math) { /* restore fpu context if we have used it before */ own_fpu(); own_fpu(0); enable_fp_in_kernel(); if (!err) err = check_and_restore_fp_context32(sc); disable_fp_in_kernel(); } else { /* signal handler may have used FPU. Give it up. */ lose_fpu(); lose_fpu(0); } preempt_enable(); return err; } Loading
arch/mips/kernel/traps.c +37 −47 Original line number Diff line number Diff line Loading @@ -610,16 +610,6 @@ asmlinkage void do_fpe(struct pt_regs *regs, unsigned long fcr31) if (fcr31 & FPU_CSR_UNI_X) { int sig; preempt_disable(); #ifdef CONFIG_PREEMPT if (!is_fpu_owner()) { /* We might lose fpu before disabling preempt... */ own_fpu(); BUG_ON(!used_math()); restore_fp(current); } #endif /* * Unimplemented operation exception. If we've got the full * software emulator on-board, let's use it... Loading @@ -630,18 +620,12 @@ asmlinkage void do_fpe(struct pt_regs *regs, unsigned long fcr31) * register operands before invoking the emulator, which seems * a bit extreme for what should be an infrequent event. */ save_fp(current); /* Ensure 'resume' not overwrite saved fp context again. */ lose_fpu(); preempt_enable(); lose_fpu(1); /* Run the emulator */ sig = fpu_emulator_cop1Handler (regs, ¤t->thread.fpu, 1); preempt_disable(); own_fpu(); /* Using the FPU again. */ /* * We can't allow the emulated instruction to leave any of * the cause bit set in $fcr31. Loading @@ -649,9 +633,7 @@ asmlinkage void do_fpe(struct pt_regs *regs, unsigned long fcr31) current->thread.fpu.fcr31 &= ~FPU_CSR_ALL_X; /* Restore the hardware register state */ restore_fp(current); preempt_enable(); own_fpu(1); /* Using the FPU again. */ /* If something went wrong, signal */ if (sig) Loading Loading @@ -775,12 +757,11 @@ asmlinkage void do_cpu(struct pt_regs *regs) { unsigned int cpid; die_if_kernel("do_cpu invoked from kernel context!", regs); cpid = (regs->cp0_cause >> CAUSEB_CE) & 3; switch (cpid) { case 0: die_if_kernel("do_cpu invoked from kernel context!", regs); if (!cpu_has_llsc) if (!simulate_llsc(regs)) return; Loading @@ -791,21 +772,30 @@ asmlinkage void do_cpu(struct pt_regs *regs) break; case 1: preempt_disable(); own_fpu(); if (used_math()) { /* Using the FPU again. */ restore_fp(current); } else { /* First time FPU user. */ if (!test_thread_flag(TIF_ALLOW_FP_IN_KERNEL)) die_if_kernel("do_cpu invoked from kernel context!", regs); if (used_math()) /* Using the FPU again. */ own_fpu(1); else { /* First time FPU user. */ init_fpu(); set_used_math(); } if (cpu_has_fpu) { preempt_enable(); if (raw_cpu_has_fpu) { if (test_thread_flag(TIF_ALLOW_FP_IN_KERNEL)) { local_irq_disable(); if (cpu_has_fpu) regs->cp0_status |= ST0_CU1; /* * We must return without enabling * interrupts to ensure keep FPU * ownership until resume. */ return; } } else { int sig; preempt_enable(); sig = fpu_emulator_cop1Handler(regs, ¤t->thread.fpu, 0); if (sig) Loading Loading @@ -1259,26 +1249,26 @@ static inline void mips_srs_init(void) /* * This is used by native signal handling */ asmlinkage int (*save_fp_context)(struct sigcontext *sc); asmlinkage int (*restore_fp_context)(struct sigcontext *sc); asmlinkage int (*save_fp_context)(struct sigcontext __user *sc); asmlinkage int (*restore_fp_context)(struct sigcontext __user *sc); extern asmlinkage int _save_fp_context(struct sigcontext *sc); extern asmlinkage int _restore_fp_context(struct sigcontext *sc); extern asmlinkage int _save_fp_context(struct sigcontext __user *sc); extern asmlinkage int _restore_fp_context(struct sigcontext __user *sc); extern asmlinkage int fpu_emulator_save_context(struct sigcontext *sc); extern asmlinkage int fpu_emulator_restore_context(struct sigcontext *sc); extern asmlinkage int fpu_emulator_save_context(struct sigcontext __user *sc); extern asmlinkage int fpu_emulator_restore_context(struct sigcontext __user *sc); #ifdef CONFIG_SMP static int smp_save_fp_context(struct sigcontext *sc) static int smp_save_fp_context(struct sigcontext __user *sc) { return cpu_has_fpu return raw_cpu_has_fpu ? _save_fp_context(sc) : fpu_emulator_save_context(sc); } static int smp_restore_fp_context(struct sigcontext *sc) static int smp_restore_fp_context(struct sigcontext __user *sc) { return cpu_has_fpu return raw_cpu_has_fpu ? _restore_fp_context(sc) : fpu_emulator_restore_context(sc); } Loading Loading @@ -1306,14 +1296,14 @@ static inline void signal_init(void) /* * This is used by 32-bit signal stuff on the 64-bit kernel */ asmlinkage int (*save_fp_context32)(struct sigcontext32 *sc); asmlinkage int (*restore_fp_context32)(struct sigcontext32 *sc); asmlinkage int (*save_fp_context32)(struct sigcontext32 __user *sc); asmlinkage int (*restore_fp_context32)(struct sigcontext32 __user *sc); extern asmlinkage int _save_fp_context32(struct sigcontext32 *sc); extern asmlinkage int _restore_fp_context32(struct sigcontext32 *sc); extern asmlinkage int _save_fp_context32(struct sigcontext32 __user *sc); extern asmlinkage int _restore_fp_context32(struct sigcontext32 __user *sc); extern asmlinkage int fpu_emulator_save_context32(struct sigcontext32 *sc); extern asmlinkage int fpu_emulator_restore_context32(struct sigcontext32 *sc); extern asmlinkage int fpu_emulator_save_context32(struct sigcontext32 __user *sc); extern asmlinkage int fpu_emulator_restore_context32(struct sigcontext32 __user *sc); static inline void signal32_init(void) { Loading