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)
seq_printf(m, "processor\t\t: %ld\n", 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 ?
cpu_data[n].cputype : CPU_UNKNOWN],
(version >> 4) & 0x0f, version & 0x0f,
......
......@@ -115,7 +115,7 @@ void start_thread(struct pt_regs * regs, unsigned long pc, unsigned long sp)
status |= KU_USER;
regs->cp0_status = status;
clear_used_math();
lose_fpu();
clear_fpu_owner();
if (cpu_has_dsp)
__init_dsp();
regs->cp0_epc = pc;
......
......@@ -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 i;
unsigned int tmp;
if (!access_ok(VERIFY_WRITE, data, 33 * 8))
return -EIO;
......@@ -121,10 +122,10 @@ int ptrace_getfpregs (struct task_struct *child, __u32 __user *data)
__put_user (child->thread.fpu.fcr31, data + 64);
preempt_disable();
if (cpu_has_fpu) {
unsigned int flags, tmp;
unsigned int flags;
preempt_disable();
if (cpu_has_mipsmt) {
unsigned int vpflags = dvpe();
flags = read_c0_status();
......@@ -138,11 +139,11 @@ int ptrace_getfpregs (struct task_struct *child, __u32 __user *data)
__asm__ __volatile__("cfc1\t%0,$0" : "=r" (tmp));
write_c0_status(flags);
}
preempt_enable();
__put_user (tmp, data + 65);
} else {
__put_user ((__u32) 0, data + 65);
tmp = 0;
}
preempt_enable();
__put_user (tmp, data + 65);
return 0;
}
......@@ -245,16 +246,17 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
unsigned int mtflags;
#endif /* CONFIG_MIPS_MT_SMTC */
if (!cpu_has_fpu)
preempt_disable();
if (!cpu_has_fpu) {
preempt_enable();
break;
}
#ifdef CONFIG_MIPS_MT_SMTC
/* Read-modify-write of Status must be atomic */
local_irq_save(irqflags);
mtflags = dmt();
#endif /* CONFIG_MIPS_MT_SMTC */
preempt_disable();
if (cpu_has_mipsmt) {
unsigned int vpflags = dvpe();
flags = read_c0_status();
......
......@@ -175,7 +175,9 @@ asmlinkage int sys32_ptrace(int request, int pid, int addr, int data)
unsigned int mtflags;
#endif /* CONFIG_MIPS_MT_SMTC */
preempt_disable();
if (!cpu_has_fpu) {
preempt_enable();
tmp = 0;
break;
}
......@@ -186,7 +188,6 @@ asmlinkage int sys32_ptrace(int request, int pid, int addr, int data)
mtflags = dmt();
#endif /* CONFIG_MIPS_MT_SMTC */
preempt_disable();
if (cpu_has_mipsmt) {
unsigned int vpflags = dvpe();
flags = read_c0_status();
......
......@@ -66,7 +66,7 @@ extern asmlinkage void handle_mcheck(void);
extern asmlinkage void handle_reserved(void);
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);
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)
preempt_enable();
/* Run the emulator */
sig = fpu_emulator_cop1Handler (regs, &current->thread.fpu);
sig = fpu_emulator_cop1Handler (regs, &current->thread.fpu, 1);
preempt_disable();
......@@ -791,11 +791,13 @@ asmlinkage void do_cpu(struct pt_regs *regs)
set_used_math();
}
preempt_enable();
if (!cpu_has_fpu) {
int sig = fpu_emulator_cop1Handler(regs,
&current->thread.fpu);
if (cpu_has_fpu) {
preempt_enable();
} else {
int sig;
preempt_enable();
sig = fpu_emulator_cop1Handler(regs,
&current->thread.fpu, 0);
if (sig)
force_sig(sig, current);
#ifdef CONFIG_MIPS_MT_FPAFF
......
......@@ -38,8 +38,6 @@
#include <asm/inst.h>
#include <asm/bootinfo.h>
#include <asm/cpu.h>
#include <asm/cpu-features.h>
#include <asm/processor.h>
#include <asm/ptrace.h>
#include <asm/signal.h>
......@@ -1233,7 +1231,8 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
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;
mips_instruction insn;
......@@ -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];
}
if (cpu_has_fpu)
if (has_fpu)
break;
if (sig)
break;
......
......@@ -134,9 +134,11 @@ static inline void restore_fp(struct task_struct *tsk)
static inline fpureg_t *get_fpu_regs(struct task_struct *tsk)
{
if (cpu_has_fpu) {
if ((tsk == current) && __is_fpu_owner())
if (tsk == current) {
preempt_disable();
if (is_fpu_owner())
_save_fp(current);
preempt_enable();
}
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