]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
MIPS: Enable HAVE_ARCH_TRACEHOOK.
authorRalf Baechle <ralf@linux-mips.org>
Fri, 17 Aug 2012 06:22:04 +0000 (08:22 +0200)
committerRalf Baechle <ralf@linux-mips.org>
Wed, 26 Sep 2012 19:45:30 +0000 (21:45 +0200)
This enables /proc/<pid>/syscall and the ptrace PTRACE_GETREGSET and
PTRACE_SETREGSET operations.

Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
arch/mips/Kconfig
arch/mips/include/asm/ptrace.h
arch/mips/include/asm/syscall.h

index faf65286574e9f28d32d9cf31e1c097afcfc7acb..88e955979b6c17fd2c649b5b715cccd7f85830db 100644 (file)
@@ -8,6 +8,7 @@ config MIPS
        select HAVE_PERF_EVENTS
        select PERF_USE_VMALLOC
        select HAVE_ARCH_KGDB
+       select HAVE_ARCH_TRACEHOOK
        select ARCH_HAVE_CUSTOM_GPIO_H
        select HAVE_FUNCTION_TRACER
        select HAVE_FUNCTION_TRACE_MCOUNT_TEST
index b8f50f98a17294db926605768b943bf3ca9f3b38..f07a4e61a0eee088acf036054f53bb5e30b345ba 100644 (file)
@@ -164,6 +164,19 @@ static inline void die_if_kernel(const char *str, struct pt_regs *regs)
                die(str, regs);
 }
 
+/* Helpers for working with the user stack pointer */
+
+static inline unsigned long user_stack_pointer(struct pt_regs *regs)
+{
+       return regs->regs[29];
+}
+
+static inline void user_stack_pointer_set(struct pt_regs *regs,
+       unsigned long val)
+{
+       regs->regs[29] = val;
+}
+
 #endif /* __KERNEL__ */
 
 #endif /* _ASM_PTRACE_H */
index ab5effdc935d3ffc2adead84543a7f5f3812ce80..00f2ffaaf293aaac6505e45df27ddcd000271684 100644 (file)
@@ -1,14 +1,81 @@
 /*
+ * Access to user system call parameters and results
+ *
  * This file is subject to the terms and conditions of the GNU General Public
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
+ * See asm-generic/syscall.h for descriptions of what we must do here.
+ *
  * Copyright (C) 2012 Ralf Baechle <ralf@linux-mips.org>
  */
 
 #ifndef __ASM_MIPS_SYSCALL_H
 #define __ASM_MIPS_SYSCALL_H
 
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/uaccess.h>
+#include <asm/ptrace.h>
+
+static inline long syscall_get_nr(struct task_struct *task,
+                                 struct pt_regs *regs)
+{
+       return regs->regs[2];
+}
+
+static inline unsigned long mips_get_syscall_arg(unsigned long *arg,
+       struct task_struct *task, struct pt_regs *regs, unsigned int n)
+{
+       unsigned long usp = regs->regs[29];
+
+       switch (n) {
+       case 0: case 1: case 2: case 3:
+               *arg = regs->regs[4 + n];
+
+               return 0;
+
+#ifdef CONFIG_32BIT
+       case 4: case 5: case 6: case 7:
+               return get_user(*arg, (int *)usp + 4 * n);
+#endif
+
+#ifdef CONFIG_64BIT
+       case 4: case 5: case 6: case 7:
+#ifdef CONFIG_MIPS32_O32
+               if (test_thread_flag(TIF_32BIT_REGS))
+                       return get_user(*arg, (int *)usp + 4 * n);
+               else
+#endif
+                       *arg = regs->regs[4 + n];
+
+               return 0;
+#endif
+
+       default:
+               BUG();
+       }
+}
+
+static inline void syscall_get_arguments(struct task_struct *task,
+                                        struct pt_regs *regs,
+                                        unsigned int i, unsigned int n,
+                                        unsigned long *args)
+{
+       unsigned long arg;
+       int ret;
+
+       while (n--)
+               ret |= mips_get_syscall_arg(&arg, task, regs, i++);
+
+       /*
+        * No way to communicate an error because this is a void function.
+        */
+#if 0
+       return ret;
+#endif
+}
+
 extern const unsigned long sys_call_table[];
 extern const unsigned long sys32_call_table[];
 extern const unsigned long sysn32_call_table[];