%gs是System V AMD64 ABI的调用者保存还是被调用者保存?



System V AMD64 ABI是否对段寄存器%gs有任何说明?它被认为是呼叫者拯救还是被呼叫者拯救?还是预订了?还是还没有定义%gs?

IIRC,调用约定/ABI根本没有太多可说的。FS基用于x86-64 System V上的线程本地存储,但是您想对GS基(和/或GS段选择器)做的任何事情都可能由您定义您的程序如何使用它。

在调用约定方面,或者更正常地在线程生命周期的早期设置一次,之后保持不变。就像MXCSR和x87舍入模式/精度控制是如何通过让函数保持不变来处理的,除了可能在进行任何进一步调用之前恢复的本地更改。(这仍然可以被描述为调用约定/ABI,但正如Nate评论的那样,它既不是保留调用也不是破坏调用。)

我认为Linux内核将保存/恢复用户空间的选择器值(也可能是段基单独从一些GDT或LDT条目中由非0选择器值选择的,而不是通过系统调用来设置写MSR,或者通过wrgsbase如果内核允许它用于支持它的HW上的用户空间使用。)如果是这样,那么用户空间将GS用于某些东西是可行的,例如替代TLS。

在实践中,您可以放心地假设调用库中编译器生成的代码(甚至是手写的)不会改变它。所以你只需要担心系统调用和上下文切换;我建议你测试一下。

请注意,mov到GS的值不是0或LDT或GDT条目的有效选择器会出错,因此您可以使用的值非常有限。

写GS也很慢(一个mov到一个分段寄存器比一个mov到一个通用寄存器慢吗?),虽然读它是相当有效的(除了P4)。也许比线程本地存储的内存位置更有效,尽管GS不能作为除存储之外的指令的源操作数。


有趣的事实:i386 SysV使用GS作为TLS;我认为x86-64更改为FS,因此内核- gs(这是特殊的,因为swapgs)可能只是为了在swapgs之后找到任务的内核堆栈,也不必是内核的TLS基础为每核变量。

最新更新