Search code examples
assemblylinux-kernelx86-64calling-convention

calling convention regarding asmlinkage


I thought calling a function with asmlinkage modifier needs to push all argument to stack, until I was baffled by the following in Linux kernel source (3.16).

source in entry_64.S link

 movq %rsp,%rdi
 call sync_regs

Definition of sync_regs in arch/x86/kernel/traps.c:

asmlinkage __visible notrace struct pt_regs *sync_regs(struct pt_regs *eregs)
{
 struct pt_regs *regs = task_pt_regs(current);
 *regs = *eregs;
 return regs;
}

Shouldn't it need to push %rdi/%rsp to stack?

Answer/takeaway: Thanks to @Jester, the answer I summarize below:

  • NOTE! On x86-64, all the arguments are in registers, so this
  • only matters on a 32-bit kernel." [linux src comment]

Solution

  • http://kernelnewbies.org/FAQ/asmlinkage says asmlinkage means args are always pushed on the stack. This is probably an old doc. 32bit i386 Linux uses a register calling convention (regparm) inside the kernel, and asmlinkage really means "follow the standard ABI, whatever it is". So the FAQ only applies to i386.

    For x86-64 (and any other architecture that doesn't override it), asmlinkage is defined to be empty, or extern "C" in c++ code. For 32 bit x86 it is defined as regparm(0). (Thanks, Jester, for digging in the header files.)