x86_64 Linux函数和系统调用ABI之间的区别

12

x86_64 SysV ABI的函数调用约定规定,整数参数#4需要在rcx寄存器中传递。相反地,Linux内核syscall ABI使用r10来传递同样的参数。对于这两个函数和syscalls,所有其他参数都使用相同的寄存器进行传递。

这导致了一些奇怪的事情。例如,在x32平台上(该平台存在相同的差异),请查看glibc中mmap的实现:

00432ce0 <__mmap>:
  432ce0:       49 89 ca                mov    %rcx,%r10
  432ce3:       b8 09 00 00 40          mov    $0x40000009,%eax
  432ce8:       0f 05                   syscall

现在所有的寄存器都已经就绪,除了我们要将rcx移动到r10

我想知道为什么不将系统调用ABI定义为与函数调用ABI相同,考虑它们已经如此相似。


另一个ABI答案中,我挖掘了一些来自AMD架构师和Linux内核开发人员的amd64邮件列表帖子的链接,这是在第一块AMD64硅片发布之前。那里有一些有趣的东西,比如实验结果(从编译SPECint并查看代码大小和指令数量)导致x86-64 SysV ABI选择用于什么的寄存器。 - Peter Cordes
2个回答

10

syscall指令旨在提供一种更快的方式进入Ring-0以执行系统调用。这意味着相比于旧的方法(在Linux上是int 0x80),它是一种改进。

指令更快的原因之一是它不会更改内存,甚至不会更改rsp以指向内核堆栈。与软件中断不同,在软件强制让CPU允许操作系统恢复操作而无需破坏任何内容的情况下,对于此命令,CPU可以假设软件知道这里正在发生某些事情。

特别地,syscall将用户空间状态的两个部分存储在寄存器中。要调用的RIP存储在rcx中,标志位存储在R11中(因为在进入内核之前,RFLAGS与内核提供的值进行了掩码处理)。这意味着该指令破坏了这两个寄存器。

由于它们被破坏,系统调用ABI使用另一个寄存器而不是rcx,因此第四个参数使用r10

r10是一个自然的选择,因为在x86-64 SystemV ABI中,它不用于传递函数参数,并且函数不需要保留其调用者的r10值。因此,系统调用包装函数可以mov %rcx,%r10,而无需进行任何保存/恢复操作。对于6个参数的系统调用和SysV ABI的函数调用约定,这将不可能使用其他任何寄存器。


BTW,32位系统调用ABI也可以通过sysenter访问,这需要用户空间和内核空间之间的协作,以允许在sysenter后返回到用户空间(即在运行sysenter之前在用户空间存储一些状态)。这比int 0x80更高效,但不太方便。尽管如此,glibc仍在使用它(通过跳转到内核映射到每个进程地址空间中的vdso页面中的用户空间代码)。
AMD的syscall是与Intel的sysenter相同思路的另一种方法:通过不保留绝对所有内容来使内核的进入/退出变得更加廉价。

这比仅仅用寄存器-寄存器传输替换掉几个存储位置更微妙。它不改变 rsp 指向内核栈的位置,因此没有一个明智的地方来推送任何想要保存的东西。内核代码在入口点必须自己处理这一问题。(使用 swapgs 使 [gs:绝对地址] 可以访问每个任务的内核数据)。CPU 内部也没有保留一个内核栈指针来用于 syscall,只有一个已保存的 gs 值。我认为这就是实现复杂度降低的原因。(而 swapgs 是一个单独的指令)。 - Peter Cordes
关于C/C++不使用r10的部分毫无意义。内核不允许假定哪种语言正在执行调用。 - Shachar Shemesh
1
我找到了一种表述方式,完全准确而且不会忽略静态链指针,同时又没有提到它们(我想:)。对于包装函数来说,它们并不相关,反而会分散注意力(特别是大多数人从未听说过它们,而我甚至不知道它们究竟是什么)。我还整理了评论线程。 - Peter Cordes

6

AMD的syscall会覆盖rcx寄存器,因此使用r10代替。


1
r10 是一个纯粹的暂存寄存器:不用于函数参数传递,也不保留调用。这使得其他包装函数(如动态链接器存根)可以将其用作临时寄存器,并仍能够通过 jmp 进行尾部调用,而无需使用 call / pop / ret。 因此,r10 是进行系统调用的不错选择。 syscall / sysret 也使用 r11。 - Peter Cordes
哎呀,我想到的是 r11。ABI 表示 r10 用于传递“静态链指针”。C/C++ 不使用它,因此在实践中,r10 也是一个纯粹的临时寄存器。 - Peter Cordes
在这个上下文中,“clobber”的意思是什么? - tuket

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接