[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [Qemu-devel] [PATCH v2] linux-user: fix preadv/pwritev offsets
From: |
Laurent Vivier |
Subject: |
Re: [Qemu-devel] [PATCH v2] linux-user: fix preadv/pwritev offsets |
Date: |
Thu, 5 Apr 2018 11:03:32 +0200 |
User-agent: |
Mozilla/5.0 (X11; Linux x86_64; rv:52.0) Gecko/20100101 Thunderbird/52.6.0 |
Le 05/04/2018 à 03:41, Max Filippov a écrit :
> preadv/pwritev accept low and high parts of file offset in two separate
> parameters. When host bitness doesn't match guest bitness these parts
> must be appropriately recombined.
> Introduce target_low_high_to_host_low_high that does this recombination
> and use it in preadv/pwritev syscalls.
>
> This fixes glibc testsuite test misc/tst-preadvwritev64.
>
> Signed-off-by: Max Filippov <address@hidden>
> ---
> Changes v1->v2:
> - fix host high computation in TARGET_LONG_BITS > HOST_LONG_BITS case
>
> linux-user/syscall.c | 27 +++++++++++++++++++++++++--
> 1 file changed, 25 insertions(+), 2 deletions(-)
>
> diff --git a/linux-user/syscall.c b/linux-user/syscall.c
> index 5ef517613577..7e014066260a 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;
> }
>
> +static void target_low_high_to_host_low_high(abi_ulong tlow,
> + abi_ulong thigh,
> + unsigned long *hlow,
> + unsigned long *hhigh)
> +{
> +#if TARGET_LONG_BITS == HOST_LONG_BITS
> + *hlow = tlow;
> + *hhigh = thigh;
> +#elif TARGET_LONG_BITS < HOST_LONG_BITS
> + *hlow = tlow | (unsigned long)thigh << TARGET_LONG_BITS;
> + *hhigh = 0;
> +#else
> + *hlow = (unsigned long)tlow;
> + *hhigh = (unsigned long)(tlow >> HOST_LONG_BITS);
> +#endif
> +}
> +
> static struct iovec *lock_iovec(int type, abi_ulong target_addr,
> abi_ulong count, int copy)
> {
> @@ -10449,7 +10466,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_low_high_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);
> @@ -10462,7 +10482,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_low_high_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);
>
Did you try to use the regpairs_aligned() and target_offset64()
functions as it is done for pread64(), pwrite64(), fadvise64(),... ?
Thanks,
Laurent