为什么我能够在 Linux 内核模块内执行浮点运算?

2024-10-21 09:14:00
admin
原创
396
摘要:问题描述:我在 x86 CentOS 6.3(内核 v2.6.32)系统上运行。我将下面的函数编译成一个简单的字符驱动模块,作为实验来查看 Linux 内核对浮点运算的反应。static unsigned floatstuff(void){ float x = 3.14; x *= 2.5; ...

问题描述:

我在 x86 CentOS 6.3(内核 v2.6.32)系统上运行。

我将下面的函数编译成一个简单的字符驱动模块,作为实验来查看 Linux 内核对浮点运算的反应。

static unsigned floatstuff(void){
    float x = 3.14;
    x *= 2.5;
    return x;
}

...

printk(KERN_INFO "x: %u", x);

代码编译成功(这是意料之外的),因此我插入模块并用 检查了日志dmesg。日志显示:x: 7

这看起来很奇怪;我以为你不能在 Linux 内核中执行浮点运算——除了一些例外,例如kernel_fpu_begin()。模块如何执行浮点运算?

这是因为我使用的是 x86 处理器吗?


解决方案 1:

我以为你不能在 Linux 内核中执行浮点运算

您不能安全地:使用kernel_fpu_begin()/失败kernel_fpu_end()并不意味着 FPU 指令会出现故障(至少在 x86 上不会)。

相反,它会悄悄破坏用户空间的 FPU 状态。这很糟糕;不要这样做。

编译器不知道这是什么kernel_fpu_begin()意思,所以它无法检查/警告在 FPU 开始区域之外编译为 FPU 指令的代码。

可能存在一种调试模式,其中内核确实禁用kernel_fpu_begin/end区域之外的 SSE、x87 和 MMX 指令,但这会比较慢并且默认情况下不会执行。

但这是可能的:设置CR0::TS = 1会导致 x87 指令出错,因此延迟的 FPU 上下文切换是可能的,并且还有其他用于 SSE 和 AVX 的位。


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


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

jmpLinux 每次进入/退出内核时都必须保存/恢复整数状态。所有代码都需要使用整数寄存器(除了以而不是retret修改)结尾的 FPU 计算的巨大直线块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 状态 + 控制字)。此外,MPXbnd0-4寄存器与“FPU”合并在一起。此时,“FPU 状态”仅表示所有非整数寄存器。在我的 Skylake 上,dmesg显示x86/fpu: Enabled xstate features 0x1f, context size is 960 bytes, using 'compacted' format.

请参阅了解 Linux 内核中的 FPU 使用情况;现代 Linux 默认不会对上下文切换执行惰性 FPU 上下文切换(仅对内核/用户转换执行惰性 FPU 上下文切换)。(但那篇文章解释了什么是惰性。)

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

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

解决方案 2:

不要这样做!

在内核空间中,FPU 模式由于以下几个原因而被禁用:

  • 它允许 Linux 在没有 FPU 的架构中运行

  • 它避免在每次内核/用户空间转换时保存和恢复整个寄存器集(它可能会使上下文切换的时间加倍)

  • 基本上所有的内核函数都使用整数来表示十进制数 - >你可能不需要浮点数

  • 在 Linux 中,当内核空间以 FPU 模式运行时,抢占被禁用

  • 浮点数是邪恶的,可能会产生非常糟糕的意外行为

如果您确实想使用 FP 数字(而您不应该这样做),那么您必须使用kernel_fpu_beginkernel_fpu_end原语来避免破坏用户空间寄存器,并且您应该考虑处理 FP 数字时可能出现的所有问题(包括安全性)。

解决方案 3:

不确定这种看法从何而来。但内核与用户模式代码在同一个处理器上执行,因此可以访问相同的指令集。如果处理器可以执行浮点运算(直接或通过协处理器),那么内核也可以。

也许你正在考虑在软件中模拟浮点运算的情况。但即便如此,它仍可在内核中使用(除非以某种方式禁用)。

我很好奇,这种看法从何而来?也许我忽略了什么。

找到了这个。似乎是一个很好的解释。

解决方案 4:

操作系统内核可能只是在内核模式下关闭 FPU。

当FPU运行时,浮点运算时内核会打开FPU,然后关闭FPU。

但你不能打印它。

相关推荐
  政府信创国产化的10大政策解读一、信创国产化的背景与意义信创国产化,即信息技术应用创新国产化,是当前中国信息技术领域的一个重要发展方向。其核心在于通过自主研发和创新,实现信息技术应用的自主可控,减少对外部技术的依赖,并规避潜在的技术制裁和风险。随着全球信息技术竞争的加剧,以及某些国家对中国在科技领域的打压,信创国产化显...
工程项目管理   1565  
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   1354  
  信创国产芯片作为信息技术创新的核心领域,对于推动国家自主可控生态建设具有至关重要的意义。在全球科技竞争日益激烈的背景下,实现信息技术的自主可控,摆脱对国外技术的依赖,已成为保障国家信息安全和产业可持续发展的关键。国产芯片作为信创产业的基石,其发展水平直接影响着整个信创生态的构建与完善。通过不断提升国产芯片的技术实力、产...
国产信创系统   21  
  信创生态建设旨在实现信息技术领域的自主创新和安全可控,涵盖了从硬件到软件的全产业链。随着数字化转型的加速,信创生态建设的重要性日益凸显,它不仅关乎国家的信息安全,更是推动产业升级和经济高质量发展的关键力量。然而,在推进信创生态建设的过程中,面临着诸多复杂且严峻的挑战,需要深入剖析并寻找切实可行的解决方案。技术创新难题技...
信创操作系统   27  
  信创产业作为国家信息技术创新发展的重要领域,对于保障国家信息安全、推动产业升级具有关键意义。而国产芯片作为信创产业的核心基石,其研发进展备受关注。在信创国产芯片的研发征程中,面临着诸多复杂且艰巨的难点,这些难点犹如一道道关卡,阻碍着国产芯片的快速发展。然而,科研人员和相关企业并未退缩,积极探索并提出了一系列切实可行的解...
国产化替代产品目录   28  
热门文章
项目管理软件有哪些?
云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用