Signed-off-by: Oren Laadan <[email protected]>
---
 clone_x86_64.c |   88 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 88 insertions(+), 0 deletions(-)
 create mode 100644 clone_x86_64.c

diff --git a/clone_x86_64.c b/clone_x86_64.c
new file mode 100644
index 0000000..d6d7e6f
--- /dev/null
+++ b/clone_x86_64.c
@@ -0,0 +1,88 @@
+/*
+ *  clone_x86_64.c: support for eclone() on x86_64
+ *
+ *  Copyright (C) Oren Laadan <[email protected]>
+ *  Copyright (C) Dave Hansen <[email protected]>
+ *
+ *  This file is subject to the terms and conditions of the GNU General Public
+ *  License.  See the file COPYING in the main directory of the Linux
+ *  distribution for more details.
+ */
+
+#define _GNU_SOURCE
+
+#include <unistd.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/syscall.h>
+#include <asm/unistd.h>
+
+/*
+ * libc doesn't support eclone() yet...
+ * below is arch-dependent code to use the syscall
+ */
+#include <linux/checkpoint.h>
+
+#include "eclone.h"
+
+#ifndef __NR_eclone
+#define __NR_eclone 299
+#endif
+
+int eclone(int (*fn)(void *), void *fn_arg, int clone_flags_low,
+          struct clone_args *clone_args, pid_t *pids)
+{
+       struct clone_args my_args;
+       long retval;
+       void **newstack;
+
+       if (clone_args->child_stack) {
+               /*
+                * Set up the stack for child:
+                *  - fn_arg will be the argument for the child function
+                *  - the fn pointer will be loaded into ebx after the clone
+                */
+               newstack = (void **)(unsigned long)(clone_args->child_stack +
+                                           clone_args->child_stack_size);
+               *--newstack = fn_arg;
+               *--newstack = fn;
+       } else
+               newstack = (void **)0;
+
+       my_args = *clone_args;
+       my_args.child_stack = (unsigned long)newstack;
+       my_args.child_stack_size = 0;
+
+        __asm__  __volatile__(
+               "movq %6, %%r10\n\t"    /* pids in r10*/
+               "syscall\n\t"           /* Linux/x86_64 system call */
+               "testq %0,%0\n\t"       /* check return value */
+               "jne 1f\n\t"            /* jump if parent */
+               "popq %%rax\n\t"        /* get subthread function */
+               "popq %%rdi\n\t"        /* get the subthread function arg */
+               "call *%%rax\n\t"       /* start subthread function */
+               "movq %2,%0\n\t"
+               "syscall\n"             /* exit system call: exit subthread */
+               "1:\n\t"
+               :"=a" (retval)
+               :"0" (__NR_eclone), "i" (__NR_exit),
+                "D" (clone_flags_low), /* rdi */
+                "S" (&my_args),        /* rsi */
+                "d" (sizeof(my_args)), /* rdx */
+                "m" (pids)             /* gets moved to r10 */
+               :"rcx", "r10", "r11", "cc"
+               );
+                                       /*
+         * glibc lists 'cc' as clobbered, so we might as
+        * well do it too.  'r11' and 'rcx' are clobbered
+        * by the 'syscall' instruction itself.  'r8' and
+        * 'r9' are clobbered by the clone, but that
+        * thread will exit before getting back out to C.
+         */
+
+       if (retval < 0) {
+               errno = -retval;
+               retval = -1;
+       }
+       return retval;
+}
-- 
1.6.3.3

_______________________________________________
Containers mailing list
[email protected]
https://lists.linux-foundation.org/mailman/listinfo/containers

_______________________________________________
Devel mailing list
[email protected]
https://openvz.org/mailman/listinfo/devel

Reply via email to