[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>
This commit is contained in:
parent
f5c70dd7f3
commit
e04582b7bc
|
@ -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);
|
||||
|
||||
if (cpu_has_fpu) {
|
||||
unsigned int flags, tmp;
|
||||
|
||||
preempt_disable();
|
||||
if (cpu_has_fpu) {
|
||||
unsigned int flags;
|
||||
|
||||
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);
|
||||
}
|
||||
} else {
|
||||
tmp = 0;
|
||||
}
|
||||
preempt_enable();
|
||||
__put_user (tmp, data + 65);
|
||||
} else {
|
||||
__put_user ((__u32) 0, 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, ¤t->thread.fpu);
|
||||
sig = fpu_emulator_cop1Handler (regs, ¤t->thread.fpu, 1);
|
||||
|
||||
preempt_disable();
|
||||
|
||||
|
@ -791,11 +791,13 @@ asmlinkage void do_cpu(struct pt_regs *regs)
|
|||
set_used_math();
|
||||
}
|
||||
|
||||
if (cpu_has_fpu) {
|
||||
preempt_enable();
|
||||
|
||||
if (!cpu_has_fpu) {
|
||||
int sig = fpu_emulator_cop1Handler(regs,
|
||||
¤t->thread.fpu);
|
||||
} else {
|
||||
int sig;
|
||||
preempt_enable();
|
||||
sig = fpu_emulator_cop1Handler(regs,
|
||||
¤t->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;
|
||||
|
|
Loading…
Reference in New Issue