Re: [PATCH v2 10/12] preempt: Introduce HAS_SEPARATE_PREEMPT_RESCHED_BITS

Boqun Feng <[email protected]> Thu, 4 Jun 2026 05:40:39 -0700
Newsgroups org.kernel.vger.linux-openrisc,org.kernel.vger.bpf,org.kernel.vger.linux-arch,org.kernel.vger.linux-kernel,org.kernel.vger.linux-kselftest,org.kernel.vger.linux-s390,org.kernel.vger.rust-for-linux
Message-ID <[email protected]>
On Tue, May 26, 2026 at 08:21:46AM -0700, Boqun Feng wrote:
[...]
> +#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 {							\
> +		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)

This needs to be:

#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)

otherwise we would have an underflow issue if an NMI happen between
the "if" being true and __preempt_count_sub(_o);

Regards,
Boqun

> +
> +#endif
> +
> +
[...]