diff options
author | Edgar E. Iglesias <edgar@axis.com> | 2010-12-04 04:18:28 +0100 |
---|---|---|
committer | Edgar E. Iglesias <edgar@axis.com> | 2010-12-04 04:18:28 +0100 |
commit | bcd478781ab1d11911ab5505c34b5577de904eeb (patch) | |
tree | 879a66ede45b478b118f31c652c61241fddbc7e1 | |
parent | db1923de6099fd2d1eee0693757a639978b15e1b (diff) | |
parent | b2e7aab2502260a18c68072f6b6e4271385663c4 (diff) |
Merge branch 'linux-user-for-upstream' of git://gitorious.org/qemu-maemo/qemu
* 'linux-user-for-upstream' of git://gitorious.org/qemu-maemo/qemu:
linux-user: fix mips and ppc to use UID16
update binfmt conf
linux-user: fix compiler error on nptl
ARM: linux-user: Restore iWMMXT state from ucontext on sigreturn
ARM: linux-user: Expose iWMMXT registers to signal handlers
ARM: linux-user: Restore VFP state from ucontext on sigreturn
ARM: linux-user: Expose VFP registers to signal handlers
ARM: Expose vfp_get_fpscr() and vfp_set_fpscr() to C code
ARM: linux-user: Correct size of padding in target_ucontext_v2
target-sparc: remove unused functions cpu_lock(), cpu_unlock()
ARM: enable XScale/iWMMXT in linux-user mode
linux-user: Translate getsockopt level option
linux-user: remove unnecessary local from __get_user(), __put_user()
linux-user: fix memory leaks with NPTL emulation
linux-user: mmap_reserve() not controlled by RESERVED_VA
[PATCH] target-arm: remove unused functions cpu_lock(), cpu_unlock()
-rw-r--r-- | linux-user/main.c | 4 | ||||
-rw-r--r-- | linux-user/mips/syscall_nr.h | 38 | ||||
-rw-r--r-- | linux-user/mmap.c | 4 | ||||
-rw-r--r-- | linux-user/ppc/syscall_nr.h | 30 | ||||
-rw-r--r-- | linux-user/qemu.h | 8 | ||||
-rw-r--r-- | linux-user/signal.c | 156 | ||||
-rw-r--r-- | linux-user/syscall.c | 85 | ||||
-rw-r--r-- | linux-user/syscall_defs.h | 2 | ||||
-rw-r--r-- | qemu-binfmt-conf.sh | 8 | ||||
-rw-r--r-- | target-arm/cpu.h | 6 | ||||
-rw-r--r-- | target-arm/helper.c | 16 | ||||
-rw-r--r-- | target-arm/op_helper.c | 14 | ||||
-rw-r--r-- | target-sparc/cpu.h | 2 | ||||
-rw-r--r-- | target-sparc/helper.c | 14 |
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 = ®s1; 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, |