diff mbox series

[07/12] percpu: #ifndef __SIZEOF_INT128__

Message ID 20230531132323.722039569@infradead.org
State New
Headers show
Series Introduce cmpxchg128() -- aka. the demise of cmpxchg_double() | expand

Commit Message

Peter Zijlstra May 31, 2023, 1:08 p.m. UTC
Some 64bit architectures do not advertise __SIZEOF_INT128__ on all
supported compiler versions. Notably the HPPA64 only started doing
with GCC-11.

Since the per-cpu ops are universally availably, and
this_cpu_{,try_}cmpxchg128() is expected to be available on all 64bit
architectures a wee bodge is in order.

Sadly, while C reverts to memcpy() for assignment of POD types, it does
not revert to memcmp() for for equality. Therefore frob that manually.

Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
---
 include/asm-generic/percpu.h |   56 +++++++++++++++++++++++++++++++++++++++++++
 include/linux/types.h        |    7 +++++
 2 files changed, 63 insertions(+)

Comments

Sam James June 1, 2023, 9:08 p.m. UTC | #1
Peter Zijlstra <peterz@infradead.org> writes:

> On Thu, Jun 01, 2023 at 12:32:38PM +0200, Helge Deller wrote:
>> On 6/1/23 12:14, Peter Zijlstra wrote:
>> > On Wed, May 31, 2023 at 04:21:22PM +0200, Arnd Bergmann wrote:
>> > 
>> > > It would be nice to have the hack more localized to parisc
>> > > and guarded with a CONFIG_GCC_VERSION check so we can kill
>> > > it off in the future, once we drop either gcc-10 or parisc
>> > > support.
>> > 
>> > I vote for dropping parisc -- it's the only 64bit arch that doesn't have
>> > sane atomics.
>> 
>> Of course I'm against dropping parisc.
>
> :-)
>
>> > Anyway, the below seems to work -- build tested with GCC-10.1
>> 
>> I don't think we need to care about gcc-10 on parisc.
>> Debian and Gentoo are the only supported distributions, while Debian
>> requires gcc-12 to build > 6.x kernels, and I assume Gentoo uses at least
>> gcc-12 as well.
>> 
>> So raising the gcc limit for parisc only (at least temporarily for now)
>> should be fine and your workaround below wouldn't be necessary, right?
>
> Correct, if you're willing to set minimum GCC version to 11 for parisc
> all is well and this patch can go play in the bit bucket.

It's fine for us in Gentoo, thanks!
diff mbox series

Patch

--- a/include/asm-generic/percpu.h
+++ b/include/asm-generic/percpu.h
@@ -313,6 +313,35 @@  do {									\
 #define raw_cpu_xchg_8(pcp, nval)	raw_cpu_generic_xchg(pcp, nval)
 #endif
 
+#ifndef __SIZEOF_INT128__
+#define raw_cpu_generic_try_cmpxchg_memcmp(pcp, ovalp, nval)		\
+({									\
+	typeof(pcp) *__p = raw_cpu_ptr(&(pcp));				\
+	typeof(pcp) __val = *__p, __old = *(ovalp);			\
+	bool __ret;							\
+	if (!__builtin_memcmp(&__val, &__old, sizeof(pcp))) {		\
+		*__p = nval;						\
+		__ret = true;						\
+	} else {							\
+		*(ovalp) = __val;					\
+		__ret = false;						\
+	}								\
+	__ret;								\
+})
+
+#define raw_cpu_generic_cmpxchg_memcmp(pcp, oval, nval)			\
+({									\
+	typeof(pcp) __old = (oval);					\
+	raw_cpu_generic_try_cmpxchg_memcpy(pcp, &__old, nval);		\
+	__old;								\
+})
+
+#define raw_cpu_cmpxchg128(pcp, oval, nval) \
+	raw_cpu_generic_cmpxchg_memcmp(pcp, oval, nval)
+#define raw_cpu_try_cmpxchg128(pcp, ovalp, nval) \
+	raw_cpu_generic_try_cmpxchg_memcmp(pcp, ovalp, nval)
+#endif
+
 #ifndef raw_cpu_try_cmpxchg_1
 #ifdef raw_cpu_cmpxchg_1
 #define raw_cpu_try_cmpxchg_1(pcp, ovalp, nval) \
@@ -503,6 +532,33 @@  do {									\
 #define this_cpu_xchg_8(pcp, nval)	this_cpu_generic_xchg(pcp, nval)
 #endif
 
+#ifndef __SIZEOF_INT128__
+#define this_cpu_generic_try_cmpxchg_memcmp(pcp, ovalp, nval)		\
+({									\
+	bool __ret;							\
+	unsigned long __flags;						\
+	raw_local_irq_save(__flags);					\
+	__ret = raw_cpu_generic_try_cmpxchg_memcmp(pcp, ovalp, nval);	\
+	raw_local_irq_restore(__flags);					\
+	__ret;								\
+})
+
+#define this_cpu_generic_cmpxchg_memcmp(pcp, oval, nval)		\
+({									\
+	typeof(pcp) __ret;						\
+	unsigned long __flags;						\
+	raw_local_irq_save(__flags);					\
+	__ret = raw_cpu_generic_cmpxchg_memcmp(pcp, oval, nval);	\
+	raw_local_irq_restore(__flags);					\
+	__ret;								\
+})
+
+#define this_cpu_cmpxchg128(pcp, oval, nval) \
+	this_cpu_generic_cmpxchg_memcmp(pcp, oval, nval)
+#define this_cpu_try_cmpxchg128(pcp, ovalp, nval) \
+	this_cpu_generic_try_cmpxchg_memcmp(pcp, ovalp, nval)
+#endif
+
 #ifndef this_cpu_try_cmpxchg_1
 #ifdef this_cpu_cmpxchg_1
 #define this_cpu_try_cmpxchg_1(pcp, ovalp, nval) \
--- a/include/linux/types.h
+++ b/include/linux/types.h
@@ -13,6 +13,13 @@ 
 #ifdef __SIZEOF_INT128__
 typedef __s128 s128;
 typedef __u128 u128;
+#else
+#ifdef CONFIG_64BIT
+/* hack for this_cpu_cmpxchg128 */
+typedef struct {
+	u64 a, b;
+} u128 __attribute__((aligned(16)));
+#endif
 #endif
 
 typedef u32 __kernel_dev_t;