* [PATCH] ARM: Added user space support for c/r on ARM
@ 2010-03-22 1:14 Christoffer Dall
0 siblings, 0 replies; 5+ messages in thread
From: Christoffer Dall @ 2010-03-22 1:14 UTC (permalink / raw)
To: containers; +Cc: Christoffer Dall, libc-ports
General
--------
This is a first attempt to add C/R support for ARM. There are a number
of annoying changes in the extract-headers.sh and clone.h files due to
the way syscall numbers are defined on the ARM architecture.
Additionally there's introduced general support for CROSS_COMPILATION
and the SUBARCH variable is now conditionally set, depending on existing
values from the environment.
Eclone
--------
The code is based on the clone.S file from glibc. Some of the functionality
from glibc such as _syscall_error can not be linked with directly, so error
handling is performed a little different. In time, this code will hopefully
merge with libc and when that happens it is obvious how to link with libc
code instead of custom assembler.
The implementation has been tested with nsexec and seems to be working
properly. However, during testing, the code to access TLS in the libc error
handler (syscall_error) did not function correctly and in fact resulted in a
segmentation fault later on in the code. Instead of using the error
handler, we simply return to the caller and let it modify errno.
Note: The code to set an error for the child if CLONE_THREAD is not
specified, looks much like the syscall_error code and should probably
be tested later on. However, with CLONE_THREAD set there should be no
problems.
Signed-off-by: Christoffer Dall <christofferdall-77OGu6e99YhyO3AAkE1OcX9LOBIZ5rWg@public.gmane.org>
Acked-by: Oren Laadan <orenl-eQaUEPhvms7ENvBUuze7eA@public.gmane.org>
---
Makefile | 12 +++++
clone.h | 8 ++++
clone_arm.c | 79 ++++++++++++++++++++++++++++++++++
eclone_arm_.S | 86 ++++++++++++++++++++++++++++++++++++++
include/asm-arm/checkpoint_hdr.h | 54 ++++++++++++++++++++++++
include/asm/checkpoint_hdr.h | 4 +-
include/linux/checkpoint.h | 20 ++++++++-
include/linux/checkpoint_hdr.h | 2 +
| 24 ++++++++++-
test/Makefile | 6 +++
10 files changed, 291 insertions(+), 4 deletions(-)
create mode 100644 clone_arm.c
create mode 100644 eclone_arm_.S
create mode 100644 include/asm-arm/checkpoint_hdr.h
diff --git a/Makefile b/Makefile
index 64b5f73..1a96149 100644
--- a/Makefile
+++ b/Makefile
@@ -16,6 +16,13 @@ CKPT_HEADERS = include/linux/checkpoint.h \
# 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
@@ -69,6 +76,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 <christofferdall-77OGu6e99YhyO3AAkE1OcX9LOBIZ5rWg@public.gmane.org>
+ *
+ * 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 <christofferdall-77OGu6e99YhyO3AAkE1OcX9LOBIZ5rWg@public.gmane.org>
+ *
+ * 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..cec7986
--- /dev/null
+++ b/include/asm-arm/checkpoint_hdr.h
@@ -0,0 +1,54 @@
+/*
+ * 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 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 linux_arm_arch;
+ __u8 mmu; /* Checkpointed on mmu system */
+ __u8 oabi_compat; /* Checkpointed on old ABI 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 53b8b2c..490db44 100644
--- a/include/linux/checkpoint.h
+++ b/include/linux/checkpoint.h
@@ -30,7 +30,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 e8eaf23..d4f2b25 100644
--- a/include/linux/checkpoint_hdr.h
+++ b/include/linux/checkpoint_hdr.h
@@ -196,6 +196,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) */
--git a/scripts/extract-headers.sh b/scripts/extract-headers.sh
index 8c8ae69..aacb6af 100755
--- a/scripts/extract-headers.sh
+++ b/scripts/extract-headers.sh
@@ -144,7 +144,25 @@ 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()
+{
+ case "$1" in
+ arm) echo -n '[[:space:]]*#[[:space:]]*define[[:space:]]*__NR_(checkpoint|restart|clone_with_pids)[[:space:]]+'
+ echo -n '\(__NR_SYSCALL_BASE\+[[:space:]]*[0-9]*\)'
+ ;;
+ *) echo -n '[[:space:]]*#[[:space:]]*define[[:space:]]*__NR_(checkpoint|restart|clone_with_pids)[[:space:]]+[0-9]+'
+ ;;
+ esac
+ return 0
+}
cat - <<-EOFOE
/*
@@ -160,11 +178,13 @@ 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
^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [PATCH] ARM: Added user space support for c/r on ARM
[not found] ` <1269220484-24279-1-git-send-email-christofferdall-77OGu6e99YhyO3AAkE1OcX9LOBIZ5rWg@public.gmane.org>
2010-04-29 23:33 ` Matt Helsley
@ 2010-06-20 21:34 ` Oren Laadan
1 sibling, 0 replies; 5+ messages in thread
From: Oren Laadan @ 2010-06-20 21:34 UTC (permalink / raw)
To: Christoffer Dall; +Cc: containers, libc-ports
Applied on user-cr.
Oren.
On 03/21/2010 09:14 PM, Christoffer Dall wrote:
> General
> --------
>
> This is a first attempt to add C/R support for ARM. There are a number
> of annoying changes in the extract-headers.sh and clone.h files due to
> the way syscall numbers are defined on the ARM architecture.
>
> Additionally there's introduced general support for CROSS_COMPILATION
> and the SUBARCH variable is now conditionally set, depending on existing
> values from the environment.
>
> Eclone
> --------
>
> The code is based on the clone.S file from glibc. Some of the functionality
> from glibc such as _syscall_error can not be linked with directly, so error
> handling is performed a little different. In time, this code will hopefully
> merge with libc and when that happens it is obvious how to link with libc
> code instead of custom assembler.
>
> The implementation has been tested with nsexec and seems to be working
> properly. However, during testing, the code to access TLS in the libc error
> handler (syscall_error) did not function correctly and in fact resulted in a
> segmentation fault later on in the code. Instead of using the error
> handler, we simply return to the caller and let it modify errno.
>
> Note: The code to set an error for the child if CLONE_THREAD is not
> specified, looks much like the syscall_error code and should probably
> be tested later on. However, with CLONE_THREAD set there should be no
> problems.
>
> Signed-off-by: Christoffer Dall <christofferdall-77OGu6e99YhyO3AAkE1OcX9LOBIZ5rWg@public.gmane.org>
> Acked-by: Oren Laadan <orenl-eQaUEPhvms7ENvBUuze7eA@public.gmane.org>
> ---
> Makefile | 12 +++++
> clone.h | 8 ++++
> clone_arm.c | 79 ++++++++++++++++++++++++++++++++++
> eclone_arm_.S | 86 ++++++++++++++++++++++++++++++++++++++
> include/asm-arm/checkpoint_hdr.h | 54 ++++++++++++++++++++++++
> include/asm/checkpoint_hdr.h | 4 +-
> include/linux/checkpoint.h | 20 ++++++++-
> include/linux/checkpoint_hdr.h | 2 +
> scripts/extract-headers.sh | 24 ++++++++++-
> test/Makefile | 6 +++
> 10 files changed, 291 insertions(+), 4 deletions(-)
> create mode 100644 clone_arm.c
> create mode 100644 eclone_arm_.S
> create mode 100644 include/asm-arm/checkpoint_hdr.h
>
> diff --git a/Makefile b/Makefile
> index 64b5f73..1a96149 100644
> --- a/Makefile
> +++ b/Makefile
> @@ -16,6 +16,13 @@ CKPT_HEADERS = include/linux/checkpoint.h \
> # 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
>
> @@ -69,6 +76,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 <christofferdall-77OGu6e99YhyO3AAkE1OcX9LOBIZ5rWg@public.gmane.org>
> + *
> + * 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 <christofferdall-77OGu6e99YhyO3AAkE1OcX9LOBIZ5rWg@public.gmane.org>
> + *
> + * 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..cec7986
> --- /dev/null
> +++ b/include/asm-arm/checkpoint_hdr.h
> @@ -0,0 +1,54 @@
> +/*
> + * 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 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 linux_arm_arch;
> + __u8 mmu; /* Checkpointed on mmu system */
> + __u8 oabi_compat; /* Checkpointed on old ABI 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 53b8b2c..490db44 100644
> --- a/include/linux/checkpoint.h
> +++ b/include/linux/checkpoint.h
> @@ -30,7 +30,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 e8eaf23..d4f2b25 100644
> --- a/include/linux/checkpoint_hdr.h
> +++ b/include/linux/checkpoint_hdr.h
> @@ -196,6 +196,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..aacb6af 100755
> --- a/scripts/extract-headers.sh
> +++ b/scripts/extract-headers.sh
> @@ -144,7 +144,25 @@ 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()
> +{
> + case "$1" in
> + arm) echo -n '[[:space:]]*#[[:space:]]*define[[:space:]]*__NR_(checkpoint|restart|clone_with_pids)[[:space:]]+'
> + echo -n '\(__NR_SYSCALL_BASE\+[[:space:]]*[0-9]*\)'
> + ;;
> + *) echo -n '[[:space:]]*#[[:space:]]*define[[:space:]]*__NR_(checkpoint|restart|clone_with_pids)[[:space:]]+[0-9]+'
> + ;;
> + esac
> + return 0
> +}
>
> cat - <<-EOFOE
> /*
> @@ -160,11 +178,13 @@ 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
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH] ARM: Added user space support for c/r on ARM
[not found] ` <1272439752-4021-1-git-send-email-christofferdall-77OGu6e99YhyO3AAkE1OcX9LOBIZ5rWg@public.gmane.org>
@ 2010-04-30 9:42 ` Christoffer Dall
0 siblings, 0 replies; 5+ messages in thread
From: Christoffer Dall @ 2010-04-30 9:42 UTC (permalink / raw)
To: Matt Helsley; +Cc: containers, Christoffer Dall, libc-ports
On Wed, Apr 28, 2010 at 8:29 AM, Christoffer Dall
<christofferdall-77OGu6e99YhyO3AAkE1OcX9LOBIZ5rWg@public.gmane.org> wrote:
> 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.
sorry, I forgot to include the changes to test/Makefile in the patch below.
>
>
> 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 <christofferdall@christofferdall.dk>
> + *
> + * 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 <christofferdall@christofferdall.dk>
> + *
> + * 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
>
>
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH] ARM: Added user space support for c/r on ARM
[not found] ` <1269220484-24279-1-git-send-email-christofferdall-77OGu6e99YhyO3AAkE1OcX9LOBIZ5rWg@public.gmane.org>
@ 2010-04-29 23:33 ` Matt Helsley
2010-06-20 21:34 ` Oren Laadan
1 sibling, 0 replies; 5+ messages in thread
From: Matt Helsley @ 2010-04-29 23:33 UTC (permalink / raw)
To: Christoffer Dall; +Cc: containers, libc-ports
On Sun, Mar 21, 2010 at 09:14:44PM -0400, Christoffer Dall wrote:
> General
> --------
>
> This is a first attempt to add C/R support for ARM. There are a number
> of annoying changes in the extract-headers.sh and clone.h files due to
> the way syscall numbers are defined on the ARM architecture.
<snip>
> diff --git a/scripts/extract-headers.sh b/scripts/extract-headers.sh
> index 8c8ae69..aacb6af 100755
> --- a/scripts/extract-headers.sh
> +++ b/scripts/extract-headers.sh
> @@ -144,7 +144,25 @@ 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]+'
Just a heads up in case there's a merge conflict later:
I think I need to submit a patch which does s/clone_with_pids// since
eclone.h and the respective clone_*.* arch files define NR_eclone anyway.
> +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()
> +{
You could decompose the regex and make it easy to see what's so special
about ARM syscall nrs:
local SYS_NR_DEF_REGEX='[[:space:]]*#[[:space:]]*define[[:space:]]*__NR_(checkpoint|restart|clone_with_pids)[[:space:]]+'
> + case "$1" in
> + arm) echo -n '[[:space:]]*#[[:space:]]*define[[:space:]]*__NR_(checkpoint|restart|clone_with_pids)[[:space:]]+'
echo -n "${SYS_NR_DEF_REGEX}"'\(__NR_SYSCALL_BASE\+[[:space:]]*[0-9]*\)'
> + ;;
> + *) echo -n '[[:space:]]*#[[:space:]]*define[[:space:]]*__NR_(checkpoint|restart|clone_with_pids)[[:space:]]+[0-9]+'
echo -n "${SYS_NR_DEF_REGEX}"'[0-9]+'
> + ;;
> + esac
> + return 0
> +}
>
> cat - <<-EOFOE
> /*
> @@ -160,11 +178,13 @@ 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"
nit:
I can see what you're trying to do but this introduces arch-specific code
in the middle of nicely arch-generic code. Currently, as you've done with
get_unistd_regex, we've nicely encapsulated those pieces into functions.
Perhaps adding blank lines above and below this is sufficient since I
can't think of an arch-generic function which would be appropriate here.
> 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
GNU Make nit: I prefer the :=, or simple assignment, operator. Both = and :=
(amongst others) expand the values of variables. However = is "recursive"
and the right-hand side is evaluated multiple times -- I think
everywhere the variable on the left-hand side is used. In contrast the
right-hand side of := is evaluated everywhere the left-hand side is defined
(usually once). This is faster and non-recursive. See
"The Two Flavors of Variables" in the GNU Make info file for a more rigorous
discussion of the differences.
Cheers,
-Matt Helsley
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH] ARM: Added user space support for c/r on ARM
[not found] ` <20100429233346.GZ32490-52DBMbEzqgQ/wnmkkaCWp/UQ3DHhIser@public.gmane.org>
@ 2010-04-28 7:29 ` Christoffer Dall
0 siblings, 0 replies; 5+ messages in thread
From: Christoffer Dall @ 2010-04-28 7:29 UTC (permalink / raw)
To: Matt Helsley; +Cc: containers, Christoffer Dall, libc-ports
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 <christofferdall-77OGu6e99YhyO3AAkE1OcX9LOBIZ5rWg@public.gmane.org>
+ *
+ * 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 <christofferdall-77OGu6e99YhyO3AAkE1OcX9LOBIZ5rWg@public.gmane.org>
+ *
+ * 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
^ permalink raw reply related [flat|nested] 5+ messages in thread
end of thread, other threads:[~2010-06-20 21:34 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2010-03-22 1:14 [PATCH] ARM: Added user space support for c/r on ARM Christoffer Dall
[not found] <20100429233346.GZ32490@count0.beaverton.ibm.com>
[not found] ` <20100429233346.GZ32490-52DBMbEzqgQ/wnmkkaCWp/UQ3DHhIser@public.gmane.org>
2010-04-28 7:29 ` Christoffer Dall
[not found] ` <1272439752-4021-1-git-send-email-christofferdall@christofferdall.dk>
[not found] ` <1272439752-4021-1-git-send-email-christofferdall-77OGu6e99YhyO3AAkE1OcX9LOBIZ5rWg@public.gmane.org>
2010-04-30 9:42 ` Christoffer Dall
[not found] <1269220484-24279-1-git-send-email-christofferdall@christofferdall.dk>
[not found] ` <1269220484-24279-1-git-send-email-christofferdall-77OGu6e99YhyO3AAkE1OcX9LOBIZ5rWg@public.gmane.org>
2010-04-29 23:33 ` Matt Helsley
2010-06-20 21:34 ` Oren Laadan
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.