You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何__nmi_enter()中要执行__preempt_count_add(NMI_OFFSET+HARDIRQ_OFFSET)?

关于Linux内核__nmi_enter()宏的两个问题

代码背景

#define __nmi_enter()                       
    do {                            
        lockdep_off();                  
        arch_nmi_enter();               
        BUG_ON(in_nmi() == NMI_MASK);           
        __preempt_count_add(NMI_OFFSET + HARDIRQ_OFFSET);   
    } while (0)

问题1:为何累加NMI_OFFSET + HARDIRQ_OFFSET而非仅NMI_OFFSET?

要理解这个设计,得从preempt_count的核心作用说起——它是内核跟踪抢占状态、中断嵌套的核心计数器,不同偏移对应不同的上下文标识:

  • HARDIRQ_OFFSET用于标记当前处于硬中断上下文,内核里大量通用逻辑(比如判断是否允许调度、能否执行进程上下文专属操作)会通过in_hardirq()检查这个位。
  • NMI_OFFSET是专门标记NMI专属上下文的偏移,用来区分NMI和普通硬中断。

同时累加两个偏移的原因主要有两点:

  1. 复用通用硬中断检查逻辑:NMI本质是特殊的硬中断,需要让in_hardirq()这类通用函数也能识别出当前处于硬中断类上下文,避免进程上下文的操作(如抢占、调度)在NMI中执行。
  2. 正确跟踪嵌套关系:NMI可以嵌套在普通硬中断上下文中触发,累加两个偏移后,内核能准确识别NMI的嵌套层数,同时保留硬中断上下文的标识,确保所有中断相关的安全检查逻辑正常工作。

退出NMI时,内核会对应执行__preempt_count_sub(NMI_OFFSET + HARDIRQ_OFFSET),保证计数器状态回退正确。

问题2:NMI属于硬中断吗?

是的,NMI(不可屏蔽中断)属于硬中断的特殊子类:

  • 它由硬件触发,和普通硬中断一样是外部硬件信号引发的中断请求。
  • 区别在于普通硬中断可通过CPU的中断屏蔽寄存器关闭,而NMI优先级更高,无法被屏蔽,专门用于处理最紧急的硬件故障(如内存校验错误、CPU温度过高)。
  • 内核在设计中把NMI归为硬中断范畴,只是它的处理流程更特殊:可以嵌套在普通硬中断上下文里执行,且处理过程中不会被普通中断打断。

内容的提问来源于stack exchange,提问作者Mark Kang

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 11:03:27