Messages in this thread | | | Date | Thu, 14 Sep 2017 23:21:14 +0300 | From | "Dmitry V. Levin" <> | Subject | Re: [PATCH] x86/asm/64: do not clear high 32 bits of syscall number when CONFIG_X86_X32=y |
| |
On Wed, Sep 13, 2017 at 06:49:21PM +0200, Oleg Nesterov wrote: > On 09/13, Dmitry V. Levin wrote: > > > > Before this change, CONFIG_X86_X32=y fastpath behaviour was different > > from slowpath: > > and even with this change they differ if CONFIG_X86_X32=n?
No, I don't think so.
> do_syscall_64() does "nr & __SYSCALL_MASK" unconditionally,
yes
> this clears the upper bits, no?
Why? As "nr" is of type "unsigned long" and __SYSCALL_MASK is either (~(__X32_SYSCALL_BIT)) or (~0), that is, an integer with the sign bit set, in "nr & __SYSCALL_MASK" expression __SYSCALL_MASK is sign-extended to unsigned long. When __SYSCALL_MASK is defined to (~0), "nr & __SYSCALL_MASK" is optimized to "nr" at compilation time:
$ echo 'unsigned long foo(unsigned long nr) { return nr & (~0); }' | gcc -Wall -O2 -xc -S -o - - | sed -n '/cfi_/,/cfi_/p' .cfi_startproc movq %rdi, %rax ret .cfi_endproc
> And why __SYSCALL_MASK is not "unsigned long" ? IOW, why do we want to silently > ignore the upper bits in $rax ?
__SYSCALL_MASK is "int" but it is being sign-extended to unsigned long in all (two) places of arch/x86/entry/common.c where it is used.
> Or I am totally confused?
The thing looks like it was designed to confuse people.
-- ldv [unhandled content-type:application/pgp-signature] | |