Thread (76 messages) 76 messages, 7 authors, 2016-01-07

[PATCH v6 12/20] arm64:ilp32: add sys_ilp32.c and a separate table (in entry.S) to use it

From: arnd@arndb.de (Arnd Bergmann)
Date: 2015-12-18 12:54:13
Also in: lkml

On Friday 18 December 2015 11:42:19 Catalin Marinas wrote:
On Thu, Dec 17, 2015 at 12:14:20PM -0800, Andrew Pinski wrote:
quoted
Well (just like LP64 on AARCH64), when passing a 32bit value to a
function, the upper 32bits are undefined.  I ran into this when I was
debugging the GCC go library on ILP32 (though reproduced with pure C
code) and the assembly functions inside glibc where pointers are
passed with the upper 32bits as undefined.
So we have an issue if called with syscall function or using pure
assembly to create the syscall functions (which glibc does).
I think the ILP32 syscall ABI should follow the PCS convention where the
top 32-bit of a register is not guaranteed 0 when the size of the
argument is 32-bit. So take the read(2) syscall:

        ssize_t read(int fd, void *buf, size_t count);

From the ILP32 code perspective, void * and size_t are both 32-bit. It
would call into the kernel leaving the top 32-bit as undefined (if we
follow the PCS). Normally, calling a function with the same size
arguments is not a problem since the compiler generates the callee code
accordingly. However, we route the syscall directly into the native
sys_read() where void * and size_t are 64-bit with the top 32-bit left
undefined.

We have three options here:

1. Always follow PCS convention across user/kernel call and add wrappers
   in the kernel (preferred)
Yes, I also think this is best.
2. Follow the PCS up to glibc and get glibc to zero the top part (not
   always safe with hand-written assembly, though we already do this for
   AArch32 where the PCS only specifies 4 arguments in registers, the
   rest go on the stack)
I assume this needs special handling for syscalls with 64-bit arguments
in both glibc and kernel.
3. Follow the PCS up to glibc but always pass syscall arguments in W
   registers, like AArch32 compat support (the least preferred option,
   the only advantage is a single wrapper for all syscalls but it would
   be doing unnecessary zeroing even for syscalls where it isn't needed)
This would mean we cannot pass 64-bit arguments in registers, right?
 
My preference, as stated above, is (1). You can write the wrappers in C
directly and let the compiler upgrade the types when calling the native
syscall. But any other option would be fine (take some inspiration from
other architectures). Unfortunately we don't have COMPAT_SYSCALL_DEFINE
for all functions that we need to wrap, it would have been easier (so we
need to add them but probably in the arch/arm64 code).
It would be nice to have that code architecture-independent, so we can
share it with s390 and only need to update one place when new syscalls
get added.

	Arnd
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help