Skip to content

Commit 2f1a90f

Browse files
wathsalavtmonjalo
authored andcommitted
eal/arm: add WFET in power management intrinsics
Wait for event with timeout (WFET) puts the CPU in a low power mode and stays there until an event is signalled (SEV), loss of an exclusive monitor or a timeout. WFET is enabled selectively by checking FEAT_WFxT in Linux auxiliary vector. If FEAT_WFxT is not available power management will fallback to WFE. WFE is available on all the Arm platforms supported by DPDK. Therefore, the RTE_ARM_USE_WFE macro is not required to enable the WFE feature for PMD power monitoring.  RTE_ARM_USE_WFE is used at the build time to use the WFE instruction where applicable in the code at the developer's discretion rather than as an indicator of the instruction's availability. Signed-off-by: Wathsala Vithanage <[email protected]> Reviewed-by: Dhruv Tripathi <[email protected]> Reviewed-by: Honnappa Nagarahalli <[email protected]> Reviewed-by: Jack Bond-Preston <[email protected]> Reviewed-by: Nick Connolly <[email protected]> Reviewed-by: Vinod Krishna <[email protected]>
1 parent cdbcdc5 commit 2f1a90f

File tree

6 files changed

+49
-14
lines changed

6 files changed

+49
-14
lines changed

.mailmap

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1567,6 +1567,7 @@ Vincent Li <[email protected]>
15671567
Vincent S. Cojot <[email protected]>
15681568
Vinh Tran <[email protected]>
15691569
Vipin Padmam Ramesh <[email protected]>
1570+
Vinod Krishna <[email protected]>
15701571
15711572
Vipul Ashri <[email protected]>
15721573
Visa Hankala <[email protected]>

app/test/test_cpuflags.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,9 @@ test_cpuflags(void)
156156

157157
printf("Check for SVEBF16:\t");
158158
CHECK_FOR_FLAG(RTE_CPUFLAG_SVEBF16);
159+
160+
printf("Check for WFXT:\t");
161+
CHECK_FOR_FLAG(RTE_CPUFLAG_WFXT);
159162
#endif
160163

161164
#if defined(RTE_ARCH_X86_64) || defined(RTE_ARCH_I686)

lib/eal/arm/include/rte_cpuflags_64.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,9 @@ enum rte_cpu_flag_t {
3232
RTE_CPUFLAG_SVEF64MM,
3333
RTE_CPUFLAG_SVEBF16,
3434
RTE_CPUFLAG_AARCH64,
35+
36+
/* WFET and WFIT instructions */
37+
RTE_CPUFLAG_WFXT,
3538
};
3639

3740
#include "generic/rte_cpuflags.h"

lib/eal/arm/include/rte_pause_64.h

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,15 +24,27 @@ static inline void rte_pause(void)
2424
asm volatile("yield" ::: "memory");
2525
}
2626

27-
/* Send a local event to quit WFE. */
27+
/* Send a local event to quit WFE/WFxT. */
2828
#define __RTE_ARM_SEVL() { asm volatile("sevl" : : : "memory"); }
2929

30-
/* Send a global event to quit WFE for all cores. */
30+
/* Send a global event to quit WFE/WFxT for all cores. */
3131
#define __RTE_ARM_SEV() { asm volatile("sev" : : : "memory"); }
3232

3333
/* Put processor into low power WFE(Wait For Event) state. */
3434
#define __RTE_ARM_WFE() { asm volatile("wfe" : : : "memory"); }
3535

36+
/* Put processor into low power WFET (WFE with Timeout) state. */
37+
#ifdef RTE_ARM_FEATURE_WFXT
38+
#define __RTE_ARM_WFET(t) { \
39+
asm volatile("wfet %x[to]" \
40+
: \
41+
: [to] "r" (t) \
42+
: "memory"); \
43+
}
44+
#else
45+
#define __RTE_ARM_WFET(t) { RTE_SET_USED(t); }
46+
#endif
47+
3648
/*
3749
* Atomic exclusive load from addr, it returns the 8-bit content of
3850
* *addr while making it 'monitored', when it is written by someone

lib/eal/arm/rte_cpuflags.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,7 @@ const struct feature_entry rte_cpu_feature_table[] = {
115115
FEAT_DEF(SVEF32MM, REG_HWCAP2, 10)
116116
FEAT_DEF(SVEF64MM, REG_HWCAP2, 11)
117117
FEAT_DEF(SVEBF16, REG_HWCAP2, 12)
118+
FEAT_DEF(WFXT, REG_HWCAP2, 31)
118119
FEAT_DEF(AARCH64, REG_PLATFORM, 0)
119120
};
120121
#endif /* RTE_ARCH */

lib/eal/arm/rte_power_intrinsics.c

Lines changed: 27 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,19 +4,32 @@
44

55
#include <errno.h>
66

7+
#include "rte_cpuflags.h"
78
#include "rte_power_intrinsics.h"
89

910
/**
10-
* This function uses WFE instruction to make lcore suspend
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
1127
* execution on ARM.
12-
* Note that timestamp based timeout is not supported yet.
1328
*/
1429
int
1530
rte_power_monitor(const struct rte_power_monitor_cond *pmc,
1631
const uint64_t tsc_timestamp)
1732
{
18-
RTE_SET_USED(tsc_timestamp);
19-
2033
#ifdef RTE_ARCH_64
2134
const unsigned int lcore_id = rte_lcore_id();
2235
uint64_t cur_value;
@@ -33,28 +46,30 @@ rte_power_monitor(const struct rte_power_monitor_cond *pmc,
3346

3447
switch (pmc->size) {
3548
case sizeof(uint8_t):
36-
__RTE_ARM_LOAD_EXC_8(pmc->addr, cur_value, rte_memory_order_relaxed)
37-
__RTE_ARM_WFE()
49+
__RTE_ARM_LOAD_EXC_8(pmc->addr, cur_value, rte_memory_order_relaxed);
3850
break;
3951
case sizeof(uint16_t):
40-
__RTE_ARM_LOAD_EXC_16(pmc->addr, cur_value, rte_memory_order_relaxed)
41-
__RTE_ARM_WFE()
52+
__RTE_ARM_LOAD_EXC_16(pmc->addr, cur_value, rte_memory_order_relaxed);
4253
break;
4354
case sizeof(uint32_t):
44-
__RTE_ARM_LOAD_EXC_32(pmc->addr, cur_value, rte_memory_order_relaxed)
45-
__RTE_ARM_WFE()
55+
__RTE_ARM_LOAD_EXC_32(pmc->addr, cur_value, rte_memory_order_relaxed);
4656
break;
4757
case sizeof(uint64_t):
48-
__RTE_ARM_LOAD_EXC_64(pmc->addr, cur_value, rte_memory_order_relaxed)
49-
__RTE_ARM_WFE()
58+
__RTE_ARM_LOAD_EXC_64(pmc->addr, cur_value, rte_memory_order_relaxed);
5059
break;
5160
default:
5261
return -EINVAL; /* unexpected size */
5362
}
5463

64+
if (wfet_en)
65+
__RTE_ARM_WFET(tsc_timestamp)
66+
else
67+
__RTE_ARM_WFE()
68+
5569
return 0;
5670
#else
5771
RTE_SET_USED(pmc);
72+
RTE_SET_USED(tsc_timestamp);
5873

5974
return -ENOTSUP;
6075
#endif /* RTE_ARCH_64 */

0 commit comments

Comments
 (0)