xref: /dpdk/lib/eal/arm/rte_power_intrinsics.c (revision 2f1a90f0455b4920df3a767ab5d9be37dcbf0d12)
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