On Wed, Oct 14, 2020 at 7:00 PM Anatoly Burakov <anatoly.bura...@intel.com> 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.bura...@intel.com> > Acked-by: David Christensen <d...@linux.vnet.ibm.com>
Acked-by: Jerin Jacob <jer...@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(+) > > 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 f9522f2776..1c176e4ef5 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. Must be aligned on an 64-byte boundary. > * @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. Must be aligned on an 64-byte boundary. > * @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; > + } > +} > -- > 2.17.1