[PATCH RFC] arm64: Mark set_preempt_need_resched() access to .need_resched

Marco Elver elver at google.com
Fri Aug 7 05:21:39 PDT 2026


On Fri, 7 Aug 2026 at 14:06, Will Deacon <will at kernel.org> wrote:
>
> [+KCSAN maintainers]
>
> On Thu, Aug 06, 2026 at 10:25:37AM -0700, Paul E. McKenney wrote:
> > On Thu, Aug 06, 2026 at 12:58:40PM +0100, Will Deacon wrote:
> > > On Fri, Jul 31, 2026 at 11:39:14AM -0700, Paul E. McKenney wrote:
> > > > On Fri, Jul 31, 2026 at 09:44:16AM -0700, Paul E. McKenney wrote:
> > > > > On Fri, Jul 31, 2026 at 01:51:26PM +0100, Mark Rutland wrote:
> > > > > > On Thu, Jul 30, 2026 at 04:59:57PM -0700, Paul E. McKenney wrote:
> > > > > > > The .need_resched field can be accessed from both task level and
> > > > > > > from interrrupt handlers, so apply WRITE_ONCE() to the update in
> > > > > > > set_preempt_need_resched().  This also brings arm64 in line with s390
> > > > > > > (which uses atomic operations) and x86 (which uses inline assembly).
> > > > > > > Other architectures avoid this issue via the empty definition in
> > > > > > > include/asm-generic/preempt.h.
> > > > > > >
> > > > > > > KCSAN located this issue.
> > > > > >
> > > > > > Do you have the KCSAN splat to hand? Seeing the exact race (and the
> > > > > > relevant reader(s)) would be handy.
> > > > > >
> > > > > > > Signed-off-by: Paul E. McKenney <paulmck at kernel.org>
> > > > > > > Cc: Catalin Marinas <catalin.marinas at arm.com>
> > > > > > > Cc: Will Deacon <will at kernel.org>
> > > > > > > Cc: Jinjie Ruan <ruanjinjie at huawei.com>
> > > > > > > Cc: Ada Couprie Diaz <ada.coupriediaz at arm.com>
> > > > > > > Cc: <linux-arm-kernel at lists.infradead.org>
> > > > > > >
> > > > > > > ---
> > > > > > >  preempt.h |    2 +-
> > > > > > >  1 file changed, 1 insertion(+), 1 deletion(-)
> > > > > > >
> > > > > > > diff --git a/arch/arm64/include/asm/preempt.h b/arch/arm64/include/asm/preempt.h
> > > > > > > index 932ea4b6204289..610853da140a78 100644
> > > > > > > --- a/arch/arm64/include/asm/preempt.h
> > > > > > > +++ b/arch/arm64/include/asm/preempt.h
> > > > > > > @@ -28,7 +28,7 @@ static inline void preempt_count_set(u64 pc)
> > > > > > >
> > > > > > >  static inline void set_preempt_need_resched(void)
> > > > > > >  {
> > > > > > > -   current_thread_info()->preempt.need_resched = 0;
> > > > > > > +   WRITE_ONCE(current_thread_info()->preempt.need_resched, 0);
> > > > > > >  }
> > > > > >
> > > > > > I was under the impression that we only used this in a context where we
> > > > > > couldn't have a nested writer (e.g. within a scheduler IRQ hook, with
> > > > > > IRQs disabled).
> > > > > >
> > > > > > If we have concurrent writers, this is probably broken regardless of
> > > > > > whether it is single-copy-atomic, and I worry WRITE_ONCE() will mask a
> > > > > > bug.
> > > > > >
> > > > > > If you can share the KCSAN splat, that'd really help.
> > > > >
> > > > > Let me regenerate it...
> > > >
> > > > And please see below.
> > > >
> > > > > > I think we need READ_ONCE() in test_preempt_need_resched(), but today
> > > > > > that's only used by tracing to determine what to log.
> > > > >
> > > > > I do have tracing enabled on some of my runs.
> > > >
> > > > I did build with CONFIG_TRACEPOINTS=y.  Or let me know what sort of tracing
> > > > you are interested in.  Or I can send you this guy from my ARM test system:
> > > >
> > > > tools/testing/selftests/rcutorture/res/2026.07.31-10.25.08-torture/results-rcutorture-kcsan/TREE01/.config
> > > >
> > > >                                                   Thanx, Paul
> > > >
> > > > ------------------------------------------------------------------------
> > > >
> > > > [  738.696166] BUG: KCSAN: data-race in __delay / set_need_resched_current
> > > > [  738.696184]
> > > > [  738.696188] read (marked) to 0xffff000005899b48 of 8 bytes by interrupt on cpu 8:
> > > > [  738.696198]  __delay+0xb0/0x378
> > > > [  738.696212]  __udelay+0x4c/0x60
> > > > [  738.696225]  kcsan_setup_watchpoint+0x3b4/0x820
> > > > [  738.696238]  __tsan_unaligned_write4+0x228/0x26c
> > > > [  738.696249]  set_need_resched_current+0x138/0x1a8
> > > > [  738.696260]  rcu_exp_handler+0x418/0x4a0
> > > > [  738.696273]  __flush_smp_call_function_queue+0x36c/0x4a0
> > > > [  738.696288]  generic_smp_call_function_single_interrupt+0x20/0x30
> > >
> > > This is a bit weird -- it looks like the read is occuring from within
> > > kcsan itself?
> >
> > Ah, you are right, as part of KCSAN's software watchpoints.
> >
> > What do you suggest?
>
> I suppose we could add some __no_kcsan annotations to everything that is
> called from the KCSAN implementation but it feels error-prone and could
> hide races exposed by other callers.
>
> I've added the KCSAN folks to see if they have any other ideas; it looks
> like the sort of thing you'd expect them to have encountered already.

Most of KCSAN's internals are not instrumented, but do call out to
some instrumented bits where that's safe. In this case, it looks like
a real data race, even though the access comes from __delay that was
called by KCSAN, I don't think it's any less valid.

I have a fix pending [1] (queued for next merge window), however,
which would have suppressed this one.

[1] https://lore.kernel.org/all/20260722212700.828037-1-elver@google.com/



More information about the linux-arm-kernel mailing list