This is the mail archive of the libc-ports@sources.redhat.com mailing list for the libc-ports project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [PATCH] ARM: Added user space support for c/r on ARM


On Wed, Apr 28, 2010 at 8:29 AM, Christoffer Dall
<christofferdall@christofferdall.dk> 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
>
>


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]