qemu-devel
[Top][All Lists]
Advanced

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

Re: [Qemu-devel] [PATCH] linux-user: Fix sched_get/setaffinity conversio


From: Laurent Vivier
Subject: Re: [Qemu-devel] [PATCH] linux-user: Fix sched_get/setaffinity conversion
Date: Thu, 28 Dec 2017 18:50:14 +0100
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:52.0) Gecko/20100101 Thunderbird/52.5.0

Le 28/12/2017 à 15:11, Samuel Thibault a écrit :
> sched_get/setaffinity linux-user syscalls were missing conversions for
> little/big endian, which is hairy since longs may not be the same size
> either.
> 
> For simplicity, this just introduces loops to convert bit by bit like is
> done for select.
> 

I think you should introduce two new functions:
target_to_host_cpu_mask()/host_to_target_cpu_mask().

> Signed-off-by: Samuel Thibault <address@hidden>
> ---
>  linux-user/syscall.c | 48 ++++++++++++++++++++++++++++++++++++++++++++----
>  1 file changed, 44 insertions(+), 4 deletions(-)
> 
> diff --git a/linux-user/syscall.c b/linux-user/syscall.c
> index 11c9116c4a..8ec7de96ce 100644
> --- a/linux-user/syscall.c
> +++ b/linux-user/syscall.c
> @@ -10341,6 +10341,8 @@ abi_long do_syscall(void *cpu_env, int num, abi_long 
> arg1,
>          {
>              unsigned int mask_size;
>              unsigned long *mask;
> +            abi_ulong *abimask;
> +            unsigned i, j;
>  
>              /*
>               * sched_getaffinity needs multiples of ulong, so need to take
> @@ -10353,6 +10355,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long 
> arg1,
>              mask_size = (arg2 + (sizeof(*mask) - 1)) & ~(sizeof(*mask) - 1);
>  
>              mask = alloca(mask_size);
> +            memset(mask, 0, mask_size);
>              ret = get_errno(sys_sched_getaffinity(arg1, mask_size, mask));
>  
>              if (!is_error(ret)) {
> @@ -10372,9 +10375,27 @@ abi_long do_syscall(void *cpu_env, int num, abi_long 
> arg1,
>                      ret = arg2;
>                  }
>  
> -                if (copy_to_user(arg3, mask, ret)) {
> +                abimask = lock_user(VERIFY_WRITE, arg3, arg2, 0);
> +                if (!abimask) {
>                      goto efault;
>                  }
> +
> +                for (i = 0 ; i < arg2 / sizeof(abi_ulong); i++) {
> +                    unsigned abi_ubits = sizeof(abi_ulong) * 8;
> +                    unsigned ubits = sizeof(*mask) * 8;
> +                    unsigned bit = i * abi_ubits;
> +                    abi_ulong val = 0;
> +
> +                    for (j = 0; j < abi_ubits; j++, bit++) {
> +                        if (mask[bit / ubits] & (1UL << (bit % ubits))) {

You should use __CPUMASK() and introduce a TARGET_CPUMASK().

Thanks,
Laurent



reply via email to

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