Re: 64 bit types with varargs on ARM

  • From: Justin Cormack <justin@xxxxxxxxxxxxxxxxxxxxx>
  • To: luajit@xxxxxxxxxxxxx
  • Date: Mon, 13 Aug 2012 11:53:58 +0100

On 13 Aug 2012 11:19, "Mike Pall" <mike-1208@xxxxxxxxxx> wrote:
>
> Justin Cormack wrote:
> > local function fallocate(fd, mode, offset, len)
> >   return ffi.C.syscall(fa[ffi.arch], int(fd), uint(0), loff(offset),
loff(len))
> > end
>
> This is not LuaJIT's fault -- it correctly implements the ARM
> calling convention.
>
> But you're not using the correct calling convention for 32 bit
> user mode when calling a Linux system call with 64 bit arguments.
>
> It happens to work on x86, because 64 bit arguments are not
> specially aligned. And it works on x64, because 64 bit arguments
> are passed in a single register.
>
> But most other 32 bit ABIs (e.g. ARM or PPC) align 64 bit arguments
> to even/odd register pairs or stack slots. This creates a dummy
> padding argument before the offset argument for syscall(). However,
> the actual kernel interface has the system call number in a
> special register. Then fd is the first argument and there's no
> need for padding the offset. With e.g. ftruncate, you'd get the
> opposite problem (no padding in syscall, padding in kernel call).
>
> The implication would be that syscall() couldn't simply shift down
> its arguments -- it would depend on the system call how to do
> that. That's not really workable, so it was decided a long time
> ago that 64 bit Linux system call arguments are to be passed as
> two 32 bit arguments from 32 bit user mode and as a single 64 bit
> argument from 64 bit user mode.
>
> Have a look at the eglibc 32 bit user mode wrapper for fallocate64:
>
>
http://www.eglibc.org/cgi-bin/viewvc.cgi/trunk/libc/sysdeps/unix/sysv/linux/fallocate64.c?revision=17195&view=markup
>
> tl;dr: Use the code quoted above for 64 bit archs, but split up
> 64 bit arguments for 32 bit archs when using syscall().
>
> --Mike
>

Ah OK thanks for that explanation.

Justin

Other related posts: