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 <samuel.thiba...@ens-lyon.org> > --- > 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