我知道禁止在内核中使用任何种类的浮点代码,并且我们绝不应该使用任何可以生成FP / SIMD指令的GCC标志,但是使用某些源代码(尤其是arch/x86/crypto/*
)呢? kernel_fpu_begin()
和kernel_fpu_end()
?
[我有一个古老的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的状态?
这是正确的
不,绝对不要这样做。这些选项告诉GCC它可以在此编译单元中使用SIMD / FP指令anywhere,包括before kernel_fpu_begin()
或kernel_fpu_end()
之后,或从未调用kernel_fpu_begin()
的函数中。
例如它可能会发出movdqu
加载或存储以复制16个字节的结构,并且corrupt user-space XMM register state 之前 kernel_fpu_begin
保存了它。
并且将优化FP / SIMD代码?
否,使用kernel_fpu_begin()
的内核代码也使用嵌入式asm运行SIMD指令。这将发出SIMD指令无编译器的任何帮助。
或者从理论上讲,某些内核代码可以使用函数属性,例如__attribute__((target("sse2")))
或类似的属性,用于从kernel_fpu_begin()
/ end
块内部调用的辅助函数。但是我认为Linux更喜欢内联汇编,而不是内在汇编或自动向量化。
如果内核从中获得零收益,它就不会费心地包含kernel_fpu_begin()
/ end
调用。顺便说一句,您可以反汇编相关的.ko
内核模块,并查看它们实际上是否包含使用XMM寄存器的SIMD指令。使用objdump -drwC -Mintel foo.ko