Re: [PATCH 17/19] LoongArch: Add multi-processor (SMP) support

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi, Peter,

On Tue, Jul 6, 2021 at 7:32 PM Peter Zijlstra <peterz@xxxxxxxxxxxxx> wrote:
>
> On Tue, Jul 06, 2021 at 12:18:18PM +0800, Huacai Chen wrote:
> > diff --git a/arch/loongarch/include/asm/barrier.h b/arch/loongarch/include/asm/barrier.h
> > index 8ab8d8f15b88..ad09a3b31cba 100644
> > --- a/arch/loongarch/include/asm/barrier.h
> > +++ b/arch/loongarch/include/asm/barrier.h
> > @@ -20,6 +20,19 @@
> >  #define mb()         fast_mb()
> >  #define iob()                fast_iob()
> >
> > +#define __smp_mb()   __asm__ __volatile__("dbar 0" : : : "memory")
> > +#define __smp_rmb()  __asm__ __volatile__("dbar 0" : : : "memory")
> > +#define __smp_wmb()  __asm__ __volatile__("dbar 0" : : : "memory")
>
> :-(
>
> > +
> > +#ifdef CONFIG_SMP
> > +#define __WEAK_LLSC_MB               "       dbar 0  \n"
> > +#else
> > +#define __WEAK_LLSC_MB               "               \n"
> > +#endif
>
> Isn't that spelled smp_mb() ?
Yes, but __WEAK_LLSC_MB is used in inline asm.

>
> > +
> > +#define __smp_mb__before_atomic()    barrier()
> > +#define __smp_mb__after_atomic()     __smp_mb()
>
> Clarification please.
>
> Does this imply LL is sequentially consistent, while SC is not?
I'm wrong here, no mb() is needed after atomic operations.

Huacai
>
> > +
> >  /**
> >   * array_index_mask_nospec() - generate a ~0 mask when index < size, 0 otherwise
> >   * @index: array element index
> > @@ -48,6 +61,112 @@ static inline unsigned long array_index_mask_nospec(unsigned long index,
> >       return mask;
> >  }
> >
> > +#define __smp_load_acquire(p)                                                        \
> > +({                                                                           \
> > +     union { typeof(*p) __val; char __c[1]; } __u;                           \
> > +     unsigned long __tmp = 0;                                                        \
> > +     compiletime_assert_atomic_type(*p);                                     \
> > +     switch (sizeof(*p)) {                                                   \
> > +     case 1:                                                                 \
> > +             *(__u8 *)__u.__c = *(volatile __u8 *)p;                         \
> > +             __smp_mb();                                                     \
> > +             break;                                                          \
> > +     case 2:                                                                 \
> > +             *(__u16 *)__u.__c = *(volatile __u16 *)p;                       \
> > +             __smp_mb();                                                     \
> > +             break;                                                          \
> > +     case 4:                                                                 \
> > +             __asm__ __volatile__(                                           \
> > +             "amor.w %[val], %[tmp], %[mem]  \n"                             \
> > +             : [val] "=&r" (*(__u32 *)__u.__c)                               \
> > +             : [mem] "ZB" (*(u32 *) p), [tmp] "r" (__tmp)                    \
> > +             : "memory");                                                    \
> > +             break;                                                          \
> > +     case 8:                                                                 \
> > +             __asm__ __volatile__(                                           \
> > +             "amor.d %[val], %[tmp], %[mem]  \n"                             \
> > +             : [val] "=&r" (*(__u64 *)__u.__c)                               \
> > +             : [mem] "ZB" (*(u64 *) p), [tmp] "r" (__tmp)                    \
> > +             : "memory");                                                    \
> > +             break;                                                          \
> > +     default:                                                                \
> > +             barrier();                                                      \
> > +             __builtin_memcpy((void *)__u.__c, (const void *)p, sizeof(*p)); \
> > +             __smp_mb();                                                     \
> > +     }                                                                       \
> > +     __u.__val;                                                              \
> > +})
> > +
> > +#define __smp_store_release(p, v)                                            \
> > +do {                                                                         \
> > +     union { typeof(*p) __val; char __c[1]; } __u =                          \
> > +             { .__val = (__force typeof(*p)) (v) };                          \
> > +     unsigned long __tmp;                                                    \
> > +     compiletime_assert_atomic_type(*p);                                     \
> > +     switch (sizeof(*p)) {                                                   \
> > +     case 1:                                                                 \
> > +             __smp_mb();                                                     \
> > +             *(volatile __u8 *)p = *(__u8 *)__u.__c;                         \
> > +             break;                                                          \
> > +     case 2:                                                                 \
> > +             __smp_mb();                                                     \
> > +             *(volatile __u16 *)p = *(__u16 *)__u.__c;                       \
> > +             break;                                                          \
> > +     case 4:                                                                 \
> > +             __asm__ __volatile__(                                           \
> > +             "amswap.w %[tmp], %[val], %[mem]        \n"                     \
> > +             : [mem] "+ZB" (*(u32 *)p), [tmp] "=&r" (__tmp)                  \
> > +             : [val] "r" (*(__u32 *)__u.__c)                                 \
> > +             : );                                                            \
> > +             break;                                                          \
> > +     case 8:                                                                 \
> > +             __asm__ __volatile__(                                           \
> > +             "amswap.d %[tmp], %[val], %[mem]        \n"                     \
> > +             : [mem] "+ZB" (*(u64 *)p), [tmp] "=&r" (__tmp)                  \
> > +             : [val] "r" (*(__u64 *)__u.__c)                                 \
> > +             : );                                                            \
> > +             break;                                                          \
> > +     default:                                                                \
> > +             __smp_mb();                                                     \
> > +             __builtin_memcpy((void *)p, (const void *)__u.__c, sizeof(*p)); \
> > +             barrier();                                                      \
> > +     }                                                                       \
> > +} while (0)
>
> What's the actual ordering of those AMO things?
>



[Index of Archives]     [Linux Kernel]     [Kernel Newbies]     [x86 Platform Driver]     [Netdev]     [Linux Wireless]     [Netfilter]     [Bugtraq]     [Linux Filesystems]     [Yosemite Discussion]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Samba]     [Device Mapper]

  Powered by Linux