summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--linux-user/main.c4
-rw-r--r--linux-user/mips/syscall_nr.h38
-rw-r--r--linux-user/mmap.c4
-rw-r--r--linux-user/ppc/syscall_nr.h30
-rw-r--r--linux-user/qemu.h8
-rw-r--r--linux-user/signal.c156
-rw-r--r--linux-user/syscall.c85
-rw-r--r--linux-user/syscall_defs.h2
-rw-r--r--qemu-binfmt-conf.sh8
-rw-r--r--target-arm/cpu.h6
-rw-r--r--target-arm/helper.c16
-rw-r--r--target-arm/op_helper.c14
-rw-r--r--target-sparc/cpu.h2
-rw-r--r--target-sparc/helper.c14
14 files changed, 292 insertions, 95 deletions
diff --git a/linux-user/main.c b/linux-user/main.c
index dbba8befe7..7d41d4ab88 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -2711,7 +2711,7 @@ int main(int argc, char **argv, char **envp)
     struct target_pt_regs regs1, *regs = &regs1;
     struct image_info info1, *info = &info1;
     struct linux_binprm bprm;
-    TaskState ts1, *ts = &ts1;
+    TaskState *ts;
     CPUState *env;
     int optind;
     const char *r;
@@ -3038,7 +3038,7 @@ int main(int argc, char **argv, char **envp)
     }
     target_argv[target_argc] = NULL;
 
-    memset(ts, 0, sizeof(TaskState));
+    ts = qemu_mallocz (sizeof(TaskState));
     init_task_state(ts);
     /* build Task State */
     ts->info = info;
diff --git a/linux-user/mips/syscall_nr.h b/linux-user/mips/syscall_nr.h
index 8228616074..059530801b 100644
--- a/linux-user/mips/syscall_nr.h
+++ b/linux-user/mips/syscall_nr.h
@@ -18,15 +18,15 @@
 #define TARGET_NR_time			(TARGET_NR_Linux +  13)
 #define TARGET_NR_mknod			(TARGET_NR_Linux +  14)
 #define TARGET_NR_chmod			(TARGET_NR_Linux +  15)
-#define TARGET_NR_lchown32		(TARGET_NR_Linux +  16)
+#define TARGET_NR_lchown		(TARGET_NR_Linux +  16)
 #define TARGET_NR_break			(TARGET_NR_Linux +  17)
 #define TARGET_NR_unused18		(TARGET_NR_Linux +  18)
 #define TARGET_NR_lseek			(TARGET_NR_Linux +  19)
 #define TARGET_NR_getpid		(TARGET_NR_Linux +  20)
 #define TARGET_NR_mount			(TARGET_NR_Linux +  21)
 #define TARGET_NR_umount		(TARGET_NR_Linux +  22)
-#define TARGET_NR_setuid32		(TARGET_NR_Linux +  23)
-#define TARGET_NR_getuid32		(TARGET_NR_Linux +  24)
+#define TARGET_NR_setuid		(TARGET_NR_Linux +  23)
+#define TARGET_NR_getuid		(TARGET_NR_Linux +  24)
 #define TARGET_NR_stime			(TARGET_NR_Linux +  25)
 #define TARGET_NR_ptrace		(TARGET_NR_Linux +  26)
 #define TARGET_NR_alarm			(TARGET_NR_Linux +  27)
@@ -48,11 +48,11 @@
 #define TARGET_NR_times			(TARGET_NR_Linux +  43)
 #define TARGET_NR_prof			(TARGET_NR_Linux +  44)
 #define TARGET_NR_brk			(TARGET_NR_Linux +  45)
-#define TARGET_NR_setgid32		(TARGET_NR_Linux +  46)
-#define TARGET_NR_getgid32		(TARGET_NR_Linux +  47)
+#define TARGET_NR_setgid		(TARGET_NR_Linux +  46)
+#define TARGET_NR_getgid		(TARGET_NR_Linux +  47)
 #define TARGET_NR_signal		(TARGET_NR_Linux +  48)
-#define TARGET_NR_geteuid32		(TARGET_NR_Linux +  49)
-#define TARGET_NR_getegid32		(TARGET_NR_Linux +  50)
+#define TARGET_NR_geteuid		(TARGET_NR_Linux +  49)
+#define TARGET_NR_getegid		(TARGET_NR_Linux +  50)
 #define TARGET_NR_acct			(TARGET_NR_Linux +  51)
 #define TARGET_NR_umount2		(TARGET_NR_Linux +  52)
 #define TARGET_NR_lock			(TARGET_NR_Linux +  53)
@@ -72,8 +72,8 @@
 #define TARGET_NR_sigaction		(TARGET_NR_Linux +  67)
 #define TARGET_NR_sgetmask		(TARGET_NR_Linux +  68)
 #define TARGET_NR_ssetmask		(TARGET_NR_Linux +  69)
-#define TARGET_NR_setreuid32		(TARGET_NR_Linux +  70)
-#define TARGET_NR_setregid32		(TARGET_NR_Linux +  71)
+#define TARGET_NR_setreuid		(TARGET_NR_Linux +  70)
+#define TARGET_NR_setregid		(TARGET_NR_Linux +  71)
 #define TARGET_NR_sigsuspend		(TARGET_NR_Linux +  72)
 #define TARGET_NR_sigpending		(TARGET_NR_Linux +  73)
 #define TARGET_NR_sethostname		(TARGET_NR_Linux +  74)
@@ -82,8 +82,8 @@
 #define TARGET_NR_getrusage		(TARGET_NR_Linux +  77)
 #define TARGET_NR_gettimeofday		(TARGET_NR_Linux +  78)
 #define TARGET_NR_settimeofday		(TARGET_NR_Linux +  79)
-#define TARGET_NR_getgroups32		(TARGET_NR_Linux +  80)
-#define TARGET_NR_setgroups32		(TARGET_NR_Linux +  81)
+#define TARGET_NR_getgroups		(TARGET_NR_Linux +  80)
+#define TARGET_NR_setgroups		(TARGET_NR_Linux +  81)
 #define TARGET_NR_reserved82		(TARGET_NR_Linux +  82)
 #define TARGET_NR_symlink		(TARGET_NR_Linux +  83)
 #define TARGET_NR_unused84		(TARGET_NR_Linux +  84)
@@ -97,7 +97,7 @@
 #define TARGET_NR_truncate		(TARGET_NR_Linux +  92)
 #define TARGET_NR_ftruncate		(TARGET_NR_Linux +  93)
 #define TARGET_NR_fchmod		(TARGET_NR_Linux +  94)
-#define TARGET_NR_fchown32		(TARGET_NR_Linux +  95)
+#define TARGET_NR_fchown		(TARGET_NR_Linux +  95)
 #define TARGET_NR_getpriority		(TARGET_NR_Linux +  96)
 #define TARGET_NR_setpriority		(TARGET_NR_Linux +  97)
 #define TARGET_NR_profil		(TARGET_NR_Linux +  98)
@@ -140,8 +140,8 @@
 #define TARGET_NR_sysfs			(TARGET_NR_Linux + 135)
 #define TARGET_NR_personality		(TARGET_NR_Linux + 136)
 #define TARGET_NR_afs_syscall		(TARGET_NR_Linux + 137) /* Syscall for Andrew File System */
-#define TARGET_NR_setfsuid32		(TARGET_NR_Linux + 138)
-#define TARGET_NR_setfsgid32		(TARGET_NR_Linux + 139)
+#define TARGET_NR_setfsuid		(TARGET_NR_Linux + 138)
+#define TARGET_NR_setfsgid		(TARGET_NR_Linux + 139)
 #define TARGET_NR__llseek		(TARGET_NR_Linux + 140)
 #define TARGET_NR_getdents		(TARGET_NR_Linux + 141)
 #define TARGET_NR__newselect		(TARGET_NR_Linux + 142)
@@ -187,13 +187,13 @@
 #define TARGET_NR_shutdown		(TARGET_NR_Linux + 182)
 #define TARGET_NR_socket		(TARGET_NR_Linux + 183)
 #define TARGET_NR_socketpair		(TARGET_NR_Linux + 184)
-#define TARGET_NR_setresuid32		(TARGET_NR_Linux + 185)
-#define TARGET_NR_getresuid32		(TARGET_NR_Linux + 186)
+#define TARGET_NR_setresuid		(TARGET_NR_Linux + 185)
+#define TARGET_NR_getresuid		(TARGET_NR_Linux + 186)
 #define TARGET_NR_query_module		(TARGET_NR_Linux + 187)
 #define TARGET_NR_poll			(TARGET_NR_Linux + 188)
 #define TARGET_NR_nfsservctl		(TARGET_NR_Linux + 189)
-#define TARGET_NR_setresgid32		(TARGET_NR_Linux + 190)
-#define TARGET_NR_getresgid32		(TARGET_NR_Linux + 191)
+#define TARGET_NR_setresgid		(TARGET_NR_Linux + 190)
+#define TARGET_NR_getresgid		(TARGET_NR_Linux + 191)
 #define TARGET_NR_prctl			(TARGET_NR_Linux + 192)
 #define TARGET_NR_rt_sigreturn		(TARGET_NR_Linux + 193)
 #define TARGET_NR_rt_sigaction		(TARGET_NR_Linux + 194)
@@ -204,7 +204,7 @@
 #define TARGET_NR_rt_sigsuspend		(TARGET_NR_Linux + 199)
 #define TARGET_NR_pread64		(TARGET_NR_Linux + 200)
 #define TARGET_NR_pwrite64		(TARGET_NR_Linux + 201)
-#define TARGET_NR_chown32		(TARGET_NR_Linux + 202)
+#define TARGET_NR_chown 		(TARGET_NR_Linux + 202)
 #define TARGET_NR_getcwd		(TARGET_NR_Linux + 203)
 #define TARGET_NR_capget		(TARGET_NR_Linux + 204)
 #define TARGET_NR_capset		(TARGET_NR_Linux + 205)
diff --git a/linux-user/mmap.c b/linux-user/mmap.c
index 035dfbd076..abf21f6064 100644
--- a/linux-user/mmap.c
+++ b/linux-user/mmap.c
@@ -697,7 +697,9 @@ abi_long target_mremap(abi_ulong old_addr, abi_ulong old_size,
                                          old_size, new_size,
                                          flags | MREMAP_FIXED,
                                          g2h(mmap_start));
-            mmap_reserve(old_addr, old_size);
+            if ( RESERVED_VA ) {
+                mmap_reserve(old_addr, old_size);
+            }
         }
     } else {
         int prot = 0;
diff --git a/linux-user/ppc/syscall_nr.h b/linux-user/ppc/syscall_nr.h
index f54276ba33..cc84a4c04d 100644
--- a/linux-user/ppc/syscall_nr.h
+++ b/linux-user/ppc/syscall_nr.h
@@ -17,15 +17,15 @@
 #define TARGET_NR_time                    13
 #define TARGET_NR_mknod                   14
 #define TARGET_NR_chmod                   15
-#define TARGET_NR_lchown32                16
+#define TARGET_NR_lchown                  16
 #define TARGET_NR_break                   17
 #define TARGET_NR_oldstat                 18
 #define TARGET_NR_lseek                   19
 #define TARGET_NR_getpid                  20
 #define TARGET_NR_mount                   21
 #define TARGET_NR_umount                  22
-#define TARGET_NR_setuid32                23
-#define TARGET_NR_getuid32                24
+#define TARGET_NR_setuid                  23
+#define TARGET_NR_getuid                  24
 #define TARGET_NR_stime                   25
 #define TARGET_NR_ptrace                  26
 #define TARGET_NR_alarm                   27
@@ -47,11 +47,11 @@
 #define TARGET_NR_times                   43
 #define TARGET_NR_prof                    44
 #define TARGET_NR_brk                     45
-#define TARGET_NR_setgid32                46
-#define TARGET_NR_getgid32                47
+#define TARGET_NR_setgid                  46
+#define TARGET_NR_getgid                  47
 #define TARGET_NR_signal                  48
-#define TARGET_NR_geteuid32               49
-#define TARGET_NR_getegid32               50
+#define TARGET_NR_geteuid                 49
+#define TARGET_NR_getegid                 50
 #define TARGET_NR_acct                    51
 #define TARGET_NR_umount2                 52
 #define TARGET_NR_lock                    53
@@ -71,8 +71,8 @@
 #define TARGET_NR_sigaction               67
 #define TARGET_NR_sgetmask                68
 #define TARGET_NR_ssetmask                69
-#define TARGET_NR_setreuid32              70
-#define TARGET_NR_setregid32              71
+#define TARGET_NR_setreuid                70
+#define TARGET_NR_setregid                71
 #define TARGET_NR_sigsuspend              72
 #define TARGET_NR_sigpending              73
 #define TARGET_NR_sethostname             74
@@ -81,8 +81,8 @@
 #define TARGET_NR_getrusage               77
 #define TARGET_NR_gettimeofday            78
 #define TARGET_NR_settimeofday            79
-#define TARGET_NR_getgroups32             80
-#define TARGET_NR_setgroups32             81
+#define TARGET_NR_getgroups               80
+#define TARGET_NR_setgroups               81
 #define TARGET_NR_select                  82
 #define TARGET_NR_symlink                 83
 #define TARGET_NR_oldlstat                84
@@ -96,7 +96,7 @@
 #define TARGET_NR_truncate                92
 #define TARGET_NR_ftruncate               93
 #define TARGET_NR_fchmod                  94
-#define TARGET_NR_fchown32                95
+#define TARGET_NR_fchown                  95
 #define TARGET_NR_getpriority             96
 #define TARGET_NR_setpriority             97
 #define TARGET_NR_profil                  98
@@ -139,8 +139,8 @@
 #define TARGET_NR_sysfs                  135
 #define TARGET_NR_personality            136
 #define TARGET_NR_afs_syscall            137 /* Syscall for Andrew File System */
-#define TARGET_NR_setfsuid32             138
-#define TARGET_NR_setfsgid32             139
+#define TARGET_NR_setfsuid               138
+#define TARGET_NR_setfsgid               139
 #define TARGET_NR__llseek                140
 #define TARGET_NR_getdents               141
 #define TARGET_NR__newselect             142
@@ -182,7 +182,7 @@
 #define TARGET_NR_rt_sigsuspend          178
 #define TARGET_NR_pread64                179
 #define TARGET_NR_pwrite64               180
-#define TARGET_NR_chown32                181
+#define TARGET_NR_chown                  181
 #define TARGET_NR_getcwd                 182
 #define TARGET_NR_capget                 183
 #define TARGET_NR_capset                 184
diff --git a/linux-user/qemu.h b/linux-user/qemu.h
index 708021e006..e66a02bce3 100644
--- a/linux-user/qemu.h
+++ b/linux-user/qemu.h
@@ -126,8 +126,6 @@ typedef struct TaskState {
     struct sigqueue sigqueue_table[MAX_SIGQUEUE_SIZE]; /* siginfo queue */
     struct sigqueue *first_free; /* first free siginfo queue entry */
     int signal_pending; /* non zero if a signal may be pending */
-
-    uint8_t stack[0];
 } __attribute__((aligned(16))) TaskState;
 
 extern char *exec_path;
@@ -266,8 +264,7 @@ static inline int access_ok(int type, abi_ulong addr, abi_ulong size)
  */
 #define __put_user(x, hptr)\
 ({\
-    int size = sizeof(*hptr);\
-    switch(size) {\
+    switch(sizeof(*hptr)) {\
     case 1:\
         *(uint8_t *)(hptr) = (uint8_t)(typeof(*hptr))(x);\
         break;\
@@ -288,8 +285,7 @@ static inline int access_ok(int type, abi_ulong addr, abi_ulong size)
 
 #define __get_user(x, hptr) \
 ({\
-    int size = sizeof(*hptr);\
-    switch(size) {\
+    switch(sizeof(*hptr)) {\
     case 1:\
         x = (typeof(*hptr))*(uint8_t *)(hptr);\
         break;\
diff --git a/linux-user/signal.c b/linux-user/signal.c
index 7c62fac938..c846b8c7d4 100644
--- a/linux-user/signal.c
+++ b/linux-user/signal.c
@@ -1108,10 +1108,44 @@ struct target_ucontext_v2 {
     target_stack_t tuc_stack;
     struct target_sigcontext tuc_mcontext;
     target_sigset_t  tuc_sigmask;	/* mask last for extensibility */
-    char __unused[128 - sizeof(sigset_t)];
+    char __unused[128 - sizeof(target_sigset_t)];
     abi_ulong tuc_regspace[128] __attribute__((__aligned__(8)));
 };
 
+struct target_user_vfp {
+    uint64_t fpregs[32];
+    abi_ulong fpscr;
+};
+
+struct target_user_vfp_exc {
+    abi_ulong fpexc;
+    abi_ulong fpinst;
+    abi_ulong fpinst2;
+};
+
+struct target_vfp_sigframe {
+    abi_ulong magic;
+    abi_ulong size;
+    struct target_user_vfp ufp;
+    struct target_user_vfp_exc ufp_exc;
+} __attribute__((__aligned__(8)));
+
+struct target_iwmmxt_sigframe {
+    abi_ulong magic;
+    abi_ulong size;
+    uint64_t regs[16];
+    /* Note that not all the coprocessor control registers are stored here */
+    uint32_t wcssf;
+    uint32_t wcasf;
+    uint32_t wcgr0;
+    uint32_t wcgr1;
+    uint32_t wcgr2;
+    uint32_t wcgr3;
+} __attribute__((__aligned__(8)));
+
+#define TARGET_VFP_MAGIC 0x56465001
+#define TARGET_IWMMXT_MAGIC 0x12ef842a
+
 struct sigframe_v1
 {
     struct target_sigcontext sc;
@@ -1255,11 +1289,48 @@ setup_return(CPUState *env, struct target_sigaction *ka,
 	return 0;
 }
 
+static abi_ulong *setup_sigframe_v2_vfp(abi_ulong *regspace, CPUState *env)
+{
+    int i;
+    struct target_vfp_sigframe *vfpframe;
+    vfpframe = (struct target_vfp_sigframe *)regspace;
+    __put_user(TARGET_VFP_MAGIC, &vfpframe->magic);
+    __put_user(sizeof(*vfpframe), &vfpframe->size);
+    for (i = 0; i < 32; i++) {
+        __put_user(env->vfp.regs[i], &vfpframe->ufp.fpregs[i]);
+    }
+    __put_user(vfp_get_fpscr(env), &vfpframe->ufp.fpscr);
+    __put_user(env->vfp.xregs[ARM_VFP_FPEXC], &vfpframe->ufp_exc.fpexc);
+    __put_user(env->vfp.xregs[ARM_VFP_FPINST], &vfpframe->ufp_exc.fpinst);
+    __put_user(env->vfp.xregs[ARM_VFP_FPINST2], &vfpframe->ufp_exc.fpinst2);
+    return (abi_ulong*)(vfpframe+1);
+}
+
+static abi_ulong *setup_sigframe_v2_iwmmxt(abi_ulong *regspace, CPUState *env)
+{
+    int i;
+    struct target_iwmmxt_sigframe *iwmmxtframe;
+    iwmmxtframe = (struct target_iwmmxt_sigframe *)regspace;
+    __put_user(TARGET_IWMMXT_MAGIC, &iwmmxtframe->magic);
+    __put_user(sizeof(*iwmmxtframe), &iwmmxtframe->size);
+    for (i = 0; i < 16; i++) {
+        __put_user(env->iwmmxt.regs[i], &iwmmxtframe->regs[i]);
+    }
+    __put_user(env->vfp.xregs[ARM_IWMMXT_wCSSF], &iwmmxtframe->wcssf);
+    __put_user(env->vfp.xregs[ARM_IWMMXT_wCASF], &iwmmxtframe->wcssf);
+    __put_user(env->vfp.xregs[ARM_IWMMXT_wCGR0], &iwmmxtframe->wcgr0);
+    __put_user(env->vfp.xregs[ARM_IWMMXT_wCGR1], &iwmmxtframe->wcgr1);
+    __put_user(env->vfp.xregs[ARM_IWMMXT_wCGR2], &iwmmxtframe->wcgr2);
+    __put_user(env->vfp.xregs[ARM_IWMMXT_wCGR3], &iwmmxtframe->wcgr3);
+    return (abi_ulong*)(iwmmxtframe+1);
+}
+
 static void setup_sigframe_v2(struct target_ucontext_v2 *uc,
                               target_sigset_t *set, CPUState *env)
 {
     struct target_sigaltstack stack;
     int i;
+    abi_ulong *regspace;
 
     /* Clear all the bits of the ucontext we don't use.  */
     memset(uc, 0, offsetof(struct target_ucontext_v2, tuc_mcontext));
@@ -1271,7 +1342,18 @@ static void setup_sigframe_v2(struct target_ucontext_v2 *uc,
     memcpy(&uc->tuc_stack, &stack, sizeof(stack));
 
     setup_sigcontext(&uc->tuc_mcontext, env, set->sig[0]);
-    /* FIXME: Save coprocessor signal frame.  */
+    /* Save coprocessor signal frame.  */
+    regspace = uc->tuc_regspace;
+    if (arm_feature(env, ARM_FEATURE_VFP)) {
+        regspace = setup_sigframe_v2_vfp(regspace, env);
+    }
+    if (arm_feature(env, ARM_FEATURE_IWMMXT)) {
+        regspace = setup_sigframe_v2_iwmmxt(regspace, env);
+    }
+
+    /* Write terminating magic word */
+    __put_user(0, regspace);
+
     for(i = 0; i < TARGET_NSIG_WORDS; i++) {
         __put_user(set->sig[i], &uc->tuc_sigmask.sig[i]);
     }
@@ -1490,10 +1572,65 @@ badframe:
 	return 0;
 }
 
+static abi_ulong *restore_sigframe_v2_vfp(CPUState *env, abi_ulong *regspace)
+{
+    int i;
+    abi_ulong magic, sz;
+    uint32_t fpscr, fpexc;
+    struct target_vfp_sigframe *vfpframe;
+    vfpframe = (struct target_vfp_sigframe *)regspace;
+
+    __get_user(magic, &vfpframe->magic);
+    __get_user(sz, &vfpframe->size);
+    if (magic != TARGET_VFP_MAGIC || sz != sizeof(*vfpframe)) {
+        return 0;
+    }
+    for (i = 0; i < 32; i++) {
+        __get_user(env->vfp.regs[i], &vfpframe->ufp.fpregs[i]);
+    }
+    __get_user(fpscr, &vfpframe->ufp.fpscr);
+    vfp_set_fpscr(env, fpscr);
+    __get_user(fpexc, &vfpframe->ufp_exc.fpexc);
+    /* Sanitise FPEXC: ensure VFP is enabled, FPINST2 is invalid
+     * and the exception flag is cleared
+     */
+    fpexc |= (1 << 30);
+    fpexc &= ~((1 << 31) | (1 << 28));
+    env->vfp.xregs[ARM_VFP_FPEXC] = fpexc;
+    __get_user(env->vfp.xregs[ARM_VFP_FPINST], &vfpframe->ufp_exc.fpinst);
+    __get_user(env->vfp.xregs[ARM_VFP_FPINST2], &vfpframe->ufp_exc.fpinst2);
+    return (abi_ulong*)(vfpframe + 1);
+}
+
+static abi_ulong *restore_sigframe_v2_iwmmxt(CPUState *env, abi_ulong *regspace)
+{
+    int i;
+    abi_ulong magic, sz;
+    struct target_iwmmxt_sigframe *iwmmxtframe;
+    iwmmxtframe = (struct target_iwmmxt_sigframe *)regspace;
+
+    __get_user(magic, &iwmmxtframe->magic);
+    __get_user(sz, &iwmmxtframe->size);
+    if (magic != TARGET_IWMMXT_MAGIC || sz != sizeof(*iwmmxtframe)) {
+        return 0;
+    }
+    for (i = 0; i < 16; i++) {
+        __get_user(env->iwmmxt.regs[i], &iwmmxtframe->regs[i]);
+    }
+    __get_user(env->vfp.xregs[ARM_IWMMXT_wCSSF], &iwmmxtframe->wcssf);
+    __get_user(env->vfp.xregs[ARM_IWMMXT_wCASF], &iwmmxtframe->wcssf);
+    __get_user(env->vfp.xregs[ARM_IWMMXT_wCGR0], &iwmmxtframe->wcgr0);
+    __get_user(env->vfp.xregs[ARM_IWMMXT_wCGR1], &iwmmxtframe->wcgr1);
+    __get_user(env->vfp.xregs[ARM_IWMMXT_wCGR2], &iwmmxtframe->wcgr2);
+    __get_user(env->vfp.xregs[ARM_IWMMXT_wCGR3], &iwmmxtframe->wcgr3);
+    return (abi_ulong*)(iwmmxtframe + 1);
+}
+
 static int do_sigframe_return_v2(CPUState *env, target_ulong frame_addr,
                                  struct target_ucontext_v2 *uc)
 {
     sigset_t host_set;
+    abi_ulong *regspace;
 
     target_to_host_sigset(&host_set, &uc->tuc_sigmask);
     sigprocmask(SIG_SETMASK, &host_set, NULL);
@@ -1501,6 +1638,21 @@ static int do_sigframe_return_v2(CPUState *env, target_ulong frame_addr,
     if (restore_sigcontext(env, &uc->tuc_mcontext))
         return 1;
 
+    /* Restore coprocessor signal frame */
+    regspace = uc->tuc_regspace;
+    if (arm_feature(env, ARM_FEATURE_VFP)) {
+        regspace = restore_sigframe_v2_vfp(env, regspace);
+        if (!regspace) {
+            return 1;
+        }
+    }
+    if (arm_feature(env, ARM_FEATURE_IWMMXT)) {
+        regspace = restore_sigframe_v2_iwmmxt(env, regspace);
+        if (!regspace) {
+            return 1;
+        }
+    }
+
     if (do_sigaltstack(frame_addr + offsetof(struct target_ucontext_v2, tuc_stack), 0, get_sp_from_cpustate(env)) == -EFAULT)
         return 1;
 
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index d44f512ed3..c3e870654d 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -1374,15 +1374,66 @@ static abi_long do_getsockopt(int sockfd, int level, int optname,
 
     switch(level) {
     case TARGET_SOL_SOCKET:
-    	level = SOL_SOCKET;
-	switch (optname) {
-	case TARGET_SO_LINGER:
-	case TARGET_SO_RCVTIMEO:
-	case TARGET_SO_SNDTIMEO:
-	case TARGET_SO_PEERCRED:
-	case TARGET_SO_PEERNAME:
-	    /* These don't just return a single integer */
-	    goto unimplemented;
+        level = SOL_SOCKET;
+        switch (optname) {
+        /* These don't just return a single integer */
+        case TARGET_SO_LINGER:
+        case TARGET_SO_RCVTIMEO:
+        case TARGET_SO_SNDTIMEO:
+        case TARGET_SO_PEERCRED:
+        case TARGET_SO_PEERNAME:
+            goto unimplemented;
+        /* Options with 'int' argument.  */
+        case TARGET_SO_DEBUG:
+            optname = SO_DEBUG;
+            goto int_case;
+        case TARGET_SO_REUSEADDR:
+            optname = SO_REUSEADDR;
+            goto int_case;
+        case TARGET_SO_TYPE:
+            optname = SO_TYPE;
+            goto int_case;
+        case TARGET_SO_ERROR:
+            optname = SO_ERROR;
+            goto int_case;
+        case TARGET_SO_DONTROUTE:
+            optname = SO_DONTROUTE;
+            goto int_case;
+        case TARGET_SO_BROADCAST:
+            optname = SO_BROADCAST;
+            goto int_case;
+        case TARGET_SO_SNDBUF:
+            optname = SO_SNDBUF;
+            goto int_case;
+        case TARGET_SO_RCVBUF:
+            optname = SO_RCVBUF;
+            goto int_case;
+        case TARGET_SO_KEEPALIVE:
+            optname = SO_KEEPALIVE;
+            goto int_case;
+        case TARGET_SO_OOBINLINE:
+            optname = SO_OOBINLINE;
+            goto int_case;
+        case TARGET_SO_NO_CHECK:
+            optname = SO_NO_CHECK;
+            goto int_case;
+        case TARGET_SO_PRIORITY:
+            optname = SO_PRIORITY;
+            goto int_case;
+#ifdef SO_BSDCOMPAT
+        case TARGET_SO_BSDCOMPAT:
+            optname = SO_BSDCOMPAT;
+            goto int_case;
+#endif
+        case TARGET_SO_PASSCRED:
+            optname = SO_PASSCRED;
+            goto int_case;
+        case TARGET_SO_TIMESTAMP:
+            optname = SO_TIMESTAMP;
+            goto int_case;
+        case TARGET_SO_RCVLOWAT:
+            optname = SO_RCVLOWAT;
+            goto int_case;
         default:
             goto int_case;
         }
@@ -1406,7 +1457,7 @@ static abi_long do_getsockopt(int sockfd, int level, int optname,
         } else {
             if (put_user_u8(val, optval_addr))
                 return -TARGET_EFAULT;
-	}
+        }
         if (put_user_u32(len, optlen))
             return -TARGET_EFAULT;
         break;
@@ -3584,11 +3635,12 @@ static int do_fork(CPUState *env, unsigned int flags, abi_ulong newsp,
 {
     int ret;
     TaskState *ts;
-    uint8_t *new_stack;
     CPUState *new_env;
 #if defined(CONFIG_USE_NPTL)
     unsigned int nptl_flags;
     sigset_t sigmask;
+#else
+    uint8_t *new_stack;
 #endif
 
     /* Emulate vfork() with fork() */
@@ -3601,9 +3653,8 @@ static int do_fork(CPUState *env, unsigned int flags, abi_ulong newsp,
         new_thread_info info;
         pthread_attr_t attr;
 #endif
-        ts = qemu_mallocz(sizeof(TaskState) + NEW_STACK_SIZE);
+        ts = qemu_mallocz(sizeof(TaskState));
         init_task_state(ts);
-        new_stack = ts->stack;
         /* we create a new CPU instance. */
         new_env = cpu_copy(env);
 #if defined(TARGET_I386) || defined(TARGET_SPARC) || defined(TARGET_PPC)
@@ -3639,7 +3690,8 @@ static int do_fork(CPUState *env, unsigned int flags, abi_ulong newsp,
             info.parent_tidptr = parent_tidptr;
 
         ret = pthread_attr_init(&attr);
-        ret = pthread_attr_setstack(&attr, new_stack, NEW_STACK_SIZE);
+        ret = pthread_attr_setstacksize(&attr, NEW_STACK_SIZE);
+        ret = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
         /* It is not safe to deliver signals until the child has finished
            initializing, so temporarily block all signals.  */
         sigfillset(&sigmask);
@@ -3667,6 +3719,7 @@ static int do_fork(CPUState *env, unsigned int flags, abi_ulong newsp,
         if (flags & CLONE_NPTL_FLAGS2)
             return -EINVAL;
         /* This is probably going to die very quickly, but do it anyway.  */
+        new_stack = qemu_mallocz (NEW_STACK_SIZE);
 #ifdef __ia64__
         ret = __clone2(clone_func, new_stack, NEW_STACK_SIZE, flags, new_env);
 #else
@@ -4240,7 +4293,9 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
               sys_futex(g2h(ts->child_tidptr), FUTEX_WAKE, INT_MAX,
                         NULL, NULL, 0);
           }
-          /* TODO: Free CPU state.  */
+          thread_env = NULL;
+          qemu_free(cpu_env);
+          qemu_free(ts);
           pthread_exit(NULL);
       }
 #endif
diff --git a/linux-user/syscall_defs.h b/linux-user/syscall_defs.h
index 6c57e2481a..20c93d0f7f 100644
--- a/linux-user/syscall_defs.h
+++ b/linux-user/syscall_defs.h
@@ -49,7 +49,7 @@
 #define TARGET_IOC_TYPEBITS	8
 
 #if defined(TARGET_I386) || defined(TARGET_ARM) || defined(TARGET_SPARC) \
-    || defined(TARGET_M68K) || defined(TARGET_SH4) || defined(TARGET_CRIS)
+    || defined(TARGET_M68K) || defined(TARGET_SH4) || defined(TARGET_CRIS) || defined(TARGET_PPC) || defined(TARGET_MIPS)
     /* 16 bit uid wrappers emulation */
 #define USE_UID16
 #endif
diff --git a/qemu-binfmt-conf.sh b/qemu-binfmt-conf.sh
index ba916ac78e..c50beb7337 100644
--- a/qemu-binfmt-conf.sh
+++ b/qemu-binfmt-conf.sh
@@ -12,7 +12,7 @@ fi
 # probe cpu type
 cpu=`uname -m`
 case "$cpu" in
-  i386|i486|i586|i686|i86pc|BePC)
+  i386|i486|i586|i686|i86pc|BePC|x86_64)
     cpu="i386"
   ;;
   m68k)
@@ -24,7 +24,7 @@ case "$cpu" in
   "Power Macintosh"|ppc|ppc64)
     cpu="ppc"
   ;;
-  armv4l)
+  armv[4-9]*)
     cpu="arm"
   ;;
 esac
@@ -60,3 +60,7 @@ if [ $cpu != "mips" ] ; then
     echo   ':mips64:M::\x7fELF\x02\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x08:\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff:/usr/local/bin/qemu-mips64:' > /proc/sys/fs/binfmt_misc/register
     echo   ':mips64el:M::\x7fELF\x02\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x08\x00:\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff:/usr/local/bin/qemu-mips64el:' > /proc/sys/fs/binfmt_misc/register
 fi
+if [ $cpu != "sh" ] ; then
+    echo    ':sh4:M::\x7fELF\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x2a\x00:\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff:/usr/local/bin/qemu-sh4:' > /proc/sys/fs/binfmt_misc/register
+    echo    ':sh4eb:M::\x7fELF\x01\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x2a:\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff:/usr/local/bin/qemu-sh4eb:' > /proc/sys/fs/binfmt_misc/register
+fi
diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index b87c605f7f..340933ef50 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -227,8 +227,6 @@ int cpu_arm_handle_mmu_fault (CPUARMState *env, target_ulong address, int rw,
                               int mmu_idx, int is_softmuu);
 #define cpu_handle_mmu_fault cpu_arm_handle_mmu_fault
 
-void cpu_lock(void);
-void cpu_unlock(void);
 static inline void cpu_set_tls(CPUARMState *env, target_ulong newtls)
 {
   env->cp15.c13_tls2 = newtls;
@@ -302,6 +300,10 @@ static inline void xpsr_write(CPUARMState *env, uint32_t val, uint32_t mask)
     }
 }
 
+/* Return the current FPSCR value.  */
+uint32_t vfp_get_fpscr(CPUARMState *env);
+void vfp_set_fpscr(CPUARMState *env, uint32_t val);
+
 enum arm_cpu_mode {
   ARM_CPU_MODE_USR = 0x10,
   ARM_CPU_MODE_FIQ = 0x11,
diff --git a/target-arm/helper.c b/target-arm/helper.c
index 996d40d185..2a1f44860b 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -203,7 +203,13 @@ void cpu_reset(CPUARMState *env)
         cpu_reset_model_id(env, id);
 #if defined (CONFIG_USER_ONLY)
     env->uncached_cpsr = ARM_CPU_MODE_USR;
+    /* For user mode we must enable access to coprocessors */
     env->vfp.xregs[ARM_VFP_FPEXC] = 1 << 30;
+    if (arm_feature(env, ARM_FEATURE_IWMMXT)) {
+        env->cp15.c15_cpar = 3;
+    } else if (arm_feature(env, ARM_FEATURE_XSCALE)) {
+        env->cp15.c15_cpar = 1;
+    }
 #else
     /* SVC mode with interrupts disabled.  */
     env->uncached_cpsr = ARM_CPU_MODE_SVC | CPSR_A | CPSR_F | CPSR_I;
@@ -2245,6 +2251,11 @@ uint32_t HELPER(vfp_get_fpscr)(CPUState *env)
     return fpscr;
 }
 
+uint32_t vfp_get_fpscr(CPUState *env)
+{
+    return HELPER(vfp_get_fpscr)(env);
+}
+
 /* Convert vfp exception flags to target form.  */
 static inline int vfp_exceptbits_to_host(int target_bits)
 {
@@ -2301,6 +2312,11 @@ void HELPER(vfp_set_fpscr)(CPUState *env, uint32_t val)
     set_float_exception_flags(i, &env->vfp.fp_status);
 }
 
+void vfp_set_fpscr(CPUState *env, uint32_t val)
+{
+    HELPER(vfp_set_fpscr)(env, val);
+}
+
 #define VFP_HELPER(name, p) HELPER(glue(glue(vfp_,name),p))
 
 #define VFP_BINOP(name) \
diff --git a/target-arm/op_helper.c b/target-arm/op_helper.c
index 9b1a0143d2..43baa63006 100644
--- a/target-arm/op_helper.c
+++ b/target-arm/op_helper.c
@@ -28,20 +28,6 @@ void raise_exception(int tt)
     cpu_loop_exit();
 }
 
-/* thread support */
-
-static spinlock_t global_cpu_lock = SPIN_LOCK_UNLOCKED;
-
-void cpu_lock(void)
-{
-    spin_lock(&global_cpu_lock);
-}
-
-void cpu_unlock(void)
-{
-    spin_unlock(&global_cpu_lock);
-}
-
 uint32_t HELPER(neon_tbl)(uint32_t ireg, uint32_t def,
                           uint32_t rn, uint32_t maxindex)
 {
diff --git a/target-sparc/cpu.h b/target-sparc/cpu.h
index 7e0d17c0b1..3e93bbbdbd 100644
--- a/target-sparc/cpu.h
+++ b/target-sparc/cpu.h
@@ -444,8 +444,6 @@ CPUSPARCState *cpu_sparc_init(const char *cpu_model);
 void cpu_sparc_set_id(CPUSPARCState *env, unsigned int cpu);
 void sparc_cpu_list (FILE *f, int (*cpu_fprintf)(FILE *f, const char *fmt,
                                                  ...));
-void cpu_lock(void);
-void cpu_unlock(void);
 int cpu_sparc_handle_mmu_fault(CPUSPARCState *env1, target_ulong address, int rw,
                                int mmu_idx, int is_softmmu);
 #define cpu_handle_mmu_fault cpu_sparc_handle_mmu_fault
diff --git a/target-sparc/helper.c b/target-sparc/helper.c
index e84c31256f..7e45d7ac5c 100644
--- a/target-sparc/helper.c
+++ b/target-sparc/helper.c
@@ -41,20 +41,6 @@ static int cpu_sparc_find_by_name(sparc_def_t *cpu_def, const char *cpu_model);
 
 /* Sparc MMU emulation */
 
-/* thread support */
-
-static spinlock_t global_cpu_lock = SPIN_LOCK_UNLOCKED;
-
-void cpu_lock(void)
-{
-    spin_lock(&global_cpu_lock);
-}
-
-void cpu_unlock(void)
-{
-    spin_unlock(&global_cpu_lock);
-}
-
 #if defined(CONFIG_USER_ONLY)
 
 int cpu_sparc_handle_mmu_fault(CPUState *env1, target_ulong address, int rw,