mirror of
https://gitlab.com/qemu-project/qemu
synced 2024-09-06 18:05:37 +00:00
linux-user: Add support for a group of 2038 safe syscalls
This patch implements functionality for following time64 syscalls: *clock_getres_time64 This a year 2038 safe variant of syscall: int clock_getres(clockid_t clockid, struct timespec *res) --finding the resoultion of a specified clock-- man page: https://man7.org/linux/man-pages/man2/clock_getres.2.html *timer_gettime64 *timer_settime64 These are year 2038 safe variants of syscalls: int timer_settime(timer_t timerid, int flags, const struct itimerspec *new_value, struct itimerspec *old_value) int timer_gettime(timer_t timerid, struct itimerspec *curr_value) --arming/dissarming and fetching state of POSIX per-process timer-- man page: https://man7.org/linux/man-pages/man2/timer_settime.2.html *timerfd_gettime64 *timerfd_settime64 These are year 2038 safe variants of syscalls: int timerfd_settime(int fd, int flags, const struct itimerspec *new_value, struct itimerspec *old_value) int timerfd_gettime(int fd, struct itimerspec *curr_value) --timers that notify via file descriptor-- man page: https://man7.org/linux/man-pages/man2/timerfd_settime.2.html Implementation notes: Syscall 'clock_getres_time64' was implemented similarly to 'clock_getres()'. The only difference was that for the conversion of 'struct timespec' from host to target, function 'host_to_target_timespec64()' was used instead of 'host_to_target_timespec()'. For other syscalls, new functions 'host_to_target_itimerspec64()' and 'target_to_host_itimerspec64()' were added to convert the value of the 'struct itimerspec' from host to target and vice versa. A new type 'struct target__kernel_itimerspec' was added in 'syscall_defs.h'. This type was defined with fields which are of the already defined type 'struct target_timespec'. This new 'struct target__kernel_itimerspec' type is used in these new converting functions. These new functions were defined similarly to 'host_to_target_itimerspec()' and 'target_to_host_itimerspec()' the only difference being that 'target_to_host_timespec64()' and 'host_to_target_timespec64()' were used. Signed-off-by: Filip Bozuta <Filip.Bozuta@syrmia.com> Reviewed-by: Laurent Vivier <laurent@vivier.eu> Message-Id: <20200722153421.295411-3-Filip.Bozuta@syrmia.com> Signed-off-by: Laurent Vivier <laurent@vivier.eu>
This commit is contained in:
parent
2c86c90fe8
commit
828cb3a1a8
|
@ -1247,7 +1247,9 @@ static inline abi_long target_to_host_timespec(struct timespec *host_ts,
|
|||
}
|
||||
#endif
|
||||
|
||||
#if defined(TARGET_NR_clock_settime64) || defined(TARGET_NR_futex_time64)
|
||||
#if defined(TARGET_NR_clock_settime64) || defined(TARGET_NR_futex_time64) || \
|
||||
defined(TARGET_NR_timer_settime64) || \
|
||||
(defined(TARGET_NR_timerfd_settime64) && defined(CONFIG_TIMERFD))
|
||||
static inline abi_long target_to_host_timespec64(struct timespec *host_ts,
|
||||
abi_ulong target_addr)
|
||||
{
|
||||
|
@ -6801,6 +6803,24 @@ static inline abi_long target_to_host_itimerspec(struct itimerspec *host_its,
|
|||
}
|
||||
#endif
|
||||
|
||||
#if defined(TARGET_NR_timer_settime64) || \
|
||||
(defined(TARGET_NR_timerfd_settime64) && defined(CONFIG_TIMERFD))
|
||||
static inline abi_long target_to_host_itimerspec64(struct itimerspec *host_its,
|
||||
abi_ulong target_addr)
|
||||
{
|
||||
if (target_to_host_timespec64(&host_its->it_interval, target_addr +
|
||||
offsetof(struct target__kernel_itimerspec,
|
||||
it_interval)) ||
|
||||
target_to_host_timespec64(&host_its->it_value, target_addr +
|
||||
offsetof(struct target__kernel_itimerspec,
|
||||
it_value))) {
|
||||
return -TARGET_EFAULT;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if ((defined(TARGET_NR_timerfd_gettime) || \
|
||||
defined(TARGET_NR_timerfd_settime)) && defined(CONFIG_TIMERFD)) || \
|
||||
defined(TARGET_NR_timer_gettime) || defined(TARGET_NR_timer_settime)
|
||||
|
@ -6819,6 +6839,26 @@ static inline abi_long host_to_target_itimerspec(abi_ulong target_addr,
|
|||
}
|
||||
#endif
|
||||
|
||||
#if ((defined(TARGET_NR_timerfd_gettime64) || \
|
||||
defined(TARGET_NR_timerfd_settime64)) && defined(CONFIG_TIMERFD)) || \
|
||||
defined(TARGET_NR_timer_gettime64) || defined(TARGET_NR_timer_settime64)
|
||||
static inline abi_long host_to_target_itimerspec64(abi_ulong target_addr,
|
||||
struct itimerspec *host_its)
|
||||
{
|
||||
if (host_to_target_timespec64(target_addr +
|
||||
offsetof(struct target__kernel_itimerspec,
|
||||
it_interval),
|
||||
&host_its->it_interval) ||
|
||||
host_to_target_timespec64(target_addr +
|
||||
offsetof(struct target__kernel_itimerspec,
|
||||
it_value),
|
||||
&host_its->it_value)) {
|
||||
return -TARGET_EFAULT;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(TARGET_NR_adjtimex) || \
|
||||
(defined(TARGET_NR_clock_adjtime) && defined(CONFIG_CLOCK_ADJTIME))
|
||||
static inline abi_long target_to_host_timex(struct timex *host_tx,
|
||||
|
@ -11811,6 +11851,17 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1,
|
|||
return ret;
|
||||
}
|
||||
#endif
|
||||
#ifdef TARGET_NR_clock_getres_time64
|
||||
case TARGET_NR_clock_getres_time64:
|
||||
{
|
||||
struct timespec ts;
|
||||
ret = get_errno(clock_getres(arg1, &ts));
|
||||
if (!is_error(ret)) {
|
||||
host_to_target_timespec64(arg2, &ts);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
#ifdef TARGET_NR_clock_nanosleep
|
||||
case TARGET_NR_clock_nanosleep:
|
||||
{
|
||||
|
@ -12405,6 +12456,32 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1,
|
|||
}
|
||||
#endif
|
||||
|
||||
#ifdef TARGET_NR_timer_settime64
|
||||
case TARGET_NR_timer_settime64:
|
||||
{
|
||||
target_timer_t timerid = get_timer_id(arg1);
|
||||
|
||||
if (timerid < 0) {
|
||||
ret = timerid;
|
||||
} else if (arg3 == 0) {
|
||||
ret = -TARGET_EINVAL;
|
||||
} else {
|
||||
timer_t htimer = g_posix_timers[timerid];
|
||||
struct itimerspec hspec_new = {{0},}, hspec_old = {{0},};
|
||||
|
||||
if (target_to_host_itimerspec64(&hspec_new, arg3)) {
|
||||
return -TARGET_EFAULT;
|
||||
}
|
||||
ret = get_errno(
|
||||
timer_settime(htimer, arg2, &hspec_new, &hspec_old));
|
||||
if (arg4 && host_to_target_itimerspec64(arg4, &hspec_old)) {
|
||||
return -TARGET_EFAULT;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef TARGET_NR_timer_gettime
|
||||
case TARGET_NR_timer_gettime:
|
||||
{
|
||||
|
@ -12428,6 +12505,29 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1,
|
|||
}
|
||||
#endif
|
||||
|
||||
#ifdef TARGET_NR_timer_gettime64
|
||||
case TARGET_NR_timer_gettime64:
|
||||
{
|
||||
/* args: timer_t timerid, struct itimerspec64 *curr_value */
|
||||
target_timer_t timerid = get_timer_id(arg1);
|
||||
|
||||
if (timerid < 0) {
|
||||
ret = timerid;
|
||||
} else if (!arg2) {
|
||||
ret = -TARGET_EFAULT;
|
||||
} else {
|
||||
timer_t htimer = g_posix_timers[timerid];
|
||||
struct itimerspec hspec;
|
||||
ret = get_errno(timer_gettime(htimer, &hspec));
|
||||
|
||||
if (host_to_target_itimerspec64(arg2, &hspec)) {
|
||||
ret = -TARGET_EFAULT;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef TARGET_NR_timer_getoverrun
|
||||
case TARGET_NR_timer_getoverrun:
|
||||
{
|
||||
|
@ -12481,6 +12581,20 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1,
|
|||
return ret;
|
||||
#endif
|
||||
|
||||
#if defined(TARGET_NR_timerfd_gettime64) && defined(CONFIG_TIMERFD)
|
||||
case TARGET_NR_timerfd_gettime64:
|
||||
{
|
||||
struct itimerspec its_curr;
|
||||
|
||||
ret = get_errno(timerfd_gettime(arg1, &its_curr));
|
||||
|
||||
if (arg2 && host_to_target_itimerspec64(arg2, &its_curr)) {
|
||||
return -TARGET_EFAULT;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
#endif
|
||||
|
||||
#if defined(TARGET_NR_timerfd_settime) && defined(CONFIG_TIMERFD)
|
||||
case TARGET_NR_timerfd_settime:
|
||||
{
|
||||
|
@ -12504,6 +12618,29 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1,
|
|||
return ret;
|
||||
#endif
|
||||
|
||||
#if defined(TARGET_NR_timerfd_settime64) && defined(CONFIG_TIMERFD)
|
||||
case TARGET_NR_timerfd_settime64:
|
||||
{
|
||||
struct itimerspec its_new, its_old, *p_new;
|
||||
|
||||
if (arg3) {
|
||||
if (target_to_host_itimerspec64(&its_new, arg3)) {
|
||||
return -TARGET_EFAULT;
|
||||
}
|
||||
p_new = &its_new;
|
||||
} else {
|
||||
p_new = NULL;
|
||||
}
|
||||
|
||||
ret = get_errno(timerfd_settime(arg1, arg2, p_new, &its_old));
|
||||
|
||||
if (arg4 && host_to_target_itimerspec64(arg4, &its_old)) {
|
||||
return -TARGET_EFAULT;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
#endif
|
||||
|
||||
#if defined(TARGET_NR_ioprio_get) && defined(__NR_ioprio_get)
|
||||
case TARGET_NR_ioprio_get:
|
||||
return get_errno(ioprio_get(arg1, arg2));
|
||||
|
|
|
@ -259,6 +259,11 @@ struct target_itimerspec {
|
|||
struct target_timespec it_value;
|
||||
};
|
||||
|
||||
struct target__kernel_itimerspec {
|
||||
struct target__kernel_timespec it_interval;
|
||||
struct target__kernel_timespec it_value;
|
||||
};
|
||||
|
||||
struct target_timex {
|
||||
abi_uint modes; /* Mode selector */
|
||||
abi_long offset; /* Time offset */
|
||||
|
|
Loading…
Reference in a new issue