qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Qemu-devel] [PATCH v3 15/19] linux-user: Split out pread64, pwrite6


From: Philippe Mathieu-Daudé
Subject: Re: [Qemu-devel] [PATCH v3 15/19] linux-user: Split out pread64, pwrite64
Date: Tue, 12 Jun 2018 13:37:22 -0300
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:52.0) Gecko/20100101 Thunderbird/52.8.0

Hi Richard,

On 06/11/2018 09:51 PM, Richard Henderson wrote:
> Signed-off-by: Richard Henderson <address@hidden>
> ---
>  linux-user/syscall.h           | 44 +++++++++++++++++++++
>  linux-user/syscall.c           | 70 ----------------------------------
>  linux-user/syscall_file.c      | 61 +++++++++++++++++++++++++++--
>  linux-user/gen_syscall_list.py |  2 +
>  linux-user/strace.list         |  6 ---
>  5 files changed, 104 insertions(+), 79 deletions(-)
> 
> diff --git a/linux-user/syscall.h b/linux-user/syscall.h
> index 3fc49d5b65..a157e25bba 100644
> --- a/linux-user/syscall.h
> +++ b/linux-user/syscall.h
> @@ -174,6 +174,50 @@ struct iovec *lock_iovec(int type, abi_ulong target_addr,
>  void unlock_iovec(struct iovec *vec, abi_ulong target_addr,
>                    abi_ulong count, int copy);
>  
> +/* Returns true if syscall NUM expects 64bit types aligned even
> + * on pairs of registers.
> + */
> +static inline bool regpairs_aligned(void *cpu_env, int num)
> +{
> +#ifdef TARGET_ARM
> +    return ((CPUARMState *)cpu_env)->eabi;
> +#elif defined(TARGET_MIPS) && TARGET_ABI_BITS == 32
> +    return true;
> +#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
> +     * we start with r3 as arg1
> +     */
> +    return true;
> +#elif defined(TARGET_SH4)
> +    /* SH4 doesn't align register pairs, except for p{read,write}64 */
> +    switch (num) {
> +    case TARGET_NR_pread64:
> +    case TARGET_NR_pwrite64:
> +        return true;
> +    default:
> +        return false;
> +    }
> +#elif defined(TARGET_XTENSA)
> +    return true;
> +#else
> +    return false;
> +#endif
> +}
> +
> +static inline uint64_t target_offset64(abi_ulong word0, abi_ulong word1)
> +{
> +#if TARGET_ABI_BITS == 32
> +# ifdef TARGET_WORDS_BIGENDIAN
> +    return ((uint64_t)word0 << 32) | word1;
> +# else
> +    return ((uint64_t)word1 << 32) | word0;
> +# endif
> +#else
> +    return word0;
> +#endif
> +}
> +
>  /* Temporary declarations from syscall_foo.c back to main syscall.c.
>   * These indicate incomplete conversion.
>   */
> diff --git a/linux-user/syscall.c b/linux-user/syscall.c
> index 381ee9c3a2..cdc9787240 100644
> --- a/linux-user/syscall.c
> +++ b/linux-user/syscall.c
> @@ -642,38 +642,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
> @@ -6864,22 +6832,6 @@ void syscall_init(void)
>      }
>  }
>  
> -#if TARGET_ABI_BITS == 32
> -static inline uint64_t target_offset64(uint32_t word0, uint32_t word1)
> -{
> -#ifdef TARGET_WORDS_BIGENDIAN
> -    return ((uint64_t)word0 << 32) | word1;
> -#else
> -    return ((uint64_t)word1 << 32) | word0;
> -#endif
> -}
> -#else /* TARGET_ABI_BITS == 32 */
> -static inline uint64_t target_offset64(uint64_t word0, uint64_t word1)
> -{
> -    return word0;
> -}
> -#endif /* TARGET_ABI_BITS != 32 */
> -
>  #ifdef TARGET_NR_truncate64
>  static inline abi_long target_truncate64(void *cpu_env, const char *arg1,
>                                           abi_long arg2,
> @@ -10078,28 +10030,6 @@ static abi_long do_syscall1(void *cpu_env, int num, 
> abi_long arg1,
>  #else
>  #error unreachable
>  #endif
> -#endif
> -#ifdef TARGET_NR_pread64
> -    case TARGET_NR_pread64:
> -        if (regpairs_aligned(cpu_env, num)) {
> -            arg4 = arg5;
> -            arg5 = arg6;
> -        }
> -        if (!(p = lock_user(VERIFY_WRITE, arg2, arg3, 0)))
> -            return -TARGET_EFAULT;
> -        ret = get_errno(pread64(arg1, p, arg3, target_offset64(arg4, arg5)));
> -        unlock_user(p, arg2, ret);
> -        return ret;
> -    case TARGET_NR_pwrite64:
> -        if (regpairs_aligned(cpu_env, num)) {
> -            arg4 = arg5;
> -            arg5 = arg6;
> -        }
> -        if (!(p = lock_user(VERIFY_READ, arg2, arg3, 1)))
> -            return -TARGET_EFAULT;
> -        ret = get_errno(pwrite64(arg1, p, arg3, target_offset64(arg4, 
> arg5)));
> -        unlock_user(p, arg2, 0);
> -        return ret;
>  #endif
>      case TARGET_NR_getcwd:
>          if (!(p = lock_user(VERIFY_WRITE, arg1, arg2, 0)))
> diff --git a/linux-user/syscall_file.c b/linux-user/syscall_file.c
> index 4cc7051847..aae9c49599 100644
> --- a/linux-user/syscall_file.c
> +++ b/linux-user/syscall_file.c
> @@ -378,15 +378,70 @@ SYSCALL_IMPL(openat)
>  }
>  SYSCALL_DEF(openat, ARG_ATDIRFD, ARG_STR, ARG_OPENFLAG, ARG_MODEFLAG);
>  
> +/* Both pread64 and pwrite64 merge args into a 64-bit offset,
> + * but the input registers and ordering are target specific.
> + */
> +#if TARGET_ABI_BITS == 32
> +SYSCALL_ARGS(pread64_pwrite64)
> +{
> +    /* We have already assigned out[0-2].  */
> +    int off = regpairs_aligned(cpu_env, TARGET_NR_pread64);
> +    out[3] = target_offset64(in[3 + off], in[4 + off]);
> +    return def;
> +}
> +#else
> +#define args_pread64_pwrite64 NULL
> +#endif
> +
> +SYSCALL_IMPL(pread64)
> +{
> +    void *p = lock_user(VERIFY_WRITE, arg2, arg3, 0);
> +    abi_long ret;
> +
> +    if (!p) {
> +        return -TARGET_EFAULT;
> +    }
> +    ret = get_errno(pread64(arg1, p, arg3, arg4));
> +    unlock_user(p, arg2, ret);
> +    return ret;
> +}
> +
> +const SyscallDef def_pread64 = {
> +    .name = "pread64",
> +    .args = args_pread64_pwrite64,
> +    .impl = impl_pread64,
> +    .arg_type = { ARG_DEC, ARG_PTR, ARG_DEC, ARG_DEC64 }
> +};
> +
> +SYSCALL_IMPL(pwrite64)
> +{
> +    void *p = lock_user(VERIFY_READ, arg2, arg3, 0);
> +    abi_long ret;
> +
> +    if (!p) {
> +        return -TARGET_EFAULT;
> +    }
> +    ret = get_errno(pwrite64(arg1, p, arg3, arg4));
> +    unlock_user(p, arg2, 0);
> +    return ret;
> +}
> +
> +const SyscallDef def_pwrite64 = {
> +    .name = "pwrite64",
> +    .args = args_pread64_pwrite64,
> +    .impl = impl_pwrite64,
> +    .arg_type = { ARG_DEC, ARG_PTR, ARG_DEC, ARG_DEC64 }
> +};
> +
>  /* 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-3].  */
> -    abi_ulong lo = in[4], hi = in[5];
> -    out[4] = ((hi << (TARGET_ABI_BITS - 1)) << 1) | lo;
> +    /* We have already assigned out[0-2].  */
> +    abi_ulong lo = in[3], hi = in[4];
> +    out[3] = ((hi << (TARGET_ABI_BITS - 1)) << 1) | lo;

Why this change? If correct, can you update the comment?
Also this seems related to your previous patch #14: "Split out preadv,
pwritev, readv, writev", not this one.

>      return def;
>  }
>  #else
> diff --git a/linux-user/gen_syscall_list.py b/linux-user/gen_syscall_list.py
> index ce6dca742c..7481d030ee 100644
> --- a/linux-user/gen_syscall_list.py
> +++ b/linux-user/gen_syscall_list.py
> @@ -27,7 +27,9 @@ import sys
>  unconditional_syscalls = [
>      "close",
>      "openat",
> +    "pread64",
>      "preadv",
> +    "pwrite64",
>      "pwritev",
>      "read",
>      "readv",
> diff --git a/linux-user/strace.list b/linux-user/strace.list
> index d5ee55ac82..d978cefa31 100644
> --- a/linux-user/strace.list
> +++ b/linux-user/strace.list
> @@ -1025,9 +1025,6 @@
>  #ifdef TARGET_NR_prctl
>  { TARGET_NR_prctl, "prctl" , NULL, NULL, NULL },
>  #endif
> -#ifdef TARGET_NR_pread64
> -{ TARGET_NR_pread64, "pread64" , NULL, NULL, NULL },
> -#endif
>  #ifdef TARGET_NR_prlimit64
>  { TARGET_NR_prlimit64, "prlimit64" , NULL, NULL, NULL },
>  #endif
> @@ -1052,9 +1049,6 @@
>  #ifdef TARGET_NR_putpmsg
>  { TARGET_NR_putpmsg, "putpmsg" , NULL, NULL, NULL },
>  #endif
> -#ifdef TARGET_NR_pwrite64
> -{ TARGET_NR_pwrite64, "pwrite64" , NULL, NULL, NULL },
> -#endif
>  #ifdef TARGET_NR_query_module
>  { TARGET_NR_query_module, "query_module" , NULL, NULL, NULL },
>  #endif
> 



reply via email to

[Prev in Thread] Current Thread [Next in Thread]