From: Guenter Roeck <linux@roeck-us.net> To: Ralf Baechle <ralf@linux-mips.org>, Paul Burton <paul.burton@mips.com>, James Hogan <jhogan@kernel.org>, Benjamin Herrenschmidt <benh@kernel.crashing.org>, Paul Mackerras <paulus@samba.org>, Michael Ellerman <mpe@ellerman.id.au> Cc: linux-mips@linux-mips.org, linux-kernel@vger.kernel.org, linuxppc-dev@lists.ozlabs.org, Andrew Morton <akpm@linux-foundation.org>, Guenter Roeck <linux@roeck-us.net>, Arnd Bergmann <arnd@arndb.de>, Trond Myklebust <trond.myklebust@hammerspace.com> Subject: [RFC PATCH] lib: Introduce generic __cmpxchg_u64() and use it where needed Date: Wed, 31 Oct 2018 12:52:18 -0700 [thread overview] Message-ID: <1541015538-11382-1-git-send-email-linux@roeck-us.net> (raw) Some architectures do not or not always support cmpxchg64(). This results in on/off problems when the function is used in common code. The latest example is net/sunrpc/auth_gss/gss_krb5_seal.c: In function 'gss_seq_send64_fetch_and_inc': net/sunrpc/auth_gss/gss_krb5_seal.c:145:14: error: implicit declaration of function 'cmpxchg64' which is seen with some powerpc and mips builds. Introduce a generic version of __cmpxchg_u64() and use it for affected architectures. Fixes: 21924765862a ("SUNRPC: use cmpxchg64() in gss_seq_send64_fetch_and_inc()") Cc: Arnd Bergmann <arnd@arndb.de> Cc: Trond Myklebust <trond.myklebust@hammerspace.com> Signed-off-by: Guenter Roeck <linux@roeck-us.net> --- Couple of questions: - Is this the right (or an acceptable) approach to fix the problem ? - Should I split the patch into three, one to introduce __cmpxchg_u64() and one per architecture ? - Who should take the patch (series) ? arch/mips/Kconfig | 1 + arch/mips/include/asm/cmpxchg.h | 3 ++ arch/powerpc/Kconfig | 1 + arch/powerpc/include/asm/cmpxchg.h | 3 ++ lib/Kconfig | 3 ++ lib/Makefile | 2 ++ lib/cmpxchg64.c | 60 ++++++++++++++++++++++++++++++++++++++ 7 files changed, 73 insertions(+) create mode 100644 lib/cmpxchg64.c diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index 80778b40f8fa..7392a5f4e517 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -18,6 +18,7 @@ config MIPS select CPU_PM if CPU_IDLE select DMA_DIRECT_OPS select GENERIC_ATOMIC64 if !64BIT + select GENERIC_CMPXCHG64 if !64BIT && SMP select GENERIC_CLOCKEVENTS select GENERIC_CMOS_UPDATE select GENERIC_CPU_AUTOPROBE diff --git a/arch/mips/include/asm/cmpxchg.h b/arch/mips/include/asm/cmpxchg.h index 89e9fb7976fe..ca837b05bf3d 100644 --- a/arch/mips/include/asm/cmpxchg.h +++ b/arch/mips/include/asm/cmpxchg.h @@ -206,6 +206,9 @@ static inline unsigned long __cmpxchg(volatile void *ptr, unsigned long old, #define cmpxchg64_local(ptr, o, n) __cmpxchg64_local_generic((ptr), (o), (n)) #ifndef CONFIG_SMP #define cmpxchg64(ptr, o, n) cmpxchg64_local((ptr), (o), (n)) +#else +extern u64 __cmpxchg_u64(u64 *p, u64 old, u64 new); +#define cmpxchg64(ptr, o, n) __cmpxchg_u64((ptr), (o), (n)) #endif #endif diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index e84943d24e5c..bd1d99c664c4 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig @@ -161,6 +161,7 @@ config PPC select EDAC_ATOMIC_SCRUB select EDAC_SUPPORT select GENERIC_ATOMIC64 if PPC32 + select GENERIC_CMPXCHG64 if PPC32 select GENERIC_CLOCKEVENTS select GENERIC_CLOCKEVENTS_BROADCAST if SMP select GENERIC_CMOS_UPDATE diff --git a/arch/powerpc/include/asm/cmpxchg.h b/arch/powerpc/include/asm/cmpxchg.h index 27183871eb3b..da8be4189731 100644 --- a/arch/powerpc/include/asm/cmpxchg.h +++ b/arch/powerpc/include/asm/cmpxchg.h @@ -534,8 +534,11 @@ __cmpxchg_acquire(void *ptr, unsigned long old, unsigned long new, cmpxchg_acquire((ptr), (o), (n)); \ }) #else +extern u64 __cmpxchg_u64(u64 *p, u64 old, u64 new); + #include <asm-generic/cmpxchg-local.h> #define cmpxchg64_local(ptr, o, n) __cmpxchg64_local_generic((ptr), (o), (n)) +#define cmpxchg64(ptr, o, n) __cmpxchg_u64((ptr), (o), (n)) #endif #endif /* __KERNEL__ */ diff --git a/lib/Kconfig b/lib/Kconfig index d1573a16aa92..2b581a70ded2 100644 --- a/lib/Kconfig +++ b/lib/Kconfig @@ -500,6 +500,9 @@ config NLATTR config GENERIC_ATOMIC64 bool +config GENERIC_CMPXCHG64 + bool + config LRU_CACHE tristate diff --git a/lib/Makefile b/lib/Makefile index 988949c4fd3a..4646a06ed418 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -172,6 +172,8 @@ obj-$(CONFIG_GENERIC_CSUM) += checksum.o obj-$(CONFIG_GENERIC_ATOMIC64) += atomic64.o +obj-$(CONFIG_GENERIC_CMPXCHG64) += cmpxchg64.o + obj-$(CONFIG_ATOMIC64_SELFTEST) += atomic64_test.o obj-$(CONFIG_CPU_RMAP) += cpu_rmap.o diff --git a/lib/cmpxchg64.c b/lib/cmpxchg64.c new file mode 100644 index 000000000000..239c43d05d00 --- /dev/null +++ b/lib/cmpxchg64.c @@ -0,0 +1,60 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Generic implementation of cmpxchg64(). + * Derived from implementation in arch/sparc/lib/atomic32.c + * and from locking code implemented in lib/atomic32.c. + */ + +#include <linux/cache.h> +#include <linux/export.h> +#include <linux/irqflags.h> +#include <linux/spinlock.h> +#include <linux/types.h> + +/* + * We use a hashed array of spinlocks to provide exclusive access + * to each variable. Since this is expected to used on systems + * with small numbers of CPUs (<= 4 or so), we use a relatively + * small array of 16 spinlocks to avoid wasting too much memory + * on the spinlock array. + */ +#define NR_LOCKS 16 + +/* Ensure that each lock is in a separate cacheline */ +static union { + raw_spinlock_t lock; + char pad[L1_CACHE_BYTES]; +} cmpxchg_lock[NR_LOCKS] __cacheline_aligned_in_smp = { + [0 ... (NR_LOCKS - 1)] = { + .lock = __RAW_SPIN_LOCK_UNLOCKED(cmpxchg_lock.lock), + }, +}; + +static inline raw_spinlock_t *lock_addr(const u64 *v) +{ + unsigned long addr = (unsigned long) v; + + addr >>= L1_CACHE_SHIFT; + addr ^= (addr >> 8) ^ (addr >> 16); + return &cmpxchg_lock[addr & (NR_LOCKS - 1)].lock; +} + +/* + * Generic version of __cmpxchg_u64, to be used for cmpxchg64(). + * Takes u64 parameters. + */ +u64 __cmpxchg_u64(u64 *ptr, u64 old, u64 new) +{ + raw_spinlock_t *lock = lock_addr(ptr); + unsigned long flags; + u64 prev; + + raw_spin_lock_irqsave(lock, flags); + prev = READ_ONCE(*ptr); + if (prev == old) + *ptr = new; + raw_spin_unlock_irqrestore(lock, flags); + + return prev; +} +EXPORT_SYMBOL(__cmpxchg_u64); -- 2.7.4
WARNING: multiple messages have this Message-ID (diff)
From: Guenter Roeck <linux@roeck-us.net> To: Ralf Baechle <ralf@linux-mips.org>, Paul Burton <paul.burton@mips.com>, James Hogan <jhogan@kernel.org>, Benjamin Herrenschmidt <benh@kernel.crashing.org>, Paul Mackerras <paulus@samba.org>, Michael Ellerman <mpe@ellerman.id.au> Cc: linux-mips@linux-mips.org, Arnd Bergmann <arnd@arndb.de>, linux-kernel@vger.kernel.org, Andrew Morton <akpm@linux-foundation.org>, linuxppc-dev@lists.ozlabs.org, Trond Myklebust <trond.myklebust@hammerspace.com>, Guenter Roeck <linux@roeck-us.net> Subject: [RFC PATCH] lib: Introduce generic __cmpxchg_u64() and use it where needed Date: Wed, 31 Oct 2018 12:52:18 -0700 [thread overview] Message-ID: <1541015538-11382-1-git-send-email-linux@roeck-us.net> (raw) Some architectures do not or not always support cmpxchg64(). This results in on/off problems when the function is used in common code. The latest example is net/sunrpc/auth_gss/gss_krb5_seal.c: In function 'gss_seq_send64_fetch_and_inc': net/sunrpc/auth_gss/gss_krb5_seal.c:145:14: error: implicit declaration of function 'cmpxchg64' which is seen with some powerpc and mips builds. Introduce a generic version of __cmpxchg_u64() and use it for affected architectures. Fixes: 21924765862a ("SUNRPC: use cmpxchg64() in gss_seq_send64_fetch_and_inc()") Cc: Arnd Bergmann <arnd@arndb.de> Cc: Trond Myklebust <trond.myklebust@hammerspace.com> Signed-off-by: Guenter Roeck <linux@roeck-us.net> --- Couple of questions: - Is this the right (or an acceptable) approach to fix the problem ? - Should I split the patch into three, one to introduce __cmpxchg_u64() and one per architecture ? - Who should take the patch (series) ? arch/mips/Kconfig | 1 + arch/mips/include/asm/cmpxchg.h | 3 ++ arch/powerpc/Kconfig | 1 + arch/powerpc/include/asm/cmpxchg.h | 3 ++ lib/Kconfig | 3 ++ lib/Makefile | 2 ++ lib/cmpxchg64.c | 60 ++++++++++++++++++++++++++++++++++++++ 7 files changed, 73 insertions(+) create mode 100644 lib/cmpxchg64.c diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index 80778b40f8fa..7392a5f4e517 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -18,6 +18,7 @@ config MIPS select CPU_PM if CPU_IDLE select DMA_DIRECT_OPS select GENERIC_ATOMIC64 if !64BIT + select GENERIC_CMPXCHG64 if !64BIT && SMP select GENERIC_CLOCKEVENTS select GENERIC_CMOS_UPDATE select GENERIC_CPU_AUTOPROBE diff --git a/arch/mips/include/asm/cmpxchg.h b/arch/mips/include/asm/cmpxchg.h index 89e9fb7976fe..ca837b05bf3d 100644 --- a/arch/mips/include/asm/cmpxchg.h +++ b/arch/mips/include/asm/cmpxchg.h @@ -206,6 +206,9 @@ static inline unsigned long __cmpxchg(volatile void *ptr, unsigned long old, #define cmpxchg64_local(ptr, o, n) __cmpxchg64_local_generic((ptr), (o), (n)) #ifndef CONFIG_SMP #define cmpxchg64(ptr, o, n) cmpxchg64_local((ptr), (o), (n)) +#else +extern u64 __cmpxchg_u64(u64 *p, u64 old, u64 new); +#define cmpxchg64(ptr, o, n) __cmpxchg_u64((ptr), (o), (n)) #endif #endif diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index e84943d24e5c..bd1d99c664c4 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig @@ -161,6 +161,7 @@ config PPC select EDAC_ATOMIC_SCRUB select EDAC_SUPPORT select GENERIC_ATOMIC64 if PPC32 + select GENERIC_CMPXCHG64 if PPC32 select GENERIC_CLOCKEVENTS select GENERIC_CLOCKEVENTS_BROADCAST if SMP select GENERIC_CMOS_UPDATE diff --git a/arch/powerpc/include/asm/cmpxchg.h b/arch/powerpc/include/asm/cmpxchg.h index 27183871eb3b..da8be4189731 100644 --- a/arch/powerpc/include/asm/cmpxchg.h +++ b/arch/powerpc/include/asm/cmpxchg.h @@ -534,8 +534,11 @@ __cmpxchg_acquire(void *ptr, unsigned long old, unsigned long new, cmpxchg_acquire((ptr), (o), (n)); \ }) #else +extern u64 __cmpxchg_u64(u64 *p, u64 old, u64 new); + #include <asm-generic/cmpxchg-local.h> #define cmpxchg64_local(ptr, o, n) __cmpxchg64_local_generic((ptr), (o), (n)) +#define cmpxchg64(ptr, o, n) __cmpxchg_u64((ptr), (o), (n)) #endif #endif /* __KERNEL__ */ diff --git a/lib/Kconfig b/lib/Kconfig index d1573a16aa92..2b581a70ded2 100644 --- a/lib/Kconfig +++ b/lib/Kconfig @@ -500,6 +500,9 @@ config NLATTR config GENERIC_ATOMIC64 bool +config GENERIC_CMPXCHG64 + bool + config LRU_CACHE tristate diff --git a/lib/Makefile b/lib/Makefile index 988949c4fd3a..4646a06ed418 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -172,6 +172,8 @@ obj-$(CONFIG_GENERIC_CSUM) += checksum.o obj-$(CONFIG_GENERIC_ATOMIC64) += atomic64.o +obj-$(CONFIG_GENERIC_CMPXCHG64) += cmpxchg64.o + obj-$(CONFIG_ATOMIC64_SELFTEST) += atomic64_test.o obj-$(CONFIG_CPU_RMAP) += cpu_rmap.o diff --git a/lib/cmpxchg64.c b/lib/cmpxchg64.c new file mode 100644 index 000000000000..239c43d05d00 --- /dev/null +++ b/lib/cmpxchg64.c @@ -0,0 +1,60 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Generic implementation of cmpxchg64(). + * Derived from implementation in arch/sparc/lib/atomic32.c + * and from locking code implemented in lib/atomic32.c. + */ + +#include <linux/cache.h> +#include <linux/export.h> +#include <linux/irqflags.h> +#include <linux/spinlock.h> +#include <linux/types.h> + +/* + * We use a hashed array of spinlocks to provide exclusive access + * to each variable. Since this is expected to used on systems + * with small numbers of CPUs (<= 4 or so), we use a relatively + * small array of 16 spinlocks to avoid wasting too much memory + * on the spinlock array. + */ +#define NR_LOCKS 16 + +/* Ensure that each lock is in a separate cacheline */ +static union { + raw_spinlock_t lock; + char pad[L1_CACHE_BYTES]; +} cmpxchg_lock[NR_LOCKS] __cacheline_aligned_in_smp = { + [0 ... (NR_LOCKS - 1)] = { + .lock = __RAW_SPIN_LOCK_UNLOCKED(cmpxchg_lock.lock), + }, +}; + +static inline raw_spinlock_t *lock_addr(const u64 *v) +{ + unsigned long addr = (unsigned long) v; + + addr >>= L1_CACHE_SHIFT; + addr ^= (addr >> 8) ^ (addr >> 16); + return &cmpxchg_lock[addr & (NR_LOCKS - 1)].lock; +} + +/* + * Generic version of __cmpxchg_u64, to be used for cmpxchg64(). + * Takes u64 parameters. + */ +u64 __cmpxchg_u64(u64 *ptr, u64 old, u64 new) +{ + raw_spinlock_t *lock = lock_addr(ptr); + unsigned long flags; + u64 prev; + + raw_spin_lock_irqsave(lock, flags); + prev = READ_ONCE(*ptr); + if (prev == old) + *ptr = new; + raw_spin_unlock_irqrestore(lock, flags); + + return prev; +} +EXPORT_SYMBOL(__cmpxchg_u64); -- 2.7.4
next reply other threads:[~2018-10-31 19:52 UTC|newest] Thread overview: 94+ messages / expand[flat|nested] mbox.gz Atom feed top 2018-10-31 19:52 Guenter Roeck [this message] 2018-10-31 19:52 ` [RFC PATCH] lib: Introduce generic __cmpxchg_u64() and use it where needed Guenter Roeck 2018-10-31 21:32 ` Paul Burton 2018-10-31 21:32 ` Paul Burton 2018-10-31 22:02 ` Guenter Roeck 2018-10-31 22:02 ` Guenter Roeck 2018-10-31 23:32 ` Paul Burton 2018-10-31 23:32 ` Paul Burton 2018-11-01 0:17 ` Trond Myklebust 2018-11-01 0:17 ` Trond Myklebust 2018-11-01 0:17 ` Trond Myklebust 2018-11-01 13:18 ` Mark Rutland 2018-11-01 13:18 ` Mark Rutland 2018-11-01 13:18 ` Mark Rutland 2018-11-01 14:59 ` Peter Zijlstra 2018-11-01 14:59 ` Peter Zijlstra 2018-11-01 14:59 ` Peter Zijlstra 2018-11-01 15:22 ` Trond Myklebust 2018-11-01 15:22 ` Trond Myklebust 2018-11-01 15:22 ` Trond Myklebust 2018-11-01 16:32 ` Peter Zijlstra 2018-11-01 16:32 ` Peter Zijlstra 2018-11-01 16:32 ` Peter Zijlstra 2018-11-01 16:59 ` Eric Dumazet 2018-11-01 16:59 ` Eric Dumazet 2018-11-01 16:59 ` Eric Dumazet 2018-11-01 17:14 ` Peter Zijlstra 2018-11-01 17:14 ` Peter Zijlstra 2018-11-01 17:14 ` Peter Zijlstra 2018-11-01 17:27 ` Peter Zijlstra 2018-11-01 17:27 ` Peter Zijlstra 2018-11-01 17:27 ` Peter Zijlstra 2018-11-01 20:29 ` Paul E. McKenney 2018-11-01 20:29 ` Paul E. McKenney 2018-11-01 20:29 ` Paul E. McKenney 2018-11-01 21:38 ` Peter Zijlstra 2018-11-01 21:38 ` Peter Zijlstra 2018-11-01 21:38 ` Peter Zijlstra 2018-11-01 22:26 ` Paul E. McKenney 2018-11-01 22:26 ` Paul E. McKenney 2018-11-01 22:26 ` Paul E. McKenney 2018-11-01 17:43 ` Paul E. McKenney 2018-11-01 17:43 ` Paul E. McKenney 2018-11-01 17:43 ` Paul E. McKenney 2018-11-01 17:01 ` Paul E. McKenney 2018-11-01 17:01 ` Paul E. McKenney 2018-11-01 17:01 ` Paul E. McKenney 2018-11-01 17:18 ` Peter Zijlstra 2018-11-01 17:18 ` Peter Zijlstra 2018-11-01 17:18 ` Peter Zijlstra 2018-11-01 17:34 ` Paul E. McKenney 2018-11-01 17:34 ` Paul E. McKenney 2018-11-01 17:34 ` Paul E. McKenney 2018-11-01 17:46 ` Dmitry Vyukov 2018-11-01 17:46 ` Dmitry Vyukov 2018-11-01 17:46 ` Dmitry Vyukov 2018-11-01 21:45 ` Peter Zijlstra 2018-11-01 21:45 ` Peter Zijlstra 2018-11-01 21:45 ` Peter Zijlstra 2018-11-02 10:56 ` David Laight 2018-11-02 10:56 ` David Laight 2018-11-02 10:56 ` David Laight 2018-11-02 12:23 ` Peter Zijlstra 2018-11-02 12:23 ` Peter Zijlstra 2018-11-02 12:23 ` Peter Zijlstra 2018-11-02 13:38 ` Paul E. McKenney 2018-11-02 13:38 ` Paul E. McKenney 2018-11-02 13:38 ` Paul E. McKenney 2018-11-02 13:37 ` Paul E. McKenney 2018-11-02 13:37 ` Paul E. McKenney 2018-11-02 13:37 ` Paul E. McKenney 2018-11-02 16:19 ` Andrey Ryabinin 2018-11-02 16:19 ` Andrey Ryabinin 2018-11-02 16:19 ` Andrey Ryabinin 2018-11-05 10:38 ` Peter Zijlstra 2018-11-05 10:38 ` Peter Zijlstra 2018-11-05 10:38 ` Peter Zijlstra 2018-11-05 14:24 ` Peter Zijlstra 2018-11-05 14:24 ` Peter Zijlstra 2018-11-05 14:24 ` Peter Zijlstra 2018-11-01 17:51 ` [PATCH] SUNRPC: Use atomic(64)_t for seq_send(64) Paul Burton 2018-11-01 17:57 ` Trond Myklebust 2018-11-01 17:54 ` [RFC PATCH] lib: Introduce generic __cmpxchg_u64() and use it where needed Paul Burton 2018-11-01 17:54 ` Paul Burton 2018-11-01 17:54 ` Paul Burton 2018-11-01 17:54 ` Paul Burton 2018-11-01 1:18 ` Guenter Roeck 2018-11-01 1:18 ` Guenter Roeck 2018-11-01 6:30 ` Trond Myklebust 2018-11-01 6:30 ` Trond Myklebust 2018-11-01 6:30 ` Trond Myklebust 2018-11-01 15:28 ` Guenter Roeck 2018-11-01 15:28 ` Guenter Roeck 2018-11-01 15:28 ` Guenter Roeck
Reply instructions: You may reply publicly to this message via plain-text email using any one of the following methods: * Save the following mbox file, import it into your mail client, and reply-to-all from there: mbox Avoid top-posting and favor interleaved quoting: https://en.wikipedia.org/wiki/Posting_style#Interleaved_style * Reply using the --to, --cc, and --in-reply-to switches of git-send-email(1): git send-email \ --in-reply-to=1541015538-11382-1-git-send-email-linux@roeck-us.net \ --to=linux@roeck-us.net \ --cc=akpm@linux-foundation.org \ --cc=arnd@arndb.de \ --cc=benh@kernel.crashing.org \ --cc=jhogan@kernel.org \ --cc=linux-kernel@vger.kernel.org \ --cc=linux-mips@linux-mips.org \ --cc=linuxppc-dev@lists.ozlabs.org \ --cc=mpe@ellerman.id.au \ --cc=paul.burton@mips.com \ --cc=paulus@samba.org \ --cc=ralf@linux-mips.org \ --cc=trond.myklebust@hammerspace.com \ /path/to/YOUR_REPLY https://kernel.org/pub/software/scm/git/docs/git-send-email.html * If your mail client supports setting the In-Reply-To header via mailto: links, try the mailto: linkBe sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.