[v7,03/10] eal: add intrinsics support check infrastructure

Message ID b5a4d686cecf4e577e80b33ef8f6829b2c45c4fe.1602763439.git.anatoly.burakov@intel.com (mailing list archive)
State Superseded, archived
Delegated to: Thomas Monjalon
Headers
Series [v7,01/10] eal: add new x86 cpuid support for WAITPKG |

Checks

Context Check Description
ci/checkpatch success coding style OK

Commit Message

Anatoly Burakov Oct. 15, 2020, 12:04 p.m. UTC
  Currently, it is not possible to check support for intrinsics that
are platform-specific, cannot be abstracted in a generic way, or do not
have support on all architectures. The CPUID flags can be used to some
extent, but they are only defined for their platform, while intrinsics
will be available to all code as they are in generic headers.

This patch introduces infrastructure to check support for certain
platform-specific intrinsics, and adds support for checking support for
IA power management-related intrinsics for UMWAIT/UMONITOR and TPAUSE.

Signed-off-by: Anatoly Burakov <anatoly.burakov@intel.com>
Acked-by: David Christensen <drc@linux.vnet.ibm.com>
Acked-by: Jerin Jacob <jerinj@marvell.com>
---

Notes:
    v6:
    - Fix the comments

 lib/librte_eal/arm/rte_cpuflags.c             |  6 +++++
 lib/librte_eal/include/generic/rte_cpuflags.h | 26 +++++++++++++++++++
 .../include/generic/rte_power_intrinsics.h    | 12 +++++++++
 lib/librte_eal/ppc/rte_cpuflags.c             |  7 +++++
 lib/librte_eal/rte_eal_version.map            |  1 +
 lib/librte_eal/x86/rte_cpuflags.c             | 12 +++++++++
 6 files changed, 64 insertions(+)
  

Comments

Ruifeng Wang Oct. 16, 2020, 9:02 a.m. UTC | #1
> -----Original Message-----
> From: Anatoly Burakov <anatoly.burakov@intel.com>
> Sent: Thursday, October 15, 2020 8:04 PM
> To: dev@dpdk.org
> Cc: Jan Viktorin <viktorin@rehivetech.com>; Ruifeng Wang
> <Ruifeng.Wang@arm.com>; David Christensen <drc@linux.vnet.ibm.com>;
> Ray Kinsella <mdr@ashroe.eu>; Neil Horman <nhorman@tuxdriver.com>;
> Bruce Richardson <bruce.richardson@intel.com>; Konstantin Ananyev
> <konstantin.ananyev@intel.com>; david.hunt@intel.com;
> liang.j.ma@intel.com; jerinjacobk@gmail.com; thomas@monjalon.net;
> timothy.mcdaniel@intel.com; gage.eads@intel.com;
> chris.macnamara@intel.com
> Subject: [PATCH v7 03/10] eal: add intrinsics support check infrastructure
> 
> Currently, it is not possible to check support for intrinsics that are platform-
> specific, cannot be abstracted in a generic way, or do not have support on all
> architectures. The CPUID flags can be used to some extent, but they are only
> defined for their platform, while intrinsics will be available to all code as they
> are in generic headers.
> 
> This patch introduces infrastructure to check support for certain platform-
> specific intrinsics, and adds support for checking support for IA power
> management-related intrinsics for UMWAIT/UMONITOR and TPAUSE.
> 
> Signed-off-by: Anatoly Burakov <anatoly.burakov@intel.com>
> Acked-by: David Christensen <drc@linux.vnet.ibm.com>
> Acked-by: Jerin Jacob <jerinj@marvell.com>
> ---
> 
> Notes:
>     v6:
>     - Fix the comments
> 
>  lib/librte_eal/arm/rte_cpuflags.c             |  6 +++++
>  lib/librte_eal/include/generic/rte_cpuflags.h | 26 +++++++++++++++++++
>  .../include/generic/rte_power_intrinsics.h    | 12 +++++++++
>  lib/librte_eal/ppc/rte_cpuflags.c             |  7 +++++
>  lib/librte_eal/rte_eal_version.map            |  1 +
>  lib/librte_eal/x86/rte_cpuflags.c             | 12 +++++++++
>  6 files changed, 64 insertions(+)
> 
Acked-by: Ruifeng Wang <ruifeng.wang@arm.com>
  
Ray Kinsella Oct. 16, 2020, 11:21 a.m. UTC | #2
On 15/10/2020 13:04, Anatoly Burakov wrote:
> Currently, it is not possible to check support for intrinsics that
> are platform-specific, cannot be abstracted in a generic way, or do not
> have support on all architectures. The CPUID flags can be used to some
> extent, but they are only defined for their platform, while intrinsics
> will be available to all code as they are in generic headers.
> 
> This patch introduces infrastructure to check support for certain
> platform-specific intrinsics, and adds support for checking support for
> IA power management-related intrinsics for UMWAIT/UMONITOR and TPAUSE.
> 
> Signed-off-by: Anatoly Burakov <anatoly.burakov@intel.com>
> Acked-by: David Christensen <drc@linux.vnet.ibm.com>
> Acked-by: Jerin Jacob <jerinj@marvell.com>
> ---
> 
> Notes:
>     v6:
>     - Fix the comments
> 
>  lib/librte_eal/arm/rte_cpuflags.c             |  6 +++++
>  lib/librte_eal/include/generic/rte_cpuflags.h | 26 +++++++++++++++++++
>  .../include/generic/rte_power_intrinsics.h    | 12 +++++++++
>  lib/librte_eal/ppc/rte_cpuflags.c             |  7 +++++
>  lib/librte_eal/rte_eal_version.map            |  1 +
>  lib/librte_eal/x86/rte_cpuflags.c             | 12 +++++++++
>  6 files changed, 64 insertions(+)

Acked-by: Ray Kinsella <mdr@ashroe.eu>

> diff --git a/lib/librte_eal/arm/rte_cpuflags.c b/lib/librte_eal/arm/rte_cpuflags.c
> index 7b257b7873..e3a53bcece 100644
> --- a/lib/librte_eal/arm/rte_cpuflags.c
> +++ b/lib/librte_eal/arm/rte_cpuflags.c
> @@ -151,3 +151,9 @@ rte_cpu_get_flag_name(enum rte_cpu_flag_t feature)
>  		return NULL;
>  	return rte_cpu_feature_table[feature].name;
>  }
> +
> +void
> +rte_cpu_get_intrinsics_support(struct rte_cpu_intrinsics *intrinsics)
> +{
> +	memset(intrinsics, 0, sizeof(*intrinsics));
> +}
> diff --git a/lib/librte_eal/include/generic/rte_cpuflags.h b/lib/librte_eal/include/generic/rte_cpuflags.h
> index 872f0ebe3e..28a5aecde8 100644
> --- a/lib/librte_eal/include/generic/rte_cpuflags.h
> +++ b/lib/librte_eal/include/generic/rte_cpuflags.h
> @@ -13,6 +13,32 @@
>  #include "rte_common.h"
>  #include <errno.h>
>  
> +#include <rte_compat.h>
> +
> +/**
> + * Structure used to describe platform-specific intrinsics that may or may not
> + * be supported at runtime.
> + */
> +struct rte_cpu_intrinsics {
> +	uint32_t power_monitor : 1;
> +	/**< indicates support for rte_power_monitor function */
> +	uint32_t power_pause : 1;
> +	/**< indicates support for rte_power_pause function */
> +};
> +
> +/**
> + * @warning
> + * @b EXPERIMENTAL: this API may change without prior notice
> + *
> + * Check CPU support for various intrinsics at runtime.
> + *
> + * @param intrinsics
> + *     Pointer to a structure to be filled.
> + */
> +__rte_experimental
> +void
> +rte_cpu_get_intrinsics_support(struct rte_cpu_intrinsics *intrinsics);
> +
>  /**
>   * Enumeration of all CPU features supported
>   */
> diff --git a/lib/librte_eal/include/generic/rte_power_intrinsics.h b/lib/librte_eal/include/generic/rte_power_intrinsics.h
> index fb897d9060..03a326f076 100644
> --- a/lib/librte_eal/include/generic/rte_power_intrinsics.h
> +++ b/lib/librte_eal/include/generic/rte_power_intrinsics.h
> @@ -32,6 +32,10 @@
>   * checked against the expected value, and if they match, the entering of
>   * optimized power state may be aborted.
>   *
> + * @warning It is responsibility of the user to check if this function is
> + *   supported at runtime using `rte_cpu_get_features()` API call. Failing to do
> + *   so may result in an illegal CPU instruction error.
> + *
>   * @param p
>   *   Address to monitor for changes.
>   * @param expected_value
> @@ -69,6 +73,10 @@ static inline void rte_power_monitor(const volatile void *p,
>   * This call will also lock a spinlock on entering sleep, and release it on
>   * waking up the CPU.
>   *
> + * @warning It is responsibility of the user to check if this function is
> + *   supported at runtime using `rte_cpu_get_features()` API call. Failing to do
> + *   so may result in an illegal CPU instruction error.
> + *
>   * @param p
>   *   Address to monitor for changes.
>   * @param expected_value
> @@ -101,6 +109,10 @@ static inline void rte_power_monitor_sync(const volatile void *p,
>   * Enter an architecture-defined optimized power state until a certain TSC
>   * timestamp is reached.
>   *
> + * @warning It is responsibility of the user to check if this function is
> + *   supported at runtime using `rte_cpu_get_features()` 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
>   *   architecture-dependent.
> diff --git a/lib/librte_eal/ppc/rte_cpuflags.c b/lib/librte_eal/ppc/rte_cpuflags.c
> index 3bb7563ce9..61db5c216d 100644
> --- a/lib/librte_eal/ppc/rte_cpuflags.c
> +++ b/lib/librte_eal/ppc/rte_cpuflags.c
> @@ -8,6 +8,7 @@
>  #include <elf.h>
>  #include <fcntl.h>
>  #include <assert.h>
> +#include <string.h>
>  #include <unistd.h>
>  
>  /* Symbolic values for the entries in the auxiliary table */
> @@ -108,3 +109,9 @@ rte_cpu_get_flag_name(enum rte_cpu_flag_t feature)
>  		return NULL;
>  	return rte_cpu_feature_table[feature].name;
>  }
> +
> +void
> +rte_cpu_get_intrinsics_support(struct rte_cpu_intrinsics *intrinsics)
> +{
> +	memset(intrinsics, 0, sizeof(*intrinsics));
> +}
> diff --git a/lib/librte_eal/rte_eal_version.map b/lib/librte_eal/rte_eal_version.map
> index a93dea9fe6..ed944f2bd4 100644
> --- a/lib/librte_eal/rte_eal_version.map
> +++ b/lib/librte_eal/rte_eal_version.map
> @@ -400,6 +400,7 @@ EXPERIMENTAL {
>  	# added in 20.11
>  	__rte_eal_trace_generic_size_t;
>  	rte_service_lcore_may_be_active;
> +	rte_cpu_get_intrinsics_support;
>  };
>  
>  INTERNAL {
> diff --git a/lib/librte_eal/x86/rte_cpuflags.c b/lib/librte_eal/x86/rte_cpuflags.c
> index 0325c4b93b..a96312ff7f 100644
> --- a/lib/librte_eal/x86/rte_cpuflags.c
> +++ b/lib/librte_eal/x86/rte_cpuflags.c
> @@ -7,6 +7,7 @@
>  #include <stdio.h>
>  #include <errno.h>
>  #include <stdint.h>
> +#include <string.h>
>  
>  #include "rte_cpuid.h"
>  
> @@ -179,3 +180,14 @@ rte_cpu_get_flag_name(enum rte_cpu_flag_t feature)
>  		return NULL;
>  	return rte_cpu_feature_table[feature].name;
>  }
> +
> +void
> +rte_cpu_get_intrinsics_support(struct rte_cpu_intrinsics *intrinsics)
> +{
> +	memset(intrinsics, 0, sizeof(*intrinsics));
> +
> +	if (rte_cpu_get_flag_enabled(RTE_CPUFLAG_WAITPKG)) {
> +		intrinsics->power_monitor = 1;
> +		intrinsics->power_pause = 1;
> +	}
> +}
>
  

Patch

diff --git a/lib/librte_eal/arm/rte_cpuflags.c b/lib/librte_eal/arm/rte_cpuflags.c
index 7b257b7873..e3a53bcece 100644
--- a/lib/librte_eal/arm/rte_cpuflags.c
+++ b/lib/librte_eal/arm/rte_cpuflags.c
@@ -151,3 +151,9 @@  rte_cpu_get_flag_name(enum rte_cpu_flag_t feature)
 		return NULL;
 	return rte_cpu_feature_table[feature].name;
 }
+
+void
+rte_cpu_get_intrinsics_support(struct rte_cpu_intrinsics *intrinsics)
+{
+	memset(intrinsics, 0, sizeof(*intrinsics));
+}
diff --git a/lib/librte_eal/include/generic/rte_cpuflags.h b/lib/librte_eal/include/generic/rte_cpuflags.h
index 872f0ebe3e..28a5aecde8 100644
--- a/lib/librte_eal/include/generic/rte_cpuflags.h
+++ b/lib/librte_eal/include/generic/rte_cpuflags.h
@@ -13,6 +13,32 @@ 
 #include "rte_common.h"
 #include <errno.h>
 
+#include <rte_compat.h>
+
+/**
+ * Structure used to describe platform-specific intrinsics that may or may not
+ * be supported at runtime.
+ */
+struct rte_cpu_intrinsics {
+	uint32_t power_monitor : 1;
+	/**< indicates support for rte_power_monitor function */
+	uint32_t power_pause : 1;
+	/**< indicates support for rte_power_pause function */
+};
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice
+ *
+ * Check CPU support for various intrinsics at runtime.
+ *
+ * @param intrinsics
+ *     Pointer to a structure to be filled.
+ */
+__rte_experimental
+void
+rte_cpu_get_intrinsics_support(struct rte_cpu_intrinsics *intrinsics);
+
 /**
  * Enumeration of all CPU features supported
  */
diff --git a/lib/librte_eal/include/generic/rte_power_intrinsics.h b/lib/librte_eal/include/generic/rte_power_intrinsics.h
index fb897d9060..03a326f076 100644
--- a/lib/librte_eal/include/generic/rte_power_intrinsics.h
+++ b/lib/librte_eal/include/generic/rte_power_intrinsics.h
@@ -32,6 +32,10 @@ 
  * checked against the expected value, and if they match, the entering of
  * optimized power state may be aborted.
  *
+ * @warning It is responsibility of the user to check if this function is
+ *   supported at runtime using `rte_cpu_get_features()` API call. Failing to do
+ *   so may result in an illegal CPU instruction error.
+ *
  * @param p
  *   Address to monitor for changes.
  * @param expected_value
@@ -69,6 +73,10 @@  static inline void rte_power_monitor(const volatile void *p,
  * This call will also lock a spinlock on entering sleep, and release it on
  * waking up the CPU.
  *
+ * @warning It is responsibility of the user to check if this function is
+ *   supported at runtime using `rte_cpu_get_features()` API call. Failing to do
+ *   so may result in an illegal CPU instruction error.
+ *
  * @param p
  *   Address to monitor for changes.
  * @param expected_value
@@ -101,6 +109,10 @@  static inline void rte_power_monitor_sync(const volatile void *p,
  * Enter an architecture-defined optimized power state until a certain TSC
  * timestamp is reached.
  *
+ * @warning It is responsibility of the user to check if this function is
+ *   supported at runtime using `rte_cpu_get_features()` 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
  *   architecture-dependent.
diff --git a/lib/librte_eal/ppc/rte_cpuflags.c b/lib/librte_eal/ppc/rte_cpuflags.c
index 3bb7563ce9..61db5c216d 100644
--- a/lib/librte_eal/ppc/rte_cpuflags.c
+++ b/lib/librte_eal/ppc/rte_cpuflags.c
@@ -8,6 +8,7 @@ 
 #include <elf.h>
 #include <fcntl.h>
 #include <assert.h>
+#include <string.h>
 #include <unistd.h>
 
 /* Symbolic values for the entries in the auxiliary table */
@@ -108,3 +109,9 @@  rte_cpu_get_flag_name(enum rte_cpu_flag_t feature)
 		return NULL;
 	return rte_cpu_feature_table[feature].name;
 }
+
+void
+rte_cpu_get_intrinsics_support(struct rte_cpu_intrinsics *intrinsics)
+{
+	memset(intrinsics, 0, sizeof(*intrinsics));
+}
diff --git a/lib/librte_eal/rte_eal_version.map b/lib/librte_eal/rte_eal_version.map
index a93dea9fe6..ed944f2bd4 100644
--- a/lib/librte_eal/rte_eal_version.map
+++ b/lib/librte_eal/rte_eal_version.map
@@ -400,6 +400,7 @@  EXPERIMENTAL {
 	# added in 20.11
 	__rte_eal_trace_generic_size_t;
 	rte_service_lcore_may_be_active;
+	rte_cpu_get_intrinsics_support;
 };
 
 INTERNAL {
diff --git a/lib/librte_eal/x86/rte_cpuflags.c b/lib/librte_eal/x86/rte_cpuflags.c
index 0325c4b93b..a96312ff7f 100644
--- a/lib/librte_eal/x86/rte_cpuflags.c
+++ b/lib/librte_eal/x86/rte_cpuflags.c
@@ -7,6 +7,7 @@ 
 #include <stdio.h>
 #include <errno.h>
 #include <stdint.h>
+#include <string.h>
 
 #include "rte_cpuid.h"
 
@@ -179,3 +180,14 @@  rte_cpu_get_flag_name(enum rte_cpu_flag_t feature)
 		return NULL;
 	return rte_cpu_feature_table[feature].name;
 }
+
+void
+rte_cpu_get_intrinsics_support(struct rte_cpu_intrinsics *intrinsics)
+{
+	memset(intrinsics, 0, sizeof(*intrinsics));
+
+	if (rte_cpu_get_flag_enabled(RTE_CPUFLAG_WAITPKG)) {
+		intrinsics->power_monitor = 1;
+		intrinsics->power_pause = 1;
+	}
+}