Le 24/08/2020 à 21:21, Filip Bozuta a écrit : > This patch implements functionality for following time64 syscall: > > *clock_nanosleep_time64() > > This is a year 2038 safe vairant of syscall: > int clock_nanosleep(clockid_t clockid, int flags, > const struct timespec *request, > struct timespec *remain) > --high-resolution sleep with specifiable clock-- > man page: https://man7.org/linux/man-pages/man2/clock_nanosleep.2.html > > *clock_adjtime64() > > This is a year 2038 safe variant of syscall: > int clock_adjtime(clockid_t clk_id, struct timex *buf) > --tune kernel clock-- > man page: https://man7.org/linux/man-pages/man2/clock_adjtime.2.html > > Implementation notes: > > Syscall 'clock_nanosleep_time64()' was implemented similarly > to syscall 'clock_nanosleep()' except that 'host_to_target_timespec64()' > and 'target_to_host_timespec64()' were used instead of the regular > 'host_to_target_timespec()' and 'target_to_host_timespec()'. > > For 'clock_adjtime64()' a 64-bit target kernel version of 'struct timex' > was defined in 'syscall_defs.h': 'struct target__kernel_timex'. > This type was used to convert the values of 64-bit timex type between > host and target. For this purpose a 64-bit timex converting functions > 'target_to_host_timex64()' and 'host_to_target_timex64()'. An existing > function 'copy_to_user_timeval64()' was used to convert the field > 'time' which if of type 'struct timeval' from host to target. > Function 'copy_from_user_timveal64()' was added in this patch and > used to convert the 'time' field from target to host. > > Signed-off-by: Filip Bozuta <[email protected]> > --- > linux-user/syscall.c | 137 +++++++++++++++++++++++++++++++++++++- > linux-user/syscall_defs.h | 31 +++++++++ > 2 files changed, 166 insertions(+), 2 deletions(-) > > diff --git a/linux-user/syscall.c b/linux-user/syscall.c > index 05f03919ff..a359bd8620 100644 > --- a/linux-user/syscall.c > +++ b/linux-user/syscall.c > @@ -809,7 +809,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 > @@ -1205,8 +1206,25 @@ static inline abi_long copy_to_user_timeval(abi_ulong > target_tv_addr, > return 0; > } > > +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; > +} > + > 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; > > @@ -6771,6 +6789,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) > { > @@ -9726,6 +9825,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)); > @@ -11684,6 +11798,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: > diff --git a/linux-user/syscall_defs.h b/linux-user/syscall_defs.h > index 152ec637cb..3783c5a07e 100644 > --- a/linux-user/syscall_defs.h > +++ b/linux-user/syscall_defs.h > @@ -287,6 +287,37 @@ struct target_timex { > abi_int:32; abi_int:32; abi_int:32; > }; > > +struct target__kernel_timex { > + abi_uint modes; /* Mode selector */ > + abi_int: 32; /* pad */ > + abi_llong offset; /* Time offset */ > + abi_llong freq; /* Frequency offset */ > + abi_llong maxerror; /* Maximum error (microseconds) */ > + abi_llong esterror; /* Estimated error (microseconds) */ > + abi_int status; /* Clock command/status */ > + abi_int: 32; /* pad */ > + abi_llong constant; /* PLL (phase-locked loop) time constant */ > + abi_llong precision; /* Clock precision (microseconds, ro) */ > + abi_llong tolerance; /* Clock freq. tolerance (ppm, ro) */ > + struct target__kernel_sock_timeval time; /* Current time */ > + abi_llong tick; /* Microseconds between clock ticks */ > + abi_llong ppsfreq; /* PPS (pulse per second) frequency */ > + abi_llong jitter; /* PPS jitter (ro); nanoseconds */ > + abi_int shift; /* PPS interval duration (seconds) */ > + abi_int: 32; /* pad */ > + abi_llong stabil; /* PPS stability */ > + abi_llong jitcnt; /* PPS jitter limit exceeded (ro) */ > + abi_llong calcnt; /* PPS calibration intervals */ > + abi_llong errcnt; /* PPS calibration errors */ > + abi_llong stbcnt; /* PPS stability limit exceeded */ > + abi_int tai; /* TAI offset */ > + > + /* Further padding bytes to allow for future expansion */ > + abi_int:32; abi_int:32; abi_int:32; abi_int:32; > + abi_int:32; abi_int:32; abi_int:32; abi_int:32; > + abi_int:32; abi_int:32; abi_int:32; > +}; > + > typedef abi_long target_clock_t; > > #define TARGET_HZ 100 >
Reviewed-by: Laurent Vivier <[email protected]>
