diff options
Diffstat (limited to 'linux-user/syscall.c')
| -rw-r--r-- | linux-user/syscall.c | 102 |
1 files changed, 83 insertions, 19 deletions
diff --git a/linux-user/syscall.c b/linux-user/syscall.c index 630a455276..3ba3ef5719 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -218,7 +218,6 @@ _syscall3(int, sys_getdents, uint, fd, struct linux_dirent *, dirp, uint, count) #if defined(TARGET_NR_getdents64) && defined(__NR_getdents64) _syscall3(int, sys_getdents64, uint, fd, struct linux_dirent64 *, dirp, uint, count); #endif -_syscall2(int, sys_getpriority, int, which, int, who); #if defined(TARGET_NR__llseek) && defined(__NR_llseek) _syscall5(int, _llseek, uint, fd, ulong, hi, ulong, lo, loff_t *, res, uint, wh); @@ -261,14 +260,27 @@ static bitmask_transtbl fcntl_flags_tbl[] = { { TARGET_O_TRUNC, TARGET_O_TRUNC, O_TRUNC, O_TRUNC, }, { TARGET_O_APPEND, TARGET_O_APPEND, O_APPEND, O_APPEND, }, { TARGET_O_NONBLOCK, TARGET_O_NONBLOCK, O_NONBLOCK, O_NONBLOCK, }, + { TARGET_O_SYNC, TARGET_O_DSYNC, O_SYNC, O_DSYNC, }, { TARGET_O_SYNC, TARGET_O_SYNC, O_SYNC, O_SYNC, }, { TARGET_FASYNC, TARGET_FASYNC, FASYNC, FASYNC, }, { TARGET_O_DIRECTORY, TARGET_O_DIRECTORY, O_DIRECTORY, O_DIRECTORY, }, { TARGET_O_NOFOLLOW, TARGET_O_NOFOLLOW, O_NOFOLLOW, O_NOFOLLOW, }, - { TARGET_O_LARGEFILE, TARGET_O_LARGEFILE, O_LARGEFILE, O_LARGEFILE, }, #if defined(O_DIRECT) { TARGET_O_DIRECT, TARGET_O_DIRECT, O_DIRECT, O_DIRECT, }, #endif +#if defined(O_NOATIME) + { TARGET_O_NOATIME, TARGET_O_NOATIME, O_NOATIME, O_NOATIME }, +#endif +#if defined(O_CLOEXEC) + { TARGET_O_CLOEXEC, TARGET_O_CLOEXEC, O_CLOEXEC, O_CLOEXEC }, +#endif +#if defined(O_PATH) + { TARGET_O_PATH, TARGET_O_PATH, O_PATH, O_PATH }, +#endif + /* Don't terminate the list prematurely on 64-bit host+guest. */ +#if TARGET_O_LARGEFILE != 0 || O_LARGEFILE != 0 + { TARGET_O_LARGEFILE, TARGET_O_LARGEFILE, O_LARGEFILE, O_LARGEFILE, }, +#endif { 0, 0, 0, 0 } }; @@ -5582,7 +5594,8 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, break; #ifdef TARGET_NR_pipe2 case TARGET_NR_pipe2: - ret = do_pipe(cpu_env, arg1, arg2, 1); + ret = do_pipe(cpu_env, arg1, + target_to_host_bitmask(arg2, fcntl_flags_tbl), 1); break; #endif case TARGET_NR_times: @@ -5867,11 +5880,10 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, target_to_host_old_sigset(&set, &mask); ret = get_errno(sigprocmask(how, &set, &oldset)); - if (!is_error(ret)) { host_to_target_old_sigset(&mask, &oldset); ret = mask; - ((CPUAlphaState *)cpu_env)->[IR_V0] = 0; /* force no error */ + ((CPUAlphaState *)cpu_env)->ir[IR_V0] = 0; /* force no error */ } #else sigset_t set, oldset, *set_ptr; @@ -6432,10 +6444,21 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, break; #endif case TARGET_NR_getpriority: - /* libc does special remapping of the return value of - * sys_getpriority() so it's just easiest to call - * sys_getpriority() directly rather than through libc. */ - ret = get_errno(sys_getpriority(arg1, arg2)); + /* Note that negative values are valid for getpriority, so we must + differentiate based on errno settings. */ + errno = 0; + ret = getpriority(arg1, arg2); + if (ret == -1 && errno != 0) { + ret = -host_to_target_errno(errno); + break; + } +#ifdef TARGET_ALPHA + /* Return value is the unbiased priority. Signal no error. */ + ((CPUAlphaState *)cpu_env)->ir[IR_V0] = 0; +#else + /* Return value is a biased priority to avoid negative numbers. */ + ret = 20 - ret; +#endif break; case TARGET_NR_setpriority: ret = get_errno(setpriority(arg1, arg2, arg3)); @@ -7699,13 +7722,13 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, ret = -TARGET_EOPNOTSUPP; switch (arg1) { case TARGET_SSI_IEEE_FP_CONTROL: - case TARGET_SSI_IEEE_RAISE_EXCEPTION: { uint64_t swcr, fpcr, orig_fpcr; - if (get_user_u64 (swcr, arg2)) + if (get_user_u64 (swcr, arg2)) { goto efault; - orig_fpcr = cpu_alpha_load_fpcr (cpu_env); + } + orig_fpcr = cpu_alpha_load_fpcr(cpu_env); fpcr = orig_fpcr & FPCR_DYN_MASK; /* Copied from linux ieee_swcr_to_fpcr. */ @@ -7719,16 +7742,57 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, fpcr |= (swcr & SWCR_MAP_UMZ ? FPCR_UNDZ | FPCR_UNFD : 0); fpcr |= (~swcr & SWCR_TRAP_ENABLE_DNO) << 41; - cpu_alpha_store_fpcr (cpu_env, fpcr); + cpu_alpha_store_fpcr(cpu_env, fpcr); + ret = 0; + } + break; + + case TARGET_SSI_IEEE_RAISE_EXCEPTION: + { + uint64_t exc, fpcr, orig_fpcr; + int si_code; + + if (get_user_u64(exc, arg2)) { + goto efault; + } + + orig_fpcr = cpu_alpha_load_fpcr(cpu_env); + + /* We only add to the exception status here. */ + fpcr = orig_fpcr | ((exc & SWCR_STATUS_MASK) << 35); + + cpu_alpha_store_fpcr(cpu_env, fpcr); ret = 0; - if (arg1 == TARGET_SSI_IEEE_RAISE_EXCEPTION) { - /* Old exceptions are not signaled. */ - fpcr &= ~(orig_fpcr & FPCR_STATUS_MASK); + /* Old exceptions are not signaled. */ + fpcr &= ~(orig_fpcr & FPCR_STATUS_MASK); - /* If any exceptions set by this call, and are unmasked, - send a signal. */ - /* ??? FIXME */ + /* If any exceptions set by this call, + and are unmasked, send a signal. */ + si_code = 0; + if ((fpcr & (FPCR_INE | FPCR_INED)) == FPCR_INE) { + si_code = TARGET_FPE_FLTRES; + } + if ((fpcr & (FPCR_UNF | FPCR_UNFD)) == FPCR_UNF) { + si_code = TARGET_FPE_FLTUND; + } + if ((fpcr & (FPCR_OVF | FPCR_OVFD)) == FPCR_OVF) { + si_code = TARGET_FPE_FLTOVF; + } + if ((fpcr & (FPCR_DZE | FPCR_DZED)) == FPCR_DZE) { + si_code = TARGET_FPE_FLTDIV; + } + if ((fpcr & (FPCR_INV | FPCR_INVD)) == FPCR_INV) { + si_code = TARGET_FPE_FLTINV; + } + if (si_code != 0) { + target_siginfo_t info; + info.si_signo = SIGFPE; + info.si_errno = 0; + info.si_code = si_code; + info._sifields._sigfault._addr + = ((CPUArchState *)cpu_env)->pc; + queue_signal((CPUArchState *)cpu_env, info.si_signo, &info); } } break; |