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]
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.)