aboutsummaryrefslogtreecommitdiff
path: root/linux-user/syscall.c
diff options
context:
space:
mode:
Diffstat (limited to 'linux-user/syscall.c')
-rw-r--r--linux-user/syscall.c473
1 files changed, 396 insertions, 77 deletions
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index b4a7b605f3..d14d849a72 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -114,6 +114,7 @@
#include <sound/asound.h>
#ifdef HAVE_DRM_H
#include <libdrm/drm.h>
+#include <libdrm/i915_drm.h>
#endif
#include "linux_loop.h"
#include "uname.h"
@@ -390,7 +391,7 @@ static bitmask_transtbl fcntl_flags_tbl[] = {
_syscall2(int, sys_getcwd1, char *, buf, size_t, size)
-#ifdef TARGET_NR_utimensat
+#if defined(TARGET_NR_utimensat) || defined(TARGET_NR_utimensat_time64)
#if defined(__NR_utimensat)
#define __NR_sys_utimensat __NR_utimensat
_syscall4(int,sys_utimensat,int,dirfd,const char *,pathname,
@@ -494,38 +495,6 @@ static inline int next_free_host_timer(void)
}
#endif
-/* ARM EABI and MIPS expect 64bit types aligned even on pairs or registers */
-#ifdef TARGET_ARM
-static inline int regpairs_aligned(void *cpu_env, int num)
-{
- return ((((CPUARMState *)cpu_env)->eabi) == 1) ;
-}
-#elif defined(TARGET_MIPS) && (TARGET_ABI_BITS == 32)
-static inline int regpairs_aligned(void *cpu_env, int num) { return 1; }
-#elif defined(TARGET_PPC) && !defined(TARGET_PPC64)
-/* SysV AVI for PPC32 expects 64bit parameters to be passed on odd/even pairs
- * of registers which translates to the same as ARM/MIPS, because we start with
- * r3 as arg1 */
-static inline int regpairs_aligned(void *cpu_env, int num) { return 1; }
-#elif defined(TARGET_SH4)
-/* SH4 doesn't align register pairs, except for p{read,write}64 */
-static inline int regpairs_aligned(void *cpu_env, int num)
-{
- switch (num) {
- case TARGET_NR_pread64:
- case TARGET_NR_pwrite64:
- return 1;
-
- default:
- return 0;
- }
-}
-#elif defined(TARGET_XTENSA)
-static inline int regpairs_aligned(void *cpu_env, int num) { return 1; }
-#else
-static inline int regpairs_aligned(void *cpu_env, int num) { return 0; }
-#endif
-
#define ERRNO_TABLE_SIZE 1200
/* target_to_host_errno_table[] is initialized from
@@ -795,7 +764,7 @@ safe_syscall6(ssize_t, recvfrom, int, fd, void *, buf, size_t, len,
safe_syscall3(ssize_t, sendmsg, int, fd, const struct msghdr *, msg, int, flags)
safe_syscall3(ssize_t, recvmsg, int, fd, struct msghdr *, msg, int, flags)
safe_syscall2(int, flock, int, fd, int, operation)
-#ifdef TARGET_NR_rt_sigtimedwait
+#if defined(TARGET_NR_rt_sigtimedwait) || defined(TARGET_NR_rt_sigtimedwait_time64)
safe_syscall4(int, rt_sigtimedwait, const sigset_t *, these, siginfo_t *, uinfo,
const struct timespec *, uts, size_t, sigsetsize)
#endif
@@ -805,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
@@ -830,11 +800,13 @@ safe_syscall5(int, msgrcv, int, msgid, void *, msgp, size_t, sz,
safe_syscall4(int, semtimedop, int, semid, struct sembuf *, tsops,
unsigned, nsops, const struct timespec *, timeout)
#endif
-#ifdef TARGET_NR_mq_timedsend
+#if defined(TARGET_NR_mq_timedsend) || \
+ defined(TARGET_NR_mq_timedsend_time64)
safe_syscall5(int, mq_timedsend, int, mqdes, const char *, msg_ptr,
size_t, len, unsigned, prio, const struct timespec *, timeout)
#endif
-#ifdef TARGET_NR_mq_timedreceive
+#if defined(TARGET_NR_mq_timedreceive) || \
+ defined(TARGET_NR_mq_timedreceive_time64)
safe_syscall5(int, mq_timedreceive, int, mqdes, char *, msg_ptr,
size_t, len, unsigned *, prio, const struct timespec *, timeout)
#endif
@@ -1206,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;
@@ -1249,7 +1240,14 @@ static inline abi_long target_to_host_timespec(struct timespec *host_ts,
#if defined(TARGET_NR_clock_settime64) || defined(TARGET_NR_futex_time64) || \
defined(TARGET_NR_timer_settime64) || \
- (defined(TARGET_NR_timerfd_settime64) && defined(CONFIG_TIMERFD))
+ defined(TARGET_NR_mq_timedsend_time64) || \
+ defined(TARGET_NR_mq_timedreceive_time64) || \
+ (defined(TARGET_NR_timerfd_settime64) && defined(CONFIG_TIMERFD)) || \
+ defined(TARGET_NR_clock_nanosleep_time64) || \
+ defined(TARGET_NR_rt_sigtimedwait_time64) || \
+ defined(TARGET_NR_utimensat) || \
+ defined(TARGET_NR_utimensat_time64) || \
+ defined(TARGET_NR_semtimedop_time64)
static inline abi_long target_to_host_timespec64(struct timespec *host_ts,
abi_ulong target_addr)
{
@@ -1260,6 +1258,8 @@ static inline abi_long target_to_host_timespec64(struct timespec *host_ts,
}
__get_user(host_ts->tv_sec, &target_ts->tv_sec);
__get_user(host_ts->tv_nsec, &target_ts->tv_nsec);
+ /* in 32bit mode, this drops the padding */
+ host_ts->tv_nsec = (long)(abi_long)host_ts->tv_nsec;
unlock_user_struct(target_ts, target_addr, 0);
return 0;
}
@@ -3882,7 +3882,7 @@ static inline abi_long target_to_host_sembuf(struct sembuf *host_sembuf,
}
#if defined(TARGET_NR_ipc) || defined(TARGET_NR_semop) || \
- defined(TARGET_NR_semtimedop)
+ defined(TARGET_NR_semtimedop) || defined(TARGET_NR_semtimedop_time64)
/*
* This macro is required to handle the s390 variants, which passes the
@@ -3899,21 +3899,35 @@ static inline abi_long target_to_host_sembuf(struct sembuf *host_sembuf,
static inline abi_long do_semtimedop(int semid,
abi_long ptr,
unsigned nsops,
- abi_long timeout)
+ abi_long timeout, bool time64)
{
- struct sembuf sops[nsops];
+ struct sembuf *sops;
struct timespec ts, *pts = NULL;
abi_long ret;
if (timeout) {
pts = &ts;
- if (target_to_host_timespec(pts, timeout)) {
- return -TARGET_EFAULT;
+ if (time64) {
+ if (target_to_host_timespec64(pts, timeout)) {
+ return -TARGET_EFAULT;
+ }
+ } else {
+ if (target_to_host_timespec(pts, timeout)) {
+ return -TARGET_EFAULT;
+ }
}
}
- if (target_to_host_sembuf(sops, ptr, nsops))
+ if (nsops > TARGET_SEMOPM) {
+ return -TARGET_E2BIG;
+ }
+
+ sops = g_new(struct sembuf, nsops);
+
+ if (target_to_host_sembuf(sops, ptr, nsops)) {
+ g_free(sops);
return -TARGET_EFAULT;
+ }
ret = -TARGET_ENOSYS;
#ifdef __NR_semtimedop
@@ -3925,6 +3939,7 @@ static inline abi_long do_semtimedop(int semid,
SEMTIMEDOP_IPC_ARGS(nsops, sops, (long)pts)));
}
#endif
+ g_free(sops);
return ret;
}
#endif
@@ -4422,7 +4437,7 @@ static abi_long do_ipc(CPUArchState *cpu_env,
switch (call) {
case IPCOP_semop:
- ret = do_semtimedop(first, ptr, second, 0);
+ ret = do_semtimedop(first, ptr, second, 0, false);
break;
case IPCOP_semtimedop:
/*
@@ -4432,9 +4447,9 @@ static abi_long do_ipc(CPUArchState *cpu_env,
* to a struct timespec where the generic variant uses fifth parameter.
*/
#if defined(TARGET_S390X)
- ret = do_semtimedop(first, ptr, second, third);
+ ret = do_semtimedop(first, ptr, second, third, TARGET_ABI_BITS == 64);
#else
- ret = do_semtimedop(first, ptr, second, fifth);
+ ret = do_semtimedop(first, ptr, second, fifth, TARGET_ABI_BITS == 64);
#endif
break;
@@ -5417,6 +5432,40 @@ static abi_long do_ioctl_drm(const IOCTLEntry *ie, uint8_t *buf_temp,
return -TARGET_ENOSYS;
}
+static abi_long do_ioctl_drm_i915_getparam(const IOCTLEntry *ie,
+ struct drm_i915_getparam *gparam,
+ int fd, abi_long arg)
+{
+ abi_long ret;
+ int value;
+ struct target_drm_i915_getparam *target_gparam;
+
+ if (!lock_user_struct(VERIFY_READ, target_gparam, arg, 0)) {
+ return -TARGET_EFAULT;
+ }
+
+ __get_user(gparam->param, &target_gparam->param);
+ gparam->value = &value;
+ ret = get_errno(safe_ioctl(fd, ie->host_cmd, gparam));
+ put_user_s32(value, target_gparam->value);
+
+ unlock_user_struct(target_gparam, arg, 0);
+ return ret;
+}
+
+static abi_long do_ioctl_drm_i915(const IOCTLEntry *ie, uint8_t *buf_temp,
+ int fd, int cmd, abi_long arg)
+{
+ switch (ie->host_cmd) {
+ case DRM_IOCTL_I915_GETPARAM:
+ return do_ioctl_drm_i915_getparam(ie,
+ (struct drm_i915_getparam *)buf_temp,
+ fd, arg);
+ default:
+ return -TARGET_ENOSYS;
+ }
+}
+
#endif
IOCTLEntry ioctl_entries[] = {
@@ -5537,6 +5586,7 @@ static const bitmask_transtbl iflag_tbl[] = {
{ TARGET_IXANY, TARGET_IXANY, IXANY, IXANY },
{ TARGET_IXOFF, TARGET_IXOFF, IXOFF, IXOFF },
{ TARGET_IMAXBEL, TARGET_IMAXBEL, IMAXBEL, IMAXBEL },
+ { TARGET_IUTF8, TARGET_IUTF8, IUTF8, IUTF8},
{ 0, 0, 0, 0 }
};
@@ -5604,22 +5654,23 @@ static const bitmask_transtbl cflag_tbl[] = {
};
static const bitmask_transtbl lflag_tbl[] = {
- { TARGET_ISIG, TARGET_ISIG, ISIG, ISIG },
- { TARGET_ICANON, TARGET_ICANON, ICANON, ICANON },
- { TARGET_XCASE, TARGET_XCASE, XCASE, XCASE },
- { TARGET_ECHO, TARGET_ECHO, ECHO, ECHO },
- { TARGET_ECHOE, TARGET_ECHOE, ECHOE, ECHOE },
- { TARGET_ECHOK, TARGET_ECHOK, ECHOK, ECHOK },
- { TARGET_ECHONL, TARGET_ECHONL, ECHONL, ECHONL },
- { TARGET_NOFLSH, TARGET_NOFLSH, NOFLSH, NOFLSH },
- { TARGET_TOSTOP, TARGET_TOSTOP, TOSTOP, TOSTOP },
- { TARGET_ECHOCTL, TARGET_ECHOCTL, ECHOCTL, ECHOCTL },
- { TARGET_ECHOPRT, TARGET_ECHOPRT, ECHOPRT, ECHOPRT },
- { TARGET_ECHOKE, TARGET_ECHOKE, ECHOKE, ECHOKE },
- { TARGET_FLUSHO, TARGET_FLUSHO, FLUSHO, FLUSHO },
- { TARGET_PENDIN, TARGET_PENDIN, PENDIN, PENDIN },
- { TARGET_IEXTEN, TARGET_IEXTEN, IEXTEN, IEXTEN },
- { 0, 0, 0, 0 }
+ { TARGET_ISIG, TARGET_ISIG, ISIG, ISIG },
+ { TARGET_ICANON, TARGET_ICANON, ICANON, ICANON },
+ { TARGET_XCASE, TARGET_XCASE, XCASE, XCASE },
+ { TARGET_ECHO, TARGET_ECHO, ECHO, ECHO },
+ { TARGET_ECHOE, TARGET_ECHOE, ECHOE, ECHOE },
+ { TARGET_ECHOK, TARGET_ECHOK, ECHOK, ECHOK },
+ { TARGET_ECHONL, TARGET_ECHONL, ECHONL, ECHONL },
+ { TARGET_NOFLSH, TARGET_NOFLSH, NOFLSH, NOFLSH },
+ { TARGET_TOSTOP, TARGET_TOSTOP, TOSTOP, TOSTOP },
+ { TARGET_ECHOCTL, TARGET_ECHOCTL, ECHOCTL, ECHOCTL },
+ { TARGET_ECHOPRT, TARGET_ECHOPRT, ECHOPRT, ECHOPRT },
+ { TARGET_ECHOKE, TARGET_ECHOKE, ECHOKE, ECHOKE },
+ { TARGET_FLUSHO, TARGET_FLUSHO, FLUSHO, FLUSHO },
+ { TARGET_PENDIN, TARGET_PENDIN, PENDIN, PENDIN },
+ { TARGET_IEXTEN, TARGET_IEXTEN, IEXTEN, IEXTEN },
+ { TARGET_EXTPROC, TARGET_EXTPROC, EXTPROC, EXTPROC},
+ { 0, 0, 0, 0 }
};
static void target_to_host_termios (void *dst, const void *src)
@@ -5696,6 +5747,7 @@ static const StructEntry struct_termios_def = {
.convert = { host_to_target_termios, target_to_host_termios },
.size = { sizeof(struct target_termios), sizeof(struct host_termios) },
.align = { __alignof__(struct target_termios), __alignof__(struct host_termios) },
+ .print = print_termios,
};
static bitmask_transtbl mmap_flags_tbl[] = {
@@ -6932,6 +6984,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)
{
@@ -6963,12 +7096,18 @@ static inline int target_to_host_mlockall_arg(int arg)
{
int result = 0;
- if (arg & TARGET_MLOCKALL_MCL_CURRENT) {
+ if (arg & TARGET_MCL_CURRENT) {
result |= MCL_CURRENT;
}
- if (arg & TARGET_MLOCKALL_MCL_FUTURE) {
+ if (arg & TARGET_MCL_FUTURE) {
result |= MCL_FUTURE;
}
+#ifdef MCL_ONFAULT
+ if (arg & TARGET_MCL_ONFAULT) {
+ result |= MCL_ONFAULT;
+ }
+#endif
+
return result;
}
#endif
@@ -8916,6 +9055,48 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1,
}
return ret;
#endif
+#ifdef TARGET_NR_rt_sigtimedwait_time64
+ case TARGET_NR_rt_sigtimedwait_time64:
+ {
+ sigset_t set;
+ struct timespec uts, *puts;
+ siginfo_t uinfo;
+
+ if (arg4 != sizeof(target_sigset_t)) {
+ return -TARGET_EINVAL;
+ }
+
+ p = lock_user(VERIFY_READ, arg1, sizeof(target_sigset_t), 1);
+ if (!p) {
+ return -TARGET_EFAULT;
+ }
+ target_to_host_sigset(&set, p);
+ unlock_user(p, arg1, 0);
+ if (arg3) {
+ puts = &uts;
+ if (target_to_host_timespec64(puts, arg3)) {
+ return -TARGET_EFAULT;
+ }
+ } else {
+ puts = NULL;
+ }
+ ret = get_errno(safe_rt_sigtimedwait(&set, &uinfo, puts,
+ SIGSET_T_SIZE));
+ if (!is_error(ret)) {
+ if (arg2) {
+ p = lock_user(VERIFY_WRITE, arg2,
+ sizeof(target_siginfo_t), 0);
+ if (!p) {
+ return -TARGET_EFAULT;
+ }
+ host_to_target_siginfo(p, &uinfo);
+ unlock_user(p, arg2, sizeof(target_siginfo_t));
+ }
+ ret = host_to_target_signal(ret);
+ }
+ }
+ return ret;
+#endif
case TARGET_NR_rt_sigqueueinfo:
{
siginfo_t uinfo;
@@ -9777,11 +9958,15 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1,
#endif
#ifdef TARGET_NR_semop
case TARGET_NR_semop:
- return do_semtimedop(arg1, arg2, arg3, 0);
+ return do_semtimedop(arg1, arg2, arg3, 0, false);
#endif
#ifdef TARGET_NR_semtimedop
case TARGET_NR_semtimedop:
- return do_semtimedop(arg1, arg2, arg3, arg4);
+ return do_semtimedop(arg1, arg2, arg3, arg4, false);
+#endif
+#ifdef TARGET_NR_semtimedop_time64
+ case TARGET_NR_semtimedop_time64:
+ return do_semtimedop(arg1, arg2, arg3, arg4, true);
#endif
#ifdef TARGET_NR_semctl
case TARGET_NR_semctl:
@@ -9914,6 +10099,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:
@@ -10424,6 +10624,17 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1,
}
return ret;
#endif
+#ifdef TARGET_NR_sched_rr_get_interval_time64
+ case TARGET_NR_sched_rr_get_interval_time64:
+ {
+ struct timespec ts;
+ ret = get_errno(sched_rr_get_interval(arg1, &ts));
+ if (!is_error(ret)) {
+ ret = host_to_target_timespec64(arg2, &ts);
+ }
+ }
+ return ret;
+#endif
#if defined(TARGET_NR_nanosleep)
case TARGET_NR_nanosleep:
{
@@ -11866,7 +12077,9 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1,
case TARGET_NR_clock_nanosleep:
{
struct timespec ts;
- target_to_host_timespec(&ts, arg3);
+ if (target_to_host_timespec(&ts, arg3)) {
+ return -TARGET_EFAULT;
+ }
ret = get_errno(safe_clock_nanosleep(arg1, arg2,
&ts, arg4 ? &ts : NULL));
/*
@@ -11874,13 +12087,33 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1,
* with error -TARGET_EINTR and if arg4 is not NULL and arg2 is not
* TIMER_ABSTIME, it returns the remaining unslept time in arg4.
*/
- if (ret == -TARGET_EINTR && arg4 && arg2 != TIMER_ABSTIME) {
- host_to_target_timespec(arg4, &ts);
+ if (ret == -TARGET_EINTR && arg4 && arg2 != TIMER_ABSTIME &&
+ host_to_target_timespec(arg4, &ts)) {
+ return -TARGET_EFAULT;
}
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:
@@ -11940,6 +12173,35 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1,
}
return ret;
#endif
+#ifdef TARGET_NR_utimensat_time64
+ case TARGET_NR_utimensat_time64:
+ {
+ struct timespec *tsp, ts[2];
+ if (!arg3) {
+ tsp = NULL;
+ } else {
+ if (target_to_host_timespec64(ts, arg3)) {
+ return -TARGET_EFAULT;
+ }
+ if (target_to_host_timespec64(ts + 1, arg3 +
+ sizeof(struct target__kernel_timespec))) {
+ return -TARGET_EFAULT;
+ }
+ tsp = ts;
+ }
+ if (!arg2)
+ ret = get_errno(sys_utimensat(arg1, NULL, tsp, arg4));
+ else {
+ p = lock_user_string(arg2);
+ if (!p) {
+ return -TARGET_EFAULT;
+ }
+ ret = get_errno(sys_utimensat(arg1, path(p), tsp, arg4));
+ unlock_user(p, arg2, 0);
+ }
+ }
+ return ret;
+#endif
#ifdef TARGET_NR_futex
case TARGET_NR_futex:
return do_futex(arg1, arg2, arg3, arg4, arg5, arg6);
@@ -12019,9 +12281,13 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1,
p = lock_user (VERIFY_READ, arg2, arg3, 1);
if (arg5 != 0) {
- target_to_host_timespec(&ts, arg5);
+ if (target_to_host_timespec(&ts, arg5)) {
+ return -TARGET_EFAULT;
+ }
ret = get_errno(safe_mq_timedsend(arg1, p, arg3, arg4, &ts));
- host_to_target_timespec(arg5, &ts);
+ if (!is_error(ret) && host_to_target_timespec(arg5, &ts)) {
+ return -TARGET_EFAULT;
+ }
} else {
ret = get_errno(safe_mq_timedsend(arg1, p, arg3, arg4, NULL));
}
@@ -12029,6 +12295,27 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1,
}
return ret;
#endif
+#ifdef TARGET_NR_mq_timedsend_time64
+ case TARGET_NR_mq_timedsend_time64:
+ {
+ struct timespec ts;
+
+ p = lock_user(VERIFY_READ, arg2, arg3, 1);
+ if (arg5 != 0) {
+ if (target_to_host_timespec64(&ts, arg5)) {
+ return -TARGET_EFAULT;
+ }
+ ret = get_errno(safe_mq_timedsend(arg1, p, arg3, arg4, &ts));
+ if (!is_error(ret) && host_to_target_timespec64(arg5, &ts)) {
+ return -TARGET_EFAULT;
+ }
+ } else {
+ ret = get_errno(safe_mq_timedsend(arg1, p, arg3, arg4, NULL));
+ }
+ unlock_user(p, arg2, arg3);
+ }
+ return ret;
+#endif
#ifdef TARGET_NR_mq_timedreceive
case TARGET_NR_mq_timedreceive:
@@ -12038,10 +12325,14 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1,
p = lock_user (VERIFY_READ, arg2, arg3, 1);
if (arg5 != 0) {
- target_to_host_timespec(&ts, arg5);
+ if (target_to_host_timespec(&ts, arg5)) {
+ return -TARGET_EFAULT;
+ }
ret = get_errno(safe_mq_timedreceive(arg1, p, arg3,
&prio, &ts));
- host_to_target_timespec(arg5, &ts);
+ if (!is_error(ret) && host_to_target_timespec(arg5, &ts)) {
+ return -TARGET_EFAULT;
+ }
} else {
ret = get_errno(safe_mq_timedreceive(arg1, p, arg3,
&prio, NULL));
@@ -12052,6 +12343,33 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1,
}
return ret;
#endif
+#ifdef TARGET_NR_mq_timedreceive_time64
+ case TARGET_NR_mq_timedreceive_time64:
+ {
+ struct timespec ts;
+ unsigned int prio;
+
+ p = lock_user(VERIFY_READ, arg2, arg3, 1);
+ if (arg5 != 0) {
+ if (target_to_host_timespec64(&ts, arg5)) {
+ return -TARGET_EFAULT;
+ }
+ ret = get_errno(safe_mq_timedreceive(arg1, p, arg3,
+ &prio, &ts));
+ if (!is_error(ret) && host_to_target_timespec64(arg5, &ts)) {
+ return -TARGET_EFAULT;
+ }
+ } else {
+ ret = get_errno(safe_mq_timedreceive(arg1, p, arg3,
+ &prio, NULL));
+ }
+ unlock_user(p, arg2, arg3);
+ if (arg4 != 0) {
+ put_user_u32(prio, arg4);
+ }
+ }
+ return ret;
+#endif
/* Not implemented for now... */
/* case TARGET_NR_mq_notify: */
@@ -12722,14 +13040,15 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
arg2, arg3, arg4, arg5, arg6, arg7, arg8);
if (unlikely(qemu_loglevel_mask(LOG_STRACE))) {
- print_syscall(num, arg1, arg2, arg3, arg4, arg5, arg6);
+ print_syscall(cpu_env, num, arg1, arg2, arg3, arg4, arg5, arg6);
}
ret = do_syscall1(cpu_env, num, arg1, arg2, arg3, arg4,
arg5, arg6, arg7, arg8);
if (unlikely(qemu_loglevel_mask(LOG_STRACE))) {
- print_syscall_ret(num, ret, arg1, arg2, arg3, arg4, arg5, arg6);
+ print_syscall_ret(cpu_env, num, ret, arg1, arg2,
+ arg3, arg4, arg5, arg6);
}
record_syscall_return(cpu, num, ret);