aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnthony Liguori <aliguori@us.ibm.com>2013-07-25 15:56:06 -0500
committerAnthony Liguori <aliguori@us.ibm.com>2013-07-25 15:56:06 -0500
commit874ec3c5b3821bb964f9f37b2f930f2a9ce51652 (patch)
tree6ae8ca87e159fa7ebf3ea2db64e9bacae59e9c0c
parentd2f5ea9704af781d4cf14e4be08bb4e37a180260 (diff)
parenta033381758841837edaf307e20edf019c5900609 (diff)
downloadqemu-874ec3c5b3821bb964f9f37b2f930f2a9ce51652.zip
qemu-874ec3c5b3821bb964f9f37b2f930f2a9ce51652.tar.gz
qemu-874ec3c5b3821bb964f9f37b2f930f2a9ce51652.tar.bz2
Merge remote-tracking branch 'riku/linux-user-for-upstream' into staging
* riku/linux-user-for-upstream: (21 commits) linux-user: Handle compressed ISA encodings when processing MIPS exceptions linux-user: Unlock mmap_lock when resuming guest from page_unprotect linux-user: Reset copied CPUs in cpu_copy() always linux-user: Fix epoll on ARM hosts linux-user: fix segmentation fault passing with h2g(x) != x linux-user: Fix pipe syscall return for SPARC linux-user: Fix target_stat and target_stat64 for OpenRISC linux-user: Avoid conditional cpu_reset() configure: Make NPTL non-optional linux-user: Enable NPTL for x86-64 linux-user: Add i386 TLS setter linux-user: Clean up handling of clone() argument order linux-user: Add missing 'break' in i386 get_thread_area syscall linux-user: Enable NPTL for m68k linux-user: Enable NPTL for SPARC targets linux-user: Enable NPTL for OpenRISC linux-user: Move includes of target-specific headers to end of qemu.h configure: Enable threading for unicore32-linux-user configure: Enable threading on all ppc and mips linux-user targets configure: Don't say target_nptl="no" if there is no linux-user target ... Conflicts: linux-user/main.c Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
-rwxr-xr-xconfigure34
-rw-r--r--exec.c4
-rw-r--r--include/exec/cpu-all.h8
-rw-r--r--include/exec/gdbstub.h2
-rw-r--r--linux-user/arm/syscall.h2
-rw-r--r--linux-user/cris/syscall.h2
-rw-r--r--linux-user/i386/syscall.h2
-rw-r--r--linux-user/i386/target_cpu.h19
-rw-r--r--linux-user/m68k/target_cpu.h6
-rw-r--r--linux-user/main.c93
-rw-r--r--linux-user/microblaze/syscall.h2
-rw-r--r--linux-user/mips/syscall.h2
-rw-r--r--linux-user/mips64/syscall.h2
-rw-r--r--linux-user/mmap.c11
-rw-r--r--linux-user/openrisc/target_cpu.h9
-rw-r--r--linux-user/ppc/syscall.h2
-rw-r--r--linux-user/qemu.h20
-rw-r--r--linux-user/s390x/syscall.h2
-rw-r--r--linux-user/sparc/syscall.h7
-rw-r--r--linux-user/sparc/target_cpu.h16
-rw-r--r--linux-user/sparc64/syscall.h7
-rw-r--r--linux-user/syscall.c88
-rw-r--r--linux-user/syscall_defs.h54
-rw-r--r--translate-all.c10
-rw-r--r--user-exec.c4
25 files changed, 219 insertions, 189 deletions
diff --git a/configure b/configure
index 877a821..3d83e16 100755
--- a/configure
+++ b/configure
@@ -155,7 +155,6 @@ curl=""
curses=""
docs=""
fdt=""
-nptl=""
pixman=""
sdl=""
virtfs=""
@@ -856,10 +855,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"
@@ -1103,8 +1098,6 @@ echo " --enable-kvm enable KVM acceleration support"
echo " --disable-rdma disable RDMA-based migration support"
echo " --enable-rdma enable RDMA-based migration 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"
@@ -1439,7 +1432,7 @@ fi
##########################################
# NPTL probe
-if test "$nptl" != "no" ; then
+if test "$linux_user" = "yes"; then
cat > $TMPC <<EOF
#include <sched.h>
#include <linux/futex.h>
@@ -1450,14 +1443,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
@@ -3581,7 +3568,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"
@@ -4216,7 +4202,6 @@ mkdir -p $target_dir
echo "# Automatically generated by configure - do not modify" > $config_target_mak
bflt="no"
-target_nptl="no"
interp_prefix1=`echo "$interp_prefix" | sed "s/%M/$target_name/g"`
gdb_xml_files=""
@@ -4231,16 +4216,13 @@ case "$target_name" in
TARGET_BASE_ARCH=i386
;;
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)
;;
@@ -4251,12 +4233,10 @@ case "$target_name" in
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
@@ -4277,13 +4257,11 @@ case "$target_name" in
;;
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
@@ -4300,7 +4278,6 @@ case "$target_name" in
sh4|sh4eb)
TARGET_ARCH=sh4
bflt="yes"
- target_nptl="yes"
;;
sparc)
;;
@@ -4314,7 +4291,6 @@ case "$target_name" in
echo "TARGET_ABI32=y" >> $config_target_mak
;;
s390x)
- target_nptl="yes"
;;
unicore32)
;;
@@ -4396,10 +4372,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/exec.c b/exec.c
index 7997002..3ba9525 100644
--- a/exec.c
+++ b/exec.c
@@ -646,6 +646,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/include/exec/cpu-all.h b/include/exec/cpu-all.h
index f2800ec..a407b50 100644
--- a/include/exec/cpu-all.h
+++ b/include/exec/cpu-all.h
@@ -210,11 +210,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/include/exec/gdbstub.h b/include/exec/gdbstub.h
index 1bd00ae..7ea1ad7 100644
--- a/include/exec/gdbstub.h
+++ b/include/exec/gdbstub.h
@@ -32,7 +32,7 @@ void gdb_register_coprocessor(CPUState *cpu,
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/arm/syscall.h b/linux-user/arm/syscall.h
index 003d424..73f2931 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 50e50b4..832ee64 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 266e2c4..12b8c3b 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/i386/target_cpu.h b/linux-user/i386/target_cpu.h
index abcac79..58f8645 100644
--- a/linux-user/i386/target_cpu.h
+++ b/linux-user/i386/target_cpu.h
@@ -28,6 +28,21 @@ 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);
+}
+#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/m68k/target_cpu.h b/linux-user/m68k/target_cpu.h
index 8a2a305..cad9c90 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/main.c b/linux-user/main.c
index f6a3aad..5dc0947 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
@@ -2349,7 +2311,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;
}
@@ -2373,14 +2359,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) {
@@ -3157,12 +3159,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
}
}
@@ -3640,9 +3637,7 @@ int main(int argc, char **argv, char **envp)
exit(1);
}
cpu = ENV_GET_CPU(env);
-#if defined(TARGET_SPARC) || defined(TARGET_PPC)
- cpu_reset(cpu);
-#endif
+ cpu_reset(ENV_GET_CPU(env));
thread_cpu = cpu;
diff --git a/linux-user/microblaze/syscall.h b/linux-user/microblaze/syscall.h
index c3e5c55..d550989 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 3deb862..9d437d9 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 cd707df..1710f76 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/mmap.c b/linux-user/mmap.c
index de22197..a249f0c 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/openrisc/target_cpu.h b/linux-user/openrisc/target_cpu.h
index 501fb81..32a46ac 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
diff --git a/linux-user/ppc/syscall.h b/linux-user/ppc/syscall.h
index 481047b..ba36acb 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/qemu.h b/linux-user/qemu.h
index 6569608..4a16e8f 100644
--- a/linux-user/qemu.h
+++ b/linux-user/qemu.h
@@ -16,16 +16,10 @@
#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"
-#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
@@ -118,11 +112,10 @@ 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;
#endif
#if defined(TARGET_ARM) || defined(TARGET_M68K) || defined(TARGET_UNICORE32)
/* Extra fields for semihosted binaries. */
@@ -269,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;
@@ -450,8 +441,13 @@ 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 <pthread.h>
-#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 */
diff --git a/linux-user/s390x/syscall.h b/linux-user/s390x/syscall.h
index e4603b7..ea8c304 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 5a9bb7e..4cd64bf 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/sparc/target_cpu.h b/linux-user/sparc/target_cpu.h
index 5a620a2..4944d46 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
diff --git a/linux-user/sparc64/syscall.h b/linux-user/sparc64/syscall.h
index 81a816d..e60bf31 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 00a0390..3f6db4b 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);
@@ -1039,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
}
@@ -4055,7 +4051,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;
@@ -4189,7 +4185,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;
@@ -4227,7 +4223,6 @@ static 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 +4267,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 +4277,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,23 +4286,18 @@ 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. */
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;
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
@@ -6956,16 +6913,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
@@ -8558,6 +8519,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 +8533,13 @@ 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;
+ ret = ts->tp_value;
+ break;
+ }
#else
goto unimplemented_nowarn;
#endif
@@ -8670,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());
diff --git a/linux-user/syscall_defs.h b/linux-user/syscall_defs.h
index 92c01a9..086fbff 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;
+ unsigned int __unused4;
+ unsigned int __unused5;
+};
- abi_long __unused[3];
+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
@@ -2434,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;
diff --git a/translate-all.c b/translate-all.c
index e8683d2..3b5fc7c 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
diff --git a/user-exec.c b/user-exec.c
index d45ca8e..82bfa66 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);