[v2,01/17] eal: add max SIMD bitwidth

Message ID 20200827161304.32300-2-ciara.power@intel.com (mailing list archive)
State Superseded, archived
Delegated to: David Marchand
Headers
Series add max SIMD bitwidth to EAL |

Checks

Context Check Description
ci/checkpatch success coding style OK

Commit Message

Power, Ciara Aug. 27, 2020, 4:12 p.m. UTC
  This patch adds a max SIMD bitwidth EAL configuration. The API allows
for an app to set this value. It can also be set using EAL argument
--force-max-simd-bitwidth, which will lock the value and override any
modifications made by the app.

Signed-off-by: Ciara Power <ciara.power@intel.com>

---
v2: Added to Doxygen comment for API.
---
 lib/librte_eal/common/eal_common_options.c | 60 ++++++++++++++++++++++
 lib/librte_eal/common/eal_internal_cfg.h   |  8 +++
 lib/librte_eal/common/eal_options.h        |  2 +
 lib/librte_eal/include/rte_eal.h           | 32 ++++++++++++
 lib/librte_eal/rte_eal_version.map         |  4 ++
 5 files changed, 106 insertions(+)
  

Comments

Honnappa Nagarahalli Sept. 4, 2020, 5:30 a.m. UTC | #1
<snip>

> 
> This patch adds a max SIMD bitwidth EAL configuration. The API allows for an
> app to set this value. It can also be set using EAL argument --force-max-simd-
> bitwidth, which will lock the value and override any modifications made by
> the app.
> 
> Signed-off-by: Ciara Power <ciara.power@intel.com>
> 
> ---
> v2: Added to Doxygen comment for API.
> ---
>  lib/librte_eal/common/eal_common_options.c | 60
> ++++++++++++++++++++++
>  lib/librte_eal/common/eal_internal_cfg.h   |  8 +++
>  lib/librte_eal/common/eal_options.h        |  2 +
>  lib/librte_eal/include/rte_eal.h           | 32 ++++++++++++
>  lib/librte_eal/rte_eal_version.map         |  4 ++
>  5 files changed, 106 insertions(+)
> 
> diff --git a/lib/librte_eal/common/eal_common_options.c
> b/lib/librte_eal/common/eal_common_options.c
> index a5426e1234..90f4e8f5c3 100644
> --- a/lib/librte_eal/common/eal_common_options.c
> +++ b/lib/librte_eal/common/eal_common_options.c
> @@ -102,6 +102,7 @@ eal_long_options[] = {
>  	{OPT_MATCH_ALLOCATIONS, 0, NULL,
> OPT_MATCH_ALLOCATIONS_NUM},
>  	{OPT_TELEMETRY,         0, NULL, OPT_TELEMETRY_NUM        },
>  	{OPT_NO_TELEMETRY,      0, NULL, OPT_NO_TELEMETRY_NUM     },
> +	{OPT_FORCE_MAX_SIMD_BITWIDTH, 1, NULL,
> +OPT_FORCE_MAX_SIMD_BITWIDTH_NUM},
>  	{0,                     0, NULL, 0                        }
>  };
> 
> @@ -1309,6 +1310,32 @@ eal_parse_iova_mode(const char *name)
>  	return 0;
>  }
> 
> +static int
> +eal_parse_simd_bitwidth(const char *arg, bool locked) {
> +	char *end;
> +	uint16_t bitwidth;
> +	int ret;
> +	struct internal_config *internal_conf =
> +		eal_get_internal_configuration();
> +
> +	if (arg == NULL || arg[0] == '\0')
> +		return -1;
> +
> +	errno = 0;
> +	bitwidth = strtoul(arg, &end, 0);
> +
> +	/* check for errors */
> +	if ((errno != 0) || end == NULL || (*end != '\0'))
> +		return -1;
> +
> +	ret = rte_set_max_simd_bitwidth(bitwidth);
> +	if (ret < 0)
> +		return -1;
> +	internal_conf->max_simd_bitwidth.locked = locked;
> +	return 0;
> +}
> +
>  static int
>  eal_parse_base_virtaddr(const char *arg)  { @@ -1707,6 +1734,13 @@
> eal_parse_common_option(int opt, const char *optarg,
>  	case OPT_NO_TELEMETRY_NUM:
>  		conf->no_telemetry = 1;
>  		break;
> +	case OPT_FORCE_MAX_SIMD_BITWIDTH_NUM:
> +		if (eal_parse_simd_bitwidth(optarg, 1) < 0) {
> +			RTE_LOG(ERR, EAL, "invalid parameter for --"
> +					OPT_FORCE_MAX_SIMD_BITWIDTH
> "\n");
> +			return -1;
> +		}
> +		break;
> 
>  	/* don't know what to do, leave this to caller */
>  	default:
> @@ -1903,6 +1937,31 @@ eal_check_common_options(struct
> internal_config *internal_cfg)
>  	return 0;
>  }
> 
> +uint16_t
> +rte_get_max_simd_bitwidth(void)
> +{
> +	const struct internal_config *internal_conf =
> +		eal_get_internal_configuration();
> +	return internal_conf->max_simd_bitwidth.bitwidth;
> +}
> +
> +int
> +rte_set_max_simd_bitwidth(uint16_t bitwidth) {
> +	struct internal_config *internal_conf =
> +		eal_get_internal_configuration();
> +	if (internal_conf->max_simd_bitwidth.locked) {
> +		RTE_LOG(NOTICE, EAL, "Cannot set max SIMD bitwidth - user
> runtime override enabled");
> +		return -EPERM;
> +	}
> +	if (bitwidth < RTE_NO_SIMD || !rte_is_power_of_2(bitwidth)) {
> +		RTE_LOG(ERR, EAL, "Invalid bitwidth value!\n");
> +		return -EINVAL;
> +	}
> +	internal_conf->max_simd_bitwidth.bitwidth = bitwidth;
> +	return 0;
> +}
> +
>  void
>  eal_common_usage(void)
>  {
> @@ -1981,6 +2040,7 @@ eal_common_usage(void)
>  	       "  --"OPT_BASE_VIRTADDR"     Base virtual address\n"
>  	       "  --"OPT_TELEMETRY"   Enable telemetry support (on by
> default)\n"
>  	       "  --"OPT_NO_TELEMETRY"   Disable telemetry support\n"
> +	       "  --"OPT_FORCE_MAX_SIMD_BITWIDTH" Force the max SIMD
> bitwidth\n"
>  	       "\nEAL options for DEBUG use only:\n"
>  	       "  --"OPT_HUGE_UNLINK"       Unlink hugepage files after init\n"
>  	       "  --"OPT_NO_HUGE"           Use malloc instead of hugetlbfs\n"
> diff --git a/lib/librte_eal/common/eal_internal_cfg.h
> b/lib/librte_eal/common/eal_internal_cfg.h
> index 13f93388a7..367e0cc19e 100644
> --- a/lib/librte_eal/common/eal_internal_cfg.h
> +++ b/lib/librte_eal/common/eal_internal_cfg.h
> @@ -33,6 +33,12 @@ struct hugepage_info {
>  	int lock_descriptor;    /**< file descriptor for hugepage dir */
>  };
> 
> +struct simd_bitwidth {
> +	/**< flag indicating if bitwidth is locked from further modification */
> +	bool locked;
> +	uint16_t bitwidth; /**< bitwidth value */ };
> +
>  /**
>   * internal configuration
>   */
> @@ -85,6 +91,8 @@ struct internal_config {
>  	volatile unsigned int init_complete;
>  	/**< indicates whether EAL has completed initialization */
>  	unsigned int no_telemetry; /**< true to disable Telemetry */
> +	/** max simd bitwidth path to use */
> +	struct simd_bitwidth max_simd_bitwidth;
>  };
> 
>  void eal_reset_internal_config(struct internal_config *internal_cfg); diff --git
> a/lib/librte_eal/common/eal_options.h
> b/lib/librte_eal/common/eal_options.h
> index 89769d48b4..ef33979664 100644
> --- a/lib/librte_eal/common/eal_options.h
> +++ b/lib/librte_eal/common/eal_options.h
> @@ -85,6 +85,8 @@ enum {
>  	OPT_TELEMETRY_NUM,
>  #define OPT_NO_TELEMETRY      "no-telemetry"
>  	OPT_NO_TELEMETRY_NUM,
> +#define OPT_FORCE_MAX_SIMD_BITWIDTH  "force-max-simd-bitwidth"
> +	OPT_FORCE_MAX_SIMD_BITWIDTH_NUM,
>  	OPT_LONG_MAX_NUM
>  };
> 
> diff --git a/lib/librte_eal/include/rte_eal.h b/lib/librte_eal/include/rte_eal.h
> index ddcf6a2e7a..8148f650f2 100644
> --- a/lib/librte_eal/include/rte_eal.h
> +++ b/lib/librte_eal/include/rte_eal.h
> @@ -43,6 +43,13 @@ enum rte_proc_type_t {
>  	RTE_PROC_INVALID
>  };
> 
> +enum rte_max_simd_t {
We could add a RTE_MAX_SIMD = 0. Arm platforms can use this to choose SVE.

> +	RTE_NO_SIMD = 64,
> +	RTE_MAX_128_SIMD = 128,
> +	RTE_MAX_256_SIMD = 256,
> +	RTE_MAX_512_SIMD = 512
> +};
> +
>  /**
>   * Get the process type in a multi-process setup
>   *
> @@ -51,6 +58,31 @@ enum rte_proc_type_t {
>   */
>  enum rte_proc_type_t rte_eal_process_type(void);
> 
> +/**
> + * Get the supported SIMD bitwidth.
> + *
> + * @return
> + *   uint16_t bitwidth.
> + */
> +__rte_experimental
> +uint16_t rte_get_max_simd_bitwidth(void);
> +
> +/**
> + * Set the supported SIMD bitwidth.
> + * This API should only be called once at initialization, before EAL init.
> + *
> + * @param bitwidth
> + *   uint16_t bitwidth.
> + * @return
> + *   0 on success.
> + * @return
> + *   -EINVAL on invalid bitwidth parameter.
> + * @return
> + *   -EPERM if bitwidth is locked.
> + */
> +__rte_experimental
> +int rte_set_max_simd_bitwidth(uint16_t bitwidth);
> +
>  /**
>   * Request iopl privilege for all RPL.
>   *
> diff --git a/lib/librte_eal/rte_eal_version.map
> b/lib/librte_eal/rte_eal_version.map
> index bf0c17c233..8059ea76b6 100644
> --- a/lib/librte_eal/rte_eal_version.map
> +++ b/lib/librte_eal/rte_eal_version.map
> @@ -403,6 +403,10 @@ EXPERIMENTAL {
>  	rte_mp_disable;
>  	rte_thread_register;
>  	rte_thread_unregister;
> +
> +	# added in 20.11
> +	rte_get_max_simd_bitwidth;
> +	rte_set_max_simd_bitwidth;
>  };
> 
>  INTERNAL {
> --
> 2.17.1
  
Bruce Richardson Sept. 4, 2020, 8:45 a.m. UTC | #2
On Fri, Sep 04, 2020 at 05:30:28AM +0000, Honnappa Nagarahalli wrote:
> <snip>
> 
 > diff --git a/lib/librte_eal/include/rte_eal.h b/lib/librte_eal/include/rte_eal.h
> > index ddcf6a2e7a..8148f650f2 100644
> > --- a/lib/librte_eal/include/rte_eal.h
> > +++ b/lib/librte_eal/include/rte_eal.h
> > @@ -43,6 +43,13 @@ enum rte_proc_type_t {
> >  	RTE_PROC_INVALID
> >  };
> > 
> > +enum rte_max_simd_t {
> We could add a RTE_MAX_SIMD = 0. Arm platforms can use this to choose SVE.
> 

Is zero the best value for this? Would setting it to MAX_INT or some
other big number be better, in terms of comparisons operations, or does
that just not apply at all with SVE?

> > +	RTE_NO_SIMD = 64,
> > +	RTE_MAX_128_SIMD = 128,
> > +	RTE_MAX_256_SIMD = 256,
> > +	RTE_MAX_512_SIMD = 512
> > +};
> > +
  
Ananyev, Konstantin Sept. 6, 2020, 10:01 p.m. UTC | #3
> This patch adds a max SIMD bitwidth EAL configuration. The API allows
> for an app to set this value. It can also be set using EAL argument
> --force-max-simd-bitwidth, which will lock the value and override any
> modifications made by the app.
> 
> Signed-off-by: Ciara Power <ciara.power@intel.com>
> 
> ---
> v2: Added to Doxygen comment for API.
> ---
>  lib/librte_eal/common/eal_common_options.c | 60 ++++++++++++++++++++++
>  lib/librte_eal/common/eal_internal_cfg.h   |  8 +++
>  lib/librte_eal/common/eal_options.h        |  2 +
>  lib/librte_eal/include/rte_eal.h           | 32 ++++++++++++
>  lib/librte_eal/rte_eal_version.map         |  4 ++
>  5 files changed, 106 insertions(+)
> 
> diff --git a/lib/librte_eal/common/eal_common_options.c b/lib/librte_eal/common/eal_common_options.c
> index a5426e1234..90f4e8f5c3 100644
> --- a/lib/librte_eal/common/eal_common_options.c
> +++ b/lib/librte_eal/common/eal_common_options.c
> @@ -102,6 +102,7 @@ eal_long_options[] = {
>  	{OPT_MATCH_ALLOCATIONS, 0, NULL, OPT_MATCH_ALLOCATIONS_NUM},
>  	{OPT_TELEMETRY,         0, NULL, OPT_TELEMETRY_NUM        },
>  	{OPT_NO_TELEMETRY,      0, NULL, OPT_NO_TELEMETRY_NUM     },
> +	{OPT_FORCE_MAX_SIMD_BITWIDTH, 1, NULL, OPT_FORCE_MAX_SIMD_BITWIDTH_NUM},
>  	{0,                     0, NULL, 0                        }
>  };
> 
> @@ -1309,6 +1310,32 @@ eal_parse_iova_mode(const char *name)
>  	return 0;
>  }
> 
> +static int
> +eal_parse_simd_bitwidth(const char *arg, bool locked)
> +{
> +	char *end;
> +	uint16_t bitwidth;
> +	int ret;
> +	struct internal_config *internal_conf =
> +		eal_get_internal_configuration();
> +
> +	if (arg == NULL || arg[0] == '\0')
> +		return -1;
> +
> +	errno = 0;
> +	bitwidth = strtoul(arg, &end, 0);

As I can see with that assignment you'll loose high bits set (if any).
So, --force-max-simd-bitwidth=0xf0080
wouldn't report any error, while it probably should.
Probably something like that, as abetter way:
unsigned long t;
...
t = strtoul(arg, &end, 0);
if (t > UINT16_MAX || errno != 0 || end == NULL || *end != '\0')
	return -1;
ret = rte_set_max_simd_bitwidth(t);

> +
> +	/* check for errors */
> +	if ((errno != 0) || end == NULL || (*end != '\0'))
> +		return -1;
> +
> +	ret = rte_set_max_simd_bitwidth(bitwidth);
> +	if (ret < 0)
> +		return -1;
> +	internal_conf->max_simd_bitwidth.locked = locked;
> +	return 0;
> +}
> +
  
Honnappa Nagarahalli Sept. 9, 2020, 7:30 p.m. UTC | #4
<snip>

> >
>  > diff --git a/lib/librte_eal/include/rte_eal.h b/lib/librte_eal/include/rte_eal.h
> > > index ddcf6a2e7a..8148f650f2 100644
> > > --- a/lib/librte_eal/include/rte_eal.h
> > > +++ b/lib/librte_eal/include/rte_eal.h
> > > @@ -43,6 +43,13 @@ enum rte_proc_type_t {
> > >  	RTE_PROC_INVALID
> > >  };
> > >
> > > +enum rte_max_simd_t {
> > We could add a RTE_MAX_SIMD = 0. Arm platforms can use this to choose
> SVE.
> >
> 
> Is zero the best value for this? Would setting it to MAX_INT or some other big
> number be better, in terms of comparisons operations, or does that just not
> apply at all with SVE?
I suggested zero as the bitwidth can be specified from the command line. It would be much easier to input zero vs other number.

> 
> > > +	RTE_NO_SIMD = 64,
> > > +	RTE_MAX_128_SIMD = 128,
> > > +	RTE_MAX_256_SIMD = 256,
> > > +	RTE_MAX_512_SIMD = 512
> > > +};
> > > +
>
  
Ray Kinsella Sept. 17, 2020, 4:31 p.m. UTC | #5
On 09/09/2020 20:30, Honnappa Nagarahalli wrote:
> <snip>
> 
>>>
>>  > diff --git a/lib/librte_eal/include/rte_eal.h b/lib/librte_eal/include/rte_eal.h
>>>> index ddcf6a2e7a..8148f650f2 100644
>>>> --- a/lib/librte_eal/include/rte_eal.h
>>>> +++ b/lib/librte_eal/include/rte_eal.h
>>>> @@ -43,6 +43,13 @@ enum rte_proc_type_t {
>>>>  	RTE_PROC_INVALID
>>>>  };
>>>>
>>>> +enum rte_max_simd_t {
>>> We could add a RTE_MAX_SIMD = 0. Arm platforms can use this to choose
>> SVE.
>>>
>>
>> Is zero the best value for this? Would setting it to MAX_INT or some other big
>> number be better, in terms of comparisons operations, or does that just not
>> apply at all with SVE?
> I suggested zero as the bitwidth can be specified from the command line. It would be much easier to input zero vs other number.

Right, but it doesn't end up being that intuitive as interface 
0 is enabled, 64 is not, 128 is enabled etc .... 

Suggest we use a max 16bit integer as 0xFFFF?

> 
>>
>>>> +	RTE_NO_SIMD = 64,
>>>> +	RTE_MAX_128_SIMD = 128,
>>>> +	RTE_MAX_256_SIMD = 256,
>>>> +	RTE_MAX_512_SIMD = 512
>>>> +};
>>>> +
>>
  
Bruce Richardson Sept. 17, 2020, 4:43 p.m. UTC | #6
On Thu, Sep 17, 2020 at 05:31:52PM +0100, Kinsella, Ray wrote:
> 
> 
> On 09/09/2020 20:30, Honnappa Nagarahalli wrote:
> > <snip>
> > 
> >>>
> >>  > diff --git a/lib/librte_eal/include/rte_eal.h b/lib/librte_eal/include/rte_eal.h
> >>>> index ddcf6a2e7a..8148f650f2 100644
> >>>> --- a/lib/librte_eal/include/rte_eal.h
> >>>> +++ b/lib/librte_eal/include/rte_eal.h
> >>>> @@ -43,6 +43,13 @@ enum rte_proc_type_t {
> >>>>  	RTE_PROC_INVALID
> >>>>  };
> >>>>
> >>>> +enum rte_max_simd_t {
> >>> We could add a RTE_MAX_SIMD = 0. Arm platforms can use this to choose
> >> SVE.
> >>>
> >>
> >> Is zero the best value for this? Would setting it to MAX_INT or some other big
> >> number be better, in terms of comparisons operations, or does that just not
> >> apply at all with SVE?
> > I suggested zero as the bitwidth can be specified from the command line. It would be much easier to input zero vs other number.
> 
> Right, but it doesn't end up being that intuitive as interface 
> 0 is enabled, 64 is not, 128 is enabled etc .... 
> 
> Suggest we use a max 16bit integer as 0xFFFF?
> 
I can actually see 0 on command-line as being "unlimited", but for the APIs
and internally, I think that it should be converted to a MAX_INT value so
that the comparisons don't need to special-case zero. I agree with
Honnappa, that a -1 or maxint value is awkward on commandline, but
internally it's just an enum, so we can set it to whatever the most
practical value is.
  
Honnappa Nagarahalli Sept. 18, 2020, 2:13 a.m. UTC | #7
<snip>

> >
> >>>
> >>  > diff --git a/lib/librte_eal/include/rte_eal.h
> >> b/lib/librte_eal/include/rte_eal.h
> >>>> index ddcf6a2e7a..8148f650f2 100644
> >>>> --- a/lib/librte_eal/include/rte_eal.h
> >>>> +++ b/lib/librte_eal/include/rte_eal.h
> >>>> @@ -43,6 +43,13 @@ enum rte_proc_type_t {
> >>>>  	RTE_PROC_INVALID
> >>>>  };
> >>>>
> >>>> +enum rte_max_simd_t {
> >>> We could add a RTE_MAX_SIMD = 0. Arm platforms can use this to
> >>> choose
> >> SVE.
> >>>
> >>
> >> Is zero the best value for this? Would setting it to MAX_INT or some
> >> other big number be better, in terms of comparisons operations, or
> >> does that just not apply at all with SVE?
> > I suggested zero as the bitwidth can be specified from the command line. It
> would be much easier to input zero vs other number.
> 
> Right, but it doesn't end up being that intuitive as interface
> 0 is enabled, 64 is not, 128 is enabled etc ....
> 
> Suggest we use a max 16bit integer as 0xFFFF?
I think there are 2 things here:
1) What is the internal representation (for ex: the value of the enum)? Here assigning 0xFFFF should be fine.
2) The input value at the command line. Is it possible to say that, if the user does not provide anything, then we set the option as 0xFFFF? This would mean that SVE would be used by default on Arm platforms (which is ok for me).

> 
> >
> >>
> >>>> +	RTE_NO_SIMD = 64,
> >>>> +	RTE_MAX_128_SIMD = 128,
> >>>> +	RTE_MAX_256_SIMD = 256,
> >>>> +	RTE_MAX_512_SIMD = 512
> >>>> +};
> >>>> +
> >>
  
Bruce Richardson Sept. 18, 2020, 8:35 a.m. UTC | #8
On Fri, Sep 18, 2020 at 02:13:02AM +0000, Honnappa Nagarahalli wrote:
> <snip>
> 
> > >
> > >>>
> > >>  > diff --git a/lib/librte_eal/include/rte_eal.h
> > >> b/lib/librte_eal/include/rte_eal.h
> > >>>> index ddcf6a2e7a..8148f650f2 100644
> > >>>> --- a/lib/librte_eal/include/rte_eal.h
> > >>>> +++ b/lib/librte_eal/include/rte_eal.h
> > >>>> @@ -43,6 +43,13 @@ enum rte_proc_type_t {
> > >>>>  	RTE_PROC_INVALID
> > >>>>  };
> > >>>>
> > >>>> +enum rte_max_simd_t {
> > >>> We could add a RTE_MAX_SIMD = 0. Arm platforms can use this to
> > >>> choose
> > >> SVE.
> > >>>
> > >>
> > >> Is zero the best value for this? Would setting it to MAX_INT or some
> > >> other big number be better, in terms of comparisons operations, or
> > >> does that just not apply at all with SVE?
> > > I suggested zero as the bitwidth can be specified from the command line. It
> > would be much easier to input zero vs other number.
> > 
> > Right, but it doesn't end up being that intuitive as interface
> > 0 is enabled, 64 is not, 128 is enabled etc ....
> > 
> > Suggest we use a max 16bit integer as 0xFFFF?
> I think there are 2 things here:
> 1) What is the internal representation (for ex: the value of the enum)? Here assigning 0xFFFF should be fine.
> 2) The input value at the command line. Is it possible to say that, if the user does not provide anything, then we set the option as 0xFFFF? This would mean that SVE would be used by default on Arm platforms (which is ok for me).
>

Make sense. That all is perfectly doable because the initial default value
is set per architecture.
  

Patch

diff --git a/lib/librte_eal/common/eal_common_options.c b/lib/librte_eal/common/eal_common_options.c
index a5426e1234..90f4e8f5c3 100644
--- a/lib/librte_eal/common/eal_common_options.c
+++ b/lib/librte_eal/common/eal_common_options.c
@@ -102,6 +102,7 @@  eal_long_options[] = {
 	{OPT_MATCH_ALLOCATIONS, 0, NULL, OPT_MATCH_ALLOCATIONS_NUM},
 	{OPT_TELEMETRY,         0, NULL, OPT_TELEMETRY_NUM        },
 	{OPT_NO_TELEMETRY,      0, NULL, OPT_NO_TELEMETRY_NUM     },
+	{OPT_FORCE_MAX_SIMD_BITWIDTH, 1, NULL, OPT_FORCE_MAX_SIMD_BITWIDTH_NUM},
 	{0,                     0, NULL, 0                        }
 };
 
@@ -1309,6 +1310,32 @@  eal_parse_iova_mode(const char *name)
 	return 0;
 }
 
+static int
+eal_parse_simd_bitwidth(const char *arg, bool locked)
+{
+	char *end;
+	uint16_t bitwidth;
+	int ret;
+	struct internal_config *internal_conf =
+		eal_get_internal_configuration();
+
+	if (arg == NULL || arg[0] == '\0')
+		return -1;
+
+	errno = 0;
+	bitwidth = strtoul(arg, &end, 0);
+
+	/* check for errors */
+	if ((errno != 0) || end == NULL || (*end != '\0'))
+		return -1;
+
+	ret = rte_set_max_simd_bitwidth(bitwidth);
+	if (ret < 0)
+		return -1;
+	internal_conf->max_simd_bitwidth.locked = locked;
+	return 0;
+}
+
 static int
 eal_parse_base_virtaddr(const char *arg)
 {
@@ -1707,6 +1734,13 @@  eal_parse_common_option(int opt, const char *optarg,
 	case OPT_NO_TELEMETRY_NUM:
 		conf->no_telemetry = 1;
 		break;
+	case OPT_FORCE_MAX_SIMD_BITWIDTH_NUM:
+		if (eal_parse_simd_bitwidth(optarg, 1) < 0) {
+			RTE_LOG(ERR, EAL, "invalid parameter for --"
+					OPT_FORCE_MAX_SIMD_BITWIDTH "\n");
+			return -1;
+		}
+		break;
 
 	/* don't know what to do, leave this to caller */
 	default:
@@ -1903,6 +1937,31 @@  eal_check_common_options(struct internal_config *internal_cfg)
 	return 0;
 }
 
+uint16_t
+rte_get_max_simd_bitwidth(void)
+{
+	const struct internal_config *internal_conf =
+		eal_get_internal_configuration();
+	return internal_conf->max_simd_bitwidth.bitwidth;
+}
+
+int
+rte_set_max_simd_bitwidth(uint16_t bitwidth)
+{
+	struct internal_config *internal_conf =
+		eal_get_internal_configuration();
+	if (internal_conf->max_simd_bitwidth.locked) {
+		RTE_LOG(NOTICE, EAL, "Cannot set max SIMD bitwidth - user runtime override enabled");
+		return -EPERM;
+	}
+	if (bitwidth < RTE_NO_SIMD || !rte_is_power_of_2(bitwidth)) {
+		RTE_LOG(ERR, EAL, "Invalid bitwidth value!\n");
+		return -EINVAL;
+	}
+	internal_conf->max_simd_bitwidth.bitwidth = bitwidth;
+	return 0;
+}
+
 void
 eal_common_usage(void)
 {
@@ -1981,6 +2040,7 @@  eal_common_usage(void)
 	       "  --"OPT_BASE_VIRTADDR"     Base virtual address\n"
 	       "  --"OPT_TELEMETRY"   Enable telemetry support (on by default)\n"
 	       "  --"OPT_NO_TELEMETRY"   Disable telemetry support\n"
+	       "  --"OPT_FORCE_MAX_SIMD_BITWIDTH" Force the max SIMD bitwidth\n"
 	       "\nEAL options for DEBUG use only:\n"
 	       "  --"OPT_HUGE_UNLINK"       Unlink hugepage files after init\n"
 	       "  --"OPT_NO_HUGE"           Use malloc instead of hugetlbfs\n"
diff --git a/lib/librte_eal/common/eal_internal_cfg.h b/lib/librte_eal/common/eal_internal_cfg.h
index 13f93388a7..367e0cc19e 100644
--- a/lib/librte_eal/common/eal_internal_cfg.h
+++ b/lib/librte_eal/common/eal_internal_cfg.h
@@ -33,6 +33,12 @@  struct hugepage_info {
 	int lock_descriptor;    /**< file descriptor for hugepage dir */
 };
 
+struct simd_bitwidth {
+	/**< flag indicating if bitwidth is locked from further modification */
+	bool locked;
+	uint16_t bitwidth; /**< bitwidth value */
+};
+
 /**
  * internal configuration
  */
@@ -85,6 +91,8 @@  struct internal_config {
 	volatile unsigned int init_complete;
 	/**< indicates whether EAL has completed initialization */
 	unsigned int no_telemetry; /**< true to disable Telemetry */
+	/** max simd bitwidth path to use */
+	struct simd_bitwidth max_simd_bitwidth;
 };
 
 void eal_reset_internal_config(struct internal_config *internal_cfg);
diff --git a/lib/librte_eal/common/eal_options.h b/lib/librte_eal/common/eal_options.h
index 89769d48b4..ef33979664 100644
--- a/lib/librte_eal/common/eal_options.h
+++ b/lib/librte_eal/common/eal_options.h
@@ -85,6 +85,8 @@  enum {
 	OPT_TELEMETRY_NUM,
 #define OPT_NO_TELEMETRY      "no-telemetry"
 	OPT_NO_TELEMETRY_NUM,
+#define OPT_FORCE_MAX_SIMD_BITWIDTH  "force-max-simd-bitwidth"
+	OPT_FORCE_MAX_SIMD_BITWIDTH_NUM,
 	OPT_LONG_MAX_NUM
 };
 
diff --git a/lib/librte_eal/include/rte_eal.h b/lib/librte_eal/include/rte_eal.h
index ddcf6a2e7a..8148f650f2 100644
--- a/lib/librte_eal/include/rte_eal.h
+++ b/lib/librte_eal/include/rte_eal.h
@@ -43,6 +43,13 @@  enum rte_proc_type_t {
 	RTE_PROC_INVALID
 };
 
+enum rte_max_simd_t {
+	RTE_NO_SIMD = 64,
+	RTE_MAX_128_SIMD = 128,
+	RTE_MAX_256_SIMD = 256,
+	RTE_MAX_512_SIMD = 512
+};
+
 /**
  * Get the process type in a multi-process setup
  *
@@ -51,6 +58,31 @@  enum rte_proc_type_t {
  */
 enum rte_proc_type_t rte_eal_process_type(void);
 
+/**
+ * Get the supported SIMD bitwidth.
+ *
+ * @return
+ *   uint16_t bitwidth.
+ */
+__rte_experimental
+uint16_t rte_get_max_simd_bitwidth(void);
+
+/**
+ * Set the supported SIMD bitwidth.
+ * This API should only be called once at initialization, before EAL init.
+ *
+ * @param bitwidth
+ *   uint16_t bitwidth.
+ * @return
+ *   0 on success.
+ * @return
+ *   -EINVAL on invalid bitwidth parameter.
+ * @return
+ *   -EPERM if bitwidth is locked.
+ */
+__rte_experimental
+int rte_set_max_simd_bitwidth(uint16_t bitwidth);
+
 /**
  * Request iopl privilege for all RPL.
  *
diff --git a/lib/librte_eal/rte_eal_version.map b/lib/librte_eal/rte_eal_version.map
index bf0c17c233..8059ea76b6 100644
--- a/lib/librte_eal/rte_eal_version.map
+++ b/lib/librte_eal/rte_eal_version.map
@@ -403,6 +403,10 @@  EXPERIMENTAL {
 	rte_mp_disable;
 	rte_thread_register;
 	rte_thread_unregister;
+
+	# added in 20.11
+	rte_get_max_simd_bitwidth;
+	rte_set_max_simd_bitwidth;
 };
 
 INTERNAL {