Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[MIPS] Make sure cpu_has_fpu is used only in atomic context

Make sure cpu_has_fpu (which uses smp_processor_id()) is used only in
atomic context.

Signed-off-by: Atsushi Nemoto <anemo@mba.ocn.ne.jp>
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>

authored by

Atsushi Nemoto and committed by
Ralf Baechle
e04582b7 f5c70dd7

+30 -24
+1 -1
arch/mips/kernel/proc.c
··· 107 107 108 108 seq_printf(m, "processor\t\t: %ld\n", n); 109 109 sprintf(fmt, "cpu model\t\t: %%s V%%d.%%d%s\n", 110 - cpu_has_fpu ? " FPU V%d.%d" : ""); 110 + cpu_data[n].options & MIPS_CPU_FPU ? " FPU V%d.%d" : ""); 111 111 seq_printf(m, fmt, cpu_name[cpu_data[n].cputype <= CPU_LAST ? 112 112 cpu_data[n].cputype : CPU_UNKNOWN], 113 113 (version >> 4) & 0x0f, version & 0x0f,
+1 -1
arch/mips/kernel/process.c
··· 115 115 status |= KU_USER; 116 116 regs->cp0_status = status; 117 117 clear_used_math(); 118 - lose_fpu(); 118 + clear_fpu_owner(); 119 119 if (cpu_has_dsp) 120 120 __init_dsp(); 121 121 regs->cp0_epc = pc;
+10 -8
arch/mips/kernel/ptrace.c
··· 106 106 int ptrace_getfpregs (struct task_struct *child, __u32 __user *data) 107 107 { 108 108 int i; 109 + unsigned int tmp; 109 110 110 111 if (!access_ok(VERIFY_WRITE, data, 33 * 8)) 111 112 return -EIO; ··· 122 121 123 122 __put_user (child->thread.fpu.fcr31, data + 64); 124 123 124 + preempt_disable(); 125 125 if (cpu_has_fpu) { 126 - unsigned int flags, tmp; 126 + unsigned int flags; 127 127 128 - preempt_disable(); 129 128 if (cpu_has_mipsmt) { 130 129 unsigned int vpflags = dvpe(); 131 130 flags = read_c0_status(); ··· 139 138 __asm__ __volatile__("cfc1\t%0,$0" : "=r" (tmp)); 140 139 write_c0_status(flags); 141 140 } 142 - preempt_enable(); 143 - __put_user (tmp, data + 65); 144 141 } else { 145 - __put_user ((__u32) 0, data + 65); 142 + tmp = 0; 146 143 } 144 + preempt_enable(); 145 + __put_user (tmp, data + 65); 147 146 148 147 return 0; 149 148 } ··· 246 245 unsigned int mtflags; 247 246 #endif /* CONFIG_MIPS_MT_SMTC */ 248 247 249 - if (!cpu_has_fpu) 248 + preempt_disable(); 249 + if (!cpu_has_fpu) { 250 + preempt_enable(); 250 251 break; 252 + } 251 253 252 254 #ifdef CONFIG_MIPS_MT_SMTC 253 255 /* Read-modify-write of Status must be atomic */ 254 256 local_irq_save(irqflags); 255 257 mtflags = dmt(); 256 258 #endif /* CONFIG_MIPS_MT_SMTC */ 257 - 258 - preempt_disable(); 259 259 if (cpu_has_mipsmt) { 260 260 unsigned int vpflags = dvpe(); 261 261 flags = read_c0_status();
+2 -1
arch/mips/kernel/ptrace32.c
··· 175 175 unsigned int mtflags; 176 176 #endif /* CONFIG_MIPS_MT_SMTC */ 177 177 178 + preempt_disable(); 178 179 if (!cpu_has_fpu) { 180 + preempt_enable(); 179 181 tmp = 0; 180 182 break; 181 183 } ··· 188 186 mtflags = dmt(); 189 187 #endif /* CONFIG_MIPS_MT_SMTC */ 190 188 191 - preempt_disable(); 192 189 if (cpu_has_mipsmt) { 193 190 unsigned int vpflags = dvpe(); 194 191 flags = read_c0_status();
+9 -7
arch/mips/kernel/traps.c
··· 66 66 extern asmlinkage void handle_reserved(void); 67 67 68 68 extern int fpu_emulator_cop1Handler(struct pt_regs *xcp, 69 - struct mips_fpu_struct *ctx); 69 + struct mips_fpu_struct *ctx, int has_fpu); 70 70 71 71 void (*board_be_init)(void); 72 72 int (*board_be_handler)(struct pt_regs *regs, int is_fixup); ··· 641 641 preempt_enable(); 642 642 643 643 /* Run the emulator */ 644 - sig = fpu_emulator_cop1Handler (regs, &current->thread.fpu); 644 + sig = fpu_emulator_cop1Handler (regs, &current->thread.fpu, 1); 645 645 646 646 preempt_disable(); 647 647 ··· 791 791 set_used_math(); 792 792 } 793 793 794 - preempt_enable(); 795 - 796 - if (!cpu_has_fpu) { 797 - int sig = fpu_emulator_cop1Handler(regs, 798 - &current->thread.fpu); 794 + if (cpu_has_fpu) { 795 + preempt_enable(); 796 + } else { 797 + int sig; 798 + preempt_enable(); 799 + sig = fpu_emulator_cop1Handler(regs, 800 + &current->thread.fpu, 0); 799 801 if (sig) 800 802 force_sig(sig, current); 801 803 #ifdef CONFIG_MIPS_MT_FPAFF
+3 -4
arch/mips/math-emu/cp1emu.c
··· 38 38 39 39 #include <asm/inst.h> 40 40 #include <asm/bootinfo.h> 41 - #include <asm/cpu.h> 42 - #include <asm/cpu-features.h> 43 41 #include <asm/processor.h> 44 42 #include <asm/ptrace.h> 45 43 #include <asm/signal.h> ··· 1231 1233 return 0; 1232 1234 } 1233 1235 1234 - int fpu_emulator_cop1Handler(struct pt_regs *xcp, struct mips_fpu_struct *ctx) 1236 + int fpu_emulator_cop1Handler(struct pt_regs *xcp, struct mips_fpu_struct *ctx, 1237 + int has_fpu) 1235 1238 { 1236 1239 unsigned long oldepc, prevepc; 1237 1240 mips_instruction insn; ··· 1262 1263 ieee754_csr.rm = mips_rm[ieee754_csr.rm]; 1263 1264 } 1264 1265 1265 - if (cpu_has_fpu) 1266 + if (has_fpu) 1266 1267 break; 1267 1268 if (sig) 1268 1269 break;
+4 -2
include/asm-mips/fpu.h
··· 134 134 135 135 static inline fpureg_t *get_fpu_regs(struct task_struct *tsk) 136 136 { 137 - if (cpu_has_fpu) { 138 - if ((tsk == current) && __is_fpu_owner()) 137 + if (tsk == current) { 138 + preempt_disable(); 139 + if (is_fpu_owner()) 139 140 _save_fp(current); 141 + preempt_enable(); 140 142 } 141 143 142 144 return tsk->thread.fpu.fpr;