linux 内核使用硬浮点,c – 为什么我能在Linux内核模块中执行浮点运算?

I thought you couldn’t perform floating point operations in the Linux kernel

你不能安全:无法使用kernel_fpu_begin()/ kernel_fpu_end()并不意味着FPU指令会出错(至少不在x86上).

相反,它会默默地破坏用户空间的FPU状态.这不好;不要那样做.

编译器不知道kernel_fpu_begin()的含义,因此无法检查/警告编译到FPU-begin区域之外的FPU指令的代码.

可能存在调试模式,其中内核在kernel_fpu_begin / end region之外禁用SSE,x87和MMX指令,但这样做会更慢并且默认情况下不会完成.

但是有可能:设置CR0 :: TS = 1使x87指令失败,因此可以进行延迟FPU上下文切换,并且SSE和AVX还有其他位.

有缺陷的内核代码有很多方法可以导致严重的问题.这只是其中之一.在C中,您几乎总是知道何时使用浮点(除非拼写错误导致1.常量或实际编译的上下文中的某些内容).

为什么FP架构状态与整数不同?

Linux必须在进入/退出内核时保存/恢复整数状态.所有代码都需要使用整数寄存器(FPU计算的一个巨大的直线块除外,它以jmp而不是ret结束(ret修改rsp).)

但内核代码通常会避免FPU,因此Linux在系统调用进入时保留FPU状态,仅在实际上下文切换到不同的用户空间进程或kernel_fpu_begin之前保存.否则,在同一核心上返回相同的用户空间进程是很常见的,因此不需要恢复FPU状态,因为内核没有触及它. (如果内核任务确实修改了FPU状态,那么就会发生损坏.我认为这有两种方式:用户空间也可能破坏你的FPU状态).

整数状态相当小,只有16x 64位寄存器RFLAGS和段寄存器.即使没有AVX,FPU状态也是两倍大:8x 80位x87寄存器,16x XMM或YMM,或32x ZMM寄存器(MXCSR和x87状态控制字). MPX bnd0-4寄存器也与“FPU”混为一谈.此时“FPU状态”仅表示所有非整数寄存器.在我的Skylake上,dmesg说x86 / fpu:启用xstate功能0x1f,上下文大小为960字节,使用“压缩”格式.

见Understanding FPU usage in linux kernel;现代Linux默认情况下不为上下文切换执行惰性FPU上下文切换(仅用于内核/用户转换). (但那篇文章解释了Lazy是什么.)

大多数进程使用SSE在编译器生成的代码中复制/清零小块内存,大多数库字符串/ memcpy / memset实现使用SSE / SSE2.此外,硬件支持优化保存/恢复现在是一个事情(xsaveopt / xrstor),因此如果实际上没有使用某些/所有FP寄存器,那么“急切”FPU保存/恢复实际上可以做更少的工作.例如如果它们被vzeroupper归零,那么只保存低128b的YMM寄存器,这样CPU知道它们是干净的. (并在保存格式中仅用一位标记该事实.)

通过“急切”上下文切换,FPU指令始终保持启用状态,因此糟糕的内核代码可能随时损坏它们.

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值