This patch:
        1. changes restart to pass the right values to
                clone-with-pids.
        2. updates the clone_s390x.c to work with the
                new kernel.

All tests under cr_tests/ pass with this patch.

Signed-off-by: Serge E. Hallyn <[email protected]>
---
 clone_s390x.c |   92 +++++++++++++++++++++++++++++++++++++--------------------
 restart.c     |   14 +++++----
 2 files changed, 68 insertions(+), 38 deletions(-)

diff --git a/clone_s390x.c b/clone_s390x.c
index dada822..71cf52f 100644
--- a/clone_s390x.c
+++ b/clone_s390x.c
@@ -14,6 +14,7 @@
 
 #include <unistd.h>
 #include <errno.h>
+#include <string.h>
 #include <sys/types.h>
 #include <sys/syscall.h>
 #include <asm/unistd.h>
@@ -25,48 +26,75 @@
 #include <linux/checkpoint.h>
 #if defined(__NR_clone_with_pids)
 
-/* this really belongs to some kernel header ! */
 struct pid_set {
        int num_pids;
        pid_t *pids;
 };
 
-/* (see: http://lkml.indiana.edu/hypermail/linux/kernel/9604.3/0204.html) */
+typedef unsigned long long u64;
+typedef unsigned int u32;
+typedef int pid_t;
+struct clone_args {
+       u64 clone_flags_high;
 
-#define do_clone_with_pids(stack, flags, ptid, ctid, setp) ({ \
-       register unsigned long int __r2 asm ("2") = (unsigned long int)(stack);\
-       register unsigned long int __r3 asm ("3") = (unsigned long int)(flags);\
-       register unsigned long int __r4 asm ("4") = (unsigned long int)(ptid); \
-       register unsigned long int __r5 asm ("5") = (unsigned long int)(ctid); \
-       register unsigned long int __r6 asm ("6") = (unsigned long int)(NULL); \
-       register unsigned long int __r7 asm ("7") = (unsigned long int)(setp); \
-       register unsigned long int __result asm ("2"); \
-       __asm__ __volatile__( \
-               " lghi %%r1,%7\n" \
-               " svc 0\n" \
-               : "=d" (__result) \
-               : "0" (__r2), "d" (__r3), \
-                 "d" (__r4), "d" (__r5), "d" (__r6), "d" (__r7), \
-                 "i" (__NR_clone_with_pids) \
-               : "1", "cc", "memory" \
-       ); \
-               __result; \
-       })
+       u64 child_stack_base;
+       u64 child_stack_size;
 
-int clone_with_pids(int (*fn)(void *), void *child_stack, int flags,
+       u64 parent_tid_ptr;
+       u64 child_tid_ptr;
+
+       u32 nr_pids;
+
+       u32 reserved0;
+       u64 reserved1;
+};
+
+#define do_cwp(flags, pids, args, sz) \
+( { \
+  register unsigned long int __r1 asm ("1") = (unsigned long 
int)(__NR_clone_with_pids); \
+  register unsigned long int __r2 asm ("2") = (unsigned long int)(flags); \
+  register unsigned long int __r3 asm ("3") = (unsigned long int)(args); \
+  register unsigned long int __r4 asm ("4") = (unsigned long int)(sz); \
+  register unsigned long int __r5 asm ("5") = (unsigned long int)(pids); \
+  register long int __result asm ("2"); \
+  __asm__ __volatile__( \
+         " svc 0\n" /* do __NR_cwp syscall */ \
+         " ltgr %%r2,%%r2\n" /* returned 0? */ \
+         " jnz 1f\n" /* if not goto label 1 */ \
+         " lg %%r3,0(%%r15)\n"   /* get fnarg off stack into arg 1 */ \
+         " lg %%r2,8(%%r15)\n"   /* get fn off stack int r3 basr*/ \
+         " lgr %%r1,%%r15\n" /* tmp store old stack pointer */ \
+         " aghi %%r15,-160\n" /* move the stack */ \
+         " stg %%r1,0(%%r15)\n" /* and save old stack pointer */ \
+         " basr %%r14,%%r3\n" /* call fn(arg) */ \
+         " svc 1\n"  /* call exit */ \
+         " 1:\n" \
+         : "=d" (__result) \
+         : "d" (__r1), "0" (__r2), "d" (__r3), "d" (__r4), "d" (__r5) \
+         : "memory"); \
+       __result; \
+} )
+
+int clone_with_pids(int (*fn)(void *), void *child_stack,
+                       unsigned long stack_size, unsigned long flags,
                        struct pid_set *target_pids, void *arg)
 {
-       long retval;
-       retval = do_clone_with_pids(child_stack, flags, NULL, NULL,
-                                   target_pids);
+       struct clone_args clone_args, *ca = &clone_args;
+       u64 *s;
+
+       memset(ca, 0, sizeof(struct clone_args));
+       ca->nr_pids = target_pids->num_pids;
+       ca->child_stack_size = stack_size - 16;
+       ca->child_stack_base = (u64) child_stack;
+       if (child_stack) {
+               s = (u64 *) (ca->child_stack_base + ca->child_stack_size);
+               *--s = (u64) arg;
+               *--s = (u64) fn;
+               ca->child_stack_size -= 16;
+       }
 
-       if (retval < 0) {
-               errno = -retval;
-               return -1;
-       } else if (retval == 0) {
-               return fn(arg);
-       } else
-               return retval;
+       return do_cwp(flags, target_pids->pids, ca,
+                                   sizeof(struct clone_args));
 }
 
 #endif  /* !defined(__NR_clone_with_pids) */
diff --git a/restart.c b/restart.c
index 35c54ea..ebc7bf8 100644
--- a/restart.c
+++ b/restart.c
@@ -43,10 +43,12 @@ struct pid_set {
 
 /* (until it's supported by libc) from clone_ARCH.c */
 #if defined(__NR_clone_with_pids) && defined(ARCH_HAS_CLONE_WITH_PID)
-extern int clone_with_pids(int (*fn)(void *), void *child_stack, int flags,
+extern int clone_with_pids(int (*fn)(void *), void *child_stack,
+                          unsigned long stack_size, int flags,
                           struct pid_set *target_pids, void *arg);
 #else
-static int clone_with_pids(int (*fn)(void *), void *child_stack, int flags,
+static int clone_with_pids(int (*fn)(void *), void *child_stack,
+                           unsigned long stack_size, int flags,
                           struct pid_set *target_pids, void *arg)
 {
        return clone(fn, child_stack, flags, arg);
@@ -1749,18 +1751,17 @@ static pid_t ckpt_fork_child(struct ckpt_ctx *ctx, 
struct task *child)
 {
        struct pid_set pid_set;
        char *stack_region;
-       char *stack_start;
        unsigned long flags = SIGCHLD;
+       unsigned long stack_size = PTHREAD_STACK_MIN;
        pid_t pid = 0;
 
        ckpt_dbg("forking child vpid %d flags %#x\n", child->pid, child->flags);
 
-       stack_region = malloc(PTHREAD_STACK_MIN);
+       stack_region = malloc(stack_size);
        if (!stack_region) {
                perror("stack malloc");
                return -1;
        }
-       stack_start = stack_region + PTHREAD_STACK_MIN - 1;
 
        pid_set.pids = &pid;
        pid_set.num_pids = 1;
@@ -1788,7 +1789,8 @@ static pid_t ckpt_fork_child(struct ckpt_ctx *ctx, struct 
task *child)
        else
                child->real_parent = _getpid();
 
-       pid = clone_with_pids(ckpt_fork_stub, stack_start, flags, &pid_set, 
child);
+       pid = clone_with_pids(ckpt_fork_stub, stack_region, stack_size - 16,
+                               flags, &pid_set, child);
        if (pid < 0) {
                perror("clone");
                free(stack_region);
-- 
1.6.1.1

_______________________________________________
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