From: Boqun Feng <boqun@kernel.org>
To: Shrikanth Hegde <sshegde@linux.ibm.com>
Cc: "Peter Zijlstra" <peterz@infradead.org>,
"Ingo Molnar" <mingo@kernel.org>, "Will Deacon" <will@kernel.org>,
"Waiman Long" <longman@redhat.com>, "Gary Guo" <gary@garyguo.net>,
"Alice Ryhl" <aliceryhl@google.com>,
"Lyude Paul" <lyude@redhat.com>,
"Daniel Almeida" <daniel.almeida@collabora.com>,
"Onur Özkan" <work@onurozkan.dev>,
"Miguel Ojeda" <ojeda@kernel.org>,
"Danilo Krummrich" <dakr@kernel.org>,
linux-kernel@vger.kernel.org, rust-for-linux@vger.kernel.org
Subject: Re: [PATCH v4 10/17] preempt: Introduce HAS_SEPARATE_PREEMPT_RESCHED_BITS
Date: Wed, 5 Aug 2026 17:58:00 -0700 [thread overview]
Message-ID: <anPcGFXV1GrhJxdV@tardis.local> (raw)
In-Reply-To: <anLeKu7X6SndqFR4@tardis.local>
On Tue, Aug 04, 2026 at 11:54:34PM -0700, Boqun Feng wrote:
> On Wed, Aug 05, 2026 at 01:41:48AM +0530, Shrikanth Hegde wrote:
> > Hi Boqun,
> >
> > On 8/4/26 9:44 PM, Boqun Feng wrote:
> > > With the changes that enable preempt count to track IRQ disabling
> > > nesting, we don't have enough bits in 32-bit preempt count
> > > implementation, as a result we move NMI nesting bits out of the 32-bit
> > > preempt count. However on the architectures that can support 64-bit
> > > preempt count implementation, we can keep the NMI nesting bits in the
> > > 32-bit preempt count and avoid maintaining NMI nesting bits outside of
> > > the same cache line.
> > >
> >
> > [...]
> >
> > > --- a/include/linux/hardirq.h
> > > +++ b/include/linux/hardirq.h
> > > @@ -10,8 +10,6 @@
> > > #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);
> > > @@ -94,6 +92,37 @@ void irq_exit_rcu(void);
> > > #define arch_nmi_exit() do { } while (0)
> > > #endif
> > > +#ifdef CONFIG_HAS_SEPARATE_PREEMPT_RESCHED_BITS
> > > +static __always_inline void __preempt_count_nmi_enter(void)
> > > +{
> > > + __preempt_count_add(NMI_OFFSET + HARDIRQ_OFFSET);
> > > +}
> > > +
> > > +static __always_inline void __preempt_count_nmi_exit(void)
> > > +{
> > > + __preempt_count_sub(NMI_OFFSET + HARDIRQ_OFFSET);
> > > +}
> > > +#else
> > > +DECLARE_PER_CPU(unsigned int, nmi_nesting);
> > > +
> > > +#define __preempt_count_nmi_enter() \
> > > + do { \
> > > + __preempt_count_add(HARDIRQ_OFFSET); \
> >
> > nit: This limit is because to have the same behavior as other case when
> > NMI_BITS=4 right?
> > It is not easy to infer that from comment.
> >
>
> It's sort of design by implementation IIUC, previously because of
> NMI_BITS=4, we could only support nesting level being 15. And here we
> just want to keep the same behavior here.
>
> If your question is why 15 was a good number before this change, I guess
> would be it's just a number that is neither too big or too small.
>
> > > + /* Maximum NMI nesting is 15. */ \
> > > + BUG_ON(__this_cpu_read(nmi_nesting) >= 15); \
> > > + __this_cpu_inc(nmi_nesting); \
> > > + preempt_count_set(preempt_count() | NMI_MASK); \
> >
> >
> > Is there a reason preempt count updates are split rather than
> > folded into a single preempt_count update?
> >
>
> Keeping the implementation simple is one reason, most architectures
> could utilize the HAS_SEPARATE_PREEMPT_RESCHED_BITS for better
> performance. So that reduces the importance of having something
> complicated but saves one access here. But if you see an optimization
> that can be done here, please do share!
>
> Peter had proposed one optimization here:
>
> #define __preempt_count_nmi_enter() \
> do { \
> unsigned int _o = NMI_MASK + HARDIRQ_OFFSET; \
> /* Maximum NMI nesting is 15. */ \
> BUG_ON(__this_cpu_read(nmi_nesting) >= 15); \
> __this_cpu_inc(nmi_nesting); \
> _o -= (preempt_count() & NMI_MASK); \
> __preempt_count_add(_o); \
> } while (0)
>
> #define __preempt_count_nmi_exit() \
> do { \
> unsigned int _o = HARDIRQ_OFFSET; \
> if (!__this_cpu_dec_return(nmi_nesting)) \
> _o += NMI_MASK; \
> __preempt_count_sub(_o); \
> } while (0)
>
> but it has a problem considering this:
>
> // outermost NMI handler
> // nmi_nesting == 0
>
> nmi_enter();
> // ^ nmi_nesting == 1 and NMI_MASK is set.
> ...
> nmi_exit():
> if (!__this_cpu_dec_return(nmi_nesting)) // return true
> _o += NMI_MASK;
> <NMI start>
> nmi_enter();
> // ^ nmi_nesting == 1 and NMI_MASK is set.
> nmi_exit();
> // ^ nmi_nesting == 0 and NMI_MASK is *unset*.
> <NMI end>
>
> preempt_count_sub(_o); // _o == HARDIRQ_OFFSET + NMI_MASK,
> // underflow
>
> (Now think about this, the __preempt_count_nmi_enter() does seems
> fine, maybe we can keep that, too tired to remember whether there is any
> subtly here... will take another look tomorrow)
>
Ok, now I remember the issue of the preempt_count_add() implemented
__preempt_count_nmi_enter(), considering this:
// outermost NMI handler
// nmi_nesting == 0
nmi_enter():
__preempt_count_nmi_enter():
unsigned int _o = NMI_MASK + HARDIRQ_OFFSET;
...
__this_cpu_inc(nmi_nesting);
// ^ nmi_nesting == 1
_o -= (preempt_count() & NMI_MASK);
// ^ _o == NMI_MASK + HARDIRQ_OFFSET because the NMI_MASK bit was not set
<NMI start>
nmi_enter();
// ^ nmi_nesting == 2 and NMI_MASK is set.
nmi_exti();
// ^ nmi_nesting == 1 so NMI_MASK is *still* set
<NMI end>
__preempt_count_add(_o);
// ^ NMI_MASK overflows because of the addition.
Make sense?
But maybe there are clever ways that I don't know. Please do tell!
Regards,
Boqun
> Regards,
> Boqun
>
>
> > > + } while (0)
> > > +
> > > +#define __preempt_count_nmi_exit() \
> > > + do { \
> > > + __preempt_count_sub(HARDIRQ_OFFSET); \
> > > + if (!__this_cpu_dec_return(nmi_nesting)) \
> > > + preempt_count_set(preempt_count() & ~NMI_MASK); \
> > > + } while (0)
> > > +
> > > +#endif
> > > +
> > > /*
> > > * NMI vs Tracing
> > > * --------------
> > > @@ -110,18 +139,14 @@ void irq_exit_rcu(void);
> > > do { \
> > > lockdep_off(); \
> > > arch_nmi_enter(); \
> > > - /* Maximum NMI nesting is 15. */ \
> > > - BUG_ON(__this_cpu_read(nmi_nesting) >= 15); \
> > > - __this_cpu_inc(nmi_nesting); \
> > > - __preempt_count_add(HARDIRQ_OFFSET); \
> > > - preempt_count_set(preempt_count() | NMI_MASK); \
> > > + __preempt_count_nmi_enter(); \
> > > } while (0)
> > > #define nmi_enter() \
> > > do { \
> > > __nmi_enter(); \
> > > lockdep_hardirq_enter(); \
> > > - ct_nmi_enter(); \
> > > + ct_nmi_enter(); \
> > > instrumentation_begin(); \
> > > ftrace_nmi_enter(); \
> > > instrumentation_end(); \
> > > @@ -129,12 +154,8 @@ void irq_exit_rcu(void);
> > > #define __nmi_exit() \
> > > do { \
> > > - unsigned int nesting; \
> > > BUG_ON(!in_nmi()); \
> > > - __preempt_count_sub(HARDIRQ_OFFSET); \
> > > - nesting = __this_cpu_dec_return(nmi_nesting); \
> > > - if (!nesting) \
> > > - preempt_count_set(preempt_count() & ~NMI_MASK); \
> > > + __preempt_count_nmi_exit(); \
> > > arch_nmi_exit(); \
> > > lockdep_on(); \
> > > } while (0)
next prev parent reply other threads:[~2026-08-06 0:58 UTC|newest]
Thread overview: 66+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-08-04 16:14 [PATCH v4 00/17] Refcounted interrupt disable and SpinLockIrq for Rust Boqun Feng
2026-08-04 16:14 ` [PATCH v4 01/17] preempt: Track NMI nesting to separate per-CPU counter Boqun Feng
2026-08-08 20:48 ` [tip: locking/core] " tip-bot2 for Joel Fernandes
2026-08-04 16:14 ` [PATCH v4 02/17] preempt: Introduce HARDIRQ_DISABLE_BITS Boqun Feng
2026-08-05 6:31 ` Peter Zijlstra
2026-08-05 6:59 ` Boqun Feng
2026-08-08 20:48 ` [tip: locking/core] " tip-bot2 for Boqun Feng
2026-08-04 16:14 ` [PATCH v4 03/17] preempt: Introduce __preempt_count_{sub,add}_return() Boqun Feng
2026-08-08 20:48 ` [tip: locking/core] " tip-bot2 for Boqun Feng
2026-08-04 16:14 ` [PATCH v4 04/17] openrisc: Include <linux/cpumask.h> in smp.h Boqun Feng
2026-08-08 20:48 ` [tip: locking/core] " tip-bot2 for Lyude Paul
2026-08-04 16:14 ` [PATCH v4 05/17] irq & spin_lock: Add counted interrupt disabling/enabling Boqun Feng
2026-08-04 18:20 ` Boqun Feng
2026-08-04 18:26 ` [PATCH v4.1 " Boqun Feng
2026-08-08 20:48 ` [tip: locking/core] " tip-bot2 for Boqun Feng
2026-08-10 8:57 ` [tip: locking/core] irq,spin_lock: " tip-bot2 for Boqun Feng
2026-08-04 20:51 ` [PATCH v4 05/17] irq & spin_lock: " Shrikanth Hegde
2026-08-04 21:08 ` Boqun Feng
2026-08-05 6:36 ` Peter Zijlstra
2026-08-05 7:07 ` Boqun Feng
2026-08-05 7:09 ` Shrikanth Hegde
2026-08-05 7:19 ` Boqun Feng
2026-08-05 13:53 ` Boqun Feng
2026-08-05 14:10 ` Shrikanth Hegde
2026-08-05 14:20 ` Boqun Feng
2026-08-05 14:56 ` Shrikanth Hegde
2026-08-05 15:11 ` Boqun Feng
2026-08-05 16:53 ` Shrikanth Hegde
2026-08-05 17:38 ` Boqun Feng
2026-08-05 18:07 ` Boqun Feng
2026-08-04 16:14 ` [PATCH v4 06/17] irq: Add KUnit test for refcounted interrupt enable/disable Boqun Feng
2026-08-08 20:48 ` [tip: locking/core] " tip-bot2 for Lyude Paul
2026-08-10 8:57 ` tip-bot2 for Lyude Paul
2026-08-04 16:14 ` [PATCH v4 07/17] locking: Switch to _irq_{disable,enable}() variants in cleanup guards Boqun Feng
2026-08-08 20:48 ` [tip: locking/core] " tip-bot2 for Boqun Feng
2026-08-10 8:57 ` tip-bot2 for Boqun Feng
2026-08-04 16:14 ` [PATCH v4 08/17] sched: Remove the unused preempt_offset parameter of __cant_sleep() Boqun Feng
2026-08-08 20:48 ` [tip: locking/core] " tip-bot2 for Boqun Feng
2026-08-10 8:57 ` tip-bot2 for Boqun Feng
2026-08-04 16:14 ` [PATCH v4 09/17] sched: Avoid signed comparison of preempt_count() in __cant_migrate() Boqun Feng
2026-08-08 20:48 ` [tip: locking/core] " tip-bot2 for Boqun Feng
2026-08-10 8:57 ` tip-bot2 for Boqun Feng
2026-08-04 16:14 ` [PATCH v4 10/17] preempt: Introduce HAS_SEPARATE_PREEMPT_RESCHED_BITS Boqun Feng
2026-08-04 20:11 ` Shrikanth Hegde
2026-08-05 6:54 ` Boqun Feng
2026-08-05 7:15 ` Shrikanth Hegde
2026-08-05 7:27 ` Boqun Feng
2026-08-06 0:58 ` Boqun Feng [this message]
2026-08-04 21:09 ` Shrikanth Hegde
2026-08-04 23:14 ` Boqun Feng
2026-08-08 20:48 ` [tip: locking/core] " tip-bot2 for Boqun Feng
2026-08-10 8:57 ` tip-bot2 for Boqun Feng
2026-08-04 16:14 ` [PATCH v4 11/17] arm64: sched/preempt: Enable HAS_SEPARATE_PREEMPT_RESCHED_BITS Boqun Feng
2026-08-08 20:48 ` [tip: locking/core] " tip-bot2 for Boqun Feng
2026-08-10 8:57 ` tip-bot2 for Boqun Feng
2026-08-04 16:14 ` [PATCH v4 12/17] s390/preempt: " Boqun Feng
2026-08-04 20:27 ` Shrikanth Hegde
2026-08-05 9:42 ` Peter Zijlstra
2026-08-05 12:37 ` Shrikanth Hegde
2026-08-08 20:48 ` [tip: locking/core] " tip-bot2 for Heiko Carstens
2026-08-10 8:57 ` tip-bot2 for Heiko Carstens
2026-08-04 16:14 ` [PATCH v4 13/17] rust: Introduce interrupt module Boqun Feng
2026-08-04 16:14 ` [PATCH v4 14/17] rust: helper: Add spin_{un,}lock_irq_{enable,disable}() helpers Boqun Feng
2026-08-04 16:14 ` [PATCH v4 15/17] rust: sync: Use super::* in spinlock.rs Boqun Feng
2026-08-04 16:14 ` [PATCH v4 16/17] rust: sync: Add SpinLockIrq Boqun Feng
2026-08-04 16:14 ` [PATCH v4 17/17] rust: sync: Introduce SpinLockIrq::lock_with() and friends Boqun Feng
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=anPcGFXV1GrhJxdV@tardis.local \
--to=boqun@kernel.org \
--cc=aliceryhl@google.com \
--cc=dakr@kernel.org \
--cc=daniel.almeida@collabora.com \
--cc=gary@garyguo.net \
--cc=linux-kernel@vger.kernel.org \
--cc=longman@redhat.com \
--cc=lyude@redhat.com \
--cc=mingo@kernel.org \
--cc=ojeda@kernel.org \
--cc=peterz@infradead.org \
--cc=rust-for-linux@vger.kernel.org \
--cc=sshegde@linux.ibm.com \
--cc=will@kernel.org \
--cc=work@onurozkan.dev \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.