vserver 1.9.5.x5
[linux-2.6.git] / arch / arm26 / kernel / sys_arm.c
index 431f9f8..e7edd20 100644 (file)
@@ -13,6 +13,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>
@@ -281,3 +282,43 @@ asmlinkage int sys_execve(char *filenamei, char **argv, char **envp, struct pt_r
 out:
        return error;
 }
+
+/* FIXME - see if this is correct for arm26 */
+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);