Protect manipulation of c0_status against preemption and multithreading.
authorRalf Baechle <ralf@linux-mips.org>
Thu, 6 Oct 2005 16:39:32 +0000 (17:39 +0100)
committerRalf Baechle <ralf@linux-mips.org>
Sat, 29 Oct 2005 18:32:36 +0000 (19:32 +0100)
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
arch/mips/kernel/ptrace.c
arch/mips/kernel/ptrace32.c

index 122433f835e3d8583bb0542eba567e36cb6fe98c..fcceab8f2e009e1899e752c0b8289f0f1f64bee0 100644 (file)
@@ -33,6 +33,7 @@
 #include <asm/dsp.h>
 #include <asm/fpu.h>
 #include <asm/mipsregs.h>
+#include <asm/mipsmtregs.h>
 #include <asm/pgtable.h>
 #include <asm/page.h>
 #include <asm/system.h>
@@ -126,10 +127,21 @@ int ptrace_getfpregs (struct task_struct *child, __u32 __user *data)
 
                __put_user (child->thread.fpu.hard.fcr31, data + 64);
 
-               flags = read_c0_status();
-               __enable_fpu();
-               __asm__ __volatile__("cfc1\t%0,$0" : "=r" (tmp));
-               write_c0_status(flags);
+               preempt_disable();
+               if (cpu_has_mipsmt) {
+                       unsigned int vpflags = dvpe();
+                       flags = read_c0_status();
+                       __enable_fpu();
+                       __asm__ __volatile__("cfc1\t%0,$0" : "=r" (tmp));
+                       write_c0_status(flags);
+                       evpe(vpflags);
+               } else {
+                       flags = read_c0_status();
+                       __enable_fpu();
+                       __asm__ __volatile__("cfc1\t%0,$0" : "=r" (tmp));
+                       write_c0_status(flags);
+               }
+               preempt_enable();
                __put_user (tmp, data + 65);
        } else {
                __put_user (child->thread.fpu.soft.fcr31, data + 64);
@@ -284,10 +296,21 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
                        if (!cpu_has_fpu)
                                break;
 
-                       flags = read_c0_status();
-                       __enable_fpu();
-                       __asm__ __volatile__("cfc1\t%0,$0": "=r" (tmp));
-                       write_c0_status(flags);
+                       preempt_disable();
+                       if (cpu_has_mipsmt) {
+                               unsigned int vpflags = dvpe();
+                               flags = read_c0_status();
+                               __enable_fpu();
+                               __asm__ __volatile__("cfc1\t%0,$0": "=r" (tmp));
+                               write_c0_status(flags);
+                               evpe(vpflags);
+                       } else {
+                               flags = read_c0_status();
+                               __enable_fpu();
+                               __asm__ __volatile__("cfc1\t%0,$0": "=r" (tmp));
+                               write_c0_status(flags);
+                       }
+                       preempt_enable();
                        break;
                }
                case DSP_BASE ... DSP_BASE + 5: {
index c28cdddd4c21565ac15be445efd885fde5ab332a..9a9b049721327cb28fca14dffd8b6bf5f5d47ec1 100644 (file)
@@ -29,6 +29,7 @@
 #include <asm/dsp.h>
 #include <asm/fpu.h>
 #include <asm/mipsregs.h>
+#include <asm/mipsmtregs.h>
 #include <asm/pgtable.h>
 #include <asm/page.h>
 #include <asm/system.h>
@@ -191,10 +192,21 @@ asmlinkage int sys32_ptrace(int request, int pid, int addr, int data)
                        if (!cpu_has_fpu)
                                break;
 
-                       flags = read_c0_status();
-                       __enable_fpu();
-                       __asm__ __volatile__("cfc1\t%0,$0": "=r" (tmp));
-                       write_c0_status(flags);
+                       preempt_disable();
+                       if (cpu_has_mipsmt) {
+                               unsigned int vpflags = dvpe();
+                               flags = read_c0_status();
+                               __enable_fpu();
+                               __asm__ __volatile__("cfc1\t%0,$0": "=r" (tmp));
+                               write_c0_status(flags);
+                               evpe(vpflags);
+                       } else {
+                               flags = read_c0_status();
+                               __enable_fpu();
+                               __asm__ __volatile__("cfc1\t%0,$0": "=r" (tmp));
+                               write_c0_status(flags);
+                       }
+                       preempt_enable();
                        break;
                }
                case DSP_BASE ... DSP_BASE + 5: