From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124]) by inbox.dpdk.org (Postfix) with ESMTP id 2557744147; Tue, 4 Jun 2024 06:46:51 +0200 (CEST) Received: from mails.dpdk.org (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 22E2E4340D; Tue, 4 Jun 2024 06:46:50 +0200 (CEST) Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by mails.dpdk.org (Postfix) with ESMTP id A146843408 for ; Tue, 4 Jun 2024 06:46:48 +0200 (CEST) Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 75CEC1042; Mon, 3 Jun 2024 21:47:12 -0700 (PDT) Received: from ampere-altra-2-1.usa.Arm.com (ampere-altra-2-1.usa.arm.com [10.118.91.158]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPA id C33663F792; Mon, 3 Jun 2024 21:46:47 -0700 (PDT) From: Wathsala Vithanage To: Thomas Monjalon , Tyler Retzlaff , Ruifeng Wang Cc: dev@dpdk.org, nd@arm.com, Wathsala Vithanage , Dhruv Tripathi , Honnappa Nagarahalli , Jack Bond-Preston , Nick Connolly , Vinod Krishna Subject: [PATCH 2/2] eal: add Arm WFET in power management intrinsics Date: Tue, 4 Jun 2024 04:44:01 +0000 Message-Id: <20240604044401.3577707-2-wathsala.vithanage@arm.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240604044401.3577707-1-wathsala.vithanage@arm.com> References: <20240604044401.3577707-1-wathsala.vithanage@arm.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org 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. RTE_ARM_USE_WFE macro is not required to enable WFE feature for PMD power monitoring. Signed-off-by: Wathsala Vithanage Reviewed-by: Dhruv Tripathi Reviewed-by: Honnappa Nagarahalli Reviewed-by: Jack Bond-Preston Reviewed-by: Nick Connolly Reviewed-by: Vinod Krishna --- .mailmap | 4 +- app/test/test_cpuflags.c | 3 ++ lib/eal/arm/include/rte_cpuflags_64.h | 1 + lib/eal/arm/include/rte_pause_64.h | 21 ++++++-- lib/eal/arm/include/rte_power_intrinsics.h | 6 +++ lib/eal/arm/rte_cpuflags.c | 3 +- lib/eal/arm/rte_power_intrinsics.c | 56 ++++++++++++---------- 7 files changed, 62 insertions(+), 32 deletions(-) diff --git a/.mailmap b/.mailmap index 3843868716..eefcce4935 100644 --- a/.mailmap +++ b/.mailmap @@ -332,6 +332,7 @@ Dexia Li Dexuan Cui Dharmik Thakkar Dheemanth Mallikarjun +Dhruv Tripathi Diana Wang Didier Pallard Dilshod Urazov @@ -1027,7 +1028,7 @@ Netanel Belgazal Netanel Gonen Niall Power Nicholas Pratte -Nick Connolly +Nick Connolly Nick Nunley Niclas Storm Nicolas Chautru @@ -1516,6 +1517,7 @@ Vincent Jardin Vincent Li Vincent S. Cojot Vinh Tran +Vinod Krishna Vipin Varghese Vipul Ashri Visa Hankala diff --git a/app/test/test_cpuflags.c b/app/test/test_cpuflags.c index a0ff74720c..22ab4dff0a 100644 --- a/app/test/test_cpuflags.c +++ b/app/test/test_cpuflags.c @@ -156,6 +156,9 @@ test_cpuflags(void) printf("Check for SVEBF16:\t"); CHECK_FOR_FLAG(RTE_CPUFLAG_SVEBF16); + + printf("Check for WFXT:\t"); + CHECK_FOR_FLAG(RTE_CPUFLAG_WFXT); #endif #if defined(RTE_ARCH_X86_64) || defined(RTE_ARCH_I686) diff --git a/lib/eal/arm/include/rte_cpuflags_64.h b/lib/eal/arm/include/rte_cpuflags_64.h index afe70209c3..db61539db2 100644 --- a/lib/eal/arm/include/rte_cpuflags_64.h +++ b/lib/eal/arm/include/rte_cpuflags_64.h @@ -35,6 +35,7 @@ enum rte_cpu_flag_t { RTE_CPUFLAG_SVEF32MM, RTE_CPUFLAG_SVEF64MM, RTE_CPUFLAG_SVEBF16, + RTE_CPUFLAG_WFXT, RTE_CPUFLAG_AARCH64, }; diff --git a/lib/eal/arm/include/rte_pause_64.h b/lib/eal/arm/include/rte_pause_64.h index 5cb8b59056..f732407425 100644 --- a/lib/eal/arm/include/rte_pause_64.h +++ b/lib/eal/arm/include/rte_pause_64.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: BSD-3-Clause * Copyright(c) 2017 Cavium, Inc - * Copyright(c) 2019 Arm Limited + * Copyright(c) 2024 Arm Limited */ #ifndef _RTE_PAUSE_ARM64_H_ @@ -23,17 +23,28 @@ static inline void rte_pause(void) asm volatile("yield" ::: "memory"); } -#ifdef RTE_WAIT_UNTIL_EQUAL_ARCH_DEFINED -/* Send a local event to quit WFE. */ +/* Send a local event to quit WFE/WFxT. */ #define __RTE_ARM_SEVL() { asm volatile("sevl" : : : "memory"); } -/* Send a global event to quit WFE for all cores. */ +/* Send a global event to quit WFE/WFxT for all cores. */ #define __RTE_ARM_SEV() { asm volatile("sev" : : : "memory"); } /* Put processor into low power WFE(Wait For Event) state. */ #define __RTE_ARM_WFE() { asm volatile("wfe" : : : "memory"); } +/* Put processor into low power WFET (WFE with Timeout) state. */ +#ifdef RTE_ARM_FEATURE_WFXT +#define __RTE_ARM_WFET(t) { \ + asm volatile("wfet %x[to]" \ + : \ + : [to] "r" (t) \ + : "memory"); \ + } +#else +#define __RTE_ARM_WFET(t) { RTE_SET_USED(t); } +#endif + /* * Atomic exclusive load from addr, it returns the 8-bit content of * *addr while making it 'monitored', when it is written by someone @@ -147,6 +158,8 @@ static inline void rte_pause(void) __RTE_ARM_LOAD_EXC_128(src, dst, memorder) \ } +#ifdef RTE_WAIT_UNTIL_EQUAL_ARCH_DEFINED + static __rte_always_inline void rte_wait_until_equal_16(volatile uint16_t *addr, uint16_t expected, int memorder) diff --git a/lib/eal/arm/include/rte_power_intrinsics.h b/lib/eal/arm/include/rte_power_intrinsics.h index 9e498e9ebf..dc80fca60b 100644 --- a/lib/eal/arm/include/rte_power_intrinsics.h +++ b/lib/eal/arm/include/rte_power_intrinsics.h @@ -13,6 +13,12 @@ extern "C" { #include "generic/rte_power_intrinsics.h" +struct rte_power_monitor_info { + uint16_t init_done:1, /* Initialization status bit */ + wfet_en:1, /* FEAT_WFET enabled bit */ + reserved:14; /* Reserved */ +}; + #ifdef __cplusplus } #endif diff --git a/lib/eal/arm/rte_cpuflags.c b/lib/eal/arm/rte_cpuflags.c index 7ba4f8ba97..ad76f2448b 100644 --- a/lib/eal/arm/rte_cpuflags.c +++ b/lib/eal/arm/rte_cpuflags.c @@ -115,6 +115,7 @@ const struct feature_entry rte_cpu_feature_table[] = { FEAT_DEF(SVEF32MM, REG_HWCAP2, 10) FEAT_DEF(SVEF64MM, REG_HWCAP2, 11) FEAT_DEF(SVEBF16, REG_HWCAP2, 12) + FEAT_DEF(WFXT, REG_HWCAP2, 31) FEAT_DEF(AARCH64, REG_PLATFORM, 0) }; #endif /* RTE_ARCH */ @@ -163,7 +164,5 @@ void rte_cpu_get_intrinsics_support(struct rte_cpu_intrinsics *intrinsics) { memset(intrinsics, 0, sizeof(*intrinsics)); -#ifdef RTE_ARM_USE_WFE intrinsics->power_monitor = 1; -#endif } diff --git a/lib/eal/arm/rte_power_intrinsics.c b/lib/eal/arm/rte_power_intrinsics.c index f54cf59e80..4c858192f2 100644 --- a/lib/eal/arm/rte_power_intrinsics.c +++ b/lib/eal/arm/rte_power_intrinsics.c @@ -4,20 +4,28 @@ #include +#include + +#include "rte_cpuflags.h" #include "rte_power_intrinsics.h" /** - * This function uses WFE instruction to make lcore suspend + * Per core rte_power_monitor_info struct. + */ +RTE_DEFINE_PER_LCORE(struct rte_power_monitor_info, pm_info) = { + .init_done = 0, + .wfet_en = 0, +}; + +/** + * This function uses WFE/WFET instruction to make lcore suspend * execution on ARM. - * Note that timestamp based timeout is not supported yet. */ int rte_power_monitor(const struct rte_power_monitor_cond *pmc, const uint64_t tsc_timestamp) { - RTE_SET_USED(tsc_timestamp); - -#ifdef RTE_ARM_USE_WFE + struct rte_power_monitor_info *pminfo; const unsigned int lcore_id = rte_lcore_id(); uint64_t cur_value; @@ -31,33 +39,37 @@ rte_power_monitor(const struct rte_power_monitor_cond *pmc, if (pmc->fn == NULL) return -EINVAL; + pminfo = &RTE_PER_LCORE(pm_info); + + if (unlikely(!(pminfo->init_done))) { + if (rte_cpu_get_flag_enabled(RTE_CPUFLAG_WFXT)) + pminfo->wfet_en = 1; + pminfo->init_done = 1; + } + switch (pmc->size) { case sizeof(uint8_t): - __RTE_ARM_LOAD_EXC_8(pmc->addr, cur_value, rte_memory_order_relaxed) - __RTE_ARM_WFE() + __RTE_ARM_LOAD_EXC_8(pmc->addr, cur_value, rte_memory_order_relaxed); break; case sizeof(uint16_t): - __RTE_ARM_LOAD_EXC_16(pmc->addr, cur_value, rte_memory_order_relaxed) - __RTE_ARM_WFE() + __RTE_ARM_LOAD_EXC_16(pmc->addr, cur_value, rte_memory_order_relaxed); break; case sizeof(uint32_t): - __RTE_ARM_LOAD_EXC_32(pmc->addr, cur_value, rte_memory_order_relaxed) - __RTE_ARM_WFE() + __RTE_ARM_LOAD_EXC_32(pmc->addr, cur_value, rte_memory_order_relaxed); break; case sizeof(uint64_t): - __RTE_ARM_LOAD_EXC_64(pmc->addr, cur_value, rte_memory_order_relaxed) - __RTE_ARM_WFE() + __RTE_ARM_LOAD_EXC_64(pmc->addr, cur_value, rte_memory_order_relaxed); break; default: return -EINVAL; /* unexpected size */ } - return 0; -#else - RTE_SET_USED(pmc); + if (pminfo->wfet_en) + __RTE_ARM_WFET(tsc_timestamp) + else + __RTE_ARM_WFE() - return -ENOTSUP; -#endif + return 0; } /** @@ -80,14 +92,8 @@ int rte_power_monitor_wakeup(const unsigned int lcore_id) { RTE_SET_USED(lcore_id); - -#ifdef RTE_ARM_USE_WFE - __RTE_ARM_SEV() - + __RTE_ARM_SEV(); return 0; -#else - return -ENOTSUP; -#endif } int -- 2.34.1