c-为什么触发BUG_ON(!in_nmi())



我得到了一个内核BUG,我不知道为什么会触发它。

[ 242.337362] kernel BUG at arch/x86/kernel/cpu/mce/core.c:1364!
[ 242.337366] invalid opcode: 0000 [#1] SMP NOPTI

这是在x86_64上的CentOS 8.5内核4.18.0-348.el8.x86_64。

核心.c线1364是:

nmi_exit();

(上一行在do_machine_check()内(:

通过检查nmi_exit()

https://elixir.bootlin.com/linux/v4.18/source/include/linux/hardirq.h#L78

#define nmi_exit()                      
do {                            
trace_hardirq_exit();               
rcu_nmi_exit();                 
BUG_ON(!in_nmi());              
preempt_count_sub(NMI_OFFSET + HARDIRQ_OFFSET); 
ftrace_nmi_exit();              
lockdep_on();                   
printk_nmi_exit();              
} while (0)

看起来我击中了这个BUG_ON(!in_nmi());,但我检查了do_machine_check(),它应该仍然是in_nmi(因为第1255行是nmi_enter();(,为什么BUG_ON(!in_nmi());被触发?

其他:

  1. 以下是可在centos4.18内核中下载的源代码:

https://vault.centos.org/8.5.2111/BaseOS/Source/SPackages/kernel-4.18.0-348.el8.src.rpm

我得到了一个内核BUG,我不知道为什么会触发它?

您遇到的特定错误试图使用无效的操作码:0000[#1]SMP NOPTI

我将讨论这个问题,它的原因,以及如何解决这个问题。首先,我将定义一些术语。

什么是不可屏蔽中断(NMI(

NMI是一种硬件中断,不受操作系统启用的任何中断屏蔽的影响(例如,CentOS 8.5(。在几乎所有情况下,它都是对不可恢复的硬件错误的响应。

NMI的一些典型用途是什么1

  • 低级调试,例如早期的Apple Macintosh的";程序员按钮">
  • ECC内存奇偶校验错误超出了可以纠正的范围,可能会使系统停止运行
  • 即将到来的厄运,如突然失去使系统静止的电源
  • 如果错过了硬件看门狗定时器,则按常规启用硬件看门狗计时器以使其死机

在处理第一个NMI时,第二个NMI会到达吗

从我记事起,Linux就一直支持英特尔嵌套NMI。2012年,Intel嵌套NMI支持中的一个漏洞令人兴奋。英特尔存在NMI iret缺陷,该缺陷要求NMI处理程序在处理NMI时避免触发页面错误或断点。

2020年5月20日,ARM64和PowerPC中对nest NMI的支持被承诺用于Linux。

BUG_ON((的确切作用是什么

在Linux 2.6中启动BUG_ON((是在出现严重错误时调试宏。如果传递给宏的值为true,那么Linux内核将触发无效指令。这导致CPU抛出一个无效的操作码异常。通常情况下,如果在一个过程中发生这种情况,该过程就会死亡。如果这种情况发生在NMI期间,情况会严重得多。

BUG_ON(!in_nmi(((转换为BUG_ON

因此,in_nmi((是检查当前nmi的当前抢占位是否设置为true。

什么是NOPTI2

Linux使用它来禁用Meltdown(内核页面表隔离(缓解措施。通常,nopti被添加到内核引导选项中以禁用。

补救措施

如果是软件,我该怎么办最有可能

  • 如果当前已禁用,请尝试在启用Meltdown的情况下启动系统。或者在禁用的情况下启动(如果启用(
  • 如果可能,请将Linux升级至5.4.100或更高版本。英特尔Icelake发布前2年报告的一个错误示例
  • 迁移到AlmaLinux或Rocky Linux,CentOS 8.5的精神继承者

如果是硬件缺陷呢可能性较小

  • 一次更换一个(在与系统逻辑板兼容的配置中(,直到找到有缺陷的
  • 更换系统逻辑板和/或其他PCIe设备

TL;DR

这个问题的一个有效理论是,NMI是由未校正的硬件内存错误引起的,而编码错误造成了在第二个增量增加了preempt_counter之前检查BUG_ON(!in_NMI(((的情况。

在这种特殊情况下,原始海报使用einj_mem_uc工具来生成模拟内存错误。这启动了NMI。

相关内容

  • 没有找到相关文章

最新更新