diff options
author | Peter Maydell <peter.maydell@linaro.org> | 2018-04-10 10:22:45 +0100 |
---|---|---|
committer | Peter Maydell <peter.maydell@linaro.org> | 2018-04-10 10:22:45 +0100 |
commit | fb4fe32d5b6290deabe752b51cc1cc2a9e8573db (patch) | |
tree | 5cbefd8c98de77aa1afbf6558da58376c54272aa /linux-user/syscall.c | |
parent | 1e7e92e2ef874aa3a235d59b2be1da7a29b6fd29 (diff) | |
parent | 9ac225171c9d6b2a1cba35a94ae7eeaa0106cf7d (diff) |
Merge remote-tracking branch 'remotes/xtensa/tags/20180409-xtensa' into staging
Fix file offset for preadv/pwritev linux-user syscalls.
# gpg: Signature made Tue 10 Apr 2018 03:04:24 BST
# gpg: using RSA key 51F9CC91F83FA044
# gpg: Good signature from "Max Filippov <filippov@cadence.com>"
# gpg: aka "Max Filippov <max.filippov@cogentembedded.com>"
# gpg: aka "Max Filippov <jcmvbkbc@gmail.com>"
# Primary key fingerprint: 2B67 854B 98E5 327D CDEB 17D8 51F9 CC91 F83F A044
* remotes/xtensa/tags/20180409-xtensa:
linux-user: fix preadv/pwritev offsets
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'linux-user/syscall.c')
-rw-r--r-- | linux-user/syscall.c | 27 |
1 files changed, 25 insertions, 2 deletions
diff --git a/linux-user/syscall.c b/linux-user/syscall.c index 8671447aca..643b8833de 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -3386,6 +3386,23 @@ static abi_long do_getsockopt(int sockfd, int level, int optname, return ret; } +/* Convert target low/high pair representing file offset into the host + * low/high pair. This function doesn't handle offsets bigger than 64 bits + * as the kernel doesn't handle them either. + */ +static void target_to_host_low_high(abi_ulong tlow, + abi_ulong thigh, + unsigned long *hlow, + unsigned long *hhigh) +{ + 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; +} + static struct iovec *lock_iovec(int type, abi_ulong target_addr, abi_ulong count, int copy) { @@ -10452,7 +10469,10 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, { struct iovec *vec = lock_iovec(VERIFY_WRITE, arg2, arg3, 0); if (vec != NULL) { - ret = get_errno(safe_preadv(arg1, vec, arg3, arg4, arg5)); + unsigned long low, high; + + target_to_host_low_high(arg4, arg5, &low, &high); + ret = get_errno(safe_preadv(arg1, vec, arg3, low, high)); unlock_iovec(vec, arg2, arg3, 1); } else { ret = -host_to_target_errno(errno); @@ -10465,7 +10485,10 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, { struct iovec *vec = lock_iovec(VERIFY_READ, arg2, arg3, 1); if (vec != NULL) { - ret = get_errno(safe_pwritev(arg1, vec, arg3, arg4, arg5)); + unsigned long low, high; + + target_to_host_low_high(arg4, arg5, &low, &high); + ret = get_errno(safe_pwritev(arg1, vec, arg3, low, high)); unlock_iovec(vec, arg2, arg3, 0); } else { ret = -host_to_target_errno(errno); |