162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */
262306a36Sopenharmony_ci#ifndef _TOOLS_LINUX_ASM_AARCH64_BARRIER_H
362306a36Sopenharmony_ci#define _TOOLS_LINUX_ASM_AARCH64_BARRIER_H
462306a36Sopenharmony_ci
562306a36Sopenharmony_ci/*
662306a36Sopenharmony_ci * From tools/perf/perf-sys.h, last modified in:
762306a36Sopenharmony_ci * f428ebd184c82a7914b2aa7e9f868918aaf7ea78 perf tools: Fix AAAAARGH64 memory barriers
862306a36Sopenharmony_ci *
962306a36Sopenharmony_ci * XXX: arch/arm64/include/asm/barrier.h in the kernel sources use dsb, is this
1062306a36Sopenharmony_ci * a case like for arm32 where we do things differently in userspace?
1162306a36Sopenharmony_ci */
1262306a36Sopenharmony_ci
1362306a36Sopenharmony_ci#define mb()		asm volatile("dmb ish" ::: "memory")
1462306a36Sopenharmony_ci#define wmb()		asm volatile("dmb ishst" ::: "memory")
1562306a36Sopenharmony_ci#define rmb()		asm volatile("dmb ishld" ::: "memory")
1662306a36Sopenharmony_ci
1762306a36Sopenharmony_ci/*
1862306a36Sopenharmony_ci * Kernel uses dmb variants on arm64 for smp_*() barriers. Pretty much the same
1962306a36Sopenharmony_ci * implementation as above mb()/wmb()/rmb(), though for the latter kernel uses
2062306a36Sopenharmony_ci * dsb. In any case, should above mb()/wmb()/rmb() change, make sure the below
2162306a36Sopenharmony_ci * smp_*() don't.
2262306a36Sopenharmony_ci */
2362306a36Sopenharmony_ci#define smp_mb()	asm volatile("dmb ish" ::: "memory")
2462306a36Sopenharmony_ci#define smp_wmb()	asm volatile("dmb ishst" ::: "memory")
2562306a36Sopenharmony_ci#define smp_rmb()	asm volatile("dmb ishld" ::: "memory")
2662306a36Sopenharmony_ci
2762306a36Sopenharmony_ci#define smp_store_release(p, v)						\
2862306a36Sopenharmony_cido {									\
2962306a36Sopenharmony_ci	union { typeof(*p) __val; char __c[1]; } __u =			\
3062306a36Sopenharmony_ci		{ .__val = (v) }; 					\
3162306a36Sopenharmony_ci									\
3262306a36Sopenharmony_ci	switch (sizeof(*p)) {						\
3362306a36Sopenharmony_ci	case 1:								\
3462306a36Sopenharmony_ci		asm volatile ("stlrb %w1, %0"				\
3562306a36Sopenharmony_ci				: "=Q" (*p)				\
3662306a36Sopenharmony_ci				: "r" (*(__u8_alias_t *)__u.__c)	\
3762306a36Sopenharmony_ci				: "memory");				\
3862306a36Sopenharmony_ci		break;							\
3962306a36Sopenharmony_ci	case 2:								\
4062306a36Sopenharmony_ci		asm volatile ("stlrh %w1, %0"				\
4162306a36Sopenharmony_ci				: "=Q" (*p)				\
4262306a36Sopenharmony_ci				: "r" (*(__u16_alias_t *)__u.__c)	\
4362306a36Sopenharmony_ci				: "memory");				\
4462306a36Sopenharmony_ci		break;							\
4562306a36Sopenharmony_ci	case 4:								\
4662306a36Sopenharmony_ci		asm volatile ("stlr %w1, %0"				\
4762306a36Sopenharmony_ci				: "=Q" (*p)				\
4862306a36Sopenharmony_ci				: "r" (*(__u32_alias_t *)__u.__c)	\
4962306a36Sopenharmony_ci				: "memory");				\
5062306a36Sopenharmony_ci		break;							\
5162306a36Sopenharmony_ci	case 8:								\
5262306a36Sopenharmony_ci		asm volatile ("stlr %1, %0"				\
5362306a36Sopenharmony_ci				: "=Q" (*p)				\
5462306a36Sopenharmony_ci				: "r" (*(__u64_alias_t *)__u.__c)	\
5562306a36Sopenharmony_ci				: "memory");				\
5662306a36Sopenharmony_ci		break;							\
5762306a36Sopenharmony_ci	default:							\
5862306a36Sopenharmony_ci		/* Only to shut up gcc ... */				\
5962306a36Sopenharmony_ci		mb();							\
6062306a36Sopenharmony_ci		break;							\
6162306a36Sopenharmony_ci	}								\
6262306a36Sopenharmony_ci} while (0)
6362306a36Sopenharmony_ci
6462306a36Sopenharmony_ci#define smp_load_acquire(p)						\
6562306a36Sopenharmony_ci({									\
6662306a36Sopenharmony_ci	union { typeof(*p) __val; char __c[1]; } __u =			\
6762306a36Sopenharmony_ci		{ .__c = { 0 } };					\
6862306a36Sopenharmony_ci									\
6962306a36Sopenharmony_ci	switch (sizeof(*p)) {						\
7062306a36Sopenharmony_ci	case 1:								\
7162306a36Sopenharmony_ci		asm volatile ("ldarb %w0, %1"				\
7262306a36Sopenharmony_ci			: "=r" (*(__u8_alias_t *)__u.__c)		\
7362306a36Sopenharmony_ci			: "Q" (*p) : "memory");				\
7462306a36Sopenharmony_ci		break;							\
7562306a36Sopenharmony_ci	case 2:								\
7662306a36Sopenharmony_ci		asm volatile ("ldarh %w0, %1"				\
7762306a36Sopenharmony_ci			: "=r" (*(__u16_alias_t *)__u.__c)		\
7862306a36Sopenharmony_ci			: "Q" (*p) : "memory");				\
7962306a36Sopenharmony_ci		break;							\
8062306a36Sopenharmony_ci	case 4:								\
8162306a36Sopenharmony_ci		asm volatile ("ldar %w0, %1"				\
8262306a36Sopenharmony_ci			: "=r" (*(__u32_alias_t *)__u.__c)		\
8362306a36Sopenharmony_ci			: "Q" (*p) : "memory");				\
8462306a36Sopenharmony_ci		break;							\
8562306a36Sopenharmony_ci	case 8:								\
8662306a36Sopenharmony_ci		asm volatile ("ldar %0, %1"				\
8762306a36Sopenharmony_ci			: "=r" (*(__u64_alias_t *)__u.__c)		\
8862306a36Sopenharmony_ci			: "Q" (*p) : "memory");				\
8962306a36Sopenharmony_ci		break;							\
9062306a36Sopenharmony_ci	default:							\
9162306a36Sopenharmony_ci		/* Only to shut up gcc ... */				\
9262306a36Sopenharmony_ci		mb();							\
9362306a36Sopenharmony_ci		break;							\
9462306a36Sopenharmony_ci	}								\
9562306a36Sopenharmony_ci	__u.__val;							\
9662306a36Sopenharmony_ci})
9762306a36Sopenharmony_ci
9862306a36Sopenharmony_ci#endif /* _TOOLS_LINUX_ASM_AARCH64_BARRIER_H */
99