关于 asmlinkage 的调用约定
calling convention regarding asmlinkage
我认为使用 asmlinkage 修饰符调用函数需要将所有参数压入堆栈,直到我对 Linux 内核源代码 (3.16) 中的以下内容感到困惑。
来源在 entry_64.S link
movq %rsp,%rdi
call sync_regs
sync_regs
在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;
}
不应该把%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/asmlinkage 说 asmlinkage
意味着 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 挖掘头文件。)
我认为使用 asmlinkage 修饰符调用函数需要将所有参数压入堆栈,直到我对 Linux 内核源代码 (3.16) 中的以下内容感到困惑。
来源在 entry_64.S link
movq %rsp,%rdi
call sync_regs
sync_regs
在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;
}
不应该把%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/asmlinkage 说 asmlinkage
意味着 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 挖掘头文件。)