patch-2_6_7-vs1_9_1_12
[linux-2.6.git] / arch / arm / kernel / sys_arm.c
index 4f98f24..79acdd1 100644 (file)
@@ -12,6 +12,7 @@
  *  have a non-standard calling sequence on the Linux/arm
  *  platform.
  */
+#include <linux/module.h>
 #include <linux/errno.h>
 #include <linux/sched.h>
 #include <linux/slab.h>
@@ -282,3 +283,43 @@ asmlinkage int sys_execve(char __user *filenamei, char __user * __user *argv,
 out:
        return error;
 }
+
+long execve(const char *filename, char **argv, char **envp)
+{
+       struct pt_regs regs;
+       int ret;
+
+       memset(&regs, 0, sizeof(struct pt_regs));
+       ret = do_execve((char *)filename, (char __user * __user *)argv,
+                       (char __user * __user *)envp, &regs);
+       if (ret < 0)
+               goto out;
+
+       /*
+        * Save argc to the register structure for userspace.
+        */
+       regs.ARM_r0 = ret;
+
+       /*
+        * We were successful.  We won't be returning to our caller, but
+        * instead to user space by manipulating the kernel stack.
+        */
+       asm(    "add    r0, %0, %1\n\t"
+               "mov    r1, %2\n\t"
+               "mov    r2, %3\n\t"
+               "bl     memmove\n\t"    /* copy regs to top of stack */
+               "mov    r8, #0\n\t"     /* not a syscall */
+               "mov    r9, %0\n\t"     /* thread structure */
+               "mov    sp, r0\n\t"     /* reposition stack pointer */
+               "b      ret_to_user"
+               :
+               : "r" (current_thread_info()),
+                 "Ir" (THREAD_SIZE - 8 - sizeof(regs)),
+                 "r" (&regs),
+                 "Ir" (sizeof(regs))
+               : "r0", "r1", "r2", "r3", "ip", "memory");
+
+ out:
+       return ret;
+}
+EXPORT_SYMBOL(execve);