[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