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