199a2dd95SBruce Richardson /* SPDX-License-Identifier: BSD-3-Clause 299a2dd95SBruce Richardson * Copyright(c) 2021 Intel Corporation 399a2dd95SBruce Richardson */ 499a2dd95SBruce Richardson 572b452c5SDmitry Kozlyuk #include <errno.h> 672b452c5SDmitry Kozlyuk 7*2f1a90f0SWathsala Vithanage #include "rte_cpuflags.h" 899a2dd95SBruce Richardson #include "rte_power_intrinsics.h" 999a2dd95SBruce Richardson 1099a2dd95SBruce Richardson /** 11*2f1a90f0SWathsala Vithanage * Set wfet_en if WFET is supported 12*2f1a90f0SWathsala Vithanage */ 13*2f1a90f0SWathsala Vithanage #ifdef RTE_ARCH_64 14*2f1a90f0SWathsala Vithanage static uint8_t wfet_en; 15*2f1a90f0SWathsala Vithanage #endif /* RTE_ARCH_64 */ 16*2f1a90f0SWathsala Vithanage 17*2f1a90f0SWathsala Vithanage RTE_INIT(rte_power_intrinsics_init) 18*2f1a90f0SWathsala Vithanage { 19*2f1a90f0SWathsala Vithanage #ifdef RTE_ARCH_64 20*2f1a90f0SWathsala Vithanage if (rte_cpu_get_flag_enabled(RTE_CPUFLAG_WFXT)) 21*2f1a90f0SWathsala Vithanage wfet_en = 1; 22*2f1a90f0SWathsala Vithanage #endif /* RTE_ARCH_64 */ 23*2f1a90f0SWathsala Vithanage } 24*2f1a90f0SWathsala Vithanage 25*2f1a90f0SWathsala Vithanage /** 26*2f1a90f0SWathsala Vithanage * This function uses WFE/WFET instruction to make lcore suspend 27ac114da6SFeifei Wang * execution on ARM. 2899a2dd95SBruce Richardson */ 2999a2dd95SBruce Richardson int 3099a2dd95SBruce Richardson rte_power_monitor(const struct rte_power_monitor_cond *pmc, 3199a2dd95SBruce Richardson const uint64_t tsc_timestamp) 3299a2dd95SBruce Richardson { 33990b065fSWathsala Vithanage #ifdef RTE_ARCH_64 34ac114da6SFeifei Wang const unsigned int lcore_id = rte_lcore_id(); 35ac114da6SFeifei Wang uint64_t cur_value; 36ac114da6SFeifei Wang 37ac114da6SFeifei Wang /* prevent non-EAL thread from using this API */ 38ac114da6SFeifei Wang if (lcore_id >= RTE_MAX_LCORE) 39ac114da6SFeifei Wang return -EINVAL; 40ac114da6SFeifei Wang 41ac114da6SFeifei Wang if (pmc == NULL) 42ac114da6SFeifei Wang return -EINVAL; 43ac114da6SFeifei Wang 44ac114da6SFeifei Wang if (pmc->fn == NULL) 45ac114da6SFeifei Wang return -EINVAL; 46ac114da6SFeifei Wang 47ac114da6SFeifei Wang switch (pmc->size) { 48ac114da6SFeifei Wang case sizeof(uint8_t): 49*2f1a90f0SWathsala Vithanage __RTE_ARM_LOAD_EXC_8(pmc->addr, cur_value, rte_memory_order_relaxed); 50ac114da6SFeifei Wang break; 51ac114da6SFeifei Wang case sizeof(uint16_t): 52*2f1a90f0SWathsala Vithanage __RTE_ARM_LOAD_EXC_16(pmc->addr, cur_value, rte_memory_order_relaxed); 53ac114da6SFeifei Wang break; 54ac114da6SFeifei Wang case sizeof(uint32_t): 55*2f1a90f0SWathsala Vithanage __RTE_ARM_LOAD_EXC_32(pmc->addr, cur_value, rte_memory_order_relaxed); 56ac114da6SFeifei Wang break; 57ac114da6SFeifei Wang case sizeof(uint64_t): 58*2f1a90f0SWathsala Vithanage __RTE_ARM_LOAD_EXC_64(pmc->addr, cur_value, rte_memory_order_relaxed); 59ac114da6SFeifei Wang break; 60ac114da6SFeifei Wang default: 61ac114da6SFeifei Wang return -EINVAL; /* unexpected size */ 62ac114da6SFeifei Wang } 63ac114da6SFeifei Wang 64*2f1a90f0SWathsala Vithanage if (wfet_en) 65*2f1a90f0SWathsala Vithanage __RTE_ARM_WFET(tsc_timestamp) 66*2f1a90f0SWathsala Vithanage else 67*2f1a90f0SWathsala Vithanage __RTE_ARM_WFE() 68*2f1a90f0SWathsala Vithanage 69ac114da6SFeifei Wang return 0; 70ac114da6SFeifei Wang #else 71ac114da6SFeifei Wang RTE_SET_USED(pmc); 72*2f1a90f0SWathsala Vithanage RTE_SET_USED(tsc_timestamp); 73ac114da6SFeifei Wang 7499a2dd95SBruce Richardson return -ENOTSUP; 75990b065fSWathsala Vithanage #endif /* RTE_ARCH_64 */ 7699a2dd95SBruce Richardson } 7799a2dd95SBruce Richardson 7899a2dd95SBruce Richardson /** 7999a2dd95SBruce Richardson * This function is not supported on ARM. 8099a2dd95SBruce Richardson */ 8199a2dd95SBruce Richardson int 8299a2dd95SBruce Richardson rte_power_pause(const uint64_t tsc_timestamp) 8399a2dd95SBruce Richardson { 8499a2dd95SBruce Richardson RTE_SET_USED(tsc_timestamp); 8599a2dd95SBruce Richardson 8699a2dd95SBruce Richardson return -ENOTSUP; 8799a2dd95SBruce Richardson } 8899a2dd95SBruce Richardson 8999a2dd95SBruce Richardson /** 90ac114da6SFeifei Wang * This function uses SEV instruction to wake up all cores 91ac114da6SFeifei Wang * on ARM. 92ac114da6SFeifei Wang * Note that lcore_id is not used here. 9399a2dd95SBruce Richardson */ 9499a2dd95SBruce Richardson int 9599a2dd95SBruce Richardson rte_power_monitor_wakeup(const unsigned int lcore_id) 9699a2dd95SBruce Richardson { 9799a2dd95SBruce Richardson RTE_SET_USED(lcore_id); 9899a2dd95SBruce Richardson 99990b065fSWathsala Vithanage #ifdef RTE_ARCH_64 100ac114da6SFeifei Wang __RTE_ARM_SEV() 101ac114da6SFeifei Wang return 0; 102ac114da6SFeifei Wang #else 10399a2dd95SBruce Richardson return -ENOTSUP; 104990b065fSWathsala Vithanage #endif /* RTE_ARCH_64 */ 10599a2dd95SBruce Richardson } 10666834f29SAnatoly Burakov 10766834f29SAnatoly Burakov int 10866834f29SAnatoly Burakov rte_power_monitor_multi(const struct rte_power_monitor_cond pmc[], 10966834f29SAnatoly Burakov const uint32_t num, const uint64_t tsc_timestamp) 11066834f29SAnatoly Burakov { 11166834f29SAnatoly Burakov RTE_SET_USED(pmc); 11266834f29SAnatoly Burakov RTE_SET_USED(num); 11366834f29SAnatoly Burakov RTE_SET_USED(tsc_timestamp); 11466834f29SAnatoly Burakov 11566834f29SAnatoly Burakov return -ENOTSUP; 11666834f29SAnatoly Burakov } 117