抽丝剥茧 Linux 浮点运算方法原理

抽丝剥茧 Linux 浮点运算的原理

编者按:本文来自华辰连科技术团队,分享了他们在将浮点运算放到内核态时的探索。

最近我们有一个需求,需要把用户态的浮点数运算全部放到内核态运行,以提高运行速度,移植的过程中发现问题没有这么简单,然后我们抽丝剥茧,揭开 Linux 对浮点处理的原理。

此文章的代码基于 x86 64 位 CPU,Linux 4.14 内核。

一、 Linux 内核添加浮点运算出现的问题

我们以一个简单的浮点运算例子来说明:

#include

test_float.c

obj-m := test_float.o KDIR := /lib/modules/$(shelluname -r)/build all:make -C $(KDIR)M=$(PWD)modules

Makefile

这个内核模块就是计算了两个浮点数除的结果,然后将结果打印出来 。但是我们执行make编译的时候发现报错:

抽丝剥茧 Linux 浮点运算的原理

提示 SSE 寄存器返回的报错信息为 “SSE disabled”。我们执行make V=1查看关键的编译信息:

抽丝剥茧 Linux 浮点运算的原理

我们发现在gcc的参数中有-mno-sse -mno-mmx -mno-sse2选项,原来gcc默认的编译选项禁用了 sse、mmx、sse2 等浮点运算指令。

二、通过添加 gcc 编译参数和 kernel_fpu_begin/kernel_fpu_end 来解决问题

为了让内核支持浮点运算,我们在Makefile中添加支持 sse 等选项,源码中添加kernel_fpu_begin/kernel_fpu_end函数,修改后的源码如下所示:

#include

test_float.c

obj-m := test_float.o KDIR := /lib/modules/$(shelluname -r)/build FPU_CFLAGS += -mhard-float FPU_CFLAGS += -msse -msse2 CFLAGS_test_float.o += $(FPU_CFLAGS) all:make -C $(KDIR)M=$(PWD)modules

Makefile

此时执行make,发现编译正确通过了:

然后insmod test_float.ko,观察dmesg的输出:

从上面的例子,结合内核源码中arch/x86/Makefile中的KBUILD_CFLAGS,可以看到编译内核及内核模块时,gcc选项继承 Linux 中的规则,指定了-mno-sse -mno-mmx -mno-sse2,也就是禁用了 FPU 。所以,要想内核模组支持浮点运算,编译选项需要显式的指定-msse -msse2。

三、 Linux 内核态对浮点运算处理方式的分析

从上面可以看到,我们为了实现一个内核模块的浮点运算,添加了编译参数-mhard-float和-msse -msse2,对于编译参数来说,-mhard-float是告诉编译器直接生成浮点运算的指令,而-msse -msse2则是告诉编译器可以使用 sse/sse2 指令集来编译代码。

kernel_fpu_begin和kernel_fpu_end也是必须的,因为 Linux 内核为了提高系统的运行速率,在任务上下文切换时,只会保存/恢复普通寄存器的值,并不包括 FPU 浮点寄存器的值,而调用kernel_fpu_begin主要作用是关掉系统抢占,浮点计算结束后调用kernel_fpu_end开启系统抢占,这使得代码不会被中断,从而安全的进行浮点运算,并且要求这之间的代码不能有休眠或调度操作,另外不得有嵌套的情况出现(将会覆盖原始保存的状态,然后执行kernel_fpu_end()最终将恢复错误的 FPU 状态)。

voidkernel_fpu_begin(void){ preempt_disable; __kernel_fpu_begin; }

四、三角函数在 Linux 内核态的实现

由于内核态不支持浮点运算,所以像三角函数之类浮点运算都没有实现,如果需要,可以将用户态 glibc 中相关的三角函数的实现移植到内核态。

五、 Linux 用户态对浮点运算处理方式的分析

为什么用户态浮点运算就不需要指定编译选项以及显式调用kernel_fpu_begin和kernel_fpu_end函数呢?我们在用户态下写一个简单的带浮点运算的例子:

#include

user_float.c

我们分别使用下面四条编译指令查看编译出来的汇编:

  1. gcc -S user_float.c
  2. gcc -S user_float.c -msoft-float
  3. gcc -S user_float.c -mhard-float
  4. gcc -S user_float.c -msoft-float -mno-sse -mno-mmx -mno-sse2

前三条命令编译成功。依次查看编译生成的汇编代码,发现生成的汇编代码是完全一样的,都是用到了 sse 指令中的 mmx 寄存器,也就是使用到了 FPU。

第四条命令编译失败 ,提示error: SSE register return with SSE disabled。从上面的现象中我们可以得出结论,系统默认使用gcc编译用户态程序时,gcc默认使用 FPU,也就是使用硬浮点来编译。

经过查阅各种文档和分析代码,x86 CPU 提供如下特性:CPU 提供的 TS 寄存器的第三个位是任务已切换标志(Task Switched bit),CPU 在每次任务切换时会设置这个位。而且 TS 的这个位被设置时,当进程使用 FPU 指令时 CPU 会产生一个 DNA(Device Not Availabel)异常。Linux 使用此特性,当用户态应用程序进行浮点运算时(SSE 等指令),触发 DNA 异常,同时使用 FPU 专用寄存器和指令来执行浮点数功能,此时TS_USEDFPU标志为 1,表示用户态进程使用了 FPU。

voidfpu__restore(struct fpu *fpu) { fpu__initialize(fpu); /* Avoid __kernel_fpu_begin right after fpregs_activate */kernel_fpu_disable; trace_x86_fpu_before_restore(fpu); fpregs_activate(fpu); copy_kernel_to_fpregs(&fpu->state); trace_x86_fpu_after_restore(fpu); kernel_fpu_enable; } EXPORT_SYMBOL_GPL(fpu__restore);

假设用户态进程 A 使用到了 FPU 执行浮点运算,此时用户态进程 B 被调度执行,那么当进程 A 被调度出去的时候,内核设置 TS 并调用fpu__restore将 FPU 的内容保存。当进程 A 恢复浮点运算执行时,触发 DNA 异常,相应的异常处理程序会恢复 FPU 之前保存的状态。

假设用户态进程 A 使用到了 FPU 执行浮点运算(TS_USEDFPU标志为 1),此时内核态进程 C 调度并使用 FPU,由于内核只会保存普通的寄存器的值,并不包括 FP 等寄存器的值,所以内核会主动调用kernel_fpu_begin函数保存寄存器内容,使用完之后调用kernel_fpu_end。当用户态进程 A 恢复浮点运算执行时,触发 DNA 异常,相应的异常处理程序会恢复 FPU 寄存器的内容。

六、 结论

  1. Linux 中当任务切换时,缺省不保存浮点器寄存器。
  2. 如果需要内核态支持浮点运算,需要增加支持浮点的编译选项和使用kernel_fpu_begin和kernel_fpu_end函数手动处理上下文。
  3. 用户态缺省支持浮点运算,但是需要内核来辅助。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至19401980@qq.com举报,一经查实,本站将立刻删除。

(0)

大家都在看

  • 为什么手机发不出声音

    为什么手机发不出声音?一起来了解一下。 一、查看下是否将手机设置为了静音,通过手机侧边音量键调大手机音量,看是否能恢复。 二、长按电源键,调关机界面,点击重启即可。 三、打开设置,点击声音,关闭静音按钮,然后将上方的各种声音调节器向右侧滑动,接着点击免打扰,将关闭免打扰选项关闭即可。 若以上方法还是无法让手机恢复正常,那么可拿去相关售后手机店进行检修

    2023年5月20日
    0510
  • 电脑怎么下载网上银行?

    怎么下载掌上中国农业银行 您好!请根据账户类型选择下载方式。 个人掌银APP下载操作步骤如下: 1.iPhone版: (1)电脑下载:在电脑上登录iTunes,搜索“中国农业银行”下载。 (2)手机下载:在手机上登录Apple Store,搜索“中国农业银行”下载。 如果iPhone手机更换了手机号码建议删除原有掌银(iPhone版),重新下载安装并激活。 …

    2023年3月6日
    03190
  • 新加坡导航可以用手机吗

    新加坡导航可以用手机,可以使用百度地图(中文)、谷歌地图(英文)等导航软件。新加坡共和国,简称新加坡,旧称新嘉坡、星洲或星岛,别称为狮城,是东南亚的一个岛国,政治体制实行议会共和制,首都为新加坡市。新加坡位于马来半岛南端、马六甲海峡出入口,由新加坡岛及附近63个小岛组成,其中新加坡岛占全国面积的88.5%。

    2023年2月24日
    01260
  • FX8320评测跑分参数介绍

    这是游戏配置要求,感觉这是个A黑游戏,AMD平台优化不太好,你可以换张gtx750ti试试;就选FX8320如果单开游戏,就选I5 4570i5无论在浮点运算和整数运算,都能超越8350其实很多游戏,对单核性能浮点运算比较有要求,amd整数运算,游戏多开比较有优势,但是单核性能,完全和奔腾在一个档次;肯定是FX8320好点啦,它们的价位都不一样,FX8320…

    2023年4月26日
    0620
  • 华为nova5pro怎么安装Flash插件 华为nova5pro安装Flash插件方法【详解】

      大家都知道,使用智能手机的时候,有些朋友可能发现,我们在手机上有时候观看一些网页视频的时候发现无法打开播放,或者浏览一些网页FLASH动画也是无法进行播放的,那么华为nova5pro怎么安装Adobe Flash Player插件呢?感兴趣的朋友不要错过了。   华为nova5pro怎么安装Flash插件?   方法一、   1、打开手机的应用市场,  …

    2023年5月16日
    0450
  • iqoo10pro是曲面屏吗详情

    iQOO 10是直面屏,可以点击此链接进入vivo官网查看了解。 iQOO 10 Pro主要参数操作系统OriginOS Ocean基于Android 12屏幕678英寸,分辨率1440 x 3200 拍照后置5000万像素超感光微云台主摄+5000万像素150°鱼眼超广角微距主摄+1460万像素3XOIS人像镜头前置1600万。 不出意外,接下来各大厂商骁…

    2023年4月14日
    0670

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注