关于 asmlinkage 的调用约定

calling convention regarding asmlinkage

我认为使用 asmlinkage 修饰符调用函数需要将所有参数压入堆栈,直到我对 Linux 内核源代码 (3.16) 中的以下内容感到困惑。

来源在 entry_64.S link

 movq %rsp,%rdi
 call sync_regs

sync_regsarch/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;
}

不应该把%rdi/%rsp压入栈吗?

Answer/takeaway:感谢@Jester,我总结的答案如下:

  • 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/asmlinkageasmlinkage 意味着 args 总是被压入堆栈。这可能是一个旧文档。 32bit i386 Linux 在内核内部使用寄存器调用约定 (regparm),asmlinkage 真正意味着 "follow the standard ABI, whatever it is"。所以FAQ只适用于i386.

对于 x86-64(以及任何其他不覆盖它的架构),asmlinkage 被定义为空,或者在 c++ 代码中 extern "C"。对于 32 位 x86,它被定义为 regparm(0)。 (感谢 Jester 挖掘头文件。)