On Thu, 7 May 2026 21:21:02 -0700 Boqun Feng <[email protected]> wrote:
> From: Joel Fernandes <[email protected]> > > Move NMI nesting tracking from the preempt_count bits to a separate per-CPU > counter (nmi_nesting). This is to free up the NMI bits in the preempt_count, > allowing those bits to be repurposed for other uses. This also has the > benefit > of tracking more than 16-levels deep if there is ever a need. > > Reduce multiple bits in preempt_count for NMI tracking. Reduce NMI_BITS > from 3 to 1, using it only to detect if we're in an NMI. > > Suggested-by: Boqun Feng <[email protected]> > Signed-off-by: Joel Fernandes <[email protected]> > Signed-off-by: Lyude Paul <[email protected]> > Signed-off-by: Boqun Feng <[email protected]> > Link: https://patch.msgid.link/[email protected] > --- > include/linux/hardirq.h | 16 ++++++++++++---- > include/linux/preempt.h | 13 +++++++++---- > kernel/softirq.c | 2 ++ > 3 files changed, 23 insertions(+), 8 deletions(-) > > diff --git a/include/linux/hardirq.h b/include/linux/hardirq.h > index d57cab4d4c06..cc06bda52c3e 100644 > --- a/include/linux/hardirq.h > +++ b/include/linux/hardirq.h > @@ -10,6 +10,8 @@ > #include <linux/vtime.h> > #include <asm/hardirq.h> > > +DECLARE_PER_CPU(unsigned int, nmi_nesting); > + > extern void synchronize_irq(unsigned int irq); > extern bool synchronize_hardirq(unsigned int irq); > > @@ -102,14 +104,16 @@ void irq_exit_rcu(void); > */ > > /* > - * nmi_enter() can nest up to 15 times; see NMI_BITS. > + * nmi_enter() can nest - nesting is tracked in a per-CPU counter. > */ > #define __nmi_enter() \ > do { \ > lockdep_off(); \ > arch_nmi_enter(); \ > - BUG_ON(in_nmi() == NMI_MASK); \ > - __preempt_count_add(NMI_OFFSET + HARDIRQ_OFFSET); \ > + BUG_ON(__this_cpu_read(nmi_nesting) == UINT_MAX); \ I think we should keep the max nesting fixed to 15. If this doesn't trigger until UINT_MAX, it may take a long time to see that, and there's no reason NMIs should nest more than 15 anyway. Just because the counter allows it, doesn't me the system should allow it. -- Steve > + __this_cpu_inc(nmi_nesting); \ > + __preempt_count_add(HARDIRQ_OFFSET); \ > + preempt_count_set(preempt_count() | NMI_MASK); \ > } while (0) > > #define nmi_enter() \ > @@ -124,8 +128,12 @@ void irq_exit_rcu(void); >

