···4949#ifndef CONFIG_CPU_HAS_LLSC5050 sw zero, ll_bit5151#endif5252- mfc0 t1, CP0_STATUS5353- sw t1, THREAD_STATUS(a0)5252+ mfc0 t2, CP0_STATUS5453 cpu_save_nonscratch a05554 sw ra, THREAD_REG31(a0)5655···5960 lw t3, TASK_THREAD_INFO(a0)6061 lw t0, TI_FLAGS(t3)6162 li t1, _TIF_USEDFPU6262- and t2, t0, t16363- beqz t2, 1f6363+ and t1, t06464+ beqz t1, 1f6465 nor t1, zero, t165666667 and t0, t0, t1···7374 li t1, ~ST0_CU17475 and t0, t0, t17576 sw t0, ST_OFF(t3)7777+ /* clear thread_struct CU1 bit */7878+ and t2, t176797780 fpu_save_single a0, t0 # clobbers t0788179821:8383+ sw t2, THREAD_STATUS(a0)8084 /*8185 * The order of restoring the registers takes care of the race8286 * updating $28, $29 and kernelsp without disabling ints.
+6-4
arch/mips/kernel/r4k_switch.S
···4848#ifndef CONFIG_CPU_HAS_LLSC4949 sw zero, ll_bit5050#endif5151- mfc0 t1, CP0_STATUS5252- LONG_S t1, THREAD_STATUS(a0)5151+ mfc0 t2, CP0_STATUS5352 cpu_save_nonscratch a05453 LONG_S ra, THREAD_REG31(a0)5554···5859 PTR_L t3, TASK_THREAD_INFO(a0)5960 LONG_L t0, TI_FLAGS(t3)6061 li t1, _TIF_USEDFPU6161- and t2, t0, t16262- beqz t2, 1f6262+ and t1, t06363+ beqz t1, 1f6364 nor t1, zero, t164656566 and t0, t0, t1···7273 li t1, ~ST0_CU17374 and t0, t0, t17475 LONG_S t0, ST_OFF(t3)7676+ /* clear thread_struct CU1 bit */7777+ and t2, t175787679 fpu_save_double a0 t0 t1 # c0_status passed in t07780 # clobbers t178811:8282+ LONG_S t2, THREAD_STATUS(a0)79838084 /*8185 * The order of restoring the registers takes care of the race
+12-17
arch/mips/kernel/signal.c
···8282{8383 int err = 0;8484 int i;8585+ unsigned int used_math;85868687 err |= __put_user(regs->cp0_epc, &sc->sc_pc);8788···105104 err |= __put_user(rddsp(DSP_MASK), &sc->sc_dsp);106105 }107106108108- err |= __put_user(!!used_math(), &sc->sc_used_math);107107+ used_math = !!used_math();108108+ err |= __put_user(used_math, &sc->sc_used_math);109109110110- if (used_math()) {110110+ if (used_math) {111111 /*112112 * Save FPU state to signal context. Signal handler113113 * will "inherit" current FPU state.114114 */115115- preempt_disable();116116-117117- if (!is_fpu_owner()) {118118- own_fpu();119119- restore_fp(current);120120- }115115+ own_fpu(1);116116+ enable_fp_in_kernel();121117 err |= save_fp_context(sc);122122-123123- preempt_enable();118118+ disable_fp_in_kernel();124119 }125120 return err;126121}···185188 err |= __get_user(used_math, &sc->sc_used_math);186189 conditional_used_math(used_math);187190188188- preempt_disable();189189-190190- if (used_math()) {191191+ if (used_math) {191192 /* restore fpu context if we have used it before */192192- own_fpu();193193+ own_fpu(0);194194+ enable_fp_in_kernel();193195 if (!err)194196 err = check_and_restore_fp_context(sc);197197+ disable_fp_in_kernel();195198 } else {196199 /* signal handler may have used FPU. Give it up. */197197- lose_fpu();200200+ lose_fpu(0);198201 }199199-200200- preempt_enable();201202202203 return err;203204}
+12-17
arch/mips/kernel/signal32.c
···181181{182182 int err = 0;183183 int i;184184+ u32 used_math;184185185186 err |= __put_user(regs->cp0_epc, &sc->sc_pc);186187···201200 err |= __put_user(mflo3(), &sc->sc_lo3);202201 }203202204204- err |= __put_user(!!used_math(), &sc->sc_used_math);203203+ used_math = !!used_math();204204+ err |= __put_user(used_math, &sc->sc_used_math);205205206206- if (used_math()) {206206+ if (used_math) {207207 /*208208 * Save FPU state to signal context. Signal handler209209 * will "inherit" current FPU state.210210 */211211- preempt_disable();212212-213213- if (!is_fpu_owner()) {214214- own_fpu();215215- restore_fp(current);216216- }211211+ own_fpu(1);212212+ enable_fp_in_kernel();217213 err |= save_fp_context32(sc);218218-219219- preempt_enable();214214+ disable_fp_in_kernel();220215 }221216 return err;222217}···259262 err |= __get_user(used_math, &sc->sc_used_math);260263 conditional_used_math(used_math);261264262262- preempt_disable();263263-264264- if (used_math()) {265265+ if (used_math) {265266 /* restore fpu context if we have used it before */266266- own_fpu();267267+ own_fpu(0);268268+ enable_fp_in_kernel();267269 if (!err)268270 err = check_and_restore_fp_context32(sc);271271+ disable_fp_in_kernel();269272 } else {270273 /* signal handler may have used FPU. Give it up. */271271- lose_fpu();274274+ lose_fpu(0);272275 }273273-274274- preempt_enable();275276276277 return err;277278}
+37-47
arch/mips/kernel/traps.c
···610610 if (fcr31 & FPU_CSR_UNI_X) {611611 int sig;612612613613- preempt_disable();614614-615615-#ifdef CONFIG_PREEMPT616616- if (!is_fpu_owner()) {617617- /* We might lose fpu before disabling preempt... */618618- own_fpu();619619- BUG_ON(!used_math());620620- restore_fp(current);621621- }622622-#endif623613 /*624614 * Unimplemented operation exception. If we've got the full625615 * software emulator on-board, let's use it...···620630 * register operands before invoking the emulator, which seems621631 * a bit extreme for what should be an infrequent event.622632 */623623- save_fp(current);624633 /* Ensure 'resume' not overwrite saved fp context again. */625625- lose_fpu();626626-627627- preempt_enable();634634+ lose_fpu(1);628635629636 /* Run the emulator */630637 sig = fpu_emulator_cop1Handler (regs, ¤t->thread.fpu, 1);631638632632- preempt_disable();633633-634634- own_fpu(); /* Using the FPU again. */635639 /*636640 * We can't allow the emulated instruction to leave any of637641 * the cause bit set in $fcr31.···633649 current->thread.fpu.fcr31 &= ~FPU_CSR_ALL_X;634650635651 /* Restore the hardware register state */636636- restore_fp(current);637637-638638- preempt_enable();652652+ own_fpu(1); /* Using the FPU again. */639653640654 /* If something went wrong, signal */641655 if (sig)···757775{758776 unsigned int cpid;759777760760- die_if_kernel("do_cpu invoked from kernel context!", regs);761761-762778 cpid = (regs->cp0_cause >> CAUSEB_CE) & 3;763779764780 switch (cpid) {765781 case 0:782782+ die_if_kernel("do_cpu invoked from kernel context!", regs);766783 if (!cpu_has_llsc)767784 if (!simulate_llsc(regs))768785 return;···772791 break;773792774793 case 1:775775- preempt_disable();776776-777777- own_fpu();778778- if (used_math()) { /* Using the FPU again. */779779- restore_fp(current);780780- } else { /* First time FPU user. */794794+ if (!test_thread_flag(TIF_ALLOW_FP_IN_KERNEL))795795+ die_if_kernel("do_cpu invoked from kernel context!",796796+ regs);797797+ if (used_math()) /* Using the FPU again. */798798+ own_fpu(1);799799+ else { /* First time FPU user. */781800 init_fpu();782801 set_used_math();783802 }784803785785- if (cpu_has_fpu) {786786- preempt_enable();804804+ if (raw_cpu_has_fpu) {805805+ if (test_thread_flag(TIF_ALLOW_FP_IN_KERNEL)) {806806+ local_irq_disable();807807+ if (cpu_has_fpu)808808+ regs->cp0_status |= ST0_CU1;809809+ /*810810+ * We must return without enabling811811+ * interrupts to ensure keep FPU812812+ * ownership until resume.813813+ */814814+ return;815815+ }787816 } else {788817 int sig;789789- preempt_enable();790818 sig = fpu_emulator_cop1Handler(regs,791819 ¤t->thread.fpu, 0);792820 if (sig)···12491259/*12501260 * This is used by native signal handling12511261 */12521252-asmlinkage int (*save_fp_context)(struct sigcontext *sc);12531253-asmlinkage int (*restore_fp_context)(struct sigcontext *sc);12621262+asmlinkage int (*save_fp_context)(struct sigcontext __user *sc);12631263+asmlinkage int (*restore_fp_context)(struct sigcontext __user *sc);1254126412551255-extern asmlinkage int _save_fp_context(struct sigcontext *sc);12561256-extern asmlinkage int _restore_fp_context(struct sigcontext *sc);12651265+extern asmlinkage int _save_fp_context(struct sigcontext __user *sc);12661266+extern asmlinkage int _restore_fp_context(struct sigcontext __user *sc);1257126712581258-extern asmlinkage int fpu_emulator_save_context(struct sigcontext *sc);12591259-extern asmlinkage int fpu_emulator_restore_context(struct sigcontext *sc);12681268+extern asmlinkage int fpu_emulator_save_context(struct sigcontext __user *sc);12691269+extern asmlinkage int fpu_emulator_restore_context(struct sigcontext __user *sc);1260127012611271#ifdef CONFIG_SMP12621262-static int smp_save_fp_context(struct sigcontext *sc)12721272+static int smp_save_fp_context(struct sigcontext __user *sc)12631273{12641264- return cpu_has_fpu12741274+ return raw_cpu_has_fpu12651275 ? _save_fp_context(sc)12661276 : fpu_emulator_save_context(sc);12671277}1268127812691269-static int smp_restore_fp_context(struct sigcontext *sc)12791279+static int smp_restore_fp_context(struct sigcontext __user *sc)12701280{12711271- return cpu_has_fpu12811281+ return raw_cpu_has_fpu12721282 ? _restore_fp_context(sc)12731283 : fpu_emulator_restore_context(sc);12741284}···12961306/*12971307 * This is used by 32-bit signal stuff on the 64-bit kernel12981308 */12991299-asmlinkage int (*save_fp_context32)(struct sigcontext32 *sc);13001300-asmlinkage int (*restore_fp_context32)(struct sigcontext32 *sc);13091309+asmlinkage int (*save_fp_context32)(struct sigcontext32 __user *sc);13101310+asmlinkage int (*restore_fp_context32)(struct sigcontext32 __user *sc);1301131113021302-extern asmlinkage int _save_fp_context32(struct sigcontext32 *sc);13031303-extern asmlinkage int _restore_fp_context32(struct sigcontext32 *sc);13121312+extern asmlinkage int _save_fp_context32(struct sigcontext32 __user *sc);13131313+extern asmlinkage int _restore_fp_context32(struct sigcontext32 __user *sc);1304131413051305-extern asmlinkage int fpu_emulator_save_context32(struct sigcontext32 *sc);13061306-extern asmlinkage int fpu_emulator_restore_context32(struct sigcontext32 *sc);13151315+extern asmlinkage int fpu_emulator_save_context32(struct sigcontext32 __user *sc);13161316+extern asmlinkage int fpu_emulator_restore_context32(struct sigcontext32 __user *sc);1307131713081318static inline void signal32_init(void)13091319{
+4-4
arch/mips/math-emu/kernel_linkage.c
···5151 * with appropriate macros from uaccess.h5252 */53535454-int fpu_emulator_save_context(struct sigcontext *sc)5454+int fpu_emulator_save_context(struct sigcontext __user *sc)5555{5656 int i;5757 int err = 0;···6565 return err;6666}67676868-int fpu_emulator_restore_context(struct sigcontext *sc)6868+int fpu_emulator_restore_context(struct sigcontext __user *sc)6969{7070 int i;7171 int err = 0;···8484 * This is the o32 version8585 */86868787-int fpu_emulator_save_context32(struct sigcontext32 *sc)8787+int fpu_emulator_save_context32(struct sigcontext32 __user *sc)8888{8989 int i;9090 int err = 0;···9898 return err;9999}100100101101-int fpu_emulator_restore_context32(struct sigcontext32 *sc)101101+int fpu_emulator_restore_context32(struct sigcontext32 __user *sc)102102{103103 int i;104104 int err = 0;