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 42150A09FF; Mon, 11 Jan 2021 15:36:19 +0100 (CET) Received: from [217.70.189.124] (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 612D9140DE8; Mon, 11 Jan 2021 15:36:06 +0100 (CET) Received: from mga11.intel.com (mga11.intel.com [192.55.52.93]) by mails.dpdk.org (Postfix) with ESMTP id 26FFD140DB4 for ; Mon, 11 Jan 2021 15:36:05 +0100 (CET) IronPort-SDR: rnHUl4SIn9YPeOP2CAuqGEKWldQqgh07b8zpGqgDHUPG6EUAPdTmvsqYtEufA5Krq4thaOrmvk i3I/gbIHnJIg== X-IronPort-AV: E=McAfee;i="6000,8403,9860"; a="174360884" X-IronPort-AV: E=Sophos;i="5.79,338,1602572400"; d="scan'208";a="174360884" Received: from fmsmga005.fm.intel.com ([10.253.24.32]) by fmsmga102.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 11 Jan 2021 06:36:04 -0800 IronPort-SDR: uy8B7W6USRcJajGbeCUfflDqlUJkxsqAOLuuW5sOQaNeGS1OBVkf6FeVjPs7OMx0EbTeQ70ug2 8eseuLUNSOHA== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.79,338,1602572400"; d="scan'208";a="571410597" Received: from silpixa00399498.ir.intel.com (HELO silpixa00399498.ger.corp.intel.com) ([10.237.222.179]) by fmsmga005.fm.intel.com with ESMTP; 11 Jan 2021 06:36:02 -0800 From: Anatoly Burakov To: dev@dpdk.org Cc: Bruce Richardson , Konstantin Ananyev , thomas@monjalon.net, timothy.mcdaniel@intel.com, david.hunt@intel.com, chris.macnamara@intel.com Date: Mon, 11 Jan 2021 14:35:47 +0000 Message-Id: X-Mailer: git-send-email 2.25.1 In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Subject: [dpdk-dev] [PATCH v14 02/11] eal: avoid invalid API usage in power intrinsics 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 Sender: "dev" Currently, the API documentation mandates that if the user wants to use the power management intrinsics, they need to call the `rte_cpu_get_intrinsics_support` API and check support for specific intrinsics. However, if the user does not do that, it is possible to get illegal instruction error because we're using raw instruction opcodes, which may or may not be supported at runtime. Now that we have everything in a C file, we can check for support at startup and prevent the user from possibly encountering illegal instruction errors. Signed-off-by: Anatoly Burakov --- Notes: v14: - Replace uint8_t with bool .../include/generic/rte_power_intrinsics.h | 3 -- lib/librte_eal/x86/rte_power_intrinsics.c | 31 +++++++++++++++++-- 2 files changed, 28 insertions(+), 6 deletions(-) diff --git a/lib/librte_eal/include/generic/rte_power_intrinsics.h b/lib/librte_eal/include/generic/rte_power_intrinsics.h index 67977bd511..ffa72f7578 100644 --- a/lib/librte_eal/include/generic/rte_power_intrinsics.h +++ b/lib/librte_eal/include/generic/rte_power_intrinsics.h @@ -34,7 +34,6 @@ * * @warning It is responsibility of the user to check if this function is * supported at runtime using `rte_cpu_get_intrinsics_support()` API call. - * Failing to do so may result in an illegal CPU instruction error. * * @param p * Address to monitor for changes. @@ -75,7 +74,6 @@ void rte_power_monitor(const volatile void *p, * * @warning It is responsibility of the user to check if this function is * supported at runtime using `rte_cpu_get_intrinsics_support()` API call. - * Failing to do so may result in an illegal CPU instruction error. * * @param p * Address to monitor for changes. @@ -111,7 +109,6 @@ void rte_power_monitor_sync(const volatile void *p, * * @warning It is responsibility of the user to check if this function is * supported at runtime using `rte_cpu_get_intrinsics_support()` API call. - * Failing to do so may result in an illegal CPU instruction error. * * @param tsc_timestamp * Maximum TSC timestamp to wait for. Note that the wait behavior is diff --git a/lib/librte_eal/x86/rte_power_intrinsics.c b/lib/librte_eal/x86/rte_power_intrinsics.c index 34c5fd9c3e..050ae612a8 100644 --- a/lib/librte_eal/x86/rte_power_intrinsics.c +++ b/lib/librte_eal/x86/rte_power_intrinsics.c @@ -4,6 +4,8 @@ #include "rte_power_intrinsics.h" +static bool wait_supported; + static inline uint64_t __get_umwait_val(const volatile void *p, const uint8_t sz) { @@ -35,6 +37,11 @@ rte_power_monitor(const volatile void *p, const uint64_t expected_value, { const uint32_t tsc_l = (uint32_t)tsc_timestamp; const uint32_t tsc_h = (uint32_t)(tsc_timestamp >> 32); + + /* prevent user from running this instruction if it's not supported */ + if (!wait_supported) + return; + /* * we're using raw byte codes for now as only the newest compiler * versions support this instruction natively. @@ -72,6 +79,11 @@ rte_power_monitor_sync(const volatile void *p, const uint64_t expected_value, { const uint32_t tsc_l = (uint32_t)tsc_timestamp; const uint32_t tsc_h = (uint32_t)(tsc_timestamp >> 32); + + /* prevent user from running this instruction if it's not supported */ + if (!wait_supported) + return; + /* * we're using raw byte codes for now as only the newest compiler * versions support this instruction natively. @@ -112,9 +124,22 @@ rte_power_pause(const uint64_t tsc_timestamp) const uint32_t tsc_l = (uint32_t)tsc_timestamp; const uint32_t tsc_h = (uint32_t)(tsc_timestamp >> 32); + /* prevent user from running this instruction if it's not supported */ + if (!wait_supported) + return; + /* execute TPAUSE */ asm volatile(".byte 0x66, 0x0f, 0xae, 0xf7;" - : /* ignore rflags */ - : "D"(0), /* enter C0.2 */ - "a"(tsc_l), "d"(tsc_h)); + : /* ignore rflags */ + : "D"(0), /* enter C0.2 */ + "a"(tsc_l), "d"(tsc_h)); +} + +RTE_INIT(rte_power_intrinsics_init) { + struct rte_cpu_intrinsics i; + + rte_cpu_get_intrinsics_support(&i); + + if (i.power_monitor && i.power_pause) + wait_supported = 1; } -- 2.25.1