Skip to content

Commit 1658ef4

Browse files
Alexandre Ghitipalmer-dabbelt
authored andcommitted
riscv: Implement cmpxchg8/16() using Zabha
This adds runtime support for Zabha in cmpxchg8/16() operations. Note that in the absence of Zacas support in the toolchain, CAS instructions from Zabha won't be used. Signed-off-by: Alexandre Ghiti <alexghiti@rivosinc.com> Reviewed-by: Andrew Jones <ajones@ventanamicro.com> Reviewed-by: Andrea Parri <parri.andrea@gmail.com> Link: https://lore.kernel.org/r/20241103145153.105097-6-alexghiti@rivosinc.com Signed-off-by: Palmer Dabbelt <palmer@rivosinc.com>
1 parent 51624dd commit 1658ef4

File tree

5 files changed

+72
-29
lines changed

5 files changed

+72
-29
lines changed

arch/riscv/Kconfig

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -632,6 +632,24 @@ config RISCV_ISA_ZAWRS
632632
use of these instructions in the kernel when the Zawrs extension is
633633
detected at boot.
634634

635+
config TOOLCHAIN_HAS_ZABHA
636+
bool
637+
default y
638+
depends on !64BIT || $(cc-option,-mabi=lp64 -march=rv64ima_zabha)
639+
depends on !32BIT || $(cc-option,-mabi=ilp32 -march=rv32ima_zabha)
640+
depends on AS_HAS_OPTION_ARCH
641+
642+
config RISCV_ISA_ZABHA
643+
bool "Zabha extension support for atomic byte/halfword operations"
644+
depends on TOOLCHAIN_HAS_ZABHA
645+
depends on RISCV_ALTERNATIVE
646+
default y
647+
help
648+
Enable the use of the Zabha ISA-extension to implement kernel
649+
byte/halfword atomic memory operations when it is detected at boot.
650+
651+
If you don't know what to do here, say Y.
652+
635653
config TOOLCHAIN_HAS_ZACAS
636654
bool
637655
default y

arch/riscv/Makefile

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,9 @@ endif
8585
# Check if the toolchain supports Zacas
8686
riscv-march-$(CONFIG_TOOLCHAIN_HAS_ZACAS) := $(riscv-march-y)_zacas
8787

88+
# Check if the toolchain supports Zabha
89+
riscv-march-$(CONFIG_TOOLCHAIN_HAS_ZABHA) := $(riscv-march-y)_zabha
90+
8891
# Remove F,D,V from isa string for all. Keep extensions between "fd" and "v" by
8992
# matching non-v and non-multi-letter extensions out with the filter ([^v_]*)
9093
KBUILD_CFLAGS += -march=$(shell echo $(riscv-march-y) | sed -E 's/(rv32ima|rv64ima)fd([^v_]*)v?/\1\2/')

arch/riscv/include/asm/cmpxchg.h

Lines changed: 49 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -108,34 +108,49 @@
108108
* indicated by comparing RETURN with OLD.
109109
*/
110110

111-
#define __arch_cmpxchg_masked(sc_sfx, prepend, append, r, p, o, n) \
112-
({ \
113-
u32 *__ptr32b = (u32 *)((ulong)(p) & ~0x3); \
114-
ulong __s = ((ulong)(p) & (0x4 - sizeof(*p))) * BITS_PER_BYTE; \
115-
ulong __mask = GENMASK(((sizeof(*p)) * BITS_PER_BYTE) - 1, 0) \
116-
<< __s; \
117-
ulong __newx = (ulong)(n) << __s; \
118-
ulong __oldx = (ulong)(o) << __s; \
119-
ulong __retx; \
120-
ulong __rc; \
121-
\
122-
__asm__ __volatile__ ( \
123-
prepend \
124-
"0: lr.w %0, %2\n" \
125-
" and %1, %0, %z5\n" \
126-
" bne %1, %z3, 1f\n" \
127-
" and %1, %0, %z6\n" \
128-
" or %1, %1, %z4\n" \
129-
" sc.w" sc_sfx " %1, %1, %2\n" \
130-
" bnez %1, 0b\n" \
131-
append \
132-
"1:\n" \
133-
: "=&r" (__retx), "=&r" (__rc), "+A" (*(__ptr32b)) \
134-
: "rJ" ((long)__oldx), "rJ" (__newx), \
135-
"rJ" (__mask), "rJ" (~__mask) \
136-
: "memory"); \
137-
\
138-
r = (__typeof__(*(p)))((__retx & __mask) >> __s); \
111+
#define __arch_cmpxchg_masked(sc_sfx, cas_sfx, prepend, append, r, p, o, n) \
112+
({ \
113+
if (IS_ENABLED(CONFIG_RISCV_ISA_ZABHA) && \
114+
IS_ENABLED(CONFIG_RISCV_ISA_ZACAS) && \
115+
riscv_has_extension_unlikely(RISCV_ISA_EXT_ZABHA) && \
116+
riscv_has_extension_unlikely(RISCV_ISA_EXT_ZACAS)) { \
117+
r = o; \
118+
\
119+
__asm__ __volatile__ ( \
120+
prepend \
121+
" amocas" cas_sfx " %0, %z2, %1\n" \
122+
append \
123+
: "+&r" (r), "+A" (*(p)) \
124+
: "rJ" (n) \
125+
: "memory"); \
126+
} else { \
127+
u32 *__ptr32b = (u32 *)((ulong)(p) & ~0x3); \
128+
ulong __s = ((ulong)(p) & (0x4 - sizeof(*p))) * BITS_PER_BYTE; \
129+
ulong __mask = GENMASK(((sizeof(*p)) * BITS_PER_BYTE) - 1, 0) \
130+
<< __s; \
131+
ulong __newx = (ulong)(n) << __s; \
132+
ulong __oldx = (ulong)(o) << __s; \
133+
ulong __retx; \
134+
ulong __rc; \
135+
\
136+
__asm__ __volatile__ ( \
137+
prepend \
138+
"0: lr.w %0, %2\n" \
139+
" and %1, %0, %z5\n" \
140+
" bne %1, %z3, 1f\n" \
141+
" and %1, %0, %z6\n" \
142+
" or %1, %1, %z4\n" \
143+
" sc.w" sc_sfx " %1, %1, %2\n" \
144+
" bnez %1, 0b\n" \
145+
append \
146+
"1:\n" \
147+
: "=&r" (__retx), "=&r" (__rc), "+A" (*(__ptr32b)) \
148+
: "rJ" ((long)__oldx), "rJ" (__newx), \
149+
"rJ" (__mask), "rJ" (~__mask) \
150+
: "memory"); \
151+
\
152+
r = (__typeof__(*(p)))((__retx & __mask) >> __s); \
153+
} \
139154
})
140155

141156
#define __arch_cmpxchg(lr_sfx, sc_cas_sfx, prepend, append, r, p, co, o, n) \
@@ -177,8 +192,13 @@
177192
\
178193
switch (sizeof(*__ptr)) { \
179194
case 1: \
195+
__arch_cmpxchg_masked(sc_cas_sfx, ".b" sc_cas_sfx, \
196+
prepend, append, \
197+
__ret, __ptr, __old, __new); \
198+
break; \
180199
case 2: \
181-
__arch_cmpxchg_masked(sc_cas_sfx, prepend, append, \
200+
__arch_cmpxchg_masked(sc_cas_sfx, ".h" sc_cas_sfx, \
201+
prepend, append, \
182202
__ret, __ptr, __old, __new); \
183203
break; \
184204
case 4: \

arch/riscv/include/asm/hwcap.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@
9393
#define RISCV_ISA_EXT_ZCMOP 84
9494
#define RISCV_ISA_EXT_ZAWRS 85
9595
#define RISCV_ISA_EXT_SVVPTC 86
96+
#define RISCV_ISA_EXT_ZABHA 87
9697

9798
#define RISCV_ISA_EXT_XLINUXENVCFG 127
9899

arch/riscv/kernel/cpufeature.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -322,6 +322,7 @@ const struct riscv_isa_ext_data riscv_isa_ext[] = {
322322
__RISCV_ISA_EXT_DATA(zihintpause, RISCV_ISA_EXT_ZIHINTPAUSE),
323323
__RISCV_ISA_EXT_DATA(zihpm, RISCV_ISA_EXT_ZIHPM),
324324
__RISCV_ISA_EXT_DATA(zimop, RISCV_ISA_EXT_ZIMOP),
325+
__RISCV_ISA_EXT_DATA(zabha, RISCV_ISA_EXT_ZABHA),
325326
__RISCV_ISA_EXT_DATA(zacas, RISCV_ISA_EXT_ZACAS),
326327
__RISCV_ISA_EXT_DATA(zawrs, RISCV_ISA_EXT_ZAWRS),
327328
__RISCV_ISA_EXT_DATA(zfa, RISCV_ISA_EXT_ZFA),

0 commit comments

Comments
 (0)