]> err.no Git - linux-2.6/commitdiff
[MIPS] Make sure cpu_has_fpu is used only in atomic context
authorAtsushi Nemoto <anemo@mba.ocn.ne.jp>
Sun, 8 Oct 2006 15:10:01 +0000 (00:10 +0900)
committerRalf Baechle <ralf@linux-mips.org>
Mon, 9 Oct 2006 22:20:48 +0000 (23:20 +0100)
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>
arch/mips/kernel/proc.c
arch/mips/kernel/process.c
arch/mips/kernel/ptrace.c
arch/mips/kernel/ptrace32.c
arch/mips/kernel/traps.c
arch/mips/math-emu/cp1emu.c
include/asm-mips/fpu.h

index 46ee5a68ab13bed851b1a0e3a4459d830830f2b3..4ed37ba19731071b369180cd12d3895ece7becbe 100644 (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,
index 045d987bc683b3da05fe6f5a700c413154d9e5f8..9f307eb1a31ec79fa9f8331573df09d00da608c9 100644 (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;
index 362d1728e5317d7b99f014a045f2c821c341056f..258d74fd0b638a8eb7c64c9431c3b7bdc26dc58e 100644 (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();
index f40ecd8be05fc7b5376a4b24856d9236f17fb5c2..d9a39c1694505c61370c610079514af27825a11d 100644 (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();
index b7292a56d4cd80b65d4bf2ef6f6ff016d371c857..cce8313ec27dcacc41247e863376efe50d986809 100644 (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
index 3f0d5d26d506d27abc452b394268a57532df00b4..80531b35cd61e315382e2d036eaff313e94973f8 100644 (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;
index 58c561a9ec6b74b8eaf4c48d0609c44098e96538..efef843b93f0c1694a2084f1a502523a5ac69318 100644 (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;