Thread (110 messages) 110 messages, 12 authors, 2021-08-27

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

From: Huacai Chen <hidden>
Date: 2021-08-12 11:39:39

Hi, Peter,

On Tue, Jul 6, 2021 at 7:32 PM Peter Zijlstra [off-list ref] wrote:
On Tue, Jul 06, 2021 at 12:18:18PM +0800, Huacai Chen wrote:
quoted
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")
:-(
quoted
+
+#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.
quoted
+
+#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
quoted
+
 /**
  * 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?
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help