在Linux 5.10 AArch64
syscall.c
源代码中,有一个函数sve_user_discard()
,可以将SVE寄存器的[max:128]位清零。 这是代码。
我无法理解这个功能的用法。谁能给我解释一下吗?
我在运行SVE程序时遇到了一个bug,最后发现根本原因是
sve_user_discard()
。这个函数使得用户空间中的SVE寄存器只保留位[127:0],这使得我的程序无法按预期工作。
经过一番研究后,我发现我所需要做的就是 RTFM :')。此行为是有意为之并记录在案的。
Linux ARM64 Syscall ABI 显式重置系统调用条目上 Z 寄存器的 127 位以上、P 寄存器的所有位以及 FFR 寄存器。因此,无法在系统调用之间保留 ARM64 Linux 上的完整 SVE 状态。如果您的代码使用 SVE,则需要将其拆分,以便 SVE 仅在系统调用之间使用。即使向量长度为 128 位,您仍然会在系统调用输入时丢失 P0..P15 和 FFR 的值。
这里引用了 SVE 上的内核文档,证实了这种行为。我用粗体突出显示了有趣的部分:
3.系统调用行为
在系统调用中,V0..V31 被保留(与没有 SVE 一样)。因此,位[127:0] Z0..Z31 被保留。 Z0..Z31 的所有其他位,以及 P0..P15 和 FFR 的所有位 从系统调用返回时变得未指定。
SVE 寄存器不用于传递参数或接收结果 任何系统调用。
实际上受影响的寄存器/位将被保留或将被替换 从系统调用返回时为零,但用户空间不应使 对此的假设。 内核行为可能会因具体情况而异 基础。