xref: /dpdk/lib/eal/arm/include/rte_pause_64.h (revision 2f1a90f0455b4920df3a767ab5d9be37dcbf0d12)
199a2dd95SBruce Richardson /* SPDX-License-Identifier: BSD-3-Clause
299a2dd95SBruce Richardson  * Copyright(c) 2017 Cavium, Inc
399a2dd95SBruce Richardson  * Copyright(c) 2019 Arm Limited
499a2dd95SBruce Richardson  */
599a2dd95SBruce Richardson 
699a2dd95SBruce Richardson #ifndef _RTE_PAUSE_ARM64_H_
799a2dd95SBruce Richardson #define _RTE_PAUSE_ARM64_H_
899a2dd95SBruce Richardson 
999a2dd95SBruce Richardson #include <rte_common.h>
10d7fcf40eSDaniel Gregory #include <rte_stdatomic.h>
1199a2dd95SBruce Richardson 
1299a2dd95SBruce Richardson #ifdef RTE_ARM_USE_WFE
1399a2dd95SBruce Richardson #define RTE_WAIT_UNTIL_EQUAL_ARCH_DEFINED
1499a2dd95SBruce Richardson #endif
1599a2dd95SBruce Richardson 
1699a2dd95SBruce Richardson #include "generic/rte_pause.h"
1799a2dd95SBruce Richardson 
18719834a6SMattias Rönnblom #ifdef __cplusplus
19719834a6SMattias Rönnblom extern "C" {
20719834a6SMattias Rönnblom #endif
21719834a6SMattias Rönnblom 
2299a2dd95SBruce Richardson static inline void rte_pause(void)
2399a2dd95SBruce Richardson {
2499a2dd95SBruce Richardson 	asm volatile("yield" ::: "memory");
2599a2dd95SBruce Richardson }
2699a2dd95SBruce Richardson 
27*2f1a90f0SWathsala Vithanage /* Send a local event to quit WFE/WFxT. */
28875f3509SFeifei Wang #define __RTE_ARM_SEVL() { asm volatile("sevl" : : : "memory"); }
2999a2dd95SBruce Richardson 
30*2f1a90f0SWathsala Vithanage /* Send a global event to quit WFE/WFxT for all cores. */
31ac114da6SFeifei Wang #define __RTE_ARM_SEV() { asm volatile("sev" : : : "memory"); }
32ac114da6SFeifei Wang 
3399a2dd95SBruce Richardson /* Put processor into low power WFE(Wait For Event) state. */
34875f3509SFeifei Wang #define __RTE_ARM_WFE() { asm volatile("wfe" : : : "memory"); }
3599a2dd95SBruce Richardson 
36*2f1a90f0SWathsala Vithanage /* Put processor into low power WFET (WFE with Timeout) state. */
37*2f1a90f0SWathsala Vithanage #ifdef RTE_ARM_FEATURE_WFXT
38*2f1a90f0SWathsala Vithanage #define __RTE_ARM_WFET(t) {                               \
39*2f1a90f0SWathsala Vithanage 	asm volatile("wfet %x[to]"                        \
40*2f1a90f0SWathsala Vithanage 			:                                 \
41*2f1a90f0SWathsala Vithanage 			: [to] "r" (t)                    \
42*2f1a90f0SWathsala Vithanage 			: "memory");                      \
43*2f1a90f0SWathsala Vithanage 	}
44*2f1a90f0SWathsala Vithanage #else
45*2f1a90f0SWathsala Vithanage #define __RTE_ARM_WFET(t) { RTE_SET_USED(t); }
46*2f1a90f0SWathsala Vithanage #endif
47*2f1a90f0SWathsala Vithanage 
4899a2dd95SBruce Richardson /*
49ac114da6SFeifei Wang  * Atomic exclusive load from addr, it returns the 8-bit content of
50ac114da6SFeifei Wang  * *addr while making it 'monitored', when it is written by someone
51ac114da6SFeifei Wang  * else, the 'monitored' state is cleared and an event is generated
52ac114da6SFeifei Wang  * implicitly to exit WFE.
53ac114da6SFeifei Wang  */
54ac114da6SFeifei Wang #define __RTE_ARM_LOAD_EXC_8(src, dst, memorder) {       \
551ec6a845STyler Retzlaff 	if (memorder == rte_memory_order_relaxed) {       \
56ac114da6SFeifei Wang 		asm volatile("ldxrb %w[tmp], [%x[addr]]"  \
57ac114da6SFeifei Wang 			: [tmp] "=&r" (dst)               \
58ac114da6SFeifei Wang 			: [addr] "r" (src)                \
59ac114da6SFeifei Wang 			: "memory");                      \
60ac114da6SFeifei Wang 	} else {                                          \
61ac114da6SFeifei Wang 		asm volatile("ldaxrb %w[tmp], [%x[addr]]" \
62ac114da6SFeifei Wang 			: [tmp] "=&r" (dst)               \
63ac114da6SFeifei Wang 			: [addr] "r" (src)                \
64ac114da6SFeifei Wang 			: "memory");                      \
65ac114da6SFeifei Wang 	} }
66ac114da6SFeifei Wang 
67ac114da6SFeifei Wang /*
6899a2dd95SBruce Richardson  * Atomic exclusive load from addr, it returns the 16-bit content of
6999a2dd95SBruce Richardson  * *addr while making it 'monitored', when it is written by someone
70875f3509SFeifei Wang  * else, the 'monitored' state is cleared and an event is generated
7199a2dd95SBruce Richardson  * implicitly to exit WFE.
7299a2dd95SBruce Richardson  */
73875f3509SFeifei Wang #define __RTE_ARM_LOAD_EXC_16(src, dst, memorder) {       \
741ec6a845STyler Retzlaff 	if (memorder == rte_memory_order_relaxed) {       \
7599a2dd95SBruce Richardson 		asm volatile("ldxrh %w[tmp], [%x[addr]]"  \
7699a2dd95SBruce Richardson 			: [tmp] "=&r" (dst)               \
7799a2dd95SBruce Richardson 			: [addr] "r" (src)                \
7899a2dd95SBruce Richardson 			: "memory");                      \
7999a2dd95SBruce Richardson 	} else {                                          \
8099a2dd95SBruce Richardson 		asm volatile("ldaxrh %w[tmp], [%x[addr]]" \
8199a2dd95SBruce Richardson 			: [tmp] "=&r" (dst)               \
8299a2dd95SBruce Richardson 			: [addr] "r" (src)                \
8399a2dd95SBruce Richardson 			: "memory");                      \
8499a2dd95SBruce Richardson 	} }
8599a2dd95SBruce Richardson 
8699a2dd95SBruce Richardson /*
8799a2dd95SBruce Richardson  * Atomic exclusive load from addr, it returns the 32-bit content of
8899a2dd95SBruce Richardson  * *addr while making it 'monitored', when it is written by someone
89875f3509SFeifei Wang  * else, the 'monitored' state is cleared and an event is generated
9099a2dd95SBruce Richardson  * implicitly to exit WFE.
9199a2dd95SBruce Richardson  */
92875f3509SFeifei Wang #define __RTE_ARM_LOAD_EXC_32(src, dst, memorder) {      \
931ec6a845STyler Retzlaff 	if (memorder == rte_memory_order_relaxed) {      \
9499a2dd95SBruce Richardson 		asm volatile("ldxr %w[tmp], [%x[addr]]"  \
9599a2dd95SBruce Richardson 			: [tmp] "=&r" (dst)              \
9699a2dd95SBruce Richardson 			: [addr] "r" (src)               \
9799a2dd95SBruce Richardson 			: "memory");                     \
9899a2dd95SBruce Richardson 	} else {                                         \
9999a2dd95SBruce Richardson 		asm volatile("ldaxr %w[tmp], [%x[addr]]" \
10099a2dd95SBruce Richardson 			: [tmp] "=&r" (dst)              \
10199a2dd95SBruce Richardson 			: [addr] "r" (src)               \
10299a2dd95SBruce Richardson 			: "memory");                     \
10399a2dd95SBruce Richardson 	} }
10499a2dd95SBruce Richardson 
10599a2dd95SBruce Richardson /*
10699a2dd95SBruce Richardson  * Atomic exclusive load from addr, it returns the 64-bit content of
10799a2dd95SBruce Richardson  * *addr while making it 'monitored', when it is written by someone
108875f3509SFeifei Wang  * else, the 'monitored' state is cleared and an event is generated
10999a2dd95SBruce Richardson  * implicitly to exit WFE.
11099a2dd95SBruce Richardson  */
111875f3509SFeifei Wang #define __RTE_ARM_LOAD_EXC_64(src, dst, memorder) {      \
1121ec6a845STyler Retzlaff 	if (memorder == rte_memory_order_relaxed) {      \
11399a2dd95SBruce Richardson 		asm volatile("ldxr %x[tmp], [%x[addr]]"  \
11499a2dd95SBruce Richardson 			: [tmp] "=&r" (dst)              \
11599a2dd95SBruce Richardson 			: [addr] "r" (src)               \
11699a2dd95SBruce Richardson 			: "memory");                     \
11799a2dd95SBruce Richardson 	} else {                                         \
11899a2dd95SBruce Richardson 		asm volatile("ldaxr %x[tmp], [%x[addr]]" \
11999a2dd95SBruce Richardson 			: [tmp] "=&r" (dst)              \
12099a2dd95SBruce Richardson 			: [addr] "r" (src)               \
12199a2dd95SBruce Richardson 			: "memory");                     \
12299a2dd95SBruce Richardson 	} }
12399a2dd95SBruce Richardson 
124875f3509SFeifei Wang /*
125875f3509SFeifei Wang  * Atomic exclusive load from addr, it returns the 128-bit content of
126875f3509SFeifei Wang  * *addr while making it 'monitored', when it is written by someone
127875f3509SFeifei Wang  * else, the 'monitored' state is cleared and an event is generated
128875f3509SFeifei Wang  * implicitly to exit WFE.
129875f3509SFeifei Wang  */
130875f3509SFeifei Wang #define __RTE_ARM_LOAD_EXC_128(src, dst, memorder) {                    \
131875f3509SFeifei Wang 	volatile rte_int128_t *dst_128 = (volatile rte_int128_t *)&dst; \
1321ec6a845STyler Retzlaff 	if (memorder == rte_memory_order_relaxed) {                     \
133875f3509SFeifei Wang 		asm volatile("ldxp %x[tmp0], %x[tmp1], [%x[addr]]"      \
134875f3509SFeifei Wang 			: [tmp0] "=&r" (dst_128->val[0]),               \
135875f3509SFeifei Wang 			  [tmp1] "=&r" (dst_128->val[1])                \
136875f3509SFeifei Wang 			: [addr] "r" (src)                              \
137875f3509SFeifei Wang 			: "memory");                                    \
138875f3509SFeifei Wang 	} else {                                                        \
139875f3509SFeifei Wang 		asm volatile("ldaxp %x[tmp0], %x[tmp1], [%x[addr]]"     \
140875f3509SFeifei Wang 			: [tmp0] "=&r" (dst_128->val[0]),               \
141875f3509SFeifei Wang 			  [tmp1] "=&r" (dst_128->val[1])                \
142875f3509SFeifei Wang 			: [addr] "r" (src)                              \
143875f3509SFeifei Wang 			: "memory");                                    \
144875f3509SFeifei Wang 	} }                                                             \
145875f3509SFeifei Wang 
146875f3509SFeifei Wang #define __RTE_ARM_LOAD_EXC(src, dst, memorder, size) {     \
147ac114da6SFeifei Wang 	RTE_BUILD_BUG_ON(size != 8 && size != 16 &&        \
148ac114da6SFeifei Wang 		size != 32 && size != 64 && size != 128);  \
149ac114da6SFeifei Wang 	if (size == 8)                                    \
150ac114da6SFeifei Wang 		__RTE_ARM_LOAD_EXC_8(src, dst, memorder)   \
151ac114da6SFeifei Wang 	else if (size == 16)                               \
152875f3509SFeifei Wang 		__RTE_ARM_LOAD_EXC_16(src, dst, memorder)  \
153875f3509SFeifei Wang 	else if (size == 32)                               \
154875f3509SFeifei Wang 		__RTE_ARM_LOAD_EXC_32(src, dst, memorder)  \
155875f3509SFeifei Wang 	else if (size == 64)                               \
156875f3509SFeifei Wang 		__RTE_ARM_LOAD_EXC_64(src, dst, memorder)  \
157875f3509SFeifei Wang 	else if (size == 128)                              \
158875f3509SFeifei Wang 		__RTE_ARM_LOAD_EXC_128(src, dst, memorder) \
159875f3509SFeifei Wang }
160875f3509SFeifei Wang 
161990b065fSWathsala Vithanage #ifdef RTE_WAIT_UNTIL_EQUAL_ARCH_DEFINED
162990b065fSWathsala Vithanage 
163875f3509SFeifei Wang static __rte_always_inline void
164875f3509SFeifei Wang rte_wait_until_equal_16(volatile uint16_t *addr, uint16_t expected,
165d7fcf40eSDaniel Gregory 		rte_memory_order memorder)
166875f3509SFeifei Wang {
167875f3509SFeifei Wang 	uint16_t value;
168875f3509SFeifei Wang 
1691ec6a845STyler Retzlaff 	RTE_BUILD_BUG_ON(memorder != rte_memory_order_acquire &&
1701ec6a845STyler Retzlaff 		memorder != rte_memory_order_relaxed);
171875f3509SFeifei Wang 
172875f3509SFeifei Wang 	__RTE_ARM_LOAD_EXC_16(addr, value, memorder)
17399a2dd95SBruce Richardson 	if (value != expected) {
174875f3509SFeifei Wang 		__RTE_ARM_SEVL()
17599a2dd95SBruce Richardson 		do {
176875f3509SFeifei Wang 			__RTE_ARM_WFE()
177875f3509SFeifei Wang 			__RTE_ARM_LOAD_EXC_16(addr, value, memorder)
17899a2dd95SBruce Richardson 		} while (value != expected);
17999a2dd95SBruce Richardson 	}
18099a2dd95SBruce Richardson }
18199a2dd95SBruce Richardson 
182875f3509SFeifei Wang static __rte_always_inline void
183875f3509SFeifei Wang rte_wait_until_equal_32(volatile uint32_t *addr, uint32_t expected,
184d7fcf40eSDaniel Gregory 		rte_memory_order memorder)
185875f3509SFeifei Wang {
186875f3509SFeifei Wang 	uint32_t value;
18799a2dd95SBruce Richardson 
1881ec6a845STyler Retzlaff 	RTE_BUILD_BUG_ON(memorder != rte_memory_order_acquire &&
1891ec6a845STyler Retzlaff 		memorder != rte_memory_order_relaxed);
190875f3509SFeifei Wang 
191875f3509SFeifei Wang 	__RTE_ARM_LOAD_EXC_32(addr, value, memorder)
192875f3509SFeifei Wang 	if (value != expected) {
193875f3509SFeifei Wang 		__RTE_ARM_SEVL()
194875f3509SFeifei Wang 		do {
195875f3509SFeifei Wang 			__RTE_ARM_WFE()
196875f3509SFeifei Wang 			__RTE_ARM_LOAD_EXC_32(addr, value, memorder)
197875f3509SFeifei Wang 		} while (value != expected);
198875f3509SFeifei Wang 	}
199875f3509SFeifei Wang }
200875f3509SFeifei Wang 
201875f3509SFeifei Wang static __rte_always_inline void
202875f3509SFeifei Wang rte_wait_until_equal_64(volatile uint64_t *addr, uint64_t expected,
203d7fcf40eSDaniel Gregory 		rte_memory_order memorder)
204875f3509SFeifei Wang {
205875f3509SFeifei Wang 	uint64_t value;
206875f3509SFeifei Wang 
2071ec6a845STyler Retzlaff 	RTE_BUILD_BUG_ON(memorder != rte_memory_order_acquire &&
2081ec6a845STyler Retzlaff 		memorder != rte_memory_order_relaxed);
209875f3509SFeifei Wang 
210875f3509SFeifei Wang 	__RTE_ARM_LOAD_EXC_64(addr, value, memorder)
211875f3509SFeifei Wang 	if (value != expected) {
212875f3509SFeifei Wang 		__RTE_ARM_SEVL()
213875f3509SFeifei Wang 		do {
214875f3509SFeifei Wang 			__RTE_ARM_WFE()
215875f3509SFeifei Wang 			__RTE_ARM_LOAD_EXC_64(addr, value, memorder)
216875f3509SFeifei Wang 		} while (value != expected);
217875f3509SFeifei Wang 	}
218875f3509SFeifei Wang }
219875f3509SFeifei Wang 
220875f3509SFeifei Wang #define RTE_WAIT_UNTIL_MASKED(addr, mask, cond, expected, memorder) do {  \
221875f3509SFeifei Wang 	RTE_BUILD_BUG_ON(!__builtin_constant_p(memorder));                \
2221ec6a845STyler Retzlaff 	RTE_BUILD_BUG_ON(memorder != rte_memory_order_acquire &&          \
2231ec6a845STyler Retzlaff 		memorder != rte_memory_order_relaxed);                    \
224875f3509SFeifei Wang 	const uint32_t size = sizeof(*(addr)) << 3;                       \
225875f3509SFeifei Wang 	typeof(*(addr)) expected_value = (expected);                      \
226875f3509SFeifei Wang 	typeof(*(addr)) value;                                            \
227875f3509SFeifei Wang 	__RTE_ARM_LOAD_EXC((addr), value, memorder, size)                 \
228875f3509SFeifei Wang 	if (!((value & (mask)) cond expected_value)) {                    \
229875f3509SFeifei Wang 		__RTE_ARM_SEVL()                                          \
230875f3509SFeifei Wang 		do {                                                      \
231875f3509SFeifei Wang 			__RTE_ARM_WFE()                                   \
232875f3509SFeifei Wang 			__RTE_ARM_LOAD_EXC((addr), value, memorder, size) \
233875f3509SFeifei Wang 		} while (!((value & (mask)) cond expected_value));        \
234875f3509SFeifei Wang 	}                                                                 \
235875f3509SFeifei Wang } while (0)
236875f3509SFeifei Wang 
237875f3509SFeifei Wang #endif /* RTE_WAIT_UNTIL_EQUAL_ARCH_DEFINED */
23899a2dd95SBruce Richardson 
23999a2dd95SBruce Richardson #ifdef __cplusplus
24099a2dd95SBruce Richardson }
24199a2dd95SBruce Richardson #endif
24299a2dd95SBruce Richardson 
24399a2dd95SBruce Richardson #endif /* _RTE_PAUSE_ARM64_H_ */
244