1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright(c) 2021 Intel Corporation 3 */ 4 5 #include <errno.h> 6 7 #include "rte_cpuflags.h" 8 #include "rte_power_intrinsics.h" 9 10 /** 11 * Set wfet_en if WFET is supported 12 */ 13 #ifdef RTE_ARCH_64 14 static uint8_t wfet_en; 15 #endif /* RTE_ARCH_64 */ 16 17 RTE_INIT(rte_power_intrinsics_init) 18 { 19 #ifdef RTE_ARCH_64 20 if (rte_cpu_get_flag_enabled(RTE_CPUFLAG_WFXT)) 21 wfet_en = 1; 22 #endif /* RTE_ARCH_64 */ 23 } 24 25 /** 26 * This function uses WFE/WFET instruction to make lcore suspend 27 * execution on ARM. 28 */ 29 int 30 rte_power_monitor(const struct rte_power_monitor_cond *pmc, 31 const uint64_t tsc_timestamp) 32 { 33 #ifdef RTE_ARCH_64 34 const unsigned int lcore_id = rte_lcore_id(); 35 uint64_t cur_value; 36 37 /* prevent non-EAL thread from using this API */ 38 if (lcore_id >= RTE_MAX_LCORE) 39 return -EINVAL; 40 41 if (pmc == NULL) 42 return -EINVAL; 43 44 if (pmc->fn == NULL) 45 return -EINVAL; 46 47 switch (pmc->size) { 48 case sizeof(uint8_t): 49 __RTE_ARM_LOAD_EXC_8(pmc->addr, cur_value, rte_memory_order_relaxed); 50 break; 51 case sizeof(uint16_t): 52 __RTE_ARM_LOAD_EXC_16(pmc->addr, cur_value, rte_memory_order_relaxed); 53 break; 54 case sizeof(uint32_t): 55 __RTE_ARM_LOAD_EXC_32(pmc->addr, cur_value, rte_memory_order_relaxed); 56 break; 57 case sizeof(uint64_t): 58 __RTE_ARM_LOAD_EXC_64(pmc->addr, cur_value, rte_memory_order_relaxed); 59 break; 60 default: 61 return -EINVAL; /* unexpected size */ 62 } 63 64 if (wfet_en) 65 __RTE_ARM_WFET(tsc_timestamp) 66 else 67 __RTE_ARM_WFE() 68 69 return 0; 70 #else 71 RTE_SET_USED(pmc); 72 RTE_SET_USED(tsc_timestamp); 73 74 return -ENOTSUP; 75 #endif /* RTE_ARCH_64 */ 76 } 77 78 /** 79 * This function is not supported on ARM. 80 */ 81 int 82 rte_power_pause(const uint64_t tsc_timestamp) 83 { 84 RTE_SET_USED(tsc_timestamp); 85 86 return -ENOTSUP; 87 } 88 89 /** 90 * This function uses SEV instruction to wake up all cores 91 * on ARM. 92 * Note that lcore_id is not used here. 93 */ 94 int 95 rte_power_monitor_wakeup(const unsigned int lcore_id) 96 { 97 RTE_SET_USED(lcore_id); 98 99 #ifdef RTE_ARCH_64 100 __RTE_ARM_SEV() 101 return 0; 102 #else 103 return -ENOTSUP; 104 #endif /* RTE_ARCH_64 */ 105 } 106 107 int 108 rte_power_monitor_multi(const struct rte_power_monitor_cond pmc[], 109 const uint32_t num, const uint64_t tsc_timestamp) 110 { 111 RTE_SET_USED(pmc); 112 RTE_SET_USED(num); 113 RTE_SET_USED(tsc_timestamp); 114 115 return -ENOTSUP; 116 } 117