[PATCH] riscv: Avoid smp_mb__after_spinlock() fences on non-SMP

Davidlohr Bueso dave at stgolabs.net
Fri Nov 6 06:28:57 PST 2026


ping?

On Sun, 18 Oct 2026, Davidlohr Bueso wrote:

>smp_mb__after_spinlock() is defined in asm/barrier.h, which
>linux/spinlock.h includes unconditionally, so non-SMP kernels get
>RISCV_FENCE(iorw, iorw) as well and emit a full fence.
>
>The other architectures that override it, arm64, csky, powerpc and
>xtensa, define it in asm/spinlock.h, which linux/spinlock.h only
>includes for CONFIG_SMP, so their non-SMP builds get the generic
>kcsan_mb() fallback. Move the riscv definition, the SMP fence is
>unchanged.
>
>Signed-off-by: Davidlohr Bueso <dave at stgolabs.net>
>---
> arch/riscv/include/asm/barrier.h  | 27 ---------------------------
> arch/riscv/include/asm/spinlock.h | 27 +++++++++++++++++++++++++++
> 2 files changed, 27 insertions(+), 27 deletions(-)
>
>diff --git a/arch/riscv/include/asm/barrier.h b/arch/riscv/include/asm/barrier.h
>index 700ba3f922cb..2284473844d8 100644
>--- a/arch/riscv/include/asm/barrier.h
>+++ b/arch/riscv/include/asm/barrier.h
>@@ -24,33 +24,6 @@
> #define __smp_rmb()	RISCV_FENCE(r, r)
> #define __smp_wmb()	RISCV_FENCE(w, w)
>
>-/*
>- * This is a very specific barrier: it's currently only used in two places in
>- * the kernel, both in the scheduler.  See include/linux/spinlock.h for the two
>- * orderings it guarantees, but the "critical section is RCsc" guarantee
>- * mandates a barrier on RISC-V.  The sequence looks like:
>- *
>- *    lr.aq lock
>- *    sc    lock <= LOCKED
>- *    smp_mb__after_spinlock()
>- *    // critical section
>- *    lr    lock
>- *    sc.rl lock <= UNLOCKED
>- *
>- * The AQ/RL pair provides a RCpc critical section, but there's not really any
>- * way we can take advantage of that here because the ordering is only enforced
>- * on that one lock.  Thus, we're just doing a full fence.
>- *
>- * Since we allow writeX to be called from preemptive regions we need at least
>- * an "o" in the predecessor set to ensure device writes are visible before the
>- * task is marked as available for scheduling on a new hart.  While I don't see
>- * any concrete reason we need a full IO fence, it seems safer to just upgrade
>- * this in order to avoid any IO crossing a scheduling boundary.  In both
>- * instances the scheduler pairs this with an mb(), so nothing is necessary on
>- * the new hart.
>- */
>-#define smp_mb__after_spinlock()	RISCV_FENCE(iorw, iorw)
>-
> #define __smp_store_release(p, v)					\
> do {									\
> 	compiletime_assert_atomic_type(*p);				\
>diff --git a/arch/riscv/include/asm/spinlock.h b/arch/riscv/include/asm/spinlock.h
>index 52f11bfd0079..54bd8db8eb4f 100644
>--- a/arch/riscv/include/asm/spinlock.h
>+++ b/arch/riscv/include/asm/spinlock.h
>@@ -3,6 +3,33 @@
> #ifndef __ASM_RISCV_SPINLOCK_H
> #define __ASM_RISCV_SPINLOCK_H
>
>+#include <asm/fence.h>
>+
>+/*
>+ * This is a very specific barrier.  See include/linux/spinlock.h for the two
>+ * orderings it guarantees, but the "critical section is RCsc" guarantee
>+ * mandates a barrier on RISC-V.  The sequence looks like:
>+ *
>+ *    lr.aq lock
>+ *    sc    lock <= LOCKED
>+ *    smp_mb__after_spinlock()
>+ *    // critical section
>+ *    lr    lock
>+ *    sc.rl lock <= UNLOCKED
>+ *
>+ * The AQ/RL pair provides a RCpc critical section, but there's not really any
>+ * way we can take advantage of that here because the ordering is only enforced
>+ * on that one lock.  Thus, we're just doing a full fence.
>+ *
>+ * Since we allow writeX to be called from preemptive regions we need at least
>+ * an "o" in the predecessor set to ensure device writes are visible before the
>+ * task is marked as available for scheduling on a new hart.  While I don't see
>+ * any concrete reason we need a full IO fence, it seems safer to just upgrade
>+ * this in order to avoid any IO crossing a scheduling boundary.  The
>+ * scheduler pairs this with an mb(), so nothing is necessary on the new hart.
>+ */
>+#define smp_mb__after_spinlock()	RISCV_FENCE(iorw, iorw)
>+
> #ifdef CONFIG_QUEUED_SPINLOCKS
> #define _Q_PENDING_LOOPS	(1 << 9)
> #endif
>-- 
>2.39.5
>
>
>_______________________________________________
>linux-riscv mailing list
>linux-riscv at lists.infradead.org
>http://lists.infradead.org/mailman/listinfo/linux-riscv



More information about the linux-riscv mailing list