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" +#endifIsn'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?