Skip to content

Commit

Permalink
linux-user: Clean up handling of clone() argument order
Browse files Browse the repository at this point in the history
Linux manages to have three separate orderings of the arguments to
the clone() syscall on different architectures. In the kernel these
are selected via CONFIG_CLONE_BACKWARDS and CONFIG_CLONE_BACKWARDS2.
Clean up our implementation of this to use similar #define names
rather than a TARGET_* ifdef ladder.

This includes behaviour changes fixing bugs on cris, x86-64, m68k,
openrisc and unicore32.  cris had explicit but wrong handling; the
others were just incorrectly using QEMU's default, which happened
to be the equivalent of CONFIG_CLONE_BACKWARDS. (unicore32 appears
to be broken in the mainline kernel in that it tries to use arg3 for
both parent_tidptr and newtls simultaneously -- we don't attempt
to emulate this bug...)

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Riku Voipio <riku.voipio@linaro.org>
  • Loading branch information
pm215 authored and Riku Voipio committed Jul 22, 2013
1 parent d312bbe commit 4ce6243
Show file tree
Hide file tree
Showing 11 changed files with 41 additions and 7 deletions.
2 changes: 2 additions & 0 deletions linux-user/arm/syscall.h
Expand Up @@ -40,3 +40,5 @@ struct target_pt_regs {
#else
#define UNAME_MACHINE "armv5tel"
#endif

#define TARGET_CLONE_BACKWARDS
2 changes: 2 additions & 0 deletions linux-user/cris/syscall.h
Expand Up @@ -38,4 +38,6 @@ struct target_pt_regs {
unsigned long eda;
};

#define TARGET_CLONE_BACKWARDS2

#endif
2 changes: 2 additions & 0 deletions linux-user/i386/syscall.h
Expand Up @@ -144,3 +144,5 @@ struct target_vm86plus_struct {
};

#define UNAME_MACHINE "i686"

#define TARGET_CLONE_BACKWARDS
2 changes: 2 additions & 0 deletions linux-user/microblaze/syscall.h
Expand Up @@ -48,4 +48,6 @@ struct target_pt_regs {
uint32_t kernel_mode;
};

#define TARGET_CLONE_BACKWARDS

#endif
2 changes: 2 additions & 0 deletions linux-user/mips/syscall.h
Expand Up @@ -225,3 +225,5 @@ struct target_pt_regs {
#define TARGET_QEMU_ESIGRETURN 255

#define UNAME_MACHINE "mips"

#define TARGET_CLONE_BACKWARDS
2 changes: 2 additions & 0 deletions linux-user/mips64/syscall.h
Expand Up @@ -222,3 +222,5 @@ struct target_pt_regs {
#define TARGET_QEMU_ESIGRETURN 255

#define UNAME_MACHINE "mips64"

#define TARGET_CLONE_BACKWARDS
2 changes: 2 additions & 0 deletions linux-user/ppc/syscall.h
Expand Up @@ -62,3 +62,5 @@ struct target_revectored_struct {
#else
#define UNAME_MACHINE "ppc"
#endif

#define TARGET_CLONE_BACKWARDS
2 changes: 2 additions & 0 deletions linux-user/s390x/syscall.h
Expand Up @@ -21,3 +21,5 @@ struct target_pt_regs {
};

#define UNAME_MACHINE "s390x"

#define TARGET_CLONE_BACKWARDS
7 changes: 7 additions & 0 deletions linux-user/sparc/syscall.h
Expand Up @@ -7,3 +7,10 @@ struct target_pt_regs {
};

#define UNAME_MACHINE "sun4"

/* SPARC kernels don't define this in their Kconfig, but they have the
* same ABI as if they did, implemented by sparc-specific code which fishes
* directly in the u_regs() struct for half the parameters in sparc_do_fork()
* and copy_thread().
*/
#define TARGET_CLONE_BACKWARDS
7 changes: 7 additions & 0 deletions linux-user/sparc64/syscall.h
Expand Up @@ -8,3 +8,10 @@ struct target_pt_regs {
};

#define UNAME_MACHINE "sun4u"

/* SPARC kernels don't define this in their Kconfig, but they have the
* same ABI as if they did, implemented by sparc-specific code which fishes
* directly in the u_regs() struct for half the parameters in sparc_do_fork()
* and copy_thread().
*/
#define TARGET_CLONE_BACKWARDS
18 changes: 11 additions & 7 deletions linux-user/syscall.c
Expand Up @@ -6956,16 +6956,20 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
ret = get_errno(fsync(arg1));
break;
case TARGET_NR_clone:
#if defined(TARGET_SH4) || defined(TARGET_ALPHA)
ret = get_errno(do_fork(cpu_env, arg1, arg2, arg3, arg5, arg4));
#elif defined(TARGET_CRIS)
ret = get_errno(do_fork(cpu_env, arg2, arg1, arg3, arg4, arg5));
#elif defined(TARGET_MICROBLAZE)
/* Linux manages to have three different orderings for its
* arguments to clone(); the BACKWARDS and BACKWARDS2 defines
* match the kernel's CONFIG_CLONE_* settings.
* Microblaze is further special in that it uses a sixth
* implicit argument to clone for the TLS pointer.
*/
#if defined(TARGET_MICROBLAZE)
ret = get_errno(do_fork(cpu_env, arg1, arg2, arg4, arg6, arg5));
#elif defined(TARGET_S390X)
#elif defined(TARGET_CLONE_BACKWARDS)
ret = get_errno(do_fork(cpu_env, arg1, arg2, arg3, arg4, arg5));
#elif defined(TARGET_CLONE_BACKWARDS2)
ret = get_errno(do_fork(cpu_env, arg2, arg1, arg3, arg5, arg4));
#else
ret = get_errno(do_fork(cpu_env, arg1, arg2, arg3, arg4, arg5));
ret = get_errno(do_fork(cpu_env, arg1, arg2, arg3, arg5, arg4));
#endif
break;
#ifdef __NR_exit_group
Expand Down

0 comments on commit 4ce6243

Please sign in to comment.