Commit e04582b7 authored by Atsushi Nemoto's avatar Atsushi Nemoto Committed by Ralf Baechle

[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: default avatarAtsushi Nemoto <anemo@mba.ocn.ne.jp>
Signed-off-by: default avatarRalf Baechle <ralf@linux-mips.org>
parent f5c70dd7
...@@ -107,7 +107,7 @@ static int show_cpuinfo(struct seq_file *m, void *v) ...@@ -107,7 +107,7 @@ static int show_cpuinfo(struct seq_file *m, void *v)
seq_printf(m, "processor\t\t: %ld\n", n); seq_printf(m, "processor\t\t: %ld\n", n);
sprintf(fmt, "cpu model\t\t: %%s V%%d.%%d%s\n", sprintf(fmt, "cpu model\t\t: %%s V%%d.%%d%s\n",
cpu_has_fpu ? " FPU V%d.%d" : ""); cpu_data[n].options & MIPS_CPU_FPU ? " FPU V%d.%d" : "");
seq_printf(m, fmt, cpu_name[cpu_data[n].cputype <= CPU_LAST ? seq_printf(m, fmt, cpu_name[cpu_data[n].cputype <= CPU_LAST ?
cpu_data[n].cputype : CPU_UNKNOWN], cpu_data[n].cputype : CPU_UNKNOWN],
(version >> 4) & 0x0f, version & 0x0f, (version >> 4) & 0x0f, version & 0x0f,
......
...@@ -115,7 +115,7 @@ void start_thread(struct pt_regs * regs, unsigned long pc, unsigned long sp) ...@@ -115,7 +115,7 @@ void start_thread(struct pt_regs * regs, unsigned long pc, unsigned long sp)
status |= KU_USER; status |= KU_USER;
regs->cp0_status = status; regs->cp0_status = status;
clear_used_math(); clear_used_math();
lose_fpu(); clear_fpu_owner();
if (cpu_has_dsp) if (cpu_has_dsp)
__init_dsp(); __init_dsp();
regs->cp0_epc = pc; regs->cp0_epc = pc;
......
...@@ -106,6 +106,7 @@ int ptrace_setregs (struct task_struct *child, __s64 __user *data) ...@@ -106,6 +106,7 @@ int ptrace_setregs (struct task_struct *child, __s64 __user *data)
int ptrace_getfpregs (struct task_struct *child, __u32 __user *data) int ptrace_getfpregs (struct task_struct *child, __u32 __user *data)
{ {
int i; int i;
unsigned int tmp;
if (!access_ok(VERIFY_WRITE, data, 33 * 8)) if (!access_ok(VERIFY_WRITE, data, 33 * 8))
return -EIO; return -EIO;
...@@ -121,10 +122,10 @@ int ptrace_getfpregs (struct task_struct *child, __u32 __user *data) ...@@ -121,10 +122,10 @@ int ptrace_getfpregs (struct task_struct *child, __u32 __user *data)
__put_user (child->thread.fpu.fcr31, data + 64); __put_user (child->thread.fpu.fcr31, data + 64);
preempt_disable();
if (cpu_has_fpu) { if (cpu_has_fpu) {
unsigned int flags, tmp; unsigned int flags;
preempt_disable();
if (cpu_has_mipsmt) { if (cpu_has_mipsmt) {
unsigned int vpflags = dvpe(); unsigned int vpflags = dvpe();
flags = read_c0_status(); flags = read_c0_status();
...@@ -138,11 +139,11 @@ int ptrace_getfpregs (struct task_struct *child, __u32 __user *data) ...@@ -138,11 +139,11 @@ int ptrace_getfpregs (struct task_struct *child, __u32 __user *data)
__asm__ __volatile__("cfc1\t%0,$0" : "=r" (tmp)); __asm__ __volatile__("cfc1\t%0,$0" : "=r" (tmp));
write_c0_status(flags); write_c0_status(flags);
} }
preempt_enable();
__put_user (tmp, data + 65);
} else { } else {
__put_user ((__u32) 0, data + 65); tmp = 0;
} }
preempt_enable();
__put_user (tmp, data + 65);
return 0; return 0;
} }
...@@ -245,16 +246,17 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) ...@@ -245,16 +246,17 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
unsigned int mtflags; unsigned int mtflags;
#endif /* CONFIG_MIPS_MT_SMTC */ #endif /* CONFIG_MIPS_MT_SMTC */
if (!cpu_has_fpu) preempt_disable();
if (!cpu_has_fpu) {
preempt_enable();
break; break;
}
#ifdef CONFIG_MIPS_MT_SMTC #ifdef CONFIG_MIPS_MT_SMTC
/* Read-modify-write of Status must be atomic */ /* Read-modify-write of Status must be atomic */
local_irq_save(irqflags); local_irq_save(irqflags);
mtflags = dmt(); mtflags = dmt();
#endif /* CONFIG_MIPS_MT_SMTC */ #endif /* CONFIG_MIPS_MT_SMTC */
preempt_disable();
if (cpu_has_mipsmt) { if (cpu_has_mipsmt) {
unsigned int vpflags = dvpe(); unsigned int vpflags = dvpe();
flags = read_c0_status(); flags = read_c0_status();
......
...@@ -175,7 +175,9 @@ asmlinkage int sys32_ptrace(int request, int pid, int addr, int data) ...@@ -175,7 +175,9 @@ asmlinkage int sys32_ptrace(int request, int pid, int addr, int data)
unsigned int mtflags; unsigned int mtflags;
#endif /* CONFIG_MIPS_MT_SMTC */ #endif /* CONFIG_MIPS_MT_SMTC */
preempt_disable();
if (!cpu_has_fpu) { if (!cpu_has_fpu) {
preempt_enable();
tmp = 0; tmp = 0;
break; break;
} }
...@@ -186,7 +188,6 @@ asmlinkage int sys32_ptrace(int request, int pid, int addr, int data) ...@@ -186,7 +188,6 @@ asmlinkage int sys32_ptrace(int request, int pid, int addr, int data)
mtflags = dmt(); mtflags = dmt();
#endif /* CONFIG_MIPS_MT_SMTC */ #endif /* CONFIG_MIPS_MT_SMTC */
preempt_disable();
if (cpu_has_mipsmt) { if (cpu_has_mipsmt) {
unsigned int vpflags = dvpe(); unsigned int vpflags = dvpe();
flags = read_c0_status(); flags = read_c0_status();
......
...@@ -66,7 +66,7 @@ extern asmlinkage void handle_mcheck(void); ...@@ -66,7 +66,7 @@ extern asmlinkage void handle_mcheck(void);
extern asmlinkage void handle_reserved(void); extern asmlinkage void handle_reserved(void);
extern int fpu_emulator_cop1Handler(struct pt_regs *xcp, extern int fpu_emulator_cop1Handler(struct pt_regs *xcp,
struct mips_fpu_struct *ctx); struct mips_fpu_struct *ctx, int has_fpu);
void (*board_be_init)(void); void (*board_be_init)(void);
int (*board_be_handler)(struct pt_regs *regs, int is_fixup); int (*board_be_handler)(struct pt_regs *regs, int is_fixup);
...@@ -641,7 +641,7 @@ asmlinkage void do_fpe(struct pt_regs *regs, unsigned long fcr31) ...@@ -641,7 +641,7 @@ asmlinkage void do_fpe(struct pt_regs *regs, unsigned long fcr31)
preempt_enable(); preempt_enable();
/* Run the emulator */ /* Run the emulator */
sig = fpu_emulator_cop1Handler (regs, &current->thread.fpu); sig = fpu_emulator_cop1Handler (regs, &current->thread.fpu, 1);
preempt_disable(); preempt_disable();
...@@ -791,11 +791,13 @@ asmlinkage void do_cpu(struct pt_regs *regs) ...@@ -791,11 +791,13 @@ asmlinkage void do_cpu(struct pt_regs *regs)
set_used_math(); set_used_math();
} }
if (cpu_has_fpu) {
preempt_enable(); preempt_enable();
} else {
if (!cpu_has_fpu) { int sig;
int sig = fpu_emulator_cop1Handler(regs, preempt_enable();
&current->thread.fpu); sig = fpu_emulator_cop1Handler(regs,
&current->thread.fpu, 0);
if (sig) if (sig)
force_sig(sig, current); force_sig(sig, current);
#ifdef CONFIG_MIPS_MT_FPAFF #ifdef CONFIG_MIPS_MT_FPAFF
......
...@@ -38,8 +38,6 @@ ...@@ -38,8 +38,6 @@
#include <asm/inst.h> #include <asm/inst.h>
#include <asm/bootinfo.h> #include <asm/bootinfo.h>
#include <asm/cpu.h>
#include <asm/cpu-features.h>
#include <asm/processor.h> #include <asm/processor.h>
#include <asm/ptrace.h> #include <asm/ptrace.h>
#include <asm/signal.h> #include <asm/signal.h>
...@@ -1233,7 +1231,8 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx, ...@@ -1233,7 +1231,8 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
return 0; return 0;
} }
int fpu_emulator_cop1Handler(struct pt_regs *xcp, struct mips_fpu_struct *ctx) int fpu_emulator_cop1Handler(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
int has_fpu)
{ {
unsigned long oldepc, prevepc; unsigned long oldepc, prevepc;
mips_instruction insn; mips_instruction insn;
...@@ -1263,7 +1262,7 @@ int fpu_emulator_cop1Handler(struct pt_regs *xcp, struct mips_fpu_struct *ctx) ...@@ -1263,7 +1262,7 @@ int fpu_emulator_cop1Handler(struct pt_regs *xcp, struct mips_fpu_struct *ctx)
ieee754_csr.rm = mips_rm[ieee754_csr.rm]; ieee754_csr.rm = mips_rm[ieee754_csr.rm];
} }
if (cpu_has_fpu) if (has_fpu)
break; break;
if (sig) if (sig)
break; break;
......
...@@ -134,9 +134,11 @@ static inline void restore_fp(struct task_struct *tsk) ...@@ -134,9 +134,11 @@ static inline void restore_fp(struct task_struct *tsk)
static inline fpureg_t *get_fpu_regs(struct task_struct *tsk) static inline fpureg_t *get_fpu_regs(struct task_struct *tsk)
{ {
if (cpu_has_fpu) { if (tsk == current) {
if ((tsk == current) && __is_fpu_owner()) preempt_disable();
if (is_fpu_owner())
_save_fp(current); _save_fp(current);
preempt_enable();
} }
return tsk->thread.fpu.fpr; return tsk->thread.fpu.fpr;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment