Re: [PATCH v2 07/12] parisc/percpu: Work around the lack of __SIZEOF_INT128__

Helge Deller
2023-06-01T10:35:06Z

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?

Helge

> ---
> Subject: parisc/percpu: Work around the lack of __SIZEOF_INT128__
> From: Peter Zijlstra <peterz@infradead.org>
> Date: Tue May 30 22:27:40 CEST 2023
>
> HPPA64 is unique in not providing __SIZEOF_INT128__ across all
> supported compilers, specifically it only started doing this 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>
> ---
> arch/parisc/include/asm/percpu.h | 77 +++++++++++++++++++++++++++++++++++++++
> 1 file changed, 77 insertions(+)
>
> --- /dev/null
> +++ b/arch/parisc/include/asm/percpu.h
> @@ -0,0 +1,77 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +#ifndef _ASM_PARISC_PERCPU_H
> +#define _ASM_PARISC_PERCPU_H
> +
> +#include <linux/types.h>
> +
> +#if defined(CONFIG_64BIT) && CONFIG_GCC_VERSION < 1100000
> +
> +/*
> + * GCC prior to 11 does not provide __SIZEOF_INT128__ on HPPA64
> + * as such we need to provide an alternative implementation of
> + * {raw,this}_cpu_{,try_}cmpxchg128().
> + *
> + * This obviously doesn't function as u128 should, but for the purpose
> + * of per-cpu cmpxchg128 it might just do.
> + */
> +typedef struct {
> + u64 a, b;
> +} u128 __attribute__((aligned(16)));
> +
> +#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)
> +
> +#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 /* !__SIZEOF_INT128__ */
> +
> +#include <asm-generic/percpu.h>
> +
> +#endif /* _ASM_PARISC_PERCPU_H */