[PATCH V8 07/10] riscv: Add qspinlock support
From: guoren
Date: Sun Jul 24 2022 - 08:26:44 EST
From: Guo Ren <guoren@xxxxxxxxxxxxxxxxx>
Enable qspinlock by the requirements mentioned in a8ad07e5240c9
("asm-generic: qspinlock: Indicate the use of mixed-size atomics").
- RISC-V atomic_*_release()/atomic_*_acquire() are implemented with
own relaxed version plus acquire/release_fence for RCsc
synchronization.
- RISC-V LR/SC pairs could provide a strong/weak forward guarantee
that depends on micro-architecture. And RISC-V ISA spec has given
out several limitations to let hardware support strict forward
guarantee (RISC-V User ISA - 8.3 Eventual Success of
Store-Conditional Instructions). Some riscv cores such as BOOMv3
& XiangShan could provide strict & strong forward guarantee (The
cache line would be kept in an exclusive state for Backoff cycles,
and only this core's interrupt could break the LR/SC pair).
- RISC-V provides cheap atomic_fetch_or_acquire() with RCsc.
- RISC-V only provides relaxed xchg16 to support qspinlock.
Signed-off-by: Guo Ren <guoren@xxxxxxxxxxxxxxxxx>
Signed-off-by: Guo Ren <guoren@xxxxxxxxxx>
---
arch/riscv/Kconfig | 16 ++++++++++++++++
arch/riscv/include/asm/Kbuild | 2 ++
arch/riscv/include/asm/cmpxchg.h | 17 +++++++++++++++++
3 files changed, 35 insertions(+)
diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig
index bff04916a6c5..721f098228a8 100644
--- a/arch/riscv/Kconfig
+++ b/arch/riscv/Kconfig
@@ -359,6 +359,22 @@ config NODES_SHIFT
Specify the maximum number of NUMA Nodes available on the target
system. Increases memory reserved to accommodate various tables.
+choice
+ prompt "RISC-V spinlock type"
+ default RISCV_TICKET_SPINLOCKS
+
+config RISCV_TICKET_SPINLOCKS
+ bool "Using ticket spinlock"
+
+config RISCV_QUEUED_SPINLOCKS
+ bool "Using queued spinlock"
+ depends on SMP && MMU
+ select ARCH_USE_QUEUED_SPINLOCKS
+ help
+ Make sure your micro arch LL/SC has a strong forward progress guarantee.
+ Otherwise, stay at ticket-lock/combo-lock.
+endchoice
+
config RISCV_ALTERNATIVE
bool
depends on !XIP_KERNEL
diff --git a/arch/riscv/include/asm/Kbuild b/arch/riscv/include/asm/Kbuild
index 504f8b7e72d4..2cce98c7b653 100644
--- a/arch/riscv/include/asm/Kbuild
+++ b/arch/riscv/include/asm/Kbuild
@@ -2,7 +2,9 @@
generic-y += early_ioremap.h
generic-y += flat.h
generic-y += kvm_para.h
+generic-y += mcs_spinlock.h
generic-y += parport.h
+generic-y += qspinlock.h
generic-y += spinlock.h
generic-y += spinlock_types.h
generic-y += qrwlock.h
diff --git a/arch/riscv/include/asm/cmpxchg.h b/arch/riscv/include/asm/cmpxchg.h
index 67ab6375b650..6bf2726d4500 100644
--- a/arch/riscv/include/asm/cmpxchg.h
+++ b/arch/riscv/include/asm/cmpxchg.h
@@ -17,6 +17,23 @@
__typeof__(new) __new = (new); \
__typeof__(*(ptr)) __ret; \
switch (size) { \
+ case 2: { \
+ u32 tmp, ret; \
+ u32 shif = ((ulong)__ptr & 2) ? 16 : 0; \
+ u32 mask = 0xffff << shif; \
+ __ptr = (__typeof__(ptr))((ulong)__ptr & ~2); \
+ __asm__ __volatile__ ( \
+ "0: lr.w %0, %2\n" \
+ " and %1, %0, %z3\n" \
+ " or %1, %1, %z4\n" \
+ " sc.w %1, %1, %2\n" \
+ " bnez %1, 0b\n" \
+ : "=&r" (ret), "=&r" (tmp), "+A" (*__ptr) \
+ : "rJ" (~mask), "rJ" ((u32)__new << shif) \
+ : "memory"); \
+ __ret = (__typeof__(*(ptr)))((ret & mask) >> shif); \
+ break; \
+ } \
case 4: \
__asm__ __volatile__ ( \
" amoswap.w %0, %2, %1\n" \
--
2.36.1