From patchwork Thu Aug 25 06:42:50 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Feifei Wang X-Patchwork-Id: 115406 X-Patchwork-Delegate: david.marchand@redhat.com Return-Path: X-Original-To: patchwork@inbox.dpdk.org Delivered-To: patchwork@inbox.dpdk.org Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124]) by inbox.dpdk.org (Postfix) with ESMTP id 0E0F0A00C5; Thu, 25 Aug 2022 08:43:11 +0200 (CEST) Received: from [217.70.189.124] (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 55EF84280C; Thu, 25 Aug 2022 08:43:05 +0200 (CEST) Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by mails.dpdk.org (Postfix) with ESMTP id 68BCD4280B for ; Thu, 25 Aug 2022 08:43:04 +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 54540D6E; Wed, 24 Aug 2022 23:43:08 -0700 (PDT) Received: from net-x86-dell-8268.shanghai.arm.com (net-x86-dell-8268.shanghai.arm.com [10.169.210.137]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPA id 7E5053F71A; Wed, 24 Aug 2022 23:43:30 -0700 (PDT) From: Feifei Wang To: Ruifeng Wang , Jan Viktorin Cc: dev@dpdk.org, nd@arm.com, Feifei Wang Subject: [PATCH v1 2/3] eal: add power mgmt support on Arm Date: Thu, 25 Aug 2022 14:42:50 +0800 Message-Id: <20220825064251.2637274-3-feifei.wang2@arm.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220825064251.2637274-1-feifei.wang2@arm.com> References: <20220825064251.2637274-1-feifei.wang2@arm.com> MIME-Version: 1.0 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 For Arm aarch, use WFE instruction to enable power monitor API, and use SEV instruction to enable wake up API. Signed-off-by: Feifei Wang Reviewed-by: Ruifeng Wang --- lib/eal/arm/include/rte_pause_64.h | 5 ++- lib/eal/arm/rte_cpuflags.c | 5 +++ lib/eal/arm/rte_power_intrinsics.c | 72 ++++++++++++++++++++++++++++-- 3 files changed, 78 insertions(+), 4 deletions(-) diff --git a/lib/eal/arm/include/rte_pause_64.h b/lib/eal/arm/include/rte_pause_64.h index c21600ca96..5f70e97481 100644 --- a/lib/eal/arm/include/rte_pause_64.h +++ b/lib/eal/arm/include/rte_pause_64.h @@ -25,9 +25,12 @@ static inline void rte_pause(void) #ifdef RTE_WAIT_UNTIL_EQUAL_ARCH_DEFINED -/* Send an event to quit WFE. */ +/* Send a local event to quit WFE. */ #define __RTE_ARM_SEVL() { asm volatile("sevl" : : : "memory"); } +/* Send a global event to quit WFE 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"); } diff --git a/lib/eal/arm/rte_cpuflags.c b/lib/eal/arm/rte_cpuflags.c index 93461191c7..90b80709fd 100644 --- a/lib/eal/arm/rte_cpuflags.c +++ b/lib/eal/arm/rte_cpuflags.c @@ -163,4 +163,9 @@ 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 78f55b7203..2a94dd7cd9 100644 --- a/lib/eal/arm/rte_power_intrinsics.c +++ b/lib/eal/arm/rte_power_intrinsics.c @@ -4,17 +4,75 @@ #include "rte_power_intrinsics.h" +#ifdef RTE_ARM_USE_WFE +static inline int +__check_val_size(const uint8_t sz) +{ + switch (sz) { + case sizeof(uint8_t): /* fall-through */ + case sizeof(uint16_t): /* fall-through */ + case sizeof(uint32_t): /* fall-through */ + case sizeof(uint64_t): /* fall-through */ + return 0; + default: + /* unexpected size */ + return -1; + } +} +#endif + /** - * This function is not supported on ARM. + * This function uses WFE 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(pmc); RTE_SET_USED(tsc_timestamp); +#ifdef RTE_ARM_USE_WFE + const unsigned int lcore_id = rte_lcore_id(); + uint64_t cur_value; + + /* prevent non-EAL thread from using this API */ + if (lcore_id >= RTE_MAX_LCORE) + return -EINVAL; + + if (pmc == NULL) + return -EINVAL; + + if (__check_val_size(pmc->size) < 0) + return -EINVAL; + + if (pmc->fn == NULL) + return -EINVAL; + + switch (pmc->size) { + case sizeof(uint8_t): + __RTE_ARM_LOAD_EXC_8(pmc->addr, cur_value, __ATOMIC_RELAXED); + __RTE_ARM_WFE() + break; + case sizeof(uint16_t): + __RTE_ARM_LOAD_EXC_16(pmc->addr, cur_value, __ATOMIC_RELAXED); + __RTE_ARM_WFE() + break; + case sizeof(uint32_t): + __RTE_ARM_LOAD_EXC_32(pmc->addr, cur_value, __ATOMIC_RELAXED); + __RTE_ARM_WFE() + break; + case sizeof(uint64_t): + __RTE_ARM_LOAD_EXC_64(pmc->addr, cur_value, __ATOMIC_RELAXED); + __RTE_ARM_WFE() + } + + return 0; +#else + RTE_SET_USED(pmc); + return -ENOTSUP; +#endif } /** @@ -29,14 +87,22 @@ rte_power_pause(const uint64_t tsc_timestamp) } /** - * This function is not supported on ARM. + * This function uses SEV instruction to wake up all cores + * on ARM. + * Note that lcore_id is not used here. */ int rte_power_monitor_wakeup(const unsigned int lcore_id) { RTE_SET_USED(lcore_id); +#ifdef RTE_ARM_USE_WFE + __RTE_ARM_SEV() + + return 0; +#else return -ENOTSUP; +#endif } int