Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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>

authored by

Alexandre Ghiti and committed by
Palmer Dabbelt
1658ef43 51624ddc

+72 -29
+18
arch/riscv/Kconfig
··· 632 632 use of these instructions in the kernel when the Zawrs extension is 633 633 detected at boot. 634 634 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 + 635 653 config TOOLCHAIN_HAS_ZACAS 636 654 bool 637 655 default y
+3
arch/riscv/Makefile
··· 85 85 # Check if the toolchain supports Zacas 86 86 riscv-march-$(CONFIG_TOOLCHAIN_HAS_ZACAS) := $(riscv-march-y)_zacas 87 87 88 + # Check if the toolchain supports Zabha 89 + riscv-march-$(CONFIG_TOOLCHAIN_HAS_ZABHA) := $(riscv-march-y)_zabha 90 + 88 91 # Remove F,D,V from isa string for all. Keep extensions between "fd" and "v" by 89 92 # matching non-v and non-multi-letter extensions out with the filter ([^v_]*) 90 93 KBUILD_CFLAGS += -march=$(shell echo $(riscv-march-y) | sed -E 's/(rv32ima|rv64ima)fd([^v_]*)v?/\1\2/')
+49 -29
arch/riscv/include/asm/cmpxchg.h
··· 108 108 * indicated by comparing RETURN with OLD. 109 109 */ 110 110 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 + } \ 139 154 }) 140 155 141 156 #define __arch_cmpxchg(lr_sfx, sc_cas_sfx, prepend, append, r, p, co, o, n) \ ··· 192 177 \ 193 178 switch (sizeof(*__ptr)) { \ 194 179 case 1: \ 180 + __arch_cmpxchg_masked(sc_cas_sfx, ".b" sc_cas_sfx, \ 181 + prepend, append, \ 182 + __ret, __ptr, __old, __new); \ 183 + break; \ 195 184 case 2: \ 196 - __arch_cmpxchg_masked(sc_cas_sfx, prepend, append, \ 185 + __arch_cmpxchg_masked(sc_cas_sfx, ".h" sc_cas_sfx, \ 186 + prepend, append, \ 197 187 __ret, __ptr, __old, __new); \ 198 188 break; \ 199 189 case 4: \
+1
arch/riscv/include/asm/hwcap.h
··· 93 93 #define RISCV_ISA_EXT_ZCMOP 84 94 94 #define RISCV_ISA_EXT_ZAWRS 85 95 95 #define RISCV_ISA_EXT_SVVPTC 86 96 + #define RISCV_ISA_EXT_ZABHA 87 96 97 97 98 #define RISCV_ISA_EXT_XLINUXENVCFG 127 98 99
+1
arch/riscv/kernel/cpufeature.c
··· 322 322 __RISCV_ISA_EXT_DATA(zihintpause, RISCV_ISA_EXT_ZIHINTPAUSE), 323 323 __RISCV_ISA_EXT_DATA(zihpm, RISCV_ISA_EXT_ZIHPM), 324 324 __RISCV_ISA_EXT_DATA(zimop, RISCV_ISA_EXT_ZIMOP), 325 + __RISCV_ISA_EXT_DATA(zabha, RISCV_ISA_EXT_ZABHA), 325 326 __RISCV_ISA_EXT_DATA(zacas, RISCV_ISA_EXT_ZACAS), 326 327 __RISCV_ISA_EXT_DATA(zawrs, RISCV_ISA_EXT_ZAWRS), 327 328 __RISCV_ISA_EXT_DATA(zfa, RISCV_ISA_EXT_ZFA),