System V AMD64 ABI 的 %gs caller- 或 callee-save 是吗?

Is %gs caller- or callee-save for the System V AMD64 ABI?

System V AMD64 ABI 是否说明了段寄存器 %gs?它被认为是调用者保存还是被调用者保存?还是预留的?或者还没有为 %gs 定义什么?

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

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

我认为 Linux 内核将 save/restore user-space 的选择器值(也可能是段基数与某个 GDT 或 LDT 条目中的任何内容分开非 0 选择器值,而不是通过系统调用设置以写入 MSR,或者通过 wrgsbase 如果内核为用户启用它 - space 在支持它的硬件上使用。)如果是这样那么它会用户 space 可以将 GS 用于某些用途,例如备用 TLS。

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

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

写 GS 也很慢 (),虽然读它相当高效(P4 除外)。也许比线程本地存储内存位置更有效,尽管 GS 不能作为存储以外的指令的源操作数。


有趣的事实:i386 SysV 将 GS 用于 TLS;我认为 x86-64 已更改为 FS,因此 kernel-GS(由于 swapgs 而特殊)可能仅用于在 swapgs 之后查找任务的内核堆栈,而不必成为内核的 TLS 基础对于每个核心变量。