|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] [PATCH v2 07/15] x86: implement set value flow for MBA
On Thu, Aug 24, 2017 at 09:14:41AM +0800, Yi Sun wrote:
> This patch implements set value flow for MBA including its callback
> function and domctl interface.
>
> It also changes the memebers in 'cos_write_info' to transfer the
> feature array, feature properties array and value array. Then, we
> can write all features values on the cos id into MSRs.
>
> Because multiple features may co-exist, we need handle all features to write
> values of them into a COS register with new COS ID. E.g:
> 1. L3 CAT and MBA co-exist.
> 2. Dom1 and Dom2 share a same COS ID (2). The L3 CAT CBM of Dom1 is 0x1ff,
> the MBA Thrtle of Dom1 is 0xa.
> 3. User wants to change MBA Thrtl of Dom1 to be 0x14. Because COS ID 2 is
> used by Dom2 too, we have to pick a new COS ID 3. The original values of
> Dom1 on COS ID 3 may be below:
What original values? You said you pick COS ID 3, because I think it's
assumed to be empty? In which case there are no original values in COS
ID 3.
> ---------
> | COS 3 |
> ---------
> L3 CAT | 0x7ff |
> ---------
> MBA | 0x0 |
> ---------
> 4. After setting, the L3 CAT CBM value of Dom1 should be kept and the new MBA
> Thrtl is set. So, the values on COS ID 3 should be below.
> ---------
> | COS 3 |
> ---------
> L3 CAT | 0x1ff |
> ---------
> MBA | 0x14 |
> ---------
>
> So, we should write all features values into their MSRs. That requires the
> feature array, feature properties array and value array are input.
^ as
>
> Signed-off-by: Yi Sun <yi.y.sun@xxxxxxxxxxxxxxx>
> ---
> v2:
> - remove linear mode 'thrtl_max' check in 'mba_check_thrtl' because it has
> been checked in 'mba_init_feature'.
> (suggested by Chao Peng)
> - for non-linear mode, check if '*thrtl' is not 0 in 'mba_check_thrtl'. If
> it is 0, we do not need to change it.
> (suggested by Chao Peng)
> - move comments to explain changes of 'cos_write_info' from psr.c to
> commit
> message.
> (suggested by Chao Peng)
> ---
> xen/arch/x86/domctl.c | 6 ++
> xen/arch/x86/psr.c | 150
> ++++++++++++++++++++++++++++++--------------
> xen/include/public/domctl.h | 1 +
> 3 files changed, 109 insertions(+), 48 deletions(-)
>
> diff --git a/xen/arch/x86/domctl.c b/xen/arch/x86/domctl.c
> index 4936bcb..0ae4799 100644
> --- a/xen/arch/x86/domctl.c
> +++ b/xen/arch/x86/domctl.c
> @@ -1468,6 +1468,12 @@ long arch_do_domctl(
> PSR_VAL_TYPE_L2_CBM);
> break;
>
> + case XEN_DOMCTL_PSR_MBA_OP_SET_THRTL:
> + ret = psr_set_val(d, domctl->u.psr_alloc_op.target,
> + domctl->u.psr_alloc_op.data,
> + PSR_VAL_TYPE_MBA);
> + break;
> +
> case XEN_DOMCTL_PSR_CAT_OP_GET_L3_CBM:
> ret = psr_get_val(d, domctl->u.psr_alloc_op.target,
> &val32, PSR_VAL_TYPE_L3_CBM);
> diff --git a/xen/arch/x86/psr.c b/xen/arch/x86/psr.c
> index 4a0c982..ce82975 100644
> --- a/xen/arch/x86/psr.c
> +++ b/xen/arch/x86/psr.c
> @@ -138,6 +138,12 @@ static const struct feat_props {
>
> /* write_msr is used to write out feature MSR register. */
> void (*write_msr)(unsigned int cos, uint32_t val, enum psr_val_type
> type);
> +
> + /*
> + * check_val is used to check if input val fulfills SDM requirement.
> + * Change it to valid value if SDM allows.
I'm not really sure it's a good idea to change the value to a valid
one, IMHO you should just check and print an error if the value is
invalid (and return false of course).
> + */
> + bool (*check_val)(const struct feat_node *feat, unsigned long *val);
> } *feat_props[FEAT_TYPE_NUM];
>
> /*
> @@ -275,29 +281,6 @@ static enum psr_feat_type psr_val_type_to_feat_type(enum
> psr_val_type type)
> return feat_type;
> }
>
> -static bool psr_check_cbm(unsigned int cbm_len, unsigned long cbm)
> -{
> - unsigned int first_bit, zero_bit;
> -
> - /* Set bits should only in the range of [0, cbm_len]. */
> - if ( cbm & (~0ul << cbm_len) )
> - return false;
> -
> - /* At least one bit need to be set. */
> - if ( cbm == 0 )
> - return false;
> -
> - first_bit = find_first_bit(&cbm, cbm_len);
> - zero_bit = find_next_zero_bit(&cbm, cbm_len, first_bit);
> -
> - /* Set bits should be contiguous. */
> - if ( zero_bit < cbm_len &&
> - find_next_bit(&cbm, cbm_len, zero_bit) < cbm_len )
> - return false;
> -
> - return true;
> -}
> -
> /* Implementation of allocation features' functions. */
> static int cat_init_feature(const struct cpuid_leaf *regs,
> struct feat_node *feat,
> @@ -433,6 +416,30 @@ static bool cat_get_feat_info(const struct feat_node
> *feat,
> return true;
> }
>
> +static bool cat_check_cbm(const struct feat_node *feat, unsigned long *cbm)
> +{
> + unsigned int first_bit, zero_bit;
> + unsigned int cbm_len = feat->cat_info.cbm_len;
> +
> + /* Set bits should only in the range of [0, cbm_len]. */
> + if ( *cbm & (~0ul << cbm_len) )
> + return false;
> +
> + /* At least one bit need to be set. */
> + if ( *cbm == 0 )
> + return false;
> +
> + first_bit = find_first_bit(cbm, cbm_len);
> + zero_bit = find_next_zero_bit(cbm, cbm_len, first_bit);
> +
> + /* Set bits should be contiguous. */
> + if ( zero_bit < cbm_len &&
> + find_next_bit(cbm, cbm_len, zero_bit) < cbm_len )
> + return false;
> +
> + return true;
> +}
> +
> /* L3 CAT props */
> static void l3_cat_write_msr(unsigned int cos, uint32_t val,
> enum psr_val_type type)
> @@ -446,6 +453,7 @@ static const struct feat_props l3_cat_props = {
> .alt_type = PSR_VAL_TYPE_UNKNOWN,
> .get_feat_info = cat_get_feat_info,
> .write_msr = l3_cat_write_msr,
> + .check_val = cat_check_cbm,
> };
Maybe the introduction of check_val should be a separate patch? It's
mostly code movement and some fixup.
> /* L3 CDP props */
> @@ -476,6 +484,7 @@ static const struct feat_props l3_cdp_props = {
> .alt_type = PSR_VAL_TYPE_L3_CBM,
> .get_feat_info = l3_cdp_get_feat_info,
> .write_msr = l3_cdp_write_msr,
> + .check_val = cat_check_cbm,
> };
>
> /* L2 CAT props */
> @@ -491,6 +500,7 @@ static const struct feat_props l2_cat_props = {
> .alt_type = PSR_VAL_TYPE_UNKNOWN,
> .get_feat_info = cat_get_feat_info,
> .write_msr = l2_cat_write_msr,
> + .check_val = cat_check_cbm,
> };
>
> /* MBA props */
> @@ -514,6 +524,40 @@ static bool mba_get_feat_info(const struct feat_node
> *feat,
> static void mba_write_msr(unsigned int cos, uint32_t val,
> enum psr_val_type type)
> {
> + wrmsrl(MSR_IA32_PSR_MBA_MASK(cos), val);
> +}
> +
> +static bool mba_check_thrtl(const struct feat_node *feat, unsigned long
> *thrtl)
> +{
> + if ( *thrtl > feat->mba_info.thrtl_max )
> + return false;
> +
> + /*
> + * Per SDM (chapter "Memory Bandwidth Allocation Configuration"):
> + * 1. Linear mode: In the linear mode the input precision is defined
> + * as 100-(MBA_MAX). For instance, if the MBA_MAX value is 90, the
> + * input precision is 10%. Values not an even multiple of the
> + * precision (e.g., 12%) will be rounded down (e.g., to 10% delay
> + * applied).
> + * 2. Non-linear mode: Input delay values are powers-of-two from zero
> + * to the MBA_MAX value from CPUID. In this case any values not a
> + * power of two will be rounded down the next nearest power of two.
> + */
> + if ( feat->mba_info.linear )
> + {
> + unsigned int mod;
> +
> + mod = *thrtl % (100 - feat->mba_info.thrtl_max);
> + *thrtl -= mod;
> + }
> + else
> + {
> + /* Not power of 2. */
> + if ( *thrtl && (*thrtl & (*thrtl - 1)) )
This can be joined with the else to avoid another indentation level:
else if ( *thrtl && (*thrtl & (*thrtl - 1)) )
...
> + *thrtl = *thrtl & (1 << (flsl(*thrtl) - 1));
> + }
> +
> + return true;
> }
>
> static const struct feat_props mba_props = {
> @@ -522,6 +566,7 @@ static const struct feat_props mba_props = {
> .alt_type = PSR_VAL_TYPE_UNKNOWN,
> .get_feat_info = mba_get_feat_info,
> .write_msr = mba_write_msr,
> + .check_val = mba_check_thrtl,
> };
>
> static void __init parse_psr_bool(char *s, char *value, char *feature,
> @@ -942,6 +987,7 @@ static int insert_val_into_array(uint32_t val[],
> const struct feat_node *feat;
> const struct feat_props *props;
> unsigned int i;
> + unsigned long check_val = new_val;
> int ret;
>
> ASSERT(feat_type < FEAT_TYPE_NUM);
> @@ -966,9 +1012,11 @@ static int insert_val_into_array(uint32_t val[],
> if ( array_len < props->cos_num )
> return -ENOSPC;
>
> - if ( !psr_check_cbm(feat->cat_info.cbm_len, new_val) )
> + if ( !props->check_val(feat, &check_val) )
> return -EINVAL;
>
> + new_val = check_val;
> +
> /*
> * Value setting position is same as feature array.
> * For CDP, user may set both DATA and CODE to same value. For such case,
> @@ -1198,25 +1246,42 @@ static unsigned int get_socket_cpu(unsigned int
> socket)
> struct cos_write_info
> {
> unsigned int cos;
> - struct feat_node *feature;
> + struct feat_node **features;
> const uint32_t *val;
> - const struct feat_props *props;
> + unsigned int array_len;
> + const struct feat_props **props;
> };
>
> static void do_write_psr_msrs(void *data)
> {
> const struct cos_write_info *info = data;
> - struct feat_node *feat = info->feature;
> - const struct feat_props *props = info->props;
> - unsigned int i, cos = info->cos, cos_num = props->cos_num;
> + unsigned int i, j, index = 0, array_len = info->array_len, cos =
> info->cos;
> + const uint32_t *val_array = info->val;
>
> - for ( i = 0; i < cos_num; i++ )
> + for ( i = 0; i < ARRAY_SIZE(feat_props); i++ )
> {
index and j can be defined here, they are only used inside of this for
loop AFAICT.
> - if ( feat->cos_reg_val[cos * cos_num + i] != info->val[i] )
> + struct feat_node *feat = info->features[i];
> + const struct feat_props *props = info->props[i];
> + unsigned int cos_num;
> +
> + if ( !feat || !props )
> + continue;
> +
> + cos_num = props->cos_num;
> + if ( array_len < cos_num )
> + return;
> +
> + for ( j = 0; j < cos_num; j++ )
> {
> - feat->cos_reg_val[cos * cos_num + i] = info->val[i];
> - props->write_msr(cos, info->val[i], props->type[i]);
> + if ( feat->cos_reg_val[cos * cos_num + j] != val_array[index +
> j] )
> + {
> + feat->cos_reg_val[cos * cos_num + j] = val_array[index + j];
> + props->write_msr(cos, val_array[index + j], props->type[j]);
> + }
> }
> +
> + array_len -= cos_num;
> + index += cos_num;
> }
> }
>
> @@ -1224,30 +1289,19 @@ static int write_psr_msrs(unsigned int socket,
> unsigned int cos,
> const uint32_t val[], unsigned int array_len,
> enum psr_feat_type feat_type)
> {
> - int ret;
> struct psr_socket_info *info = get_socket_info(socket);
info should probably be const here.
> struct cos_write_info data =
> {
> .cos = cos,
> - .feature = info->features[feat_type],
> - .props = feat_props[feat_type],
> + .features = info->features,
> + .val = val,
> + .array_len = array_len,
> + .props = feat_props,
> };
AFAICT data should also be const, but I guess this is not going to
work because on_selected_cpus expects a non-const payload?
Thanks, Roger.
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
https://lists.xen.org/xen-devel
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |