[PATCH v5 2/5] riscv: Apply Zalasr to smp_load_acquire/smp_store_release

Qingwei Hu qingwei.hu at bytedance.com
Fri Oct 2 09:59:07 PDT 2026


From: Xu Lu <luxu.kernel at bytedance.com>

Replace fence instructions with Zalasr instructions during
smp_load_acquire() and smp_store_release() operations.

|----------------------------------|
|    |     __smp_store_release     |
|    |-----------------------------|
|    | zalasr        | !zalasr     |
| rl |-----------------------------|
|    | s{b|h|w|d}.rl | fence rw, w |
|    |               | s{b|h|w|d}  |
|----------------------------------|
|    |    __smp_load_acquire       |
|    |-----------------------------|
|    | zalasr        | !zalasr     |
| aq |-----------------------------|
|    | l{b|h|w|d}.aq | l{b|h|w|d}  |
|    |               | fence r, rw |
|----------------------------------|

Signed-off-by: Xu Lu <luxu.kernel at bytedance.com>
Co-developed-by: Qingwei Hu <qingwei.hu at bytedance.com>
Signed-off-by: Qingwei Hu <qingwei.hu at bytedance.com>
---
 arch/riscv/include/asm/barrier.h | 78 ++++++++++++++++++++++++++++----
 1 file changed, 69 insertions(+), 9 deletions(-)

diff --git a/arch/riscv/include/asm/barrier.h b/arch/riscv/include/asm/barrier.h
index 51a73712b6a12..d2200e826ec00 100644
--- a/arch/riscv/include/asm/barrier.h
+++ b/arch/riscv/include/asm/barrier.h
@@ -13,6 +13,7 @@
 #ifndef __ASSEMBLER__
 #include <asm/cmpxchg.h>
 #include <asm/fence.h>
+#include <asm/insn-def.h>
 
 /* These barriers need to enforce ordering on both devices or memory. */
 #define __mb()		RISCV_FENCE(iorw, iorw)
@@ -53,21 +54,80 @@
 
 #define __smp_store_release(p, v)					\
 do {									\
+	typeof(p) __p = (p);						\
+	union { __unqual_scalar_typeof(*p) __val; char __c[1]; } __u =	\
+		{ .__val = (__force __unqual_scalar_typeof(*p)) (v) };	\
 	compiletime_assert_atomic_type(*p);				\
-	__asm__ __volatile__(RISCV_ZALASR_ALTERNATIVE(			\
-		RISCV_FENCE_ASM(rw, w), RISCV_FENCE_ASM(rw, rw))	\
-		::: "memory");						\
-	WRITE_ONCE(*p, v);						\
+	kasan_check_write(__p, sizeof(*p));				\
+	switch (sizeof(*p)) {						\
+	case 1:								\
+		asm volatile(RISCV_ZALASR_ALTERNATIVE(			\
+			RISCV_FENCE_ASM(rw, w) "sb %0, 0(%1)\n",	\
+			SB_RL(%0, %1) "\n" __nops(1))			\
+			: : "r" (*(__u8 *)__u.__c), "r" (__p)		\
+			: "memory");					\
+		break;							\
+	case 2:								\
+		asm volatile(RISCV_ZALASR_ALTERNATIVE(			\
+			RISCV_FENCE_ASM(rw, w) "sh %0, 0(%1)\n",	\
+			SH_RL(%0, %1) "\n" __nops(1))			\
+			: : "r" (*(__u16 *)__u.__c), "r" (__p)	\
+			: "memory");					\
+		break;							\
+	case 4:								\
+		asm volatile(RISCV_ZALASR_ALTERNATIVE(			\
+			RISCV_FENCE_ASM(rw, w) "sw %0, 0(%1)\n",	\
+			SW_RL(%0, %1) "\n" __nops(1))			\
+			: : "r" (*(__u32 *)__u.__c), "r" (__p)	\
+			: "memory");					\
+		break;							\
+	case 8:								\
+		asm volatile(RISCV_ZALASR_ALTERNATIVE(			\
+			RISCV_FENCE_ASM(rw, w) "sd %0, 0(%1)\n",	\
+			SD_RL(%0, %1) "\n" __nops(1))			\
+			: : "r" (*(__u64 *)__u.__c), "r" (__p)	\
+			: "memory");					\
+		break;							\
+	}								\
 } while (0)
 
 #define __smp_load_acquire(p)						\
 ({									\
-	typeof(*p) ___p1 = READ_ONCE(*p);				\
+	union { __unqual_scalar_typeof(*p) __val; char __c[1]; } __u;	\
+	typeof(p) __p = (p);						\
 	compiletime_assert_atomic_type(*p);				\
-	__asm__ __volatile__(RISCV_ZALASR_ALTERNATIVE(			\
-		RISCV_FENCE_ASM(r, rw), RISCV_FENCE_ASM(rw, rw))	\
-		::: "memory");						\
-	___p1;								\
+	kasan_check_read(__p, sizeof(*p));				\
+	switch (sizeof(*p)) {						\
+	case 1:								\
+		asm volatile(RISCV_ZALASR_ALTERNATIVE(			\
+			"lb %0, 0(%1)\n" RISCV_FENCE_ASM(r, rw),	\
+			LB_AQ(%0, %1) "\n" __nops(1))			\
+			: "=r" (*(__u8 *)__u.__c) : "r" (__p)		\
+			: "memory");					\
+		break;							\
+	case 2:								\
+		asm volatile(RISCV_ZALASR_ALTERNATIVE(			\
+			"lh %0, 0(%1)\n" RISCV_FENCE_ASM(r, rw),	\
+			LH_AQ(%0, %1) "\n" __nops(1))			\
+			: "=r" (*(__u16 *)__u.__c) : "r" (__p)	\
+			: "memory");					\
+		break;							\
+	case 4:								\
+		asm volatile(RISCV_ZALASR_ALTERNATIVE(			\
+			"lw %0, 0(%1)\n" RISCV_FENCE_ASM(r, rw),	\
+			LW_AQ(%0, %1) "\n" __nops(1))			\
+			: "=r" (*(__u32 *)__u.__c) : "r" (__p)	\
+			: "memory");					\
+		break;							\
+	case 8:								\
+		asm volatile(RISCV_ZALASR_ALTERNATIVE(			\
+			"ld %0, 0(%1)\n" RISCV_FENCE_ASM(r, rw),	\
+			LD_AQ(%0, %1) "\n" __nops(1))			\
+			: "=r" (*(__u64 *)__u.__c) : "r" (__p)	\
+			: "memory");					\
+		break;							\
+	}								\
+	(typeof(*p))__u.__val;						\
 })
 
 #ifdef CONFIG_RISCV_ISA_ZAWRS
-- 
2.39.5




More information about the linux-riscv mailing list