CentOS8.5内核中BUG_ON(!in_nmi())触发原因排查
内核BUG排查:
nmi_exit()中触发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
- 运行环境:CentOS 8.5,Kernel 4.18.0-348.el8.x86_64(x86_64架构)
- BUG触发点:
arch/x86/kernel/cpu/mce/core.c第1364行的nmi_exit()宏调用,实际触发了宏内的BUG_ON(!in_nmi())断言 - 代码上下文:
do_machine_check()函数第1255行已调用nmi_enter(),理论上应处于NMI上下文,但断言失败
相关代码片段
nmi_exit()宏定义
#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)
可能的触发原因
- 嵌套NMI导致preempt_count异常:若
do_machine_check()执行期间再次触发NMI,会多次调用nmi_enter()累加preempt_count。后续多次执行nmi_exit()时,preempt_count_sub()会将计数降到低于NMI_OFFSET,导致in_nmi()返回false触发断言。 - 异常分支意外修改preempt_count:MCE处理逻辑中的某些错误分支(比如硬件错误的紧急处理路径)可能提前修改了preempt_count,或调用了其他会干扰NMI上下文状态的函数,破坏了
in_nmi()的判断条件。 - 硬件异常引发的栈/寄存器破坏:本次MCE本身由硬件错误触发,若错误已破坏栈空间或preempt_count对应的寄存器值,会导致
in_nmi()的判断逻辑读取到错误的上下文状态。 - 内核定制补丁的逻辑冲突:如果系统内核存在定制化补丁,可能修改了
nmi_enter()/nmi_exit()的实现逻辑,导致NMI上下文的进入/退出状态不匹配。
内容的提问来源于stack exchange,提问作者Mark Kang
相关产品推荐
相关产品推荐

