Hi Matt.

Thanks for the feedback. I have changed the path according to your comments
and am attaching it below.

 - Let me know if I need to adjust my patch before inclusion with respect to
   the s/clone_with_pids// later.

 - Much better with the 'local SYS_NR_DEF_REGEX' in get_unistd_regex().
   Thanks.

 - I pondered about inserting arch-specific code when printing the header
   content, and thought about a file function like add_arch_syscall_base()
   but it seems rhather synthetic as I think ARM is the only possible
   architecture, which would use it. Instead, I added whitespace around the
   line as you suggest.

 - I agree regarding the make variables - it was simply a glitch. I
   adjusted the assignment in both Makefile and test/Makefile.


Thanks,
Christoffer

diff --git a/Makefile b/Makefile
index 6c9ff93..37ed40a 100644
--- a/Makefile
+++ b/Makefile
@@ -18,6 +18,13 @@ CR_OBJS = checkpoint.o checkpoint-main.o restart.o 
restart-main.o
 # detect architecture (for eclone)
 SUBARCH ?= $(patsubst i%86,x86_32,$(shell uname -m))
 
+# handle cross-compilation
+AR  := ${CROSS_COMPILE}ar
+AS  := ${CROSS_COMPILE}as
+CC  := ${CROSS_COMPILE}gcc
+CPP := ${CROSS_COMPILE}cpp
+LD  := ${CROSS_COMPILE}ld
+
 # compile with debug ?
 DEBUG = -DCHECKPOINT_DEBUG
 
@@ -77,6 +84,11 @@ ASFLAGS += -m64
 $(LIB_ECLONE): clone_$(SUBARCH)_.o
 endif
 
+# also on ARM, need also assembly file
+ifeq ($(SUBARCH),arm)
+$(LIB_ECLONE): eclone_$(SUBARCH)_.o
+endif
+
 # ckptinfo dependencies
 ckptinfo: ckptinfo_types.o
 
diff --git a/clone.h b/clone.h
index 3569a45..b6b18ce 100644
--- a/clone.h
+++ b/clone.h
@@ -25,6 +25,14 @@
 #    define __NR_unshare 303
 #elif __powerpc__
 #    define __NR_unshare 282
+#elif __arm__
+#    define __NR_OABI_SYSCALL_BASE 0x900000
+#    if defined(__thumb__) || defined(__ARM_EABI__)
+#        define __NR_SYSCALL_BASE 0
+#    else
+#        define __NR_SYSCALL_BASE __NR_OABI_SYSCALL_BASE
+#    endif
+#    define __NR_unshare (__NR_SYSCALL_BASE+337)
 #else
 #    error "Architecture not supported"
 #endif
diff --git a/clone_arm.c b/clone_arm.c
new file mode 100644
index 0000000..b62b4ad
--- /dev/null
+++ b/clone_arm.c
@@ -0,0 +1,79 @@
+/*
+ *  clone_arm.c: support for eclone() on ARM
+ *
+ *  Author:    Christoffer Dall <[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 <stdio.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"
+
+extern int __eclone(int clone_flags_low,
+                   struct clone_args *clone_args,
+                   unsigned int args_size,
+                   pid_t *pids);
+
+static unsigned long get_stack_pointer(unsigned long base, unsigned long size)
+{
+       size_t page_size = sysconf(_SC_PAGESIZE);
+       return (base + size - page_size) - 1;
+}
+
+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 newpid;
+       void **sp = NULL;
+
+       if (!fn) {
+               fprintf(stderr, "Please provide a valid function pointer "
+                               "for the child process.\n");
+               return -1;
+       }
+
+       if (clone_args->child_stack) {
+               sp = (void **)get_stack_pointer(clone_args->child_stack,
+                                               clone_args->child_stack_size);
+               *--sp = fn_arg;
+               *--sp = fn;
+       } else {
+               fprintf(stderr, "The ARM architecture requires a valid child "
+                               "stack. clon_args->child_stack was 0.\n");
+               return -1;
+       }
+
+
+       my_args = *clone_args;
+       my_args.child_stack = (unsigned long long)sp;
+       my_args.child_stack_size = 0;
+
+       newpid = __eclone(clone_flags_low,
+                         &my_args,
+                         sizeof(my_args),
+                         pids);
+
+       if (newpid < 0) {
+               errno = -newpid;
+               newpid = -1;
+       }
+
+       return newpid;
+}
diff --git a/eclone_arm_.S b/eclone_arm_.S
new file mode 100644
index 0000000..0f71d0f
--- /dev/null
+++ b/eclone_arm_.S
@@ -0,0 +1,86 @@
+/*
+ *  eclone_arm_.S: ARM support for eclone()
+ *
+ *  Author:    Christoffer Dall <[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 _ERRNO_H       1
+#include <bits/errno.h>
+#include <asm/unistd.h>
+
+
+#define CLONE_VM      0x00000100
+#define CLONE_THREAD  0x00010000
+
+#ifndef __NR_eclone
+#define __NR_eclone 366
+#endif
+
+/*
+ * Implements the following system call wrapper:
+ *
+ *     extern int __eclone(int clone_flags_low,
+ *                         struct clone_args *clone_args,
+ *                         pid_t *pids);
+ *
+ * The system call wrapper and the system call themselves have slightly
+ * different layouts and the following transformation takes place in
+ * the code below:
+ *
+ */
+
+        .text
+       .align 4
+       .globl __eclone
+       .type __eclone,%function
+__eclone:
+       @ save flags
+       mov     ip, r0
+
+       @ do the system call
+#ifdef __ARM_EABI__
+       str     r7, [sp, #-4]!
+       ldr     r7, =__NR_eclone
+       swi     0x0
+#else
+       swi     __NR_eclone
+#endif
+       cmp     r0, #0
+       beq     1f
+#ifdef __ARM_EABI__
+       ldr     r7, [sp], #4
+#endif
+       @ return to caller
+       bx      lr
+
+1:
+       tst     ip, #CLONE_THREAD
+       bne     3f
+       mov     r0, #0xffff0fff
+       mov     lr, pc
+       sub     pc, r0, #31
+       mov     r1, r0
+       tst     ip, #CLONE_VM
+       movne   r0, #-1
+#ifdef __ARM_EABI__
+       ldr     r7, =__NR_getpid
+       swieq   0x0
+#else
+       swieq   __NR_getpid
+#endif
+       str     r0, [r1, #-1108]
+       str     r0, [r1, #-1112]
+3:
+       @ pick the function arg and call address off the stack and execute
+       ldr     r0, [sp, #4]
+       mov     lr, pc
+       ldr     pc, [sp], #8
+
+       @ and we are done, passing the return value through r0
+       @b       PLTJMP(HIDDEN_JUMPTARGET(_exit))
+       b       _exit
+
diff --git a/include/asm-arm/checkpoint_hdr.h b/include/asm-arm/checkpoint_hdr.h
new file mode 100644
index 0000000..9295f85
--- /dev/null
+++ b/include/asm-arm/checkpoint_hdr.h
@@ -0,0 +1,55 @@
+/*
+ * Generated by extract-headers.sh.
+ */
+#ifndef __ASM_ARM_CHECKPOINT_HDR_H_
+#define __ASM_ARM_CHECKPOINT_HDR_H_
+
+/*
+ *  Checkpoint/restart - architecture specific headers ARM
+ *
+ *  Copyright (C) 2008-2010 Oren Laadan
+ *  Copyright (C)      2010 Christoffer Dall
+ *
+ *  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.
+ */
+
+#include <linux/types.h>
+
+/* ARM structure seen from kernel/userspace */
+
+#define CKPT_ARCH_ID CKPT_ARCH_ARM
+
+/* arch dependent constants */
+#define CKPT_ARCH_NSIG 64
+#define CKPT_TTY_NCC 8
+
+struct ckpt_hdr_header_arch {
+       struct ckpt_hdr h;
+       __u32   cpu_architecture;
+       __u8    mmu;            /* Checkpointed on mmu system */
+       __u8    aeabi;          /* Checkpointed on AEABI kernel */
+       __u8    oabi_compat;    /* Checkpointed on OABI compat. system */
+} __attribute__((aligned(8)));
+
+struct ckpt_hdr_thread {
+       struct ckpt_hdr h;
+       __u32           syscall;
+       __u32           tp_value;
+       __u32           thumbee_state;
+} __attribute__((aligned(8)));
+
+struct ckpt_hdr_cpu {
+       struct ckpt_hdr h;
+       __u32           uregs[18];
+} __attribute__((aligned(8)));
+
+struct ckpt_hdr_mm_context {
+       struct ckpt_hdr h;
+       __u32           end_brk;
+} __attribute__((aligned(8)));
+
+
+
+#endif /* __ASM_ARM_CHECKPOINT_HDR_H_ */
diff --git a/include/asm/checkpoint_hdr.h b/include/asm/checkpoint_hdr.h
index 859f58e..7f18e0e 100644
--- a/include/asm/checkpoint_hdr.h
+++ b/include/asm/checkpoint_hdr.h
@@ -3,7 +3,9 @@
  */
 #ifndef __ASM_CHECKPOINT_HDR_H_
 #define __ASM_CHECKPOINT_HDR_H_
-#if __powerpc__
+#if __arm__
+#include <asm-arm/checkpoint_hdr.h>
+#elif __powerpc__
 #include <asm-powerpc/checkpoint_hdr.h>
 #elif __s390x__
 #include <asm-s390/checkpoint_hdr.h>
diff --git a/include/linux/checkpoint.h b/include/linux/checkpoint.h
index f6a6448..359023f 100644
--- a/include/linux/checkpoint.h
+++ b/include/linux/checkpoint.h
@@ -31,7 +31,25 @@
 #define CHECKPOINT_FD_NONE -1
 
 
-#if __powerpc__
+#if __arm__
+
+#      define __NR_OABI_SYSCALL_BASE 0x900000
+#      if defined(__thumb__) || defined(__ARM_EABI__)
+#              define __NR_SYSCALL_BASE        0
+#      else
+#              define __NR_SYSCALL_BASE        __NR_OABI_SYSCALL_BASE
+#      endif
+
+
+#      ifndef __NR_checkpoint
+#              define __NR_checkpoint (__NR_SYSCALL_BASE+367)
+#      endif
+
+#      ifndef __NR_restart
+#              define __NR_restart (__NR_SYSCALL_BASE+368)
+#      endif
+
+#elif __powerpc__
 
 #      ifndef __NR_checkpoint
 #              define __NR_checkpoint 324
diff --git a/include/linux/checkpoint_hdr.h b/include/linux/checkpoint_hdr.h
index 65d5256..214cd11 100644
--- a/include/linux/checkpoint_hdr.h
+++ b/include/linux/checkpoint_hdr.h
@@ -202,6 +202,8 @@ enum {
 #define CKPT_ARCH_PPC32 CKPT_ARCH_PPC32
        CKPT_ARCH_PPC64,
 #define CKPT_ARCH_PPC64 CKPT_ARCH_PPC64
+       CKPT_ARCH_ARM,
+#define CKPT_ARCH_ARM CKPT_ARCH_ARM
 };
 
 /* shared objrects (objref) */
diff --git a/scripts/extract-headers.sh b/scripts/extract-headers.sh
index 8c8ae69..19f63b4 100755
--- a/scripts/extract-headers.sh
+++ b/scripts/extract-headers.sh
@@ -144,7 +144,27 @@ echo '#endif /* _CHECKPOINT_CKPT_HDR_H_ */' >> 
"${OUTPUT_INCLUDES}/linux/checkpo
 # We use ARCH_COND to break up architecture-specific sections of the header.
 #
 ARCH_COND='#if'
-REGEX='[[:space:]]*#[[:space:]]*define[[:space:]]*__NR_(checkpoint|restart|clone_with_pids)[[:space:]]+[0-9]+'
+ARM_SYSCALL_BASE="#    define __NR_OABI_SYSCALL_BASE 0x900000\n\
+#      if defined(__thumb__) || defined(__ARM_EABI__)\n\
+#              define __NR_SYSCALL_BASE        0\n\
+#      else\n\
+#              define __NR_SYSCALL_BASE        __NR_OABI_SYSCALL_BASE\n\
+#      endif\n"
+
+# Get the regular expression for the current architecture
+function get_unistd_regex()
+{
+       local 
SYS_NR_DEF_REGEX='[[:space:]]*#[[:space:]]*define[[:space:]]*__NR_(checkpoint|restart|clone_with_pids)[[:space:]]+'
+
+       case "$1" in
+       arm)    echo -n "${SYS_NR_DEF_REGEX}"
+               echo -n '\(__NR_SYSCALL_BASE\+[[:space:]]*[0-9]*\)'
+               ;;
+       *)      echo -n "${SYS_NR_DEF_REGEX}"'[0-9]+'
+               ;;
+       esac
+       return 0
+}
 
 cat - <<-EOFOE
 /*
@@ -160,11 +180,15 @@ do_cpp "${KERNELSRC}/include/linux/checkpoint.h" 
"_LINUX_CHECKPOINT_H_"
 find "${KERNELSRC}/arch" -name 'unistd*.h' -print | sort | \
 while read UNISTDH ; do
        [ -n "${UNISTDH}" ] || continue
-       grep -q -E "${REGEX}" "${UNISTDH}" || continue
        KARCH=$(echo "${UNISTDH}" | sed -e 's|.*/arch/\([^/]\+\)/.*|\1|')
+       REGEX="$(get_unistd_regex "${KARCH}")"
+       grep -q -E "${REGEX}" "${UNISTDH}" || continue
        WORDBITS=$(basename "${UNISTDH}" | sed -e 
's/unistd_*\([[:digit:]]\+\)\.h/\1/')
        CPPARCH="$(karch_to_cpparch "${KARCH}" "${WORDBITS}")"
        echo -e "${ARCH_COND} __${CPPARCH}__\\n"
+
+       [ "${KARCH}" == "arm" ] && echo -e "${ARM_SYSCALL_BASE}\n"
+
        grep -E "${REGEX}" "${UNISTDH}" | \
        sed -e 's/^[ \t]*#[ \t]*define[ \t]*__NR_\([^ \t]\+\)[ \t]\+\([^ 
\t]\+\).*$/#\tifndef __NR_\1\n#\t\tdefine __NR_\1 \2\n#\tendif\n/'
        ARCH_COND='#elif'
diff --git a/test/Makefile b/test/Makefile
index cad40e0..516eee8 100644
--- a/test/Makefile
+++ b/test/Makefile
@@ -1,3 +1,9 @@
+# handle cross-compilation
+AR = ${CROSS_COMPILE}ar
+AS = ${CROSS_COMPILE}as
+CC = ${CROSS_COMPILE}gcc
+CPP = ${CROSS_COMPILE}cpp
+LD = ${CROSS_COMPILE}ld
 
 # extra warnings and fun
 WARNS := -Wall -Wstrict-prototypes -Wno-trigraphs
-- 
1.5.6.5

_______________________________________________
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