diff options
Diffstat (limited to 'linux-user/syscall.c')
-rw-r--r-- | linux-user/syscall.c | 142 |
1 files changed, 139 insertions, 3 deletions
diff --git a/linux-user/syscall.c b/linux-user/syscall.c index b28c8edb42..6fd3099cd6 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -774,7 +774,8 @@ safe_syscall4(int, accept4, int, fd, struct sockaddr *, addr, socklen_t *, len, safe_syscall2(int, nanosleep, const struct timespec *, req, struct timespec *, rem) #endif -#ifdef TARGET_NR_clock_nanosleep +#if defined(TARGET_NR_clock_nanosleep) || \ + defined(TARGET_NR_clock_nanosleep_time64) safe_syscall4(int, clock_nanosleep, const clockid_t, clock, int, flags, const struct timespec *, req, struct timespec *, rem) #endif @@ -1177,8 +1178,27 @@ static inline abi_long copy_to_user_timeval(abi_ulong target_tv_addr, return 0; } +#if defined(TARGET_NR_clock_adjtime64) && defined(CONFIG_CLOCK_ADJTIME) +static inline abi_long copy_from_user_timeval64(struct timeval *tv, + abi_ulong target_tv_addr) +{ + struct target__kernel_sock_timeval *target_tv; + + if (!lock_user_struct(VERIFY_READ, target_tv, target_tv_addr, 1)) { + return -TARGET_EFAULT; + } + + __get_user(tv->tv_sec, &target_tv->tv_sec); + __get_user(tv->tv_usec, &target_tv->tv_usec); + + unlock_user_struct(target_tv, target_tv_addr, 0); + + return 0; +} +#endif + static inline abi_long copy_to_user_timeval64(abi_ulong target_tv_addr, - const struct timeval *tv) + const struct timeval *tv) { struct target__kernel_sock_timeval *target_tv; @@ -1222,7 +1242,8 @@ static inline abi_long target_to_host_timespec(struct timespec *host_ts, defined(TARGET_NR_timer_settime64) || \ defined(TARGET_NR_mq_timedsend_time64) || \ defined(TARGET_NR_mq_timedreceive_time64) || \ - (defined(TARGET_NR_timerfd_settime64) && defined(CONFIG_TIMERFD)) + (defined(TARGET_NR_timerfd_settime64) && defined(CONFIG_TIMERFD)) || \ + defined(TARGET_NR_clock_nanosleep_time64) static inline abi_long target_to_host_timespec64(struct timespec *host_ts, abi_ulong target_addr) { @@ -6953,6 +6974,87 @@ static inline abi_long host_to_target_timex(abi_long target_addr, } #endif + +#if defined(TARGET_NR_clock_adjtime64) && defined(CONFIG_CLOCK_ADJTIME) +static inline abi_long target_to_host_timex64(struct timex *host_tx, + abi_long target_addr) +{ + struct target__kernel_timex *target_tx; + + if (copy_from_user_timeval64(&host_tx->time, target_addr + + offsetof(struct target__kernel_timex, + time))) { + return -TARGET_EFAULT; + } + + if (!lock_user_struct(VERIFY_READ, target_tx, target_addr, 1)) { + return -TARGET_EFAULT; + } + + __get_user(host_tx->modes, &target_tx->modes); + __get_user(host_tx->offset, &target_tx->offset); + __get_user(host_tx->freq, &target_tx->freq); + __get_user(host_tx->maxerror, &target_tx->maxerror); + __get_user(host_tx->esterror, &target_tx->esterror); + __get_user(host_tx->status, &target_tx->status); + __get_user(host_tx->constant, &target_tx->constant); + __get_user(host_tx->precision, &target_tx->precision); + __get_user(host_tx->tolerance, &target_tx->tolerance); + __get_user(host_tx->tick, &target_tx->tick); + __get_user(host_tx->ppsfreq, &target_tx->ppsfreq); + __get_user(host_tx->jitter, &target_tx->jitter); + __get_user(host_tx->shift, &target_tx->shift); + __get_user(host_tx->stabil, &target_tx->stabil); + __get_user(host_tx->jitcnt, &target_tx->jitcnt); + __get_user(host_tx->calcnt, &target_tx->calcnt); + __get_user(host_tx->errcnt, &target_tx->errcnt); + __get_user(host_tx->stbcnt, &target_tx->stbcnt); + __get_user(host_tx->tai, &target_tx->tai); + + unlock_user_struct(target_tx, target_addr, 0); + return 0; +} + +static inline abi_long host_to_target_timex64(abi_long target_addr, + struct timex *host_tx) +{ + struct target__kernel_timex *target_tx; + + if (copy_to_user_timeval64(target_addr + + offsetof(struct target__kernel_timex, time), + &host_tx->time)) { + return -TARGET_EFAULT; + } + + if (!lock_user_struct(VERIFY_WRITE, target_tx, target_addr, 0)) { + return -TARGET_EFAULT; + } + + __put_user(host_tx->modes, &target_tx->modes); + __put_user(host_tx->offset, &target_tx->offset); + __put_user(host_tx->freq, &target_tx->freq); + __put_user(host_tx->maxerror, &target_tx->maxerror); + __put_user(host_tx->esterror, &target_tx->esterror); + __put_user(host_tx->status, &target_tx->status); + __put_user(host_tx->constant, &target_tx->constant); + __put_user(host_tx->precision, &target_tx->precision); + __put_user(host_tx->tolerance, &target_tx->tolerance); + __put_user(host_tx->tick, &target_tx->tick); + __put_user(host_tx->ppsfreq, &target_tx->ppsfreq); + __put_user(host_tx->jitter, &target_tx->jitter); + __put_user(host_tx->shift, &target_tx->shift); + __put_user(host_tx->stabil, &target_tx->stabil); + __put_user(host_tx->jitcnt, &target_tx->jitcnt); + __put_user(host_tx->calcnt, &target_tx->calcnt); + __put_user(host_tx->errcnt, &target_tx->errcnt); + __put_user(host_tx->stbcnt, &target_tx->stbcnt); + __put_user(host_tx->tai, &target_tx->tai); + + unlock_user_struct(target_tx, target_addr, 1); + return 0; +} +#endif + static inline abi_long target_to_host_sigevent(struct sigevent *host_sevp, abi_ulong target_addr) { @@ -9941,6 +10043,21 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1, } return ret; #endif +#if defined(TARGET_NR_clock_adjtime64) && defined(CONFIG_CLOCK_ADJTIME) + case TARGET_NR_clock_adjtime64: + { + struct timex htx; + + if (target_to_host_timex64(&htx, arg2) != 0) { + return -TARGET_EFAULT; + } + ret = get_errno(clock_adjtime(arg1, &htx)); + if (!is_error(ret) && host_to_target_timex64(arg2, &htx)) { + return -TARGET_EFAULT; + } + } + return ret; +#endif case TARGET_NR_getpgid: return get_errno(getpgid(arg1)); case TARGET_NR_fchdir: @@ -11911,6 +12028,25 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1, return ret; } #endif +#ifdef TARGET_NR_clock_nanosleep_time64 + case TARGET_NR_clock_nanosleep_time64: + { + struct timespec ts; + + if (target_to_host_timespec64(&ts, arg3)) { + return -TARGET_EFAULT; + } + + ret = get_errno(safe_clock_nanosleep(arg1, arg2, + &ts, arg4 ? &ts : NULL)); + + if (ret == -TARGET_EINTR && arg4 && arg2 != TIMER_ABSTIME && + host_to_target_timespec64(arg4, &ts)) { + return -TARGET_EFAULT; + } + return ret; + } +#endif #if defined(TARGET_NR_set_tid_address) && defined(__NR_set_tid_address) case TARGET_NR_set_tid_address: |