Merge branch 'misc' of master.kernel.org:/pub/scm/linux/kernel/git/galak/powerpc...
[pandora-kernel.git] / arch / mips / kernel / ptrace.c
index f1b0f3e..f3106d0 100644 (file)
@@ -64,8 +64,7 @@ int ptrace_getregs (struct task_struct *child, __s64 __user *data)
        if (!access_ok(VERIFY_WRITE, data, 38 * 8))
                return -EIO;
 
-       regs = (struct pt_regs *) ((unsigned long) child->thread_info +
-              THREAD_SIZE - 32 - sizeof(struct pt_regs));
+       regs = task_pt_regs(child);
 
        for (i = 0; i < 32; i++)
                __put_user (regs->regs[i], data + i);
@@ -92,8 +91,7 @@ int ptrace_setregs (struct task_struct *child, __s64 __user *data)
        if (!access_ok(VERIFY_READ, data, 38 * 8))
                return -EIO;
 
-       regs = (struct pt_regs *) ((unsigned long) child->thread_info +
-              THREAD_SIZE - 32 - sizeof(struct pt_regs));
+       regs = task_pt_regs(child);
 
        for (i = 0; i < 32; i++)
                __get_user (regs->regs[i], data + i);
@@ -174,51 +172,10 @@ int ptrace_setfpregs (struct task_struct *child, __u32 __user *data)
        return 0;
 }
 
-asmlinkage long sys_ptrace(long request, long pid, long addr, long data)
+long arch_ptrace(struct task_struct *child, long request, long addr, long data)
 {
-       struct task_struct *child;
        int ret;
 
-#if 0
-       printk("ptrace(r=%d,pid=%d,addr=%08lx,data=%08lx)\n",
-              (int) request, (int) pid, (unsigned long) addr,
-              (unsigned long) data);
-#endif
-       lock_kernel();
-       ret = -EPERM;
-       if (request == PTRACE_TRACEME) {
-               /* are we already being traced? */
-               if (current->ptrace & PT_PTRACED)
-                       goto out;
-               if ((ret = security_ptrace(current->parent, current)))
-                       goto out;
-               /* set the ptrace bit in the process flags. */
-               current->ptrace |= PT_PTRACED;
-               ret = 0;
-               goto out;
-       }
-       ret = -ESRCH;
-       read_lock(&tasklist_lock);
-       child = find_task_by_pid(pid);
-       if (child)
-               get_task_struct(child);
-       read_unlock(&tasklist_lock);
-       if (!child)
-               goto out;
-
-       ret = -EPERM;
-       if (pid == 1)           /* you may not mess with init */
-               goto out_tsk;
-
-       if (request == PTRACE_ATTACH) {
-               ret = ptrace_attach(child);
-               goto out_tsk;
-       }
-
-       ret = ptrace_check_attach(child, request == PTRACE_KILL);
-       if (ret < 0)
-               goto out_tsk;
-
        switch (request) {
        /* when I and D space are separate, these will need to be fixed. */
        case PTRACE_PEEKTEXT: /* read word at location addr. */
@@ -239,8 +196,7 @@ asmlinkage long sys_ptrace(long request, long pid, long addr, long data)
                struct pt_regs *regs;
                unsigned long tmp = 0;
 
-               regs = (struct pt_regs *) ((unsigned long) child->thread_info +
-                      THREAD_SIZE - 32 - sizeof(struct pt_regs));
+               regs = task_pt_regs(child);
                ret = 0;  /* Default return value. */
 
                switch (addr) {
@@ -292,10 +248,20 @@ asmlinkage long sys_ptrace(long request, long pid, long addr, long data)
                        break;
                case FPC_EIR: { /* implementation / version register */
                        unsigned int flags;
+#ifdef CONFIG_MIPS_MT_SMTC
+                       unsigned int irqflags;
+                       unsigned int mtflags;
+#endif /* CONFIG_MIPS_MT_SMTC */
 
                        if (!cpu_has_fpu)
                                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();
@@ -310,6 +276,10 @@ asmlinkage long sys_ptrace(long request, long pid, long addr, long data)
                                __asm__ __volatile__("cfc1\t%0,$0": "=r" (tmp));
                                write_c0_status(flags);
                        }
+#ifdef CONFIG_MIPS_MT_SMTC
+                       emt(mtflags);
+                       local_irq_restore(irqflags);
+#endif /* CONFIG_MIPS_MT_SMTC */
                        preempt_enable();
                        break;
                }
@@ -319,28 +289,24 @@ asmlinkage long sys_ptrace(long request, long pid, long addr, long data)
                        if (!cpu_has_dsp) {
                                tmp = 0;
                                ret = -EIO;
-                               goto out_tsk;
-                       }
-                       if (child->thread.dsp.used_dsp) {
-                               dregs = __get_dsp_regs(child);
-                               tmp = (unsigned long) (dregs[addr - DSP_BASE]);
-                       } else {
-                               tmp = -1;       /* DSP registers yet used  */
+                               goto out;
                        }
+                       dregs = __get_dsp_regs(child);
+                       tmp = (unsigned long) (dregs[addr - DSP_BASE]);
                        break;
                }
                case DSP_CONTROL:
                        if (!cpu_has_dsp) {
                                tmp = 0;
                                ret = -EIO;
-                               goto out_tsk;
+                               goto out;
                        }
                        tmp = child->thread.dsp.dspcontrol;
                        break;
                default:
                        tmp = 0;
                        ret = -EIO;
-                       goto out_tsk;
+                       goto out;
                }
                ret = put_user(tmp, (unsigned long __user *) data);
                break;
@@ -359,8 +325,7 @@ asmlinkage long sys_ptrace(long request, long pid, long addr, long data)
        case PTRACE_POKEUSR: {
                struct pt_regs *regs;
                ret = 0;
-               regs = (struct pt_regs *) ((unsigned long) child->thread_info +
-                      THREAD_SIZE - 32 - sizeof(struct pt_regs));
+               regs = task_pt_regs(child);
 
                switch (addr) {
                case 0 ... 31:
@@ -487,7 +452,7 @@ asmlinkage long sys_ptrace(long request, long pid, long addr, long data)
                break;
 
        case PTRACE_GET_THREAD_AREA:
-               ret = put_user(child->thread_info->tp_value,
+               ret = put_user(task_thread_info(child)->tp_value,
                                (unsigned long __user *) data);
                break;
 
@@ -495,11 +460,7 @@ asmlinkage long sys_ptrace(long request, long pid, long addr, long data)
                ret = ptrace_request(child, request, addr, data);
                break;
        }
-
-out_tsk:
-       put_task_struct(child);
-out:
-       unlock_kernel();
+ out:
        return ret;
 }