[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:
Atsushi Nemoto 2006-10-09 00:10:01 +09:00 committed by Ralf Baechle
parent f5c70dd7f3
commit e04582b7bc
7 changed files with 30 additions and 24 deletions

View File

@ -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,

View File

@ -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;

View File

@ -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();

View File

@ -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();

View File

@ -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

View File

@ -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;

View File

@ -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;