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>
This commit is contained in:
Anthony Liguori 2013-07-25 15:56:06 -05:00
commit 874ec3c5b3
25 changed files with 220 additions and 190 deletions

34
configure vendored
View File

@ -155,7 +155,6 @@ curl=""
curses="" curses=""
docs="" docs=""
fdt="" fdt=""
nptl=""
pixman="" pixman=""
sdl="" sdl=""
virtfs="" virtfs=""
@ -856,10 +855,6 @@ for opt do
;; ;;
--enable-fdt) fdt="yes" --enable-fdt) fdt="yes"
;; ;;
--disable-nptl) nptl="no"
;;
--enable-nptl) nptl="yes"
;;
--enable-mixemu) mixemu="yes" --enable-mixemu) mixemu="yes"
;; ;;
--disable-linux-aio) linux_aio="no" --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 " --disable-rdma disable RDMA-based migration support"
echo " --enable-rdma enable RDMA-based migration support" echo " --enable-rdma enable RDMA-based migration support"
echo " --enable-tcg-interpreter enable TCG with bytecode interpreter (TCI)" 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 " --enable-system enable all system emulation targets"
echo " --disable-system disable all system emulation targets" echo " --disable-system disable all system emulation targets"
echo " --enable-user enable supported user emulation targets" echo " --enable-user enable supported user emulation targets"
@ -1439,7 +1432,7 @@ fi
########################################## ##########################################
# NPTL probe # NPTL probe
if test "$nptl" != "no" ; then if test "$linux_user" = "yes"; then
cat > $TMPC <<EOF cat > $TMPC <<EOF
#include <sched.h> #include <sched.h>
#include <linux/futex.h> #include <linux/futex.h>
@ -1450,14 +1443,8 @@ int main(void) {
return 0; return 0;
} }
EOF EOF
if ! compile_object ; then
if compile_object ; then feature_not_found "nptl"
nptl=yes
else
if test "$nptl" = "yes" ; then
feature_not_found "nptl"
fi
nptl=no
fi fi
fi fi
@ -3581,7 +3568,6 @@ echo "bluez support $bluez"
echo "Documentation $docs" echo "Documentation $docs"
[ ! -z "$uname_release" ] && \ [ ! -z "$uname_release" ] && \
echo "uname -r $uname_release" echo "uname -r $uname_release"
echo "NPTL support $nptl"
echo "GUEST_BASE $guest_base" echo "GUEST_BASE $guest_base"
echo "PIE $pie" echo "PIE $pie"
echo "vde support $vde" echo "vde support $vde"
@ -4216,7 +4202,6 @@ mkdir -p $target_dir
echo "# Automatically generated by configure - do not modify" > $config_target_mak echo "# Automatically generated by configure - do not modify" > $config_target_mak
bflt="no" bflt="no"
target_nptl="no"
interp_prefix1=`echo "$interp_prefix" | sed "s/%M/$target_name/g"` interp_prefix1=`echo "$interp_prefix" | sed "s/%M/$target_name/g"`
gdb_xml_files="" gdb_xml_files=""
@ -4231,16 +4216,13 @@ case "$target_name" in
TARGET_BASE_ARCH=i386 TARGET_BASE_ARCH=i386
;; ;;
alpha) alpha)
target_nptl="yes"
;; ;;
arm|armeb) arm|armeb)
TARGET_ARCH=arm TARGET_ARCH=arm
bflt="yes" bflt="yes"
target_nptl="yes"
gdb_xml_files="arm-core.xml arm-vfp.xml arm-vfp3.xml arm-neon.xml" gdb_xml_files="arm-core.xml arm-vfp.xml arm-vfp3.xml arm-neon.xml"
;; ;;
cris) cris)
target_nptl="yes"
;; ;;
lm32) lm32)
;; ;;
@ -4251,12 +4233,10 @@ case "$target_name" in
microblaze|microblazeel) microblaze|microblazeel)
TARGET_ARCH=microblaze TARGET_ARCH=microblaze
bflt="yes" bflt="yes"
target_nptl="yes"
;; ;;
mips|mipsel) mips|mipsel)
TARGET_ARCH=mips TARGET_ARCH=mips
echo "TARGET_ABI_MIPSO32=y" >> $config_target_mak echo "TARGET_ABI_MIPSO32=y" >> $config_target_mak
target_nptl="yes"
;; ;;
mipsn32|mipsn32el) mipsn32|mipsn32el)
TARGET_ARCH=mips64 TARGET_ARCH=mips64
@ -4277,13 +4257,11 @@ case "$target_name" in
;; ;;
ppc) ppc)
gdb_xml_files="power-core.xml power-fpu.xml power-altivec.xml power-spe.xml" gdb_xml_files="power-core.xml power-fpu.xml power-altivec.xml power-spe.xml"
target_nptl="yes"
;; ;;
ppcemb) ppcemb)
TARGET_BASE_ARCH=ppc TARGET_BASE_ARCH=ppc
TARGET_ABI_DIR=ppc TARGET_ABI_DIR=ppc
gdb_xml_files="power-core.xml power-fpu.xml power-altivec.xml power-spe.xml" gdb_xml_files="power-core.xml power-fpu.xml power-altivec.xml power-spe.xml"
target_nptl="yes"
;; ;;
ppc64) ppc64)
TARGET_BASE_ARCH=ppc TARGET_BASE_ARCH=ppc
@ -4300,7 +4278,6 @@ case "$target_name" in
sh4|sh4eb) sh4|sh4eb)
TARGET_ARCH=sh4 TARGET_ARCH=sh4
bflt="yes" bflt="yes"
target_nptl="yes"
;; ;;
sparc) sparc)
;; ;;
@ -4314,7 +4291,6 @@ case "$target_name" in
echo "TARGET_ABI32=y" >> $config_target_mak echo "TARGET_ABI32=y" >> $config_target_mak
;; ;;
s390x) s390x)
target_nptl="yes"
;; ;;
unicore32) unicore32)
;; ;;
@ -4396,10 +4372,6 @@ fi
if test "$target_user_only" = "yes" -a "$bflt" = "yes"; then if test "$target_user_only" = "yes" -a "$bflt" = "yes"; then
echo "TARGET_HAS_BFLT=y" >> $config_target_mak echo "TARGET_HAS_BFLT=y" >> $config_target_mak
fi 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 if test "$target_user_only" = "yes" -a "$guest_base" = "yes"; then
echo "CONFIG_USE_GUEST_BASE=y" >> $config_target_mak echo "CONFIG_USE_GUEST_BASE=y" >> $config_target_mak
fi fi

4
exec.c
View File

@ -646,6 +646,10 @@ CPUArchState *cpu_copy(CPUArchState *env)
CPUWatchpoint *wp; CPUWatchpoint *wp;
#endif #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)); memcpy(new_env, env, sizeof(CPUArchState));
/* Clone all break/watchpoints. /* Clone all break/watchpoints.

View File

@ -210,11 +210,15 @@ extern unsigned long reserved_va;
}) })
#endif #endif
#define h2g(x) ({ \ #define h2g_nocheck(x) ({ \
unsigned long __ret = (unsigned long)(x) - GUEST_BASE; \ unsigned long __ret = (unsigned long)(x) - GUEST_BASE; \
(abi_ulong)__ret; \
})
#define h2g(x) ({ \
/* Check if given address fits target address space */ \ /* Check if given address fits target address space */ \
assert(h2g_valid(x)); \ assert(h2g_valid(x)); \
(abi_ulong)__ret; \ h2g_nocheck(x); \
}) })
#define saddr(x) g2h(x) #define saddr(x) g2h(x)

View File

@ -32,7 +32,7 @@ void gdb_register_coprocessor(CPUState *cpu,
static inline int cpu_index(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; return cpu->host_tid;
#else #else
return cpu->cpu_index + 1; return cpu->cpu_index + 1;

View File

@ -40,3 +40,5 @@ struct target_pt_regs {
#else #else
#define UNAME_MACHINE "armv5tel" #define UNAME_MACHINE "armv5tel"
#endif #endif
#define TARGET_CLONE_BACKWARDS

View File

@ -38,4 +38,6 @@ struct target_pt_regs {
unsigned long eda; unsigned long eda;
}; };
#define TARGET_CLONE_BACKWARDS2
#endif #endif

View File

@ -144,3 +144,5 @@ struct target_vm86plus_struct {
}; };
#define UNAME_MACHINE "i686" #define UNAME_MACHINE "i686"
#define TARGET_CLONE_BACKWARDS

View File

@ -28,6 +28,21 @@ static inline void cpu_clone_regs(CPUX86State *env, target_ulong newsp)
env->regs[R_EAX] = 0; 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) */

View File

@ -29,6 +29,10 @@ static inline void cpu_clone_regs(CPUM68KState *env, target_ulong newsp)
env->dregs[0] = 0; 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 #endif

View File

@ -92,7 +92,6 @@ int cpu_get_pic_interrupt(CPUX86State *env)
} }
#endif #endif
#if defined(CONFIG_USE_NPTL)
/***********************************************************/ /***********************************************************/
/* Helper routines for implementing atomic operations. */ /* Helper routines for implementing atomic operations. */
@ -207,43 +206,6 @@ void cpu_list_unlock(void)
{ {
pthread_mutex_unlock(&cpu_list_mutex); 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 #ifdef TARGET_I386
@ -2349,7 +2311,31 @@ done_syscall:
abi_ulong trap_instr; abi_ulong trap_instr;
unsigned int code; 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) { if (ret != 0) {
goto error; goto error;
} }
@ -2373,14 +2359,30 @@ done_syscall:
abi_ulong trap_instr; abi_ulong trap_instr;
unsigned int code = 0; 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) { if (ret != 0) {
goto error; goto error;
} }
/* The immediate versions don't provide a code. */ /* The immediate versions don't provide a code. */
if (!(trap_instr & 0xFC000000)) { 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) { if (do_break(env, &info, code) != 0) {
@ -3157,12 +3159,7 @@ THREAD CPUState *thread_cpu;
void task_settid(TaskState *ts) void task_settid(TaskState *ts)
{ {
if (ts->ts_tid == 0) { if (ts->ts_tid == 0) {
#ifdef CONFIG_USE_NPTL
ts->ts_tid = (pid_t)syscall(SYS_gettid); 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); exit(1);
} }
cpu = ENV_GET_CPU(env); cpu = ENV_GET_CPU(env);
#if defined(TARGET_SPARC) || defined(TARGET_PPC) cpu_reset(ENV_GET_CPU(env));
cpu_reset(cpu);
#endif
thread_cpu = cpu; thread_cpu = cpu;

View File

@ -48,4 +48,6 @@ struct target_pt_regs {
uint32_t kernel_mode; uint32_t kernel_mode;
}; };
#define TARGET_CLONE_BACKWARDS
#endif #endif

View File

@ -225,3 +225,5 @@ struct target_pt_regs {
#define TARGET_QEMU_ESIGRETURN 255 #define TARGET_QEMU_ESIGRETURN 255
#define UNAME_MACHINE "mips" #define UNAME_MACHINE "mips"
#define TARGET_CLONE_BACKWARDS

View File

@ -222,3 +222,5 @@ struct target_pt_regs {
#define TARGET_QEMU_ESIGRETURN 255 #define TARGET_QEMU_ESIGRETURN 255
#define UNAME_MACHINE "mips64" #define UNAME_MACHINE "mips64"
#define TARGET_CLONE_BACKWARDS

View File

@ -33,7 +33,6 @@
//#define DEBUG_MMAP //#define DEBUG_MMAP
#if defined(CONFIG_USE_NPTL)
static pthread_mutex_t mmap_mutex = PTHREAD_MUTEX_INITIALIZER; static pthread_mutex_t mmap_mutex = PTHREAD_MUTEX_INITIALIZER;
static __thread int mmap_lock_count; static __thread int mmap_lock_count;
@ -66,16 +65,6 @@ void mmap_fork_end(int child)
else else
pthread_mutex_unlock(&mmap_mutex); 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. */ /* NOTE: all the constants are the HOST ones, but addresses are target. */
int target_mprotect(abi_ulong start, abi_ulong len, int prot) int target_mprotect(abi_ulong start, abi_ulong len, int prot)

View File

@ -25,9 +25,14 @@ static inline void cpu_clone_regs(CPUOpenRISCState *env, target_ulong newsp)
if (newsp) { if (newsp) {
env->gpr[1] = 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 #endif

View File

@ -62,3 +62,5 @@ struct target_revectored_struct {
#else #else
#define UNAME_MACHINE "ppc" #define UNAME_MACHINE "ppc"
#endif #endif
#define TARGET_CLONE_BACKWARDS

View File

@ -16,16 +16,10 @@
#include "exec/user/thunk.h" #include "exec/user/thunk.h"
#include "syscall_defs.h" #include "syscall_defs.h"
#include "syscall.h" #include "syscall.h"
#include "target_cpu.h"
#include "target_signal.h"
#include "exec/gdbstub.h" #include "exec/gdbstub.h"
#include "qemu/queue.h" #include "qemu/queue.h"
#if defined(CONFIG_USE_NPTL)
#define THREAD __thread #define THREAD __thread
#else
#define THREAD
#endif
/* This struct is used to hold certain information about the image. /* This struct is used to hold certain information about the image.
* Basically, it replicates in user space what would be certain * Basically, it replicates in user space what would be certain
@ -118,11 +112,10 @@ typedef struct TaskState {
uint32_t v86flags; uint32_t v86flags;
uint32_t v86mask; uint32_t v86mask;
#endif #endif
#ifdef CONFIG_USE_NPTL
abi_ulong child_tidptr; abi_ulong child_tidptr;
#endif
#ifdef TARGET_M68K #ifdef TARGET_M68K
int sim_syscalls; int sim_syscalls;
abi_ulong tp_value;
#endif #endif
#if defined(TARGET_ARM) || defined(TARGET_M68K) || defined(TARGET_UNICORE32) #if defined(TARGET_ARM) || defined(TARGET_M68K) || defined(TARGET_UNICORE32)
/* Extra fields for semihosted binaries. */ /* Extra fields for semihosted binaries. */
@ -269,10 +262,8 @@ void mmap_unlock(void);
abi_ulong mmap_find_vma(abi_ulong, abi_ulong); abi_ulong mmap_find_vma(abi_ulong, abi_ulong);
void cpu_list_lock(void); void cpu_list_lock(void);
void cpu_list_unlock(void); void cpu_list_unlock(void);
#if defined(CONFIG_USE_NPTL)
void mmap_fork_start(void); void mmap_fork_start(void);
void mmap_fork_end(int child); void mmap_fork_end(int child);
#endif
/* main.c */ /* main.c */
extern unsigned long guest_stack_size; 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) \ #define unlock_user_struct(host_ptr, guest_addr, copy) \
unlock_user(host_ptr, guest_addr, (copy) ? sizeof(*host_ptr) : 0) unlock_user(host_ptr, guest_addr, (copy) ? sizeof(*host_ptr) : 0)
#if defined(CONFIG_USE_NPTL)
#include <pthread.h> #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 */ #endif /* QEMU_H */

View File

@ -21,3 +21,5 @@ struct target_pt_regs {
}; };
#define UNAME_MACHINE "s390x" #define UNAME_MACHINE "s390x"
#define TARGET_CLONE_BACKWARDS

View File

@ -7,3 +7,10 @@ struct target_pt_regs {
}; };
#define UNAME_MACHINE "sun4" #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

View File

@ -25,12 +25,20 @@ static inline void cpu_clone_regs(CPUSPARCState *env, target_ulong newsp)
if (newsp) { if (newsp) {
env->regwptr[22] = 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; env->regwptr[0] = 0;
/* FIXME: Do we also need to clear CF? */ #if defined(TARGET_SPARC64) && !defined(TARGET_ABI32)
/* XXXXX */ env->xcc &= ~PSR_CARRY;
printf("HELPME: %s:%d\n", __FILE__, __LINE__); #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 #endif

View File

@ -8,3 +8,10 @@ struct target_pt_regs {
}; };
#define UNAME_MACHINE "sun4u" #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

View File

@ -111,13 +111,8 @@ int __clone2(int (*fn)(void *), void *child_stack_base,
#include "qemu.h" #include "qemu.h"
#if defined(CONFIG_USE_NPTL)
#define CLONE_NPTL_FLAGS2 (CLONE_SETTLS | \ #define CLONE_NPTL_FLAGS2 (CLONE_SETTLS | \
CLONE_PARENT_SETTID | CLONE_CHILD_SETTID | CLONE_CHILD_CLEARTID) CLONE_PARENT_SETTID | CLONE_CHILD_SETTID | CLONE_CHILD_CLEARTID)
#else
/* XXX: Hardcode the above values. */
#define CLONE_NPTL_FLAGS2 0
#endif
//#define DEBUG //#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) #if defined(TARGET_NR_set_tid_address) && defined(__NR_set_tid_address)
_syscall1(int,set_tid_address,int *,tidptr) _syscall1(int,set_tid_address,int *,tidptr)
#endif #endif
#if defined(CONFIG_USE_NPTL)
#if defined(TARGET_NR_futex) && defined(__NR_futex) #if defined(TARGET_NR_futex) && defined(__NR_futex)
_syscall6(int,sys_futex,int *,uaddr,int,op,int,val, _syscall6(int,sys_futex,int *,uaddr,int,op,int,val,
const struct timespec *,timeout,int *,uaddr2,int,val3) const struct timespec *,timeout,int *,uaddr2,int,val3)
#endif #endif
#endif
#define __NR_sys_sched_getaffinity __NR_sched_getaffinity #define __NR_sys_sched_getaffinity __NR_sched_getaffinity
_syscall3(int, sys_sched_getaffinity, pid_t, pid, unsigned int, len, _syscall3(int, sys_sched_getaffinity, pid_t, pid, unsigned int, len,
unsigned long *, user_mask_ptr); unsigned long *, user_mask_ptr);
@ -1039,6 +1032,9 @@ static abi_long do_pipe(void *cpu_env, abi_ulong pipedes,
#elif defined(TARGET_SH4) #elif defined(TARGET_SH4)
((CPUSH4State*)cpu_env)->gregs[1] = host_pipe[1]; ((CPUSH4State*)cpu_env)->gregs[1] = host_pipe[1];
return host_pipe[0]; return host_pipe[0];
#elif defined(TARGET_SPARC)
((CPUSPARCState*)cpu_env)->regwptr[1] = host_pipe[1];
return host_pipe[0];
#endif #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) #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); uint64_t *gdt_table = g2h(env->gdt.base);
struct target_modify_ldt_ldt_s ldt_info; 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 */ #endif /* TARGET_I386 && TARGET_ABI32 */
#ifndef 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_long ret = 0;
abi_ulong val; 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 #define NEW_STACK_SIZE 0x40000
#if defined(CONFIG_USE_NPTL)
static pthread_mutex_t clone_lock = PTHREAD_MUTEX_INITIALIZER; static pthread_mutex_t clone_lock = PTHREAD_MUTEX_INITIALIZER;
typedef struct { typedef struct {
@ -4272,16 +4267,6 @@ static void *clone_func(void *arg)
/* never exits */ /* never exits */
return NULL; 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_fork() Must return host values and target errnos (unlike most
do_*() functions). */ do_*() functions). */
@ -4292,12 +4277,8 @@ static int do_fork(CPUArchState *env, unsigned int flags, abi_ulong newsp,
int ret; int ret;
TaskState *ts; TaskState *ts;
CPUArchState *new_env; CPUArchState *new_env;
#if defined(CONFIG_USE_NPTL)
unsigned int nptl_flags; unsigned int nptl_flags;
sigset_t sigmask; sigset_t sigmask;
#else
uint8_t *new_stack;
#endif
/* Emulate vfork() with fork() */ /* Emulate vfork() with fork() */
if (flags & CLONE_VFORK) if (flags & CLONE_VFORK)
@ -4305,23 +4286,18 @@ static int do_fork(CPUArchState *env, unsigned int flags, abi_ulong newsp,
if (flags & CLONE_VM) { if (flags & CLONE_VM) {
TaskState *parent_ts = (TaskState *)env->opaque; TaskState *parent_ts = (TaskState *)env->opaque;
#if defined(CONFIG_USE_NPTL)
new_thread_info info; new_thread_info info;
pthread_attr_t attr; pthread_attr_t attr;
#endif
ts = g_malloc0(sizeof(TaskState)); ts = g_malloc0(sizeof(TaskState));
init_task_state(ts); init_task_state(ts);
/* we create a new CPU instance. */ /* we create a new CPU instance. */
new_env = cpu_copy(env); 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. */ /* Init regs that differ from the parent. */
cpu_clone_regs(new_env, newsp); cpu_clone_regs(new_env, newsp);
new_env->opaque = ts; new_env->opaque = ts;
ts->bprm = parent_ts->bprm; ts->bprm = parent_ts->bprm;
ts->info = parent_ts->info; ts->info = parent_ts->info;
#if defined(CONFIG_USE_NPTL)
nptl_flags = flags; nptl_flags = flags;
flags &= ~CLONE_NPTL_FLAGS2; 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_cond_destroy(&info.cond);
pthread_mutex_destroy(&info.mutex); pthread_mutex_destroy(&info.mutex);
pthread_mutex_unlock(&clone_lock); 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 { } else {
/* if no CLONE_VM, we consider it is a fork */ /* if no CLONE_VM, we consider it is a fork */
if ((flags & ~(CSIGNAL | CLONE_NPTL_FLAGS2)) != 0) 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. */ /* Child Process. */
cpu_clone_regs(env, newsp); cpu_clone_regs(env, newsp);
fork_end(1); fork_end(1);
#if defined(CONFIG_USE_NPTL)
/* There is a race condition here. The parent process could /* There is a race condition here. The parent process could
theoretically read the TID in the child process before the child theoretically read the TID in the child process before the child
tid is set. This would require using either ptrace 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); cpu_set_tls (env, newtls);
if (flags & CLONE_CHILD_CLEARTID) if (flags & CLONE_CHILD_CLEARTID)
ts->child_tidptr = child_tidptr; ts->child_tidptr = child_tidptr;
#endif
} else { } else {
fork_end(0); fork_end(0);
} }
@ -4834,7 +4797,6 @@ static inline abi_long host_to_target_stat64(void *cpu_env,
} }
#endif #endif
#if defined(CONFIG_USE_NPTL)
/* ??? Using host futex calls even when target atomic operations /* ??? Using host futex calls even when target atomic operations
are not really atomic probably breaks things. However implementing are not really atomic probably breaks things. However implementing
futexes locally would make futexes shared between multiple processes 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; return -TARGET_ENOSYS;
} }
} }
#endif
/* Map host to target signal numbers for the wait family of syscalls. /* Map host to target signal numbers for the wait family of syscalls.
Assume all other status bits are the same. */ 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 arg5, abi_long arg6, abi_long arg7,
abi_long arg8) abi_long arg8)
{ {
#ifdef CONFIG_USE_NPTL
CPUState *cpu = ENV_GET_CPU(cpu_env); CPUState *cpu = ENV_GET_CPU(cpu_env);
#endif
abi_long ret; abi_long ret;
struct stat st; struct stat st;
struct statfs stfs; struct statfs stfs;
@ -5148,7 +5107,6 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
switch(num) { switch(num) {
case TARGET_NR_exit: case TARGET_NR_exit:
#ifdef CONFIG_USE_NPTL
/* In old applications this may be used to implement _exit(2). /* In old applications this may be used to implement _exit(2).
However in threaded applictions it is used for thread termination, However in threaded applictions it is used for thread termination,
and _exit_group is used for application 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); g_free(ts);
pthread_exit(NULL); pthread_exit(NULL);
} }
#endif
#ifdef TARGET_GPROF #ifdef TARGET_GPROF
_mcleanup(); _mcleanup();
#endif #endif
@ -6956,16 +6913,20 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
ret = get_errno(fsync(arg1)); ret = get_errno(fsync(arg1));
break; break;
case TARGET_NR_clone: case TARGET_NR_clone:
#if defined(TARGET_SH4) || defined(TARGET_ALPHA) /* Linux manages to have three different orderings for its
ret = get_errno(do_fork(cpu_env, arg1, arg2, arg3, arg5, arg4)); * arguments to clone(); the BACKWARDS and BACKWARDS2 defines
#elif defined(TARGET_CRIS) * match the kernel's CONFIG_CLONE_* settings.
ret = get_errno(do_fork(cpu_env, arg2, arg1, arg3, arg4, arg5)); * Microblaze is further special in that it uses a sixth
#elif defined(TARGET_MICROBLAZE) * implicit argument to clone for the TLS pointer.
*/
#if defined(TARGET_MICROBLAZE)
ret = get_errno(do_fork(cpu_env, arg1, arg2, arg4, arg6, arg5)); 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)); ret = get_errno(do_fork(cpu_env, arg2, arg1, arg3, arg5, arg4));
#else #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 #endif
break; break;
#ifdef __NR_exit_group #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) #elif defined(TARGET_I386) && defined(TARGET_ABI32)
ret = do_set_thread_area(cpu_env, arg1); ret = do_set_thread_area(cpu_env, arg1);
break; break;
#elif defined(TARGET_M68K)
{
TaskState *ts = ((CPUArchState *)cpu_env)->opaque;
ts->tp_value = arg1;
break;
}
#else #else
goto unimplemented_nowarn; goto unimplemented_nowarn;
#endif #endif
@ -8566,6 +8533,13 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
case TARGET_NR_get_thread_area: case TARGET_NR_get_thread_area:
#if defined(TARGET_I386) && defined(TARGET_ABI32) #if defined(TARGET_I386) && defined(TARGET_ABI32)
ret = do_get_thread_area(cpu_env, arg1); 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 #else
goto unimplemented_nowarn; goto unimplemented_nowarn;
#endif #endif
@ -8670,11 +8644,9 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
} }
break; break;
#endif #endif
#if defined(CONFIG_USE_NPTL)
case TARGET_NR_futex: case TARGET_NR_futex:
ret = do_futex(arg1, arg2, arg3, arg4, arg5, arg6); ret = do_futex(arg1, arg2, arg3, arg4, arg5, arg6);
break; break;
#endif
#if defined(TARGET_NR_inotify_init) && defined(__NR_inotify_init) #if defined(TARGET_NR_inotify_init) && defined(__NR_inotify_init)
case TARGET_NR_inotify_init: case TARGET_NR_inotify_init:
ret = get_errno(sys_inotify_init()); ret = get_errno(sys_inotify_init());

View File

@ -1138,8 +1138,7 @@ struct target_winsize {
#endif #endif
#if (defined(TARGET_I386) && defined(TARGET_ABI32)) || defined(TARGET_ARM) \ #if (defined(TARGET_I386) && defined(TARGET_ABI32)) || defined(TARGET_ARM) \
|| defined(TARGET_CRIS) || defined(TARGET_UNICORE32) \ || defined(TARGET_CRIS) || defined(TARGET_UNICORE32)
|| defined(TARGET_OPENRISC)
struct target_stat { struct target_stat {
unsigned short st_dev; unsigned short st_dev;
unsigned short __pad1; unsigned short __pad1;
@ -1837,29 +1836,55 @@ struct target_stat {
abi_ulong __unused[3]; abi_ulong __unused[3];
}; };
#elif defined(TARGET_OPENRISC) #elif defined(TARGET_OPENRISC)
/* These are the asm-generic versions of the stat and stat64 structures */
struct target_stat { struct target_stat {
abi_ulong st_dev; abi_ulong st_dev;
abi_ulong st_ino; abi_ulong st_ino;
abi_ulong st_nlink;
unsigned int st_mode; unsigned int st_mode;
unsigned int st_nlink;
unsigned int st_uid; unsigned int st_uid;
unsigned int st_gid; unsigned int st_gid;
unsigned int __pad0;
abi_ulong st_rdev; abi_ulong st_rdev;
abi_ulong __pad1;
abi_long st_size; abi_long st_size;
abi_long st_blksize; int st_blksize;
abi_long st_blocks; /* Number 512-byte blocks allocated. */ int __pad2;
abi_long st_blocks;
abi_ulong target_st_atime; abi_long target_st_atime;
abi_ulong target_st_atime_nsec; 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_mtime_nsec;
abi_ulong target_st_ctime; abi_long target_st_ctime;
abi_ulong target_st_ctime_nsec; abi_ulong target_st_ctime_nsec;
unsigned int __unused4;
abi_long __unused[3]; 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 #else
#error unsupported CPU #error unsupported CPU
#endif #endif
@ -2434,8 +2459,11 @@ typedef union target_epoll_data {
struct target_epoll_event { struct target_epoll_event {
uint32_t events; uint32_t events;
#ifdef TARGET_ARM
uint32_t __pad;
#endif
target_epoll_data_t data; target_epoll_data_t data;
}; } QEMU_PACKED;
#endif #endif
struct target_rlimit64 { struct target_rlimit64 {
uint64_t rlim_cur; uint64_t rlim_cur;

View File

@ -1148,7 +1148,8 @@ void tb_invalidate_phys_page_fast(tb_page_addr_t start, int len)
#if !defined(CONFIG_SOFTMMU) #if !defined(CONFIG_SOFTMMU)
static void tb_invalidate_phys_page(tb_page_addr_t addr, 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; TranslationBlock *tb;
PageDesc *p; PageDesc *p;
@ -1206,6 +1207,9 @@ static void tb_invalidate_phys_page(tb_page_addr_t addr,
itself */ itself */
cpu->current_tb = NULL; cpu->current_tb = NULL;
tb_gen_code(env, current_pc, current_cs_base, current_flags, 1); tb_gen_code(env, current_pc, current_cs_base, current_flags, 1);
if (locked) {
mmap_unlock();
}
cpu_resume_from_signal(env, puc); cpu_resume_from_signal(env, puc);
} }
#endif #endif
@ -1723,7 +1727,7 @@ void page_set_flags(target_ulong start, target_ulong end, int flags)
if (!(p->flags & PAGE_WRITE) && if (!(p->flags & PAGE_WRITE) &&
(flags & PAGE_WRITE) && (flags & PAGE_WRITE) &&
p->first_tb) { p->first_tb) {
tb_invalidate_phys_page(addr, 0, NULL); tb_invalidate_phys_page(addr, 0, NULL, false);
} }
p->flags = flags; 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 /* and since the content will be modified, we must invalidate
the corresponding translated code. */ the corresponding translated code. */
tb_invalidate_phys_page(addr, pc, puc); tb_invalidate_phys_page(addr, pc, puc, true);
#ifdef DEBUG_TB_CHECK #ifdef DEBUG_TB_CHECK
tb_invalidate_check(addr); tb_invalidate_check(addr);
#endif #endif

View File

@ -95,6 +95,10 @@ static inline int handle_cpu_signal(uintptr_t pc, unsigned long address,
return 1; return 1;
} }
/* Convert forcefully to guest address space, invalid addresses
are still valid segv ones */
address = h2g_nocheck(address);
env = current_cpu->env_ptr; env = current_cpu->env_ptr;
/* see if it is an MMU fault */ /* see if it is an MMU fault */
ret = cpu_handle_mmu_fault(env, address, is_write, MMU_USER_IDX); ret = cpu_handle_mmu_fault(env, address, is_write, MMU_USER_IDX);