From: Peter Maydell Date: Tue, 16 Jul 2013 17:44:57 +0000 (+0100) Subject: linux-user: Clean up handling of clone() argument order X-Git-Tag: v1.6.0-rc0~61^2~11 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=4ce6243dc6216e35b5b691078ffa856463bfa8db;p=thirdparty%2Fqemu.git linux-user: Clean up handling of clone() argument order 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 Signed-off-by: Riku Voipio --- diff --git a/linux-user/arm/syscall.h b/linux-user/arm/syscall.h index 003d4247017..73f29314f68 100644 --- a/linux-user/arm/syscall.h +++ b/linux-user/arm/syscall.h @@ -40,3 +40,5 @@ struct target_pt_regs { #else #define UNAME_MACHINE "armv5tel" #endif + +#define TARGET_CLONE_BACKWARDS diff --git a/linux-user/cris/syscall.h b/linux-user/cris/syscall.h index 50e50b4f3f2..832ee64bd83 100644 --- a/linux-user/cris/syscall.h +++ b/linux-user/cris/syscall.h @@ -38,4 +38,6 @@ struct target_pt_regs { unsigned long eda; }; +#define TARGET_CLONE_BACKWARDS2 + #endif diff --git a/linux-user/i386/syscall.h b/linux-user/i386/syscall.h index 266e2c4c83f..12b8c3b6729 100644 --- a/linux-user/i386/syscall.h +++ b/linux-user/i386/syscall.h @@ -144,3 +144,5 @@ struct target_vm86plus_struct { }; #define UNAME_MACHINE "i686" + +#define TARGET_CLONE_BACKWARDS diff --git a/linux-user/microblaze/syscall.h b/linux-user/microblaze/syscall.h index c3e5c55b3d4..d550989d5e4 100644 --- a/linux-user/microblaze/syscall.h +++ b/linux-user/microblaze/syscall.h @@ -48,4 +48,6 @@ struct target_pt_regs { uint32_t kernel_mode; }; +#define TARGET_CLONE_BACKWARDS + #endif diff --git a/linux-user/mips/syscall.h b/linux-user/mips/syscall.h index 3deb862cc4f..9d437d918bd 100644 --- a/linux-user/mips/syscall.h +++ b/linux-user/mips/syscall.h @@ -225,3 +225,5 @@ struct target_pt_regs { #define TARGET_QEMU_ESIGRETURN 255 #define UNAME_MACHINE "mips" + +#define TARGET_CLONE_BACKWARDS diff --git a/linux-user/mips64/syscall.h b/linux-user/mips64/syscall.h index cd707df32f3..1710f766e26 100644 --- a/linux-user/mips64/syscall.h +++ b/linux-user/mips64/syscall.h @@ -222,3 +222,5 @@ struct target_pt_regs { #define TARGET_QEMU_ESIGRETURN 255 #define UNAME_MACHINE "mips64" + +#define TARGET_CLONE_BACKWARDS diff --git a/linux-user/ppc/syscall.h b/linux-user/ppc/syscall.h index 481047b2dd6..ba36acbc337 100644 --- a/linux-user/ppc/syscall.h +++ b/linux-user/ppc/syscall.h @@ -62,3 +62,5 @@ struct target_revectored_struct { #else #define UNAME_MACHINE "ppc" #endif + +#define TARGET_CLONE_BACKWARDS diff --git a/linux-user/s390x/syscall.h b/linux-user/s390x/syscall.h index e4603b79c3d..ea8c3048405 100644 --- a/linux-user/s390x/syscall.h +++ b/linux-user/s390x/syscall.h @@ -21,3 +21,5 @@ struct target_pt_regs { }; #define UNAME_MACHINE "s390x" + +#define TARGET_CLONE_BACKWARDS diff --git a/linux-user/sparc/syscall.h b/linux-user/sparc/syscall.h index 5a9bb7e5469..4cd64bf41dd 100644 --- a/linux-user/sparc/syscall.h +++ b/linux-user/sparc/syscall.h @@ -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 diff --git a/linux-user/sparc64/syscall.h b/linux-user/sparc64/syscall.h index 81a816de94a..e60bf311c02 100644 --- a/linux-user/sparc64/syscall.h +++ b/linux-user/sparc64/syscall.h @@ -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 diff --git a/linux-user/syscall.c b/linux-user/syscall.c index 642d0a36207..b167d7f3aed 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -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