From aa004f5f9c5785273ef56b8c0b775f57ccb19168 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Tue, 16 Jul 2013 18:44:48 +0100 Subject: [PATCH 01/21] configure: Flip default of target_nptl Most targets either (a) support threading or (b) don't have a linux-user/bsd-user target, so make it default to 'yes', with those targets that don't support threading having to specifically say so. This is a mechanical no-behaviour-change commit; some of the "no" entries it adds will be taken out in later patches. Signed-off-by: Peter Maydell Reviewed-by: Richard Henderson Signed-off-by: Riku Voipio --- configure | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/configure b/configure index 7c45db2fdd..983f4d5b5d 100755 --- a/configure +++ b/configure @@ -4180,7 +4180,7 @@ mkdir -p $target_dir echo "# Automatically generated by configure - do not modify" > $config_target_mak bflt="no" -target_nptl="no" +target_nptl="yes" interp_prefix1=`echo "$interp_prefix" | sed "s/%M/$target_name/g"` gdb_xml_files="" @@ -4190,69 +4190,71 @@ TARGET_ABI_DIR="" case "$target_name" in i386) + target_nptl="no" ;; x86_64) TARGET_BASE_ARCH=i386 + target_nptl="no" ;; alpha) - target_nptl="yes" ;; arm|armeb) TARGET_ARCH=arm bflt="yes" - target_nptl="yes" gdb_xml_files="arm-core.xml arm-vfp.xml arm-vfp3.xml arm-neon.xml" ;; cris) - target_nptl="yes" ;; lm32) + target_nptl="no" ;; m68k) bflt="yes" gdb_xml_files="cf-core.xml cf-fp.xml" + target_nptl="no" ;; microblaze|microblazeel) TARGET_ARCH=microblaze bflt="yes" - target_nptl="yes" ;; mips|mipsel) TARGET_ARCH=mips echo "TARGET_ABI_MIPSO32=y" >> $config_target_mak - target_nptl="yes" ;; mipsn32|mipsn32el) TARGET_ARCH=mips64 TARGET_BASE_ARCH=mips echo "TARGET_ABI_MIPSN32=y" >> $config_target_mak echo "TARGET_ABI32=y" >> $config_target_mak + target_nptl="no" ;; mips64|mips64el) TARGET_ARCH=mips64 TARGET_BASE_ARCH=mips echo "TARGET_ABI_MIPSN64=y" >> $config_target_mak + target_nptl="no" ;; moxie) + target_nptl="no" ;; or32) TARGET_ARCH=openrisc TARGET_BASE_ARCH=openrisc + target_nptl="no" ;; ppc) gdb_xml_files="power-core.xml power-fpu.xml power-altivec.xml power-spe.xml" - target_nptl="yes" ;; ppcemb) TARGET_BASE_ARCH=ppc TARGET_ABI_DIR=ppc gdb_xml_files="power-core.xml power-fpu.xml power-altivec.xml power-spe.xml" - target_nptl="yes" ;; ppc64) TARGET_BASE_ARCH=ppc TARGET_ABI_DIR=ppc gdb_xml_files="power64-core.xml power-fpu.xml power-altivec.xml power-spe.xml" + target_nptl="no" ;; ppc64abi32) TARGET_ARCH=ppc64 @@ -4260,30 +4262,34 @@ case "$target_name" in TARGET_ABI_DIR=ppc echo "TARGET_ABI32=y" >> $config_target_mak gdb_xml_files="power64-core.xml power-fpu.xml power-altivec.xml power-spe.xml" + target_nptl="no" ;; sh4|sh4eb) TARGET_ARCH=sh4 bflt="yes" - target_nptl="yes" ;; sparc) + target_nptl="no" ;; sparc64) TARGET_BASE_ARCH=sparc + target_nptl="no" ;; sparc32plus) TARGET_ARCH=sparc64 TARGET_BASE_ARCH=sparc TARGET_ABI_DIR=sparc echo "TARGET_ABI32=y" >> $config_target_mak + target_nptl="no" ;; s390x) - target_nptl="yes" ;; unicore32) + target_nptl="no" ;; xtensa|xtensaeb) TARGET_ARCH=xtensa + target_nptl="no" ;; *) error_exit "Unsupported target CPU" From fa78f3dbe4e0e1d9a34556b73e5118cb40153875 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Tue, 16 Jul 2013 18:44:49 +0100 Subject: [PATCH 02/21] configure: Don't say target_nptl="no" if there is no linux-user target For architectures with no linux-user target, don't claim no NPTL support. This has no behavioural change, but it means that we won't accidentally add a new linux-user target without threading support in future (because attempting to do so would be a compile failure rather than a silent lack of support). Signed-off-by: Peter Maydell Reviewed-by: Richard Henderson Signed-off-by: Riku Voipio --- configure | 3 --- 1 file changed, 3 deletions(-) diff --git a/configure b/configure index 983f4d5b5d..3792607c3b 100755 --- a/configure +++ b/configure @@ -4206,7 +4206,6 @@ case "$target_name" in cris) ;; lm32) - target_nptl="no" ;; m68k) bflt="yes" @@ -4235,7 +4234,6 @@ case "$target_name" in target_nptl="no" ;; moxie) - target_nptl="no" ;; or32) TARGET_ARCH=openrisc @@ -4289,7 +4287,6 @@ case "$target_name" in ;; xtensa|xtensaeb) TARGET_ARCH=xtensa - target_nptl="no" ;; *) error_exit "Unsupported target CPU" From d769c64147d32a80e5e37d41b397f45943d45e0d Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Tue, 16 Jul 2013 18:44:50 +0100 Subject: [PATCH 03/21] configure: Enable threading on all ppc and mips linux-user targets Though threading (target_nptl) was enabled on the base PPC and MIPS targets, it wasn't enabled for the variants mipsn32, mipsn32el, mips64, mips64el, ppc64 or ppc46abi32 (probably an oversight). Enable threading consistently on all these targets. Signed-off-by: Peter Maydell Reviewed-by: Richard Henderson Reviewed-by: Richard Henderson Signed-off-by: Riku Voipio --- configure | 4 ---- 1 file changed, 4 deletions(-) diff --git a/configure b/configure index 3792607c3b..9b7101cb60 100755 --- a/configure +++ b/configure @@ -4225,13 +4225,11 @@ case "$target_name" in TARGET_BASE_ARCH=mips echo "TARGET_ABI_MIPSN32=y" >> $config_target_mak echo "TARGET_ABI32=y" >> $config_target_mak - target_nptl="no" ;; mips64|mips64el) TARGET_ARCH=mips64 TARGET_BASE_ARCH=mips echo "TARGET_ABI_MIPSN64=y" >> $config_target_mak - target_nptl="no" ;; moxie) ;; @@ -4252,7 +4250,6 @@ case "$target_name" in TARGET_BASE_ARCH=ppc TARGET_ABI_DIR=ppc gdb_xml_files="power64-core.xml power-fpu.xml power-altivec.xml power-spe.xml" - target_nptl="no" ;; ppc64abi32) TARGET_ARCH=ppc64 @@ -4260,7 +4257,6 @@ case "$target_name" in TARGET_ABI_DIR=ppc echo "TARGET_ABI32=y" >> $config_target_mak gdb_xml_files="power64-core.xml power-fpu.xml power-altivec.xml power-spe.xml" - target_nptl="no" ;; sh4|sh4eb) TARGET_ARCH=sh4 From 790d440605a997a5e146809e824e95ca22a14652 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Tue, 16 Jul 2013 18:44:51 +0100 Subject: [PATCH 04/21] configure: Enable threading for unicore32-linux-user unicore32-linux-user provides cpu_set_tls(), so the failure to enable target_nptl was presumably an oversight. Enable it. Signed-off-by: Peter Maydell Reviewed-by: Richard Henderson Signed-off-by: Riku Voipio --- configure | 1 - 1 file changed, 1 deletion(-) diff --git a/configure b/configure index 9b7101cb60..0b19408458 100755 --- a/configure +++ b/configure @@ -4279,7 +4279,6 @@ case "$target_name" in s390x) ;; unicore32) - target_nptl="no" ;; xtensa|xtensaeb) TARGET_ARCH=xtensa From dfeab06c98f7bc37f8ad8a6a2f8f677e5a57a55d Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Tue, 16 Jul 2013 18:44:52 +0100 Subject: [PATCH 05/21] linux-user: Move includes of target-specific headers to end of qemu.h The target-specific headers (target_cpu.h and target_signal.h) might need to use the target-independent structure and function definitions of qemu.h; so include them only at the bottom of qemu.h, not the top. Signed-off-by: Peter Maydell Reviewed-by: Richard Henderson Signed-off-by: Riku Voipio --- linux-user/qemu.h | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/linux-user/qemu.h b/linux-user/qemu.h index 6569608b64..8c420da5c7 100644 --- a/linux-user/qemu.h +++ b/linux-user/qemu.h @@ -16,8 +16,6 @@ #include "exec/user/thunk.h" #include "syscall_defs.h" #include "syscall.h" -#include "target_cpu.h" -#include "target_signal.h" #include "exec/gdbstub.h" #include "qemu/queue.h" @@ -454,4 +452,11 @@ static inline void *lock_user_string(abi_ulong guest_addr) #include #endif +/* Include target-specific struct and function definitions; + * they may need access to the target-independent structures + * above, so include them last. + */ +#include "target_cpu.h" +#include "target_signal.h" + #endif /* QEMU_H */ From 442a59c8ddc55f327ec0219d810fe4580177716a Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Tue, 16 Jul 2013 18:44:53 +0100 Subject: [PATCH 06/21] linux-user: Enable NPTL for OpenRISC The OpenRISC kernel ignores CLONE_SETTLS in its copy_thread() implementation, so a cpu_set_tls() implementation is a no-op. cpu_clone_regs() was setting the syscall return value in the wrong register -- it is gpr[11], not gpr[2]. With these two things fixed, we can compile with NPTL enabled. Signed-off-by: Peter Maydell Reviewed-by: Jia Liu Signed-off-by: Riku Voipio --- configure | 1 - linux-user/openrisc/target_cpu.h | 9 +++++++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/configure b/configure index 0b19408458..bfad34e327 100755 --- a/configure +++ b/configure @@ -4236,7 +4236,6 @@ case "$target_name" in or32) TARGET_ARCH=openrisc TARGET_BASE_ARCH=openrisc - target_nptl="no" ;; ppc) gdb_xml_files="power-core.xml power-fpu.xml power-altivec.xml power-spe.xml" diff --git a/linux-user/openrisc/target_cpu.h b/linux-user/openrisc/target_cpu.h index 501fb81162..32a46ac840 100644 --- a/linux-user/openrisc/target_cpu.h +++ b/linux-user/openrisc/target_cpu.h @@ -25,9 +25,14 @@ static inline void cpu_clone_regs(CPUOpenRISCState *env, target_ulong newsp) if (newsp) { env->gpr[1] = newsp; } - env->gpr[2] = 0; + env->gpr[11] = 0; } -/* TODO: need to implement cpu_set_tls() */ +static inline void cpu_set_tls(CPUOpenRISCState *env, target_ulong newtls) +{ + /* Linux kernel 3.10 does not pay any attention to CLONE_SETTLS + * in copy_thread(), so QEMU need not do so either. + */ +} #endif From f5147c93d0e7f91df0215598017a4d9d6a48f0ee Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Tue, 16 Jul 2013 18:44:54 +0100 Subject: [PATCH 07/21] linux-user: Enable NPTL for SPARC targets Provide the missing cpu_set_tls(), and resolve the FIXME in cpu_clone_regs() by clearing the carry flag for the child. This allows us to turn on building with NPTL for SPARC. Signed-off-by: Peter Maydell Reviewed-by: Richard Henderson Signed-off-by: Riku Voipio --- configure | 3 --- linux-user/sparc/target_cpu.h | 16 ++++++++++++---- 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/configure b/configure index bfad34e327..ab3dc3cbca 100755 --- a/configure +++ b/configure @@ -4262,18 +4262,15 @@ case "$target_name" in bflt="yes" ;; sparc) - target_nptl="no" ;; sparc64) TARGET_BASE_ARCH=sparc - target_nptl="no" ;; sparc32plus) TARGET_ARCH=sparc64 TARGET_BASE_ARCH=sparc TARGET_ABI_DIR=sparc echo "TARGET_ABI32=y" >> $config_target_mak - target_nptl="no" ;; s390x) ;; diff --git a/linux-user/sparc/target_cpu.h b/linux-user/sparc/target_cpu.h index 5a620a2bb7..4944d465a2 100644 --- a/linux-user/sparc/target_cpu.h +++ b/linux-user/sparc/target_cpu.h @@ -25,12 +25,20 @@ static inline void cpu_clone_regs(CPUSPARCState *env, target_ulong newsp) if (newsp) { env->regwptr[22] = newsp; } + /* syscall return for clone child: 0, and clear CF since + * this counts as a success return value. + */ env->regwptr[0] = 0; - /* FIXME: Do we also need to clear CF? */ - /* XXXXX */ - printf("HELPME: %s:%d\n", __FILE__, __LINE__); +#if defined(TARGET_SPARC64) && !defined(TARGET_ABI32) + env->xcc &= ~PSR_CARRY; +#else + env->psr &= ~PSR_CARRY; +#endif } -/* TODO: need to implement cpu_set_tls() */ +static inline void cpu_set_tls(CPUSPARCState *env, target_ulong newtls) +{ + env->gregs[7] = newtls; +} #endif From 1ccd9374af22ec4ed5f864d4935a9cfad01f1204 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Tue, 16 Jul 2013 18:44:55 +0100 Subject: [PATCH 08/21] linux-user: Enable NPTL for m68k For m68k, per-thread data is a purely kernel construct with no CPU level support. Implement it via a field in the TaskState structure, used by cpu_set_tls() and the set_thread_area/get_thread_area syscalls. This allows us to enable compilation with NPTL. Signed-off-by: Peter Maydell Reviewed-by: Laurent Vivier Signed-off-by: Riku Voipio --- configure | 1 - linux-user/m68k/target_cpu.h | 6 +++++- linux-user/qemu.h | 1 + linux-user/syscall.c | 12 ++++++++++++ 4 files changed, 18 insertions(+), 2 deletions(-) diff --git a/configure b/configure index ab3dc3cbca..f065edc8bb 100755 --- a/configure +++ b/configure @@ -4210,7 +4210,6 @@ case "$target_name" in m68k) bflt="yes" gdb_xml_files="cf-core.xml cf-fp.xml" - target_nptl="no" ;; microblaze|microblazeel) TARGET_ARCH=microblaze diff --git a/linux-user/m68k/target_cpu.h b/linux-user/m68k/target_cpu.h index 8a2a305a0b..cad9c90dd0 100644 --- a/linux-user/m68k/target_cpu.h +++ b/linux-user/m68k/target_cpu.h @@ -29,6 +29,10 @@ static inline void cpu_clone_regs(CPUM68KState *env, target_ulong newsp) env->dregs[0] = 0; } -/* TODO: need to implement cpu_set_tls() */ +static inline void cpu_set_tls(CPUM68KState *env, target_ulong newtls) +{ + TaskState *ts = env->opaque; + ts->tp_value = newtls; +} #endif diff --git a/linux-user/qemu.h b/linux-user/qemu.h index 8c420da5c7..1ff0fa8b12 100644 --- a/linux-user/qemu.h +++ b/linux-user/qemu.h @@ -121,6 +121,7 @@ typedef struct TaskState { #endif #ifdef TARGET_M68K int sim_syscalls; + abi_ulong tp_value; #endif #if defined(TARGET_ARM) || defined(TARGET_M68K) || defined(TARGET_UNICORE32) /* Extra fields for semihosted binaries. */ diff --git a/linux-user/syscall.c b/linux-user/syscall.c index 00a0390ea9..9619656d3c 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -8558,6 +8558,12 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, #elif defined(TARGET_I386) && defined(TARGET_ABI32) ret = do_set_thread_area(cpu_env, arg1); break; +#elif defined(TARGET_M68K) + { + TaskState *ts = ((CPUArchState *)cpu_env)->opaque; + ts->tp_value = arg1; + break; + } #else goto unimplemented_nowarn; #endif @@ -8566,6 +8572,12 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, case TARGET_NR_get_thread_area: #if defined(TARGET_I386) && defined(TARGET_ABI32) ret = do_get_thread_area(cpu_env, arg1); +#elif defined(TARGET_M68K) + { + TaskState *ts = ((CPUArchState *)cpu_env)->opaque; + ret = ts->tp_value; + break; + } #else goto unimplemented_nowarn; #endif From d312bbe1051fa563b557de625ca57a466772abe5 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Tue, 16 Jul 2013 18:44:56 +0100 Subject: [PATCH 09/21] linux-user: Add missing 'break' in i386 get_thread_area syscall The i386 code for the get_thread_area syscall was missing a 'break' which meant it would have fallen through into the implementation of the following syscall; add it. Signed-off-by: Peter Maydell Reviewed-by: Richard Henderson Signed-off-by: Riku Voipio --- linux-user/syscall.c | 1 + 1 file changed, 1 insertion(+) diff --git a/linux-user/syscall.c b/linux-user/syscall.c index 9619656d3c..642d0a3620 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -8572,6 +8572,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, case TARGET_NR_get_thread_area: #if defined(TARGET_I386) && defined(TARGET_ABI32) ret = do_get_thread_area(cpu_env, arg1); + break; #elif defined(TARGET_M68K) { TaskState *ts = ((CPUArchState *)cpu_env)->opaque; From 4ce6243dc6216e35b5b691078ffa856463bfa8db Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Tue, 16 Jul 2013 18:44:57 +0100 Subject: [PATCH 10/21] 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 --- linux-user/arm/syscall.h | 2 ++ linux-user/cris/syscall.h | 2 ++ linux-user/i386/syscall.h | 2 ++ linux-user/microblaze/syscall.h | 2 ++ linux-user/mips/syscall.h | 2 ++ linux-user/mips64/syscall.h | 2 ++ linux-user/ppc/syscall.h | 2 ++ linux-user/s390x/syscall.h | 2 ++ linux-user/sparc/syscall.h | 7 +++++++ linux-user/sparc64/syscall.h | 7 +++++++ linux-user/syscall.c | 18 +++++++++++------- 11 files changed, 41 insertions(+), 7 deletions(-) diff --git a/linux-user/arm/syscall.h b/linux-user/arm/syscall.h index 003d424701..73f29314f6 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 50e50b4f3f..832ee64bd8 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 266e2c4c83..12b8c3b672 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 c3e5c55b3d..d550989d5e 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 3deb862cc4..9d437d918b 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 cd707df32f..1710f766e2 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 481047b2dd..ba36acbc33 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 e4603b79c3..ea8c304840 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 5a9bb7e546..4cd64bf41d 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 81a816de94..e60bf311c0 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 642d0a3620..b167d7f3ae 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 From bc22eb447c0552e2327f278fdc6bedccb14fc7a3 Mon Sep 17 00:00:00 2001 From: Alexander Graf Date: Tue, 16 Jul 2013 18:44:58 +0100 Subject: [PATCH 11/21] linux-user: Add i386 TLS setter We can easily set the TLS on i386. Add code to do so. Signed-off-by: Alexander Graf [PMM: also remove "target_nptl=no" line from configure, for consistency with other patches in this series] Signed-off-by: Peter Maydell Signed-off-by: Riku Voipio --- configure | 1 - linux-user/i386/target_cpu.h | 12 ++++++++++-- linux-user/syscall.c | 2 +- 3 files changed, 11 insertions(+), 4 deletions(-) diff --git a/configure b/configure index f065edc8bb..547297bfb4 100755 --- a/configure +++ b/configure @@ -4190,7 +4190,6 @@ TARGET_ABI_DIR="" case "$target_name" in i386) - target_nptl="no" ;; x86_64) TARGET_BASE_ARCH=i386 diff --git a/linux-user/i386/target_cpu.h b/linux-user/i386/target_cpu.h index abcac79d25..1170d84c41 100644 --- a/linux-user/i386/target_cpu.h +++ b/linux-user/i386/target_cpu.h @@ -28,6 +28,14 @@ static inline void cpu_clone_regs(CPUX86State *env, target_ulong newsp) env->regs[R_EAX] = 0; } -/* TODO: need to implement cpu_set_tls() */ +#if defined(TARGET_ABI32) +abi_long do_set_thread_area(CPUX86State *env, abi_ulong ptr); -#endif +static inline void cpu_set_tls(CPUX86State *env, target_ulong newtls) +{ + do_set_thread_area(env, newtls); + cpu_x86_load_seg(env, R_GS, env->segs[R_GS].selector); +} +#endif /* defined(TARGET_ABI32) */ + +#endif /* !defined(TARGET_CPU_H) */ diff --git a/linux-user/syscall.c b/linux-user/syscall.c index b167d7f3ae..452b89df8d 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -4055,7 +4055,7 @@ static abi_long do_modify_ldt(CPUX86State *env, int func, abi_ulong ptr, } #if defined(TARGET_I386) && defined(TARGET_ABI32) -static abi_long do_set_thread_area(CPUX86State *env, abi_ulong ptr) +abi_long do_set_thread_area(CPUX86State *env, abi_ulong ptr) { uint64_t *gdt_table = g2h(env->gdt.base); struct target_modify_ldt_ldt_s ldt_info; From 2667e71c3d9262d756bea1473e2ea28eb2c9c070 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Tue, 16 Jul 2013 18:44:59 +0100 Subject: [PATCH 12/21] linux-user: Enable NPTL for x86-64 Add x86-64 implementation of cpu_set_tls() (like the kernel, we just have to call do_arch_prctl() to set FS); this allows us to enable NPTL. Signed-off-by: Peter Maydell Signed-off-by: Riku Voipio --- configure | 1 - linux-user/i386/target_cpu.h | 7 +++++++ linux-user/syscall.c | 2 +- 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/configure b/configure index 547297bfb4..999b2ced23 100755 --- a/configure +++ b/configure @@ -4193,7 +4193,6 @@ case "$target_name" in ;; x86_64) TARGET_BASE_ARCH=i386 - target_nptl="no" ;; alpha) ;; diff --git a/linux-user/i386/target_cpu.h b/linux-user/i386/target_cpu.h index 1170d84c41..58f86454d6 100644 --- a/linux-user/i386/target_cpu.h +++ b/linux-user/i386/target_cpu.h @@ -36,6 +36,13 @@ static inline void cpu_set_tls(CPUX86State *env, target_ulong newtls) do_set_thread_area(env, newtls); cpu_x86_load_seg(env, R_GS, env->segs[R_GS].selector); } +#else +abi_long do_arch_prctl(CPUX86State *env, int code, abi_ulong addr); + +static inline void cpu_set_tls(CPUX86State *env, target_ulong newtls) +{ + do_arch_prctl(env, TARGET_ARCH_SET_FS, newtls); +} #endif /* defined(TARGET_ABI32) */ #endif /* !defined(TARGET_CPU_H) */ diff --git a/linux-user/syscall.c b/linux-user/syscall.c index 452b89df8d..d3b3590e8d 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -4189,7 +4189,7 @@ static abi_long do_get_thread_area(CPUX86State *env, abi_ulong ptr) #endif /* TARGET_I386 && TARGET_ABI32 */ #ifndef TARGET_ABI32 -static abi_long do_arch_prctl(CPUX86State *env, int code, abi_ulong addr) +abi_long do_arch_prctl(CPUX86State *env, int code, abi_ulong addr) { abi_long ret = 0; abi_ulong val; From 24cb36a61c663d98a53338620e88e4cd3403459a Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Tue, 16 Jul 2013 18:45:00 +0100 Subject: [PATCH 13/21] configure: Make NPTL non-optional Now all linux-user targets support building with NPTL, we can make it mandatory. This is a good idea because: * NPTL is no longer new and experimental; it is completely standard * in practice, linux-user without NPTL is nearly useless for binaries built against non-ancient glibc * it allows us to delete the rather untested code for handling the non-NPTL configuration Note that this patch leaves the CONFIG_USE_NPTL ifdefs in the bsd-user codebase alone. This makes no change for bsd-user, since our configure test for NPTL had a "#include " which means bsd-user would never have been compiled with CONFIG_USE_NPTL defined, and it still is not. Signed-off-by: Peter Maydell Reviewed-by: Richard Henderson Signed-off-by: Riku Voipio --- configure | 25 +++------------------- include/exec/gdbstub.h | 2 +- linux-user/main.c | 43 -------------------------------------- linux-user/mmap.c | 11 ---------- linux-user/qemu.h | 10 --------- linux-user/syscall.c | 47 +----------------------------------------- 6 files changed, 5 insertions(+), 133 deletions(-) diff --git a/configure b/configure index 999b2ced23..9d9088ebd6 100755 --- a/configure +++ b/configure @@ -155,7 +155,6 @@ curl="" curses="" docs="" fdt="" -nptl="" pixman="" sdl="" virtfs="" @@ -855,10 +854,6 @@ for opt do ;; --enable-fdt) fdt="yes" ;; - --disable-nptl) nptl="no" - ;; - --enable-nptl) nptl="yes" - ;; --enable-mixemu) mixemu="yes" ;; --disable-linux-aio) linux_aio="no" @@ -1096,8 +1091,6 @@ echo " --disable-slirp disable SLIRP userspace network connectivity" echo " --disable-kvm disable KVM acceleration support" echo " --enable-kvm enable KVM acceleration support" echo " --enable-tcg-interpreter enable TCG with bytecode interpreter (TCI)" -echo " --disable-nptl disable usermode NPTL support" -echo " --enable-nptl enable usermode NPTL support" echo " --enable-system enable all system emulation targets" echo " --disable-system disable all system emulation targets" echo " --enable-user enable supported user emulation targets" @@ -1432,7 +1425,7 @@ fi ########################################## # NPTL probe -if test "$nptl" != "no" ; then +if test "$linux_user" = "yes"; then cat > $TMPC < #include @@ -1443,14 +1436,8 @@ int main(void) { return 0; } EOF - - if compile_object ; then - nptl=yes - else - if test "$nptl" = "yes" ; then - feature_not_found "nptl" - fi - nptl=no + if ! compile_object ; then + feature_not_found "nptl" fi fi @@ -3550,7 +3537,6 @@ echo "bluez support $bluez" echo "Documentation $docs" [ ! -z "$uname_release" ] && \ echo "uname -r $uname_release" -echo "NPTL support $nptl" echo "GUEST_BASE $guest_base" echo "PIE $pie" echo "vde support $vde" @@ -4180,7 +4166,6 @@ mkdir -p $target_dir echo "# Automatically generated by configure - do not modify" > $config_target_mak bflt="no" -target_nptl="yes" interp_prefix1=`echo "$interp_prefix" | sed "s/%M/$target_name/g"` gdb_xml_files="" @@ -4351,10 +4336,6 @@ fi if test "$target_user_only" = "yes" -a "$bflt" = "yes"; then echo "TARGET_HAS_BFLT=y" >> $config_target_mak fi -if test "$target_user_only" = "yes" \ - -a "$nptl" = "yes" -a "$target_nptl" = "yes"; then - echo "CONFIG_USE_NPTL=y" >> $config_target_mak -fi if test "$target_user_only" = "yes" -a "$guest_base" = "yes"; then echo "CONFIG_USE_GUEST_BASE=y" >> $config_target_mak fi diff --git a/include/exec/gdbstub.h b/include/exec/gdbstub.h index ded4160e57..8065f40a60 100644 --- a/include/exec/gdbstub.h +++ b/include/exec/gdbstub.h @@ -32,7 +32,7 @@ void gdb_register_coprocessor(CPUArchState *env, static inline int cpu_index(CPUState *cpu) { -#if defined(CONFIG_USER_ONLY) && defined(CONFIG_USE_NPTL) +#if defined(CONFIG_USER_ONLY) return cpu->host_tid; #else return cpu->cpu_index + 1; diff --git a/linux-user/main.c b/linux-user/main.c index 99c3b3f5ef..5537967254 100644 --- a/linux-user/main.c +++ b/linux-user/main.c @@ -92,7 +92,6 @@ int cpu_get_pic_interrupt(CPUX86State *env) } #endif -#if defined(CONFIG_USE_NPTL) /***********************************************************/ /* Helper routines for implementing atomic operations. */ @@ -207,43 +206,6 @@ void cpu_list_unlock(void) { pthread_mutex_unlock(&cpu_list_mutex); } -#else /* if !CONFIG_USE_NPTL */ -/* These are no-ops because we are not threadsafe. */ -static inline void cpu_exec_start(CPUState *cpu) -{ -} - -static inline void cpu_exec_end(CPUState *cpu) -{ -} - -static inline void start_exclusive(void) -{ -} - -static inline void end_exclusive(void) -{ -} - -void fork_start(void) -{ -} - -void fork_end(int child) -{ - if (child) { - gdbserver_fork((CPUArchState *)thread_cpu->env_ptr); - } -} - -void cpu_list_lock(void) -{ -} - -void cpu_list_unlock(void) -{ -} -#endif #ifdef TARGET_I386 @@ -3156,12 +3118,7 @@ THREAD CPUState *thread_cpu; void task_settid(TaskState *ts) { if (ts->ts_tid == 0) { -#ifdef CONFIG_USE_NPTL ts->ts_tid = (pid_t)syscall(SYS_gettid); -#else - /* when no threads are used, tid becomes pid */ - ts->ts_tid = getpid(); -#endif } } diff --git a/linux-user/mmap.c b/linux-user/mmap.c index de2219768d..a249f0ceb6 100644 --- a/linux-user/mmap.c +++ b/linux-user/mmap.c @@ -33,7 +33,6 @@ //#define DEBUG_MMAP -#if defined(CONFIG_USE_NPTL) static pthread_mutex_t mmap_mutex = PTHREAD_MUTEX_INITIALIZER; static __thread int mmap_lock_count; @@ -66,16 +65,6 @@ void mmap_fork_end(int child) else pthread_mutex_unlock(&mmap_mutex); } -#else -/* We aren't threadsafe to start with, so no need to worry about locking. */ -void mmap_lock(void) -{ -} - -void mmap_unlock(void) -{ -} -#endif /* NOTE: all the constants are the HOST ones, but addresses are target. */ int target_mprotect(abi_ulong start, abi_ulong len, int prot) diff --git a/linux-user/qemu.h b/linux-user/qemu.h index 1ff0fa8b12..4a16e8fe1d 100644 --- a/linux-user/qemu.h +++ b/linux-user/qemu.h @@ -19,11 +19,7 @@ #include "exec/gdbstub.h" #include "qemu/queue.h" -#if defined(CONFIG_USE_NPTL) #define THREAD __thread -#else -#define THREAD -#endif /* This struct is used to hold certain information about the image. * Basically, it replicates in user space what would be certain @@ -116,9 +112,7 @@ typedef struct TaskState { uint32_t v86flags; uint32_t v86mask; #endif -#ifdef CONFIG_USE_NPTL abi_ulong child_tidptr; -#endif #ifdef TARGET_M68K int sim_syscalls; abi_ulong tp_value; @@ -268,10 +262,8 @@ void mmap_unlock(void); abi_ulong mmap_find_vma(abi_ulong, abi_ulong); void cpu_list_lock(void); void cpu_list_unlock(void); -#if defined(CONFIG_USE_NPTL) void mmap_fork_start(void); void mmap_fork_end(int child); -#endif /* main.c */ extern unsigned long guest_stack_size; @@ -449,9 +441,7 @@ static inline void *lock_user_string(abi_ulong guest_addr) #define unlock_user_struct(host_ptr, guest_addr, copy) \ unlock_user(host_ptr, guest_addr, (copy) ? sizeof(*host_ptr) : 0) -#if defined(CONFIG_USE_NPTL) #include -#endif /* Include target-specific struct and function definitions; * they may need access to the target-independent structures diff --git a/linux-user/syscall.c b/linux-user/syscall.c index d3b3590e8d..5bd57d0a72 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -111,13 +111,8 @@ int __clone2(int (*fn)(void *), void *child_stack_base, #include "qemu.h" -#if defined(CONFIG_USE_NPTL) #define CLONE_NPTL_FLAGS2 (CLONE_SETTLS | \ CLONE_PARENT_SETTID | CLONE_CHILD_SETTID | CLONE_CHILD_CLEARTID) -#else -/* XXX: Hardcode the above values. */ -#define CLONE_NPTL_FLAGS2 0 -#endif //#define DEBUG @@ -234,12 +229,10 @@ _syscall1(int,exit_group,int,error_code) #if defined(TARGET_NR_set_tid_address) && defined(__NR_set_tid_address) _syscall1(int,set_tid_address,int *,tidptr) #endif -#if defined(CONFIG_USE_NPTL) #if defined(TARGET_NR_futex) && defined(__NR_futex) _syscall6(int,sys_futex,int *,uaddr,int,op,int,val, const struct timespec *,timeout,int *,uaddr2,int,val3) #endif -#endif #define __NR_sys_sched_getaffinity __NR_sched_getaffinity _syscall3(int, sys_sched_getaffinity, pid_t, pid, unsigned int, len, unsigned long *, user_mask_ptr); @@ -4227,7 +4220,6 @@ abi_long do_arch_prctl(CPUX86State *env, int code, abi_ulong addr) #define NEW_STACK_SIZE 0x40000 -#if defined(CONFIG_USE_NPTL) static pthread_mutex_t clone_lock = PTHREAD_MUTEX_INITIALIZER; typedef struct { @@ -4272,16 +4264,6 @@ static void *clone_func(void *arg) /* never exits */ return NULL; } -#else - -static int clone_func(void *arg) -{ - CPUArchState *env = arg; - cpu_loop(env); - /* never exits */ - return 0; -} -#endif /* do_fork() Must return host values and target errnos (unlike most do_*() functions). */ @@ -4292,12 +4274,8 @@ static int do_fork(CPUArchState *env, unsigned int flags, abi_ulong newsp, int ret; TaskState *ts; CPUArchState *new_env; -#if defined(CONFIG_USE_NPTL) unsigned int nptl_flags; sigset_t sigmask; -#else - uint8_t *new_stack; -#endif /* Emulate vfork() with fork() */ if (flags & CLONE_VFORK) @@ -4305,10 +4283,9 @@ static int do_fork(CPUArchState *env, unsigned int flags, abi_ulong newsp, if (flags & CLONE_VM) { TaskState *parent_ts = (TaskState *)env->opaque; -#if defined(CONFIG_USE_NPTL) new_thread_info info; pthread_attr_t attr; -#endif + ts = g_malloc0(sizeof(TaskState)); init_task_state(ts); /* we create a new CPU instance. */ @@ -4321,7 +4298,6 @@ static int do_fork(CPUArchState *env, unsigned int flags, abi_ulong newsp, new_env->opaque = ts; ts->bprm = parent_ts->bprm; ts->info = parent_ts->info; -#if defined(CONFIG_USE_NPTL) nptl_flags = flags; flags &= ~CLONE_NPTL_FLAGS2; @@ -4371,17 +4347,6 @@ static int do_fork(CPUArchState *env, unsigned int flags, abi_ulong newsp, pthread_cond_destroy(&info.cond); pthread_mutex_destroy(&info.mutex); pthread_mutex_unlock(&clone_lock); -#else - if (flags & CLONE_NPTL_FLAGS2) - return -EINVAL; - /* This is probably going to die very quickly, but do it anyway. */ - new_stack = g_malloc0 (NEW_STACK_SIZE); -#ifdef __ia64__ - ret = __clone2(clone_func, new_stack, NEW_STACK_SIZE, flags, new_env); -#else - ret = clone(clone_func, new_stack + NEW_STACK_SIZE, flags, new_env); -#endif -#endif } else { /* if no CLONE_VM, we consider it is a fork */ if ((flags & ~(CSIGNAL | CLONE_NPTL_FLAGS2)) != 0) @@ -4392,7 +4357,6 @@ static int do_fork(CPUArchState *env, unsigned int flags, abi_ulong newsp, /* Child Process. */ cpu_clone_regs(env, newsp); fork_end(1); -#if defined(CONFIG_USE_NPTL) /* There is a race condition here. The parent process could theoretically read the TID in the child process before the child tid is set. This would require using either ptrace @@ -4408,7 +4372,6 @@ static int do_fork(CPUArchState *env, unsigned int flags, abi_ulong newsp, cpu_set_tls (env, newtls); if (flags & CLONE_CHILD_CLEARTID) ts->child_tidptr = child_tidptr; -#endif } else { fork_end(0); } @@ -4834,7 +4797,6 @@ static inline abi_long host_to_target_stat64(void *cpu_env, } #endif -#if defined(CONFIG_USE_NPTL) /* ??? Using host futex calls even when target atomic operations are not really atomic probably breaks things. However implementing futexes locally would make futexes shared between multiple processes @@ -4886,7 +4848,6 @@ static int do_futex(target_ulong uaddr, int op, int val, target_ulong timeout, return -TARGET_ENOSYS; } } -#endif /* Map host to target signal numbers for the wait family of syscalls. Assume all other status bits are the same. */ @@ -5132,9 +5093,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, abi_long arg5, abi_long arg6, abi_long arg7, abi_long arg8) { -#ifdef CONFIG_USE_NPTL CPUState *cpu = ENV_GET_CPU(cpu_env); -#endif abi_long ret; struct stat st; struct statfs stfs; @@ -5148,7 +5107,6 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, switch(num) { case TARGET_NR_exit: -#ifdef CONFIG_USE_NPTL /* In old applications this may be used to implement _exit(2). However in threaded applictions it is used for thread termination, and _exit_group is used for application termination. @@ -5186,7 +5144,6 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, g_free(ts); pthread_exit(NULL); } -#endif #ifdef TARGET_GPROF _mcleanup(); #endif @@ -8687,11 +8644,9 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, } break; #endif -#if defined(CONFIG_USE_NPTL) case TARGET_NR_futex: ret = do_futex(arg1, arg2, arg3, arg4, arg5, arg6); break; -#endif #if defined(TARGET_NR_inotify_init) && defined(__NR_inotify_init) case TARGET_NR_inotify_init: ret = get_errno(sys_inotify_init()); From 885a73f72b967900296d71c97cc7c560585a9086 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20F=C3=A4rber?= Date: Wed, 10 Jul 2013 18:30:38 +0200 Subject: [PATCH 14/21] linux-user: Avoid conditional cpu_reset() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Some CPUs reset as part of cpu_init(), some others were reset afterwards, some not at all. While some targets didn't implement a cpu_[state_]reset() function, QOM cpu_reset() is always available. There's nothing wrong with resetting twice on startup, so drop the #ifdef. Suggested-by: Peter Maydell Signed-off-by: Andreas Färber Cc: Eduardo Habkost Signed-off-by: Riku Voipio --- linux-user/main.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/linux-user/main.c b/linux-user/main.c index 5537967254..547884c481 100644 --- a/linux-user/main.c +++ b/linux-user/main.c @@ -3594,9 +3594,7 @@ int main(int argc, char **argv, char **envp) fprintf(stderr, "Unable to find CPU definition\n"); exit(1); } -#if defined(TARGET_SPARC) || defined(TARGET_PPC) cpu_reset(ENV_GET_CPU(env)); -#endif thread_cpu = ENV_GET_CPU(env); From c7819dfbd22be6a3711f11056f33300e881563d5 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Sat, 6 Jul 2013 21:44:53 +0100 Subject: [PATCH 15/21] linux-user: Fix target_stat and target_stat64 for OpenRISC OpenRISC uses the asm-generic versions of target_stat and target_stat64, but it was incorrectly using the x86/ARM/etc version due to a misplaced defined(TARGET_OPENRISC). The previously unused OpenRISC section of the ifdef ladder also defined an incorrect target_stat and omitted the target_stat64 definition. Fix target_stat, provide target_stat64, and add a comment noting that these are the asm-generic versions for the benefit of future ports. Reviewed-by: Jia Liu Signed-off-by: Peter Maydell Signed-off-by: Riku Voipio --- linux-user/syscall_defs.h | 51 +++++++++++++++++++++++++++++---------- 1 file changed, 38 insertions(+), 13 deletions(-) diff --git a/linux-user/syscall_defs.h b/linux-user/syscall_defs.h index 92c01a9603..cb6341fff1 100644 --- a/linux-user/syscall_defs.h +++ b/linux-user/syscall_defs.h @@ -1138,8 +1138,7 @@ struct target_winsize { #endif #if (defined(TARGET_I386) && defined(TARGET_ABI32)) || defined(TARGET_ARM) \ - || defined(TARGET_CRIS) || defined(TARGET_UNICORE32) \ - || defined(TARGET_OPENRISC) + || defined(TARGET_CRIS) || defined(TARGET_UNICORE32) struct target_stat { unsigned short st_dev; unsigned short __pad1; @@ -1837,29 +1836,55 @@ struct target_stat { abi_ulong __unused[3]; }; #elif defined(TARGET_OPENRISC) + +/* These are the asm-generic versions of the stat and stat64 structures */ + struct target_stat { abi_ulong st_dev; abi_ulong st_ino; - abi_ulong st_nlink; - unsigned int st_mode; + unsigned int st_nlink; unsigned int st_uid; unsigned int st_gid; - unsigned int __pad0; abi_ulong st_rdev; + abi_ulong __pad1; abi_long st_size; - abi_long st_blksize; - abi_long st_blocks; /* Number 512-byte blocks allocated. */ - - abi_ulong target_st_atime; + int st_blksize; + int __pad2; + abi_long st_blocks; + abi_long target_st_atime; abi_ulong target_st_atime_nsec; - abi_ulong target_st_mtime; + abi_long target_st_mtime; abi_ulong target_st_mtime_nsec; - abi_ulong target_st_ctime; + abi_long target_st_ctime; abi_ulong target_st_ctime_nsec; - - abi_long __unused[3]; + unsigned int __unused4; + unsigned int __unused5; }; + +struct target_stat64 { + uint64_t st_dev; + uint64_t st_ino; + unsigned int st_mode; + unsigned int st_nlink; + unsigned int st_uid; + unsigned int st_gid; + uint64_t st_rdev; + uint64_t __pad1; + int64_t st_size; + int st_blksize; + int __pad2; + int64_t st_blocks; + int target_st_atime; + unsigned int target_st_atime_nsec; + int target_st_mtime; + unsigned int target_st_mtime_nsec; + int target_st_ctime; + unsigned int target_st_ctime_nsec; + unsigned int __unused4; + unsigned int __unused5; +}; + #else #error unsupported CPU #endif From 82f05b69e6b701157b4a2e7d76ae6cf5542d66c9 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Sat, 6 Jul 2013 17:39:48 +0100 Subject: [PATCH 16/21] linux-user: Fix pipe syscall return for SPARC SPARC is one of the CPUs which has a funny syscall ABI for the pipe syscall; add it to the set of special cases in do_pipe(). Signed-off-by: Peter Maydell Signed-off-by: Riku Voipio --- linux-user/syscall.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/linux-user/syscall.c b/linux-user/syscall.c index 5bd57d0a72..a797afc340 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -1032,6 +1032,9 @@ static abi_long do_pipe(void *cpu_env, abi_ulong pipedes, #elif defined(TARGET_SH4) ((CPUSH4State*)cpu_env)->gregs[1] = host_pipe[1]; return host_pipe[0]; +#elif defined(TARGET_SPARC) + ((CPUSPARCState*)cpu_env)->regwptr[1] = host_pipe[1]; + return host_pipe[0]; #endif } From 732f9e89a1c737f738c445ff24929a1bc137d1a9 Mon Sep 17 00:00:00 2001 From: Alexander Graf Date: Sat, 6 Jul 2013 14:17:49 +0200 Subject: [PATCH 17/21] linux-user: fix segmentation fault passing with h2g(x) != x When forwarding a segmentation fault into the guest process, we were passing the host's address directly into the guest process's signal descriptor. That obviously confused the guest process, since it didn't know what to make of the (usually 32-bit truncated) address. Passing in h2g(address) makes the guest process a lot happier. To make the code more obvious, introduce a h2g_nocheck() macro that does the same as h2g(), but allows us to convert addresses that may be outside of guest mapped range into the guest's view of address space. This fixes java running in arm-linux-user for me. Signed-off-by: Alexander Graf Signed-off-by: Riku Voipio --- include/exec/cpu-all.h | 8 ++++++-- user-exec.c | 4 ++++ 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/include/exec/cpu-all.h b/include/exec/cpu-all.h index 5084202217..f1cde978ab 100644 --- a/include/exec/cpu-all.h +++ b/include/exec/cpu-all.h @@ -209,11 +209,15 @@ extern unsigned long reserved_va; }) #endif -#define h2g(x) ({ \ +#define h2g_nocheck(x) ({ \ unsigned long __ret = (unsigned long)(x) - GUEST_BASE; \ + (abi_ulong)__ret; \ +}) + +#define h2g(x) ({ \ /* Check if given address fits target address space */ \ assert(h2g_valid(x)); \ - (abi_ulong)__ret; \ + h2g_nocheck(x); \ }) #define saddr(x) g2h(x) diff --git a/user-exec.c b/user-exec.c index d45ca8e877..82bfa66ce3 100644 --- a/user-exec.c +++ b/user-exec.c @@ -95,6 +95,10 @@ static inline int handle_cpu_signal(uintptr_t pc, unsigned long address, return 1; } + /* Convert forcefully to guest address space, invalid addresses + are still valid segv ones */ + address = h2g_nocheck(address); + env = current_cpu->env_ptr; /* see if it is an MMU fault */ ret = cpu_handle_mmu_fault(env, address, is_write, MMU_USER_IDX); From ddaa7e5a2ad0ef20fd3d1cc44a9ade75e5eabcfc Mon Sep 17 00:00:00 2001 From: Alexander Graf Date: Sat, 6 Jul 2013 14:17:53 +0200 Subject: [PATCH 18/21] linux-user: Fix epoll on ARM hosts The epoll emulation uses data structures without packing them, so the compiler might choose to add padding inside. This patch makes the most offending one (target_epoll_event) a packed structure to make sure we don't pad it by accident. ARM would pad it, so declare the padding mandatory for ARM targets. This fixes i386-on-ARM epoll emulation for me. Signed-off-by: Alexander Graf Signed-off-by: Riku Voipio --- linux-user/syscall_defs.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/linux-user/syscall_defs.h b/linux-user/syscall_defs.h index cb6341fff1..086fbfffe7 100644 --- a/linux-user/syscall_defs.h +++ b/linux-user/syscall_defs.h @@ -2459,8 +2459,11 @@ typedef union target_epoll_data { struct target_epoll_event { uint32_t events; +#ifdef TARGET_ARM + uint32_t __pad; +#endif target_epoll_data_t data; -}; +} QEMU_PACKED; #endif struct target_rlimit64 { uint64_t rlim_cur; From b24c882b9435d0745679a96571027a2c92065e4f Mon Sep 17 00:00:00 2001 From: Alexander Graf Date: Sat, 6 Jul 2013 14:17:51 +0200 Subject: [PATCH 19/21] linux-user: Reset copied CPUs in cpu_copy() always When a new thread gets created, we need to reset non arch specific state to get the new CPU into clean state. However this reset should happen before the arch specific CPU contents get copied over. Otherwise we end up having clean reset state in our newly created thread. Signed-off-by: Alexander Graf Signed-off-by: Riku Voipio --- exec.c | 4 ++++ linux-user/syscall.c | 3 --- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/exec.c b/exec.c index c8658c6f9d..2426bf7ce4 100644 --- a/exec.c +++ b/exec.c @@ -642,6 +642,10 @@ CPUArchState *cpu_copy(CPUArchState *env) CPUWatchpoint *wp; #endif + /* Reset non arch specific state */ + cpu_reset(ENV_GET_CPU(new_env)); + + /* Copy arch specific state into the new CPU */ memcpy(new_env, env, sizeof(CPUArchState)); /* Clone all break/watchpoints. diff --git a/linux-user/syscall.c b/linux-user/syscall.c index a797afc340..3f6db4b0d1 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -4293,9 +4293,6 @@ static int do_fork(CPUArchState *env, unsigned int flags, abi_ulong newsp, init_task_state(ts); /* we create a new CPU instance. */ new_env = cpu_copy(env); -#if defined(TARGET_I386) || defined(TARGET_SPARC) || defined(TARGET_PPC) - cpu_reset(ENV_GET_CPU(new_env)); -#endif /* Init regs that differ from the parent. */ cpu_clone_regs(new_env, newsp); new_env->opaque = ts; From d02532f08e207419e412ea7cd4eb8b36f04f426d Mon Sep 17 00:00:00 2001 From: Alexander Graf Date: Sat, 6 Jul 2013 14:17:57 +0200 Subject: [PATCH 20/21] linux-user: Unlock mmap_lock when resuming guest from page_unprotect The page_unprotect() function is running everything locked. Before every potential exit path of the function mmap_unlock() gets called to make sure we don't leak the lock. However, the function calls tb_invalidate_phys_page() which again can exit a signal through longjmp, leaving our mmap_unlock() attempts in vain. Add a hint to tb_invalidate_phys_page() that we need to unlock before we can leave back into guest context, so that we don't leak the lock. This fixes 16-bit i386 wine programs running in linux-user for me. Signed-off-by: Alexander Graf Signed-off-by: Riku Voipio --- translate-all.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/translate-all.c b/translate-all.c index e8683d2c66..3b5fc7c901 100644 --- a/translate-all.c +++ b/translate-all.c @@ -1148,7 +1148,8 @@ void tb_invalidate_phys_page_fast(tb_page_addr_t start, int len) #if !defined(CONFIG_SOFTMMU) static void tb_invalidate_phys_page(tb_page_addr_t addr, - uintptr_t pc, void *puc) + uintptr_t pc, void *puc, + bool locked) { TranslationBlock *tb; PageDesc *p; @@ -1206,6 +1207,9 @@ static void tb_invalidate_phys_page(tb_page_addr_t addr, itself */ cpu->current_tb = NULL; tb_gen_code(env, current_pc, current_cs_base, current_flags, 1); + if (locked) { + mmap_unlock(); + } cpu_resume_from_signal(env, puc); } #endif @@ -1723,7 +1727,7 @@ void page_set_flags(target_ulong start, target_ulong end, int flags) if (!(p->flags & PAGE_WRITE) && (flags & PAGE_WRITE) && p->first_tb) { - tb_invalidate_phys_page(addr, 0, NULL); + tb_invalidate_phys_page(addr, 0, NULL, false); } p->flags = flags; } @@ -1818,7 +1822,7 @@ int page_unprotect(target_ulong address, uintptr_t pc, void *puc) /* and since the content will be modified, we must invalidate the corresponding translated code. */ - tb_invalidate_phys_page(addr, pc, puc); + tb_invalidate_phys_page(addr, pc, puc, true); #ifdef DEBUG_TB_CHECK tb_invalidate_check(addr); #endif From a033381758841837edaf307e20edf019c5900609 Mon Sep 17 00:00:00 2001 From: Kwok Cheung Yeung Date: Fri, 19 Jul 2013 09:21:44 -0700 Subject: [PATCH 21/21] linux-user: Handle compressed ISA encodings when processing MIPS exceptions Decode trap instructions during the handling of an EXCP_BREAK or EXCP_TRAP according to the current ISA mode. Signed-off-by: Kwok Cheung Yeung Signed-off-by: Riku Voipio --- linux-user/main.c | 46 +++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 43 insertions(+), 3 deletions(-) diff --git a/linux-user/main.c b/linux-user/main.c index 547884c481..441e31dc01 100644 --- a/linux-user/main.c +++ b/linux-user/main.c @@ -2310,7 +2310,31 @@ done_syscall: abi_ulong trap_instr; unsigned int code; - ret = get_user_ual(trap_instr, env->active_tc.PC); + if (env->hflags & MIPS_HFLAG_M16) { + if (env->insn_flags & ASE_MICROMIPS) { + /* microMIPS mode */ + abi_ulong instr[2]; + + ret = get_user_u16(instr[0], env->active_tc.PC) || + get_user_u16(instr[1], env->active_tc.PC + 2); + + trap_instr = (instr[0] << 16) | instr[1]; + } else { + /* MIPS16e mode */ + ret = get_user_u16(trap_instr, env->active_tc.PC); + if (ret != 0) { + goto error; + } + code = (trap_instr >> 6) & 0x3f; + if (do_break(env, &info, code) != 0) { + goto error; + } + break; + } + } else { + ret = get_user_ual(trap_instr, env->active_tc.PC); + } + if (ret != 0) { goto error; } @@ -2334,14 +2358,30 @@ done_syscall: abi_ulong trap_instr; unsigned int code = 0; - ret = get_user_ual(trap_instr, env->active_tc.PC); + if (env->hflags & MIPS_HFLAG_M16) { + /* microMIPS mode */ + abi_ulong instr[2]; + + ret = get_user_u16(instr[0], env->active_tc.PC) || + get_user_u16(instr[1], env->active_tc.PC + 2); + + trap_instr = (instr[0] << 16) | instr[1]; + } else { + ret = get_user_ual(trap_instr, env->active_tc.PC); + } + if (ret != 0) { goto error; } /* The immediate versions don't provide a code. */ if (!(trap_instr & 0xFC000000)) { - code = ((trap_instr >> 6) & ((1 << 10) - 1)); + if (env->hflags & MIPS_HFLAG_M16) { + /* microMIPS mode */ + code = ((trap_instr >> 12) & ((1 << 4) - 1)); + } else { + code = ((trap_instr >> 6) & ((1 << 10) - 1)); + } } if (do_break(env, &info, code) != 0) {