【问题标题】:calling convention regarding asmlinkage关于 asmlinkage 的调用约定
【发布时间】:2015-08-10 13:28:13
【问题描述】:

我认为使用 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推入栈吗?

答案/外卖:感谢@Jester,我总结的答案如下:

  • 注意!在 x86-64 上,所有参数都在寄存器中,所以这个
  • 仅在 32 位内核上重要。" [linux src comment]

【问题讨论】:

  • 64 位调用约定使用寄存器作为前几个参数。阅读 abi 文档。
  • 我以为这是默认设置(wo asmlinkage)...所以对于 x_86_64,asmlikage 不会在堆栈上假设参数?...或者 asmlinkage 仅适用于 32 位?

标签: assembly linux-kernel x86-64 calling-convention


【解决方案1】:

http://kernelnewbies.org/FAQ/asmlinkage 表示 asmlinkage 表示 args 总是被压入堆栈。这可能是一个老文档。 32 位 i386 Linux 在内核内部使用寄存器调用约定 (regparm),asmlinkage 真正的意思是“遵循标准 ABI,不管它是什么”。所以FAQ只适用于i386。

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

【讨论】:

  • 是的,文档可能有误。但源永远不是 :) 对于 x86-64(以及任何其他不覆盖它的架构),asmlinkage 被定义为空,或者在 c++ 代码中定义为 extern "C"。对于 32 位 x86,它被定义为 regparm(0)
  • 谢谢@Jester。这证实了我的猜测,i386 Linux 使用 regparm 构建内部函数,并且仅在需要时使用“标准”堆栈上寄存器 ABI。
  • @Jester,您能否为您的陈述提供证据:“对于 x86-64(以及任何其他不覆盖它的架构),asmlinkage 被定义为空”
猜你喜欢
  • 2021-08-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-28
  • 2012-04-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多