我知道在内核中禁止使用任何类型的浮点代码,我们永远不应该使用任何可以生成FP/SID指令的GCC标志,但一些使用kernel_fpu_begin()
和kernel_fpu_end()
的源代码(尤其是arch/x86/crypto/*
(呢?
实施例1,实施例2。
我有一个古老的英特尔酷睿2双核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()
的文件中,我在它们的Makefiles
中传递FPU_CFLAGS
,如下所示:
CFLAGS_sha512_ssse3_glue.o := $(FPU_CFLAGS)
这是正确的吗?它会优化FP/SID代码吗?还是不需要它,这种实现甚至可能破坏FPU/SIMD的状态?
这是正确的吗
不,绝对不要这样做这些选项告诉GCC,它可以在此编译单元中的任何位置使用SIMD/FP指令,包括kernel_fpu_begin()
之前或kernel_fpu_end()
之后的,或者在从不调用kernel_fpu_begin()
的函数中。
例如,它可以发出movdqu
加载或存储以复制结构的16个字节,并在kernel_fpu_begin
保存它之前破坏用户空间XMM寄存器状态
,并将优化FP/SID代码?
否,使用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