在包含 kernel_fpu_begin() 的文件的 Linux 内核中生成和优化 FP/SIMD 代码?

Generate and optimize FP / SIMD code in the Linux Kernel on files which contains kernel_fpu_begin()?

我知道在内核中禁止使用任何类型的浮点代码,我们永远不应该使用任何可以生成 FP / SIMD 指令的 GCC 标志,但是一些源代码呢(尤其是 arch/x86/crypto/*) 使用 kernel_fpu_begin()kernel_fpu_end()?

Example 1, example 2.

我有一个古老的 Intel Core 2 Duo CPU 用于我的 64 位 Linux 内核,并且在主要 Makefile 我使用以下 C 标志:

# Target specific Flags
KBUILD_CFLAGS   += \
           -m64 \
           -march=core2 \
           -mtune=core2 \
           -mfpmath=sse \
           -msoft-float \
           -mno-fp-ret-in-387 \
           -mno-mmx \
           -mno-sse \
           -mno-sse2 \
           -mno-sse3 \
           -mno-ssse3

# FPU Flags
FPU_CFLAGS := $(KBUILD_CFLAGS) \
           -mhard-float \
           -mfp-ret-in-387 \
           -mmmx \
           -msse \
           -msse2 \
           -msse3 \
           -mssse3 \
           -ftree-vectorize

并且在存在 kernel_fpu_begin() 的文件中,我将 FPU_CFLAGS 传递到它们的 Makefiles 中,如下所示:

CFLAGS_sha512_ssse3_glue.o := $(FPU_CFLAGS)

这是否正确,是否会优化 FP/SIMD 代码?还是不需要并且此实现甚至可以破坏 FPU / SIMD 的状态?

Is this correct

不,绝对不要这样做。这些选项告诉GCC它可以在这个编译中使用SIMD/FP指令anywhere单位,包括 before kernel_fpu_begin()kernel_fpu_end() 之后,或在从不调用 kernel_fpu_begin().

的函数中

例如它可以发出 movdqu 加载或存储以复制结构的 16 个字节并 corrupt user-space XMM register state before kernel_fpu_begin 保存它。

and will optimize the FP / SIMD Code?

不,使用 kernel_fpu_begin() 的内核代码也使用内联 asm 到 运行 SIMD 指令。这将发出 SIMD 指令 而无需 编译器的任何帮助。

或者理论上一些内核代码可以使用函数属性,如 __attribute__((target("sse2"))) 或类似的东西,用于从 kernel_fpu_begin() / end 块内部调用的辅助函数。但我认为 Linux 更喜欢内联 asm 而不是加内在函数或自动矢量化。

如果内核从中获得的收益为零,则它不会费心去包含 kernel_fpu_begin()/end 调用。顺便说一句,您可以反汇编相关的 .ko 内核模块并查看它们实际上包含使用 XMM 寄存器的 SIMD 指令。使用 objdump -drwC -Mintel foo.ko