Merge branches 'msm-fixes' and 'msm-video' of git://codeaurora.org/quic/kernel/dwalke...
[pandora-kernel.git] / arch / frv / kernel / ptrace.c
index 5e7d401..9d68f7f 100644 (file)
@@ -19,6 +19,9 @@
 #include <linux/user.h>
 #include <linux/security.h>
 #include <linux/signal.h>
+#include <linux/regset.h>
+#include <linux/elf.h>
+#include <linux/tracehook.h>
 
 #include <asm/uaccess.h>
 #include <asm/page.h>
  * in exit.c or in signal.c.
  */
 
+/*
+ * retrieve the contents of FRV userspace general registers
+ */
+static int genregs_get(struct task_struct *target,
+                      const struct user_regset *regset,
+                      unsigned int pos, unsigned int count,
+                      void *kbuf, void __user *ubuf)
+{
+       const struct user_int_regs *iregs = &target->thread.user->i;
+       int ret;
+
+       ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
+                                 iregs, 0, sizeof(*iregs));
+       if (ret < 0)
+               return ret;
+
+       return user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf,
+                                       sizeof(*iregs), -1);
+}
+
+/*
+ * update the contents of the FRV userspace general registers
+ */
+static int genregs_set(struct task_struct *target,
+                      const struct user_regset *regset,
+                      unsigned int pos, unsigned int count,
+                      const void *kbuf, const void __user *ubuf)
+{
+       struct user_int_regs *iregs = &target->thread.user->i;
+       unsigned int offs_gr0, offs_gr1;
+       int ret;
+
+       /* not allowed to set PSR or __status */
+       if (pos < offsetof(struct user_int_regs, psr) + sizeof(long) &&
+           pos + count > offsetof(struct user_int_regs, psr))
+               return -EIO;
+
+       if (pos < offsetof(struct user_int_regs, __status) + sizeof(long) &&
+           pos + count > offsetof(struct user_int_regs, __status))
+               return -EIO;
+
+       /* set the control regs */
+       offs_gr0 = offsetof(struct user_int_regs, gr[0]);
+       offs_gr1 = offsetof(struct user_int_regs, gr[1]);
+       ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
+                                iregs, 0, offs_gr0);
+       if (ret < 0)
+               return ret;
+
+       /* skip GR0/TBR */
+       ret = user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
+                                       offs_gr0, offs_gr1);
+       if (ret < 0)
+               return ret;
+
+       /* set the general regs */
+       ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
+                                &iregs->gr[1], offs_gr1, sizeof(*iregs));
+       if (ret < 0)
+               return ret;
+
+       return user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
+                                       sizeof(*iregs), -1);
+}
+
+/*
+ * retrieve the contents of FRV userspace FP/Media registers
+ */
+static int fpmregs_get(struct task_struct *target,
+                      const struct user_regset *regset,
+                      unsigned int pos, unsigned int count,
+                      void *kbuf, void __user *ubuf)
+{
+       const struct user_fpmedia_regs *fpregs = &target->thread.user->f;
+       int ret;
+
+       ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
+                                 fpregs, 0, sizeof(*fpregs));
+       if (ret < 0)
+               return ret;
+
+       return user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf,
+                                       sizeof(*fpregs), -1);
+}
+
+/*
+ * update the contents of the FRV userspace FP/Media registers
+ */
+static int fpmregs_set(struct task_struct *target,
+                      const struct user_regset *regset,
+                      unsigned int pos, unsigned int count,
+                      const void *kbuf, const void __user *ubuf)
+{
+       struct user_fpmedia_regs *fpregs = &target->thread.user->f;
+       int ret;
+
+       ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
+                                fpregs, 0, sizeof(*fpregs));
+       if (ret < 0)
+               return ret;
+
+       return user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
+                                       sizeof(*fpregs), -1);
+}
+
+/*
+ * determine if the FP/Media registers have actually been used
+ */
+static int fpmregs_active(struct task_struct *target,
+                         const struct user_regset *regset)
+{
+       return tsk_used_math(target) ? regset->n : 0;
+}
+
+/*
+ * Define the register sets available on the FRV under Linux
+ */
+enum frv_regset {
+       REGSET_GENERAL,
+       REGSET_FPMEDIA,
+};
+
+static const struct user_regset frv_regsets[] = {
+       /*
+        * General register format is:
+        *      PSR, ISR, CCR, CCCR, LR, LCR, PC, (STATUS), SYSCALLNO, ORIG_G8
+        *      GNER0-1, IACC0, TBR, GR1-63
+        */
+       [REGSET_GENERAL] = {
+               .core_note_type = NT_PRSTATUS,
+               .n              = ELF_NGREG,
+               .size           = sizeof(long),
+               .align          = sizeof(long),
+               .get            = genregs_get,
+               .set            = genregs_set,
+       },
+       /*
+        * FPU/Media register format is:
+        *      FR0-63, FNER0-1, MSR0-1, ACC0-7, ACCG0-8, FSR
+        */
+       [REGSET_FPMEDIA] = {
+               .core_note_type = NT_PRFPREG,
+               .n              = sizeof(struct user_fpmedia_regs) / sizeof(long),
+               .size           = sizeof(long),
+               .align          = sizeof(long),
+               .get            = fpmregs_get,
+               .set            = fpmregs_set,
+               .active         = fpmregs_active,
+       },
+};
+
+static const struct user_regset_view user_frv_native_view = {
+       .name           = "frv",
+       .e_machine      = EM_FRV,
+       .regsets        = frv_regsets,
+       .n              = ARRAY_SIZE(frv_regsets),
+};
+
+const struct user_regset_view *task_user_regset_view(struct task_struct *task)
+{
+       return &user_frv_native_view;
+}
+
 /*
  * Get contents of register REGNO in task TASK.
  */
@@ -68,69 +234,46 @@ static inline int put_reg(struct task_struct *task, int regno,
        }
 }
 
-/*
- * check that an address falls within the bounds of the target process's memory
- * mappings
- */
-static inline int is_user_addr_valid(struct task_struct *child,
-                                    unsigned long start, unsigned long len)
-{
-#ifdef CONFIG_MMU
-       if (start >= PAGE_OFFSET || len > PAGE_OFFSET - start)
-               return -EIO;
-       return 0;
-#else
-       struct vm_area_struct *vma;
-
-       vma = find_vma(child->mm, start);
-       if (vma && start >= vma->vm_start && start + len <= vma->vm_end)
-               return 0;
-
-       return -EIO;
-#endif
-}
-
 /*
  * Called by kernel/ptrace.c when detaching..
  *
  * Control h/w single stepping
  */
-void ptrace_disable(struct task_struct *child)
+void user_enable_single_step(struct task_struct *child)
+{
+       child->thread.frame0->__status |= REG__STATUS_STEP;
+}
+
+void user_disable_single_step(struct task_struct *child)
 {
        child->thread.frame0->__status &= ~REG__STATUS_STEP;
 }
 
-void ptrace_enable(struct task_struct *child)
+void ptrace_disable(struct task_struct *child)
 {
-       child->thread.frame0->__status |= REG__STATUS_STEP;
+       user_disable_single_step(child);
 }
 
-long arch_ptrace(struct task_struct *child, long request, long addr, long data)
+long arch_ptrace(struct task_struct *child, long request,
+                unsigned long addr, unsigned long data)
 {
        unsigned long tmp;
        int ret;
+       int regno = addr >> 2;
+       unsigned long __user *datap = (unsigned long __user *) data;
 
        switch (request) {
-               /* when I and D space are separate, these will need to be fixed. */
-       case PTRACE_PEEKTEXT: /* read word at location addr. */
-       case PTRACE_PEEKDATA:
-               ret = -EIO;
-               if (is_user_addr_valid(child, addr, sizeof(tmp)) < 0)
-                       break;
-               ret = generic_ptrace_peekdata(child, addr, data);
-               break;
-
                /* read the word at location addr in the USER area. */
        case PTRACE_PEEKUSR: {
                tmp = 0;
                ret = -EIO;
-               if ((addr & 3) || addr < 0)
+               if (addr & 3)
                        break;
 
                ret = 0;
-               switch (addr >> 2) {
+               switch (regno) {
                case 0 ... PT__END - 1:
-                       tmp = get_reg(child, addr >> 2);
+                       tmp = get_reg(child, regno);
                        break;
 
                case PT__END + 0:
@@ -159,555 +302,77 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
                }
 
                if (ret == 0)
-                       ret = put_user(tmp, (unsigned long *) data);
+                       ret = put_user(tmp, datap);
                break;
        }
 
-               /* when I and D space are separate, this will have to be fixed. */
-       case PTRACE_POKETEXT: /* write the word at location addr. */
-       case PTRACE_POKEDATA:
-               ret = -EIO;
-               if (is_user_addr_valid(child, addr, sizeof(tmp)) < 0)
-                       break;
-               ret = generic_ptrace_pokedata(child, addr, data);
-               break;
-
        case PTRACE_POKEUSR: /* write the word at location addr in the USER area */
                ret = -EIO;
-               if ((addr & 3) || addr < 0)
-                       break;
-
-               ret = 0;
-               switch (addr >> 2) {
-               case 0 ... PT__END-1:
-                       ret = put_reg(child, addr >> 2, data);
-                       break;
-
-               default:
-                       ret = -EIO;
-                       break;
-               }
-               break;
-
-       case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */
-       case PTRACE_CONT: /* restart after signal. */
-               ret = -EIO;
-               if (!valid_signal(data))
+               if (addr & 3)
                        break;
-               if (request == PTRACE_SYSCALL)
-                       set_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
-               else
-                       clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
-               child->exit_code = data;
-               ptrace_disable(child);
-               wake_up_process(child);
-               ret = 0;
-               break;
 
-               /* make the child exit.  Best I can do is send it a sigkill.
-                * perhaps it should be put in the status that it wants to
-                * exit.
-                */
-       case PTRACE_KILL:
-               ret = 0;
-               if (child->exit_state == EXIT_ZOMBIE)   /* already dead */
-                       break;
-               child->exit_code = SIGKILL;
-               clear_tsk_thread_flag(child, TIF_SINGLESTEP);
-               ptrace_disable(child);
-               wake_up_process(child);
-               break;
-
-       case PTRACE_SINGLESTEP:  /* set the trap flag. */
-               ret = -EIO;
-               if (!valid_signal(data))
+               switch (regno) {
+               case 0 ... PT__END - 1:
+                       ret = put_reg(child, regno, data);
                        break;
-               clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
-               ptrace_enable(child);
-               child->exit_code = data;
-               wake_up_process(child);
-               ret = 0;
-               break;
-
-       case PTRACE_DETACH:     /* detach a process that was attached. */
-               ret = ptrace_detach(child, data);
-               break;
-
-       case PTRACE_GETREGS: { /* Get all integer regs from the child. */
-               int i;
-               for (i = 0; i < PT__GPEND; i++) {
-                       tmp = get_reg(child, i);
-                       if (put_user(tmp, (unsigned long *) data)) {
-                               ret = -EFAULT;
-                               break;
-                       }
-                       data += sizeof(long);
                }
-               ret = 0;
                break;
-       }
 
-       case PTRACE_SETREGS: { /* Set all integer regs in the child. */
-               int i;
-               for (i = 0; i < PT__GPEND; i++) {
-                       if (get_user(tmp, (unsigned long *) data)) {
-                               ret = -EFAULT;
-                               break;
-                       }
-                       put_reg(child, i, tmp);
-                       data += sizeof(long);
-               }
-               ret = 0;
-               break;
-       }
-
-       case PTRACE_GETFPREGS: { /* Get the child FP/Media state. */
-               ret = 0;
-               if (copy_to_user((void *) data,
-                                &child->thread.user->f,
-                                sizeof(child->thread.user->f)))
-                       ret = -EFAULT;
-               break;
-       }
-
-       case PTRACE_SETFPREGS: { /* Set the child FP/Media state. */
-               ret = 0;
-               if (copy_from_user(&child->thread.user->f,
-                                  (void *) data,
-                                  sizeof(child->thread.user->f)))
-                       ret = -EFAULT;
-               break;
-       }
-
-       case PTRACE_GETFDPIC:
-               tmp = 0;
-               switch (addr) {
-               case PTRACE_GETFDPIC_EXEC:
-                       tmp = child->mm->context.exec_fdpic_loadmap;
-                       break;
-               case PTRACE_GETFDPIC_INTERP:
-                       tmp = child->mm->context.interp_fdpic_loadmap;
-                       break;
-               default:
-                       break;
-               }
-
-               ret = 0;
-               if (put_user(tmp, (unsigned long *) data)) {
-                       ret = -EFAULT;
-                       break;
-               }
-               break;
+       case PTRACE_GETREGS:    /* Get all integer regs from the child. */
+               return copy_regset_to_user(child, &user_frv_native_view,
+                                          REGSET_GENERAL,
+                                          0, sizeof(child->thread.user->i),
+                                          datap);
+
+       case PTRACE_SETREGS:    /* Set all integer regs in the child. */
+               return copy_regset_from_user(child, &user_frv_native_view,
+                                            REGSET_GENERAL,
+                                            0, sizeof(child->thread.user->i),
+                                            datap);
+
+       case PTRACE_GETFPREGS:  /* Get the child FP/Media state. */
+               return copy_regset_to_user(child, &user_frv_native_view,
+                                          REGSET_FPMEDIA,
+                                          0, sizeof(child->thread.user->f),
+                                          datap);
+
+       case PTRACE_SETFPREGS:  /* Set the child FP/Media state. */
+               return copy_regset_from_user(child, &user_frv_native_view,
+                                            REGSET_FPMEDIA,
+                                            0, sizeof(child->thread.user->f),
+                                            datap);
 
        default:
-               ret = -EIO;
+               ret = ptrace_request(child, request, addr, data);
                break;
        }
        return ret;
 }
 
-int __nongprelbss kstrace;
-
-static const struct {
-       const char      *name;
-       unsigned        argmask;
-} __syscall_name_table[NR_syscalls] = {
-       [0]     = { "restart_syscall"                   },
-       [1]     = { "exit",             0x000001        },
-       [2]     = { "fork",             0xffffff        },
-       [3]     = { "read",             0x000141        },
-       [4]     = { "write",            0x000141        },
-       [5]     = { "open",             0x000235        },
-       [6]     = { "close",            0x000001        },
-       [7]     = { "waitpid",          0x000141        },
-       [8]     = { "creat",            0x000025        },
-       [9]     = { "link",             0x000055        },
-       [10]    = { "unlink",           0x000005        },
-       [11]    = { "execve",           0x000445        },
-       [12]    = { "chdir",            0x000005        },
-       [13]    = { "time",             0x000004        },
-       [14]    = { "mknod",            0x000325        },
-       [15]    = { "chmod",            0x000025        },
-       [16]    = { "lchown",           0x000025        },
-       [17]    = { "break" },
-       [18]    = { "oldstat",          0x000045        },
-       [19]    = { "lseek",            0x000131        },
-       [20]    = { "getpid",           0xffffff        },
-       [21]    = { "mount",            0x043555        },
-       [22]    = { "umount",           0x000005        },
-       [23]    = { "setuid",           0x000001        },
-       [24]    = { "getuid",           0xffffff        },
-       [25]    = { "stime",            0x000004        },
-       [26]    = { "ptrace",           0x004413        },
-       [27]    = { "alarm",            0x000001        },
-       [28]    = { "oldfstat",         0x000041        },
-       [29]    = { "pause",            0xffffff        },
-       [30]    = { "utime",            0x000045        },
-       [31]    = { "stty" },
-       [32]    = { "gtty" },
-       [33]    = { "access",           0x000025        },
-       [34]    = { "nice",             0x000001        },
-       [35]    = { "ftime" },
-       [36]    = { "sync",             0xffffff        },
-       [37]    = { "kill",             0x000011        },
-       [38]    = { "rename",           0x000055        },
-       [39]    = { "mkdir",            0x000025        },
-       [40]    = { "rmdir",            0x000005        },
-       [41]    = { "dup",              0x000001        },
-       [42]    = { "pipe",             0x000004        },
-       [43]    = { "times",            0x000004        },
-       [44]    = { "prof" },
-       [45]    = { "brk",              0x000004        },
-       [46]    = { "setgid",           0x000001        },
-       [47]    = { "getgid",           0xffffff        },
-       [48]    = { "signal",           0x000041        },
-       [49]    = { "geteuid",          0xffffff        },
-       [50]    = { "getegid",          0xffffff        },
-       [51]    = { "acct",             0x000005        },
-       [52]    = { "umount2",          0x000035        },
-       [53]    = { "lock" },
-       [54]    = { "ioctl",            0x000331        },
-       [55]    = { "fcntl",            0x000331        },
-       [56]    = { "mpx" },
-       [57]    = { "setpgid",          0x000011        },
-       [58]    = { "ulimit" },
-       [60]    = { "umask",            0x000002        },
-       [61]    = { "chroot",           0x000005        },
-       [62]    = { "ustat",            0x000043        },
-       [63]    = { "dup2",             0x000011        },
-       [64]    = { "getppid",          0xffffff        },
-       [65]    = { "getpgrp",          0xffffff        },
-       [66]    = { "setsid",           0xffffff        },
-       [67]    = { "sigaction" },
-       [68]    = { "sgetmask" },
-       [69]    = { "ssetmask" },
-       [70]    = { "setreuid" },
-       [71]    = { "setregid" },
-       [72]    = { "sigsuspend" },
-       [73]    = { "sigpending" },
-       [74]    = { "sethostname" },
-       [75]    = { "setrlimit" },
-       [76]    = { "getrlimit" },
-       [77]    = { "getrusage" },
-       [78]    = { "gettimeofday" },
-       [79]    = { "settimeofday" },
-       [80]    = { "getgroups" },
-       [81]    = { "setgroups" },
-       [82]    = { "select" },
-       [83]    = { "symlink" },
-       [84]    = { "oldlstat" },
-       [85]    = { "readlink" },
-       [86]    = { "uselib" },
-       [87]    = { "swapon" },
-       [88]    = { "reboot" },
-       [89]    = { "readdir" },
-       [91]    = { "munmap",           0x000034        },
-       [92]    = { "truncate" },
-       [93]    = { "ftruncate" },
-       [94]    = { "fchmod" },
-       [95]    = { "fchown" },
-       [96]    = { "getpriority" },
-       [97]    = { "setpriority" },
-       [99]    = { "statfs" },
-       [100]   = { "fstatfs" },
-       [102]   = { "socketcall" },
-       [103]   = { "syslog" },
-       [104]   = { "setitimer" },
-       [105]   = { "getitimer" },
-       [106]   = { "stat" },
-       [107]   = { "lstat" },
-       [108]   = { "fstat" },
-       [111]   = { "vhangup" },
-       [114]   = { "wait4" },
-       [115]   = { "swapoff" },
-       [116]   = { "sysinfo" },
-       [117]   = { "ipc" },
-       [118]   = { "fsync" },
-       [119]   = { "sigreturn" },
-       [120]   = { "clone" },
-       [121]   = { "setdomainname" },
-       [122]   = { "uname" },
-       [123]   = { "modify_ldt" },
-       [123]   = { "cacheflush" },
-       [124]   = { "adjtimex" },
-       [125]   = { "mprotect" },
-       [126]   = { "sigprocmask" },
-       [127]   = { "create_module" },
-       [128]   = { "init_module" },
-       [129]   = { "delete_module" },
-       [130]   = { "get_kernel_syms" },
-       [131]   = { "quotactl" },
-       [132]   = { "getpgid" },
-       [133]   = { "fchdir" },
-       [134]   = { "bdflush" },
-       [135]   = { "sysfs" },
-       [136]   = { "personality" },
-       [137]   = { "afs_syscall" },
-       [138]   = { "setfsuid" },
-       [139]   = { "setfsgid" },
-       [140]   = { "_llseek",                  0x014331        },
-       [141]   = { "getdents" },
-       [142]   = { "_newselect",               0x000141        },
-       [143]   = { "flock" },
-       [144]   = { "msync" },
-       [145]   = { "readv" },
-       [146]   = { "writev" },
-       [147]   = { "getsid",                   0x000001        },
-       [148]   = { "fdatasync",                0x000001        },
-       [149]   = { "_sysctl",                  0x000004        },
-       [150]   = { "mlock" },
-       [151]   = { "munlock" },
-       [152]   = { "mlockall" },
-       [153]   = { "munlockall" },
-       [154]   = { "sched_setparam" },
-       [155]   = { "sched_getparam" },
-       [156]   = { "sched_setscheduler" },
-       [157]   = { "sched_getscheduler" },
-       [158]   = { "sched_yield" },
-       [159]   = { "sched_get_priority_max" },
-       [160]   = { "sched_get_priority_min" },
-       [161]   = { "sched_rr_get_interval" },
-       [162]   = { "nanosleep",                0x000044        },
-       [163]   = { "mremap" },
-       [164]   = { "setresuid" },
-       [165]   = { "getresuid" },
-       [166]   = { "vm86" },
-       [167]   = { "query_module" },
-       [168]   = { "poll" },
-       [169]   = { "nfsservctl" },
-       [170]   = { "setresgid" },
-       [171]   = { "getresgid" },
-       [172]   = { "prctl",                    0x333331        },
-       [173]   = { "rt_sigreturn",             0xffffff        },
-       [174]   = { "rt_sigaction",             0x001441        },
-       [175]   = { "rt_sigprocmask",           0x001441        },
-       [176]   = { "rt_sigpending",            0x000014        },
-       [177]   = { "rt_sigtimedwait",          0x001444        },
-       [178]   = { "rt_sigqueueinfo",          0x000411        },
-       [179]   = { "rt_sigsuspend",            0x000014        },
-       [180]   = { "pread",                    0x003341        },
-       [181]   = { "pwrite",                   0x003341        },
-       [182]   = { "chown",                    0x000115        },
-       [183]   = { "getcwd" },
-       [184]   = { "capget" },
-       [185]   = { "capset" },
-       [186]   = { "sigaltstack" },
-       [187]   = { "sendfile" },
-       [188]   = { "getpmsg" },
-       [189]   = { "putpmsg" },
-       [190]   = { "vfork",                    0xffffff        },
-       [191]   = { "ugetrlimit" },
-       [192]   = { "mmap2",                    0x313314        },
-       [193]   = { "truncate64" },
-       [194]   = { "ftruncate64" },
-       [195]   = { "stat64",                   0x000045        },
-       [196]   = { "lstat64",                  0x000045        },
-       [197]   = { "fstat64",                  0x000041        },
-       [198]   = { "lchown32" },
-       [199]   = { "getuid32",                 0xffffff        },
-       [200]   = { "getgid32",                 0xffffff        },
-       [201]   = { "geteuid32",                0xffffff        },
-       [202]   = { "getegid32",                0xffffff        },
-       [203]   = { "setreuid32" },
-       [204]   = { "setregid32" },
-       [205]   = { "getgroups32" },
-       [206]   = { "setgroups32" },
-       [207]   = { "fchown32" },
-       [208]   = { "setresuid32" },
-       [209]   = { "getresuid32" },
-       [210]   = { "setresgid32" },
-       [211]   = { "getresgid32" },
-       [212]   = { "chown32" },
-       [213]   = { "setuid32" },
-       [214]   = { "setgid32" },
-       [215]   = { "setfsuid32" },
-       [216]   = { "setfsgid32" },
-       [217]   = { "pivot_root" },
-       [218]   = { "mincore" },
-       [219]   = { "madvise" },
-       [220]   = { "getdents64" },
-       [221]   = { "fcntl64" },
-       [223]   = { "security" },
-       [224]   = { "gettid" },
-       [225]   = { "readahead" },
-       [226]   = { "setxattr" },
-       [227]   = { "lsetxattr" },
-       [228]   = { "fsetxattr" },
-       [229]   = { "getxattr" },
-       [230]   = { "lgetxattr" },
-       [231]   = { "fgetxattr" },
-       [232]   = { "listxattr" },
-       [233]   = { "llistxattr" },
-       [234]   = { "flistxattr" },
-       [235]   = { "removexattr" },
-       [236]   = { "lremovexattr" },
-       [237]   = { "fremovexattr" },
-       [238]   = { "tkill" },
-       [239]   = { "sendfile64" },
-       [240]   = { "futex" },
-       [241]   = { "sched_setaffinity" },
-       [242]   = { "sched_getaffinity" },
-       [243]   = { "set_thread_area" },
-       [244]   = { "get_thread_area" },
-       [245]   = { "io_setup" },
-       [246]   = { "io_destroy" },
-       [247]   = { "io_getevents" },
-       [248]   = { "io_submit" },
-       [249]   = { "io_cancel" },
-       [250]   = { "fadvise64" },
-       [252]   = { "exit_group",               0x000001        },
-       [253]   = { "lookup_dcookie" },
-       [254]   = { "epoll_create" },
-       [255]   = { "epoll_ctl" },
-       [256]   = { "epoll_wait" },
-       [257]   = { "remap_file_pages" },
-       [258]   = { "set_tid_address" },
-       [259]   = { "timer_create" },
-       [260]   = { "timer_settime" },
-       [261]   = { "timer_gettime" },
-       [262]   = { "timer_getoverrun" },
-       [263]   = { "timer_delete" },
-       [264]   = { "clock_settime" },
-       [265]   = { "clock_gettime" },
-       [266]   = { "clock_getres" },
-       [267]   = { "clock_nanosleep" },
-       [268]   = { "statfs64" },
-       [269]   = { "fstatfs64" },
-       [270]   = { "tgkill" },
-       [271]   = { "utimes" },
-       [272]   = { "fadvise64_64" },
-       [273]   = { "vserver" },
-       [274]   = { "mbind" },
-       [275]   = { "get_mempolicy" },
-       [276]   = { "set_mempolicy" },
-       [277]   = { "mq_open" },
-       [278]   = { "mq_unlink" },
-       [279]   = { "mq_timedsend" },
-       [280]   = { "mq_timedreceive" },
-       [281]   = { "mq_notify" },
-       [282]   = { "mq_getsetattr" },
-       [283]   = { "sys_kexec_load" },
-};
-
-asmlinkage void do_syscall_trace(int leaving)
+/*
+ * handle tracing of system call entry
+ * - return the revised system call number or ULONG_MAX to cause ENOSYS
+ */
+asmlinkage unsigned long syscall_trace_entry(void)
 {
-#if 0
-       unsigned long *argp;
-       const char *name;
-       unsigned argmask;
-       char buffer[16];
-
-       if (!kstrace)
-               return;
-
-       if (!current->mm)
-               return;
-
-       if (__frame->gr7 == __NR_close)
-               return;
-
-#if 0
-       if (__frame->gr7 != __NR_mmap2 &&
-           __frame->gr7 != __NR_vfork &&
-           __frame->gr7 != __NR_execve &&
-           __frame->gr7 != __NR_exit)
-               return;
-#endif
-
-       argmask = 0;
-       name = NULL;
-       if (__frame->gr7 < NR_syscalls) {
-               name = __syscall_name_table[__frame->gr7].name;
-               argmask = __syscall_name_table[__frame->gr7].argmask;
-       }
-       if (!name) {
-               sprintf(buffer, "sys_%lx", __frame->gr7);
-               name = buffer;
-       }
-
-       if (!leaving) {
-               if (!argmask) {
-                       printk(KERN_CRIT "[%d] %s(%lx,%lx,%lx,%lx,%lx,%lx)\n",
-                              current->pid,
-                              name,
-                              __frame->gr8,
-                              __frame->gr9,
-                              __frame->gr10,
-                              __frame->gr11,
-                              __frame->gr12,
-                              __frame->gr13);
-               }
-               else if (argmask == 0xffffff) {
-                       printk(KERN_CRIT "[%d] %s()\n",
-                              current->pid,
-                              name);
-               }
-               else {
-                       printk(KERN_CRIT "[%d] %s(",
-                              current->pid,
-                              name);
-
-                       argp = &__frame->gr8;
-
-                       do {
-                               switch (argmask & 0xf) {
-                               case 1:
-                                       printk("%ld", (long) *argp);
-                                       break;
-                               case 2:
-                                       printk("%lo", *argp);
-                                       break;
-                               case 3:
-                                       printk("%lx", *argp);
-                                       break;
-                               case 4:
-                                       printk("%p", (void *) *argp);
-                                       break;
-                               case 5:
-                                       printk("\"%s\"", (char *) *argp);
-                                       break;
-                               }
-
-                               argp++;
-                               argmask >>= 4;
-                               if (argmask)
-                                       printk(",");
-
-                       } while (argmask);
-
-                       printk(")\n");
-               }
-       }
-       else {
-               if ((int)__frame->gr8 > -4096 && (int)__frame->gr8 < 4096)
-                       printk(KERN_CRIT "[%d] %s() = %ld\n", current->pid, name, __frame->gr8);
-               else
-                       printk(KERN_CRIT "[%d] %s() = %lx\n", current->pid, name, __frame->gr8);
+       __frame->__status |= REG__STATUS_SYSC_ENTRY;
+       if (tracehook_report_syscall_entry(__frame)) {
+               /* tracing decided this syscall should not happen, so
+                * We'll return a bogus call number to get an ENOSYS
+                * error, but leave the original number in
+                * __frame->syscallno
+                */
+               return ULONG_MAX;
        }
-       return;
-#endif
-
-       if (!test_thread_flag(TIF_SYSCALL_TRACE))
-               return;
 
-       if (!(current->ptrace & PT_PTRACED))
-               return;
-
-       /* we need to indicate entry or exit to strace */
-       if (leaving)
-               __frame->__status |= REG__STATUS_SYSC_EXIT;
-       else
-               __frame->__status |= REG__STATUS_SYSC_ENTRY;
-
-       ptrace_notify(SIGTRAP);
+       return __frame->syscallno;
+}
 
-       /*
-        * this isn't the same as continuing with a signal, but it will do
-        * for normal use.  strace only continues with a signal if the
-        * stopping signal is not SIGTRAP.  -brl
-        */
-       if (current->exit_code) {
-               send_sig(current->exit_code, current, 1);
-               current->exit_code = 0;
-       }
+/*
+ * handle tracing of system call exit
+ */
+asmlinkage void syscall_trace_exit(void)
+{
+       __frame->__status |= REG__STATUS_SYSC_EXIT;
+       tracehook_report_syscall_exit(__frame, 0);
 }