On 19/12/2018 05:21, Richard Henderson wrote: > Signed-off-by: Richard Henderson <richard.hender...@linaro.org> > --- > linux-user/syscall-defs.h | 14 ++++ > linux-user/syscall-file.inc.c | 124 ++++++++++++++++++++++++++++++++++ > linux-user/syscall.c | 93 ------------------------- > linux-user/strace.list | 18 ----- > 4 files changed, 138 insertions(+), 111 deletions(-) > ... > diff --git a/linux-user/syscall-file.inc.c b/linux-user/syscall-file.inc.c > index 11e75044c1..410a763eee 100644 > --- a/linux-user/syscall-file.inc.c > +++ b/linux-user/syscall-file.inc.c > @@ -315,6 +315,104 @@ SYSCALL_IMPL(openat) ... > + > +/* > + * Both preadv and pwritev merge args 4/5 into a 64-bit offset. > + * Moreover, the parts are *always* in little-endian order. > + */ > +#if TARGET_ABI_BITS == 32 > +SYSCALL_ARGS(preadv_pwritev) > +{ > + /* We have already assigned out[0-2]. */ > + abi_ulong lo = in[3], hi = in[4]; > + out[3] = ((hi << (TARGET_ABI_BITS - 1)) << 1) | lo; > + return def; > +} > +#else > +#define args_preadv_pwritev NULL > +#endif > + > +/* Perform the inverse operation for the host. */ > +static inline void host_offset64_low_high(unsigned long *l, unsigned long *h, > + uint64_t off) > +{ > + *l = off; > + *h = (off >> (HOST_LONG_BITS - 1)) >> 1; > +}
I have an error with preadv() on a 32bit target (powerpc, LTP test preadv02). It works if I use: static inline void host_offset64_low_high(unsigned long *hlow, unsigned long *hhigh, abi_ulong tlow, abi_ulong thigh) { uint64_t off = tlow | ((unsigned long long)thigh << TARGET_LONG_BITS / 2) << TARGET_LONG_BITS / 2; *hlow = off; *hhigh = (off >> HOST_LONG_BITS / 2) >> HOST_LONG_BITS / 2; } > + > +SYSCALL_IMPL(preadv) > +{ > + struct iovec *vec = lock_iovec(VERIFY_WRITE, arg2, arg3, 0); > + unsigned long lo, hi; > + abi_long ret; > + > + if (vec == NULL) { > + return -host_to_target_errno(errno); > + } > + > + host_offset64_low_high(&lo, &hi, arg4); > + ret = get_errno(safe_preadv(arg1, vec, arg3, lo, hi)); > + unlock_iovec(vec, arg2, arg3, 1); > + return ret; > +} > + > +SYSCALL_IMPL(pwritev) > +{ > + struct iovec *vec = lock_iovec(VERIFY_READ, arg2, arg3, 1); > + unsigned long lo, hi; > + abi_long ret; > + > + if (vec == NULL) { > + ret = -host_to_target_errno(errno); return -host_to_target_errno(errno); > + } > + > + host_offset64_low_high(&lo, &hi, arg4); > + ret = get_errno(safe_pwritev(arg1, vec, arg3, lo, hi)); > + unlock_iovec(vec, arg2, arg3, 0); > + return ret; > +} > + > SYSCALL_IMPL(read) > { > abi_long ret;