[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Xen-devel] [PATCH v9 10/25] x86: refactor psr: L3 CAT: set value: assemble features value array.



>>> On 16.03.17 at 12:08, <yi.y.sun@xxxxxxxxxxxxxxx> wrote:
> --- a/xen/arch/x86/psr.c
> +++ b/xen/arch/x86/psr.c
> @@ -101,6 +101,28 @@ struct feat_node {
>          /* get_val is used to get feature COS register value. */
>          void (*get_val)(const struct feat_node *feat, unsigned int cos,
>                          enum cbm_type type, uint32_t *val);
> +
> +        /*
> +         * get_old_val and set_new_val are a pair of functions called in 
> order.
> +         * The caller will traverse all features in the array and call
> +         * 'get_old_val' to get old_cos register value of all supported
> +         * features. Then, call 'set_new_val' to set the new value for the
> +         * designated feature.
> +         *
> +         * All the values are set into value array according to the traversal
> +         * order, meaning the same order of feature array members.
> +         *
> +         * The return value meaning of set_new_val:
> +         * 0 - success.
> +         * negative - error.
> +         */
> +        void (*get_old_val)(uint32_t val[],
> +                            const struct feat_node *feat,
> +                            unsigned int old_cos);
> +        int (*set_new_val)(uint32_t val[],
> +                           const struct feat_node *feat,
> +                           enum cbm_type type,
> +                           uint32_t new_val);

Along the lines of an earlier comment - are "old" and "new" really
meaningful here?

> @@ -212,6 +234,29 @@ static enum psr_feat_type psr_cbm_type_to_feat_type(enum 
> cbm_type type)
>  }
>  
>  /* CAT common functions implementation. */
> +static bool psr_check_cbm(unsigned int cbm_len, uint32_t cbm)
> +{
> +    unsigned int first_bit, zero_bit;
> +
> +    /* Set bits should only in the range of [0, cbm_len]. */
> +    if ( cbm & (~0ul << cbm_len) )

Same question as elsewhere about the use of the ul suffix here:
Can cbm_len really be any value in [0,32]? If not, I don't see
why the calculation needs to be done as unsigned long. Otoh ...

> +        return false;
> +
> +    /* At least one bit need to be set. */
> +    if ( cbm == 0 )
> +        return false;
> +
> +    first_bit = find_first_bit((uint64_t *)&cbm, cbm_len);
> +    zero_bit = find_next_zero_bit((uint64_t *)&cbm, cbm_len, first_bit);

... these bogus casts suggest that the function would best have
an "unsigned long" parameter.

> @@ -285,11 +330,35 @@ static void cat_get_val(const struct feat_node *feat, 
> unsigned int cos,
>      *val = feat->cos_reg_val[cos];
>  }
>  
> +/* val[] len checking is done by caller. */
> +static void cat_get_old_val(uint32_t val[],
> +                            const struct feat_node *feat,
> +                            unsigned int old_cos)
> +{
> +    cat_get_val(feat, old_cos, 0, &val[0]);
> +}
> +
> +/* val[] len checking is done by caller. */
> +static int cat_set_new_val(uint32_t val[],
> +                           const struct feat_node *feat,
> +                           enum cbm_type type,
> +                           uint32_t new_val)
> +{
> +    if ( !psr_check_cbm(feat->info.cat_info.cbm_len, new_val) )
> +        return -EINVAL;
> +
> +    val[0] = new_val;
> +
> +    return 0;
> +}
> +
>  /* L3 CAT ops */
>  static const struct feat_ops l3_cat_ops = {
>      .get_cos_max = cat_get_cos_max,
>      .get_feat_info = cat_get_feat_info,
>      .get_val = cat_get_val,
> +    .get_old_val = cat_get_old_val,
> +    .set_new_val = cat_set_new_val,
>  };
>  
>  static void __init parse_psr_bool(char *s, char *value, char *feature,
> @@ -581,7 +650,21 @@ int psr_get_val(struct domain *d, unsigned int socket,
>  /* Set value functions */
>  static unsigned int get_cos_num(const struct psr_socket_info *info)
>  {
> -    return 0;
> +    const struct feat_node *feat;
> +    unsigned int num = 0, i;
> +
> +    /* Get all features total amount. */
> +    for ( i = 0; i < PSR_SOCKET_MAX_FEAT; i++ )
> +    {
> +        if ( !info->features[i] )
> +            continue;
> +
> +        feat = info->features[i];
> +
> +        num += feat->cos_num;
> +    }
> +
> +    return num;
>  }
>  
>  static int gather_val_array(uint32_t val[],
> @@ -589,7 +672,34 @@ static int gather_val_array(uint32_t val[],
>                              const struct psr_socket_info *info,
>                              unsigned int old_cos)
>  {
> -    return -EINVAL;
> +    const struct feat_node *feat;
> +    unsigned int i;
> +
> +    if ( !val )
> +        return -EINVAL;
> +
> +    /* Get all features current values according to old_cos. */
> +    for ( i = 0; i < PSR_SOCKET_MAX_FEAT; i++ )
> +    {
> +        if ( !info->features[i] )
> +            continue;
> +
> +        feat = info->features[i];
> +
> +        if ( old_cos > feat->ops.get_cos_max(feat) )
> +            old_cos = 0;
> +
> +        /* value getting order is same as feature array */
> +        feat->ops.get_old_val(val, feat, old_cos);
> +
> +        array_len -= feat->cos_num;

So this I should really have asked about on a much earlier patch,
but I've recognize the oddity only now: Why is cos_num
per-feature-node instead of per-feature? This should really be a
field in struct feat_ops (albeit the name "ops" then will be slightly
misleading, but I think that's tolerable if you can't think of a better
name).

> +        if ( array_len < 0 )
> +            return -ENOSPC;

This check needs doing earlier - you need to make sure array_len
>= ops.cos_num prior to calling ops.get_old_val(). (Doing the
check after the subtraction even causes wrapping issues, which
are even more visible in similar code further down.)

> @@ -599,7 +709,43 @@ static int insert_new_val_to_array(uint32_t val[],
>                                     enum cbm_type type,
>                                     uint32_t new_val)
>  {
> -    return -EINVAL;
> +    const struct feat_node *feat;
> +    int ret;
> +    unsigned int i;
> +
> +    ASSERT(feat_type < PSR_SOCKET_MAX_FEAT);
> +
> +    /* Set new value into array according to feature's position in array. */
> +    for ( i = 0; i < feat_type; i++ )
> +    {
> +        if ( !info->features[i] )
> +            continue;
> +
> +        feat = info->features[i];
> +
> +        array_len -= feat->cos_num;
> +        if ( array_len <= 0 )
> +            return -ENOSPC;
> +
> +        val += feat->cos_num;
> +    }
> +
> +    feat = info->features[feat_type];
> +
> +    array_len -= feat->cos_num;
> +    if ( array_len < 0 )
> +        return -ENOSPC;
> +
> +    /*
> +     * Value setting position is same as feature array.
> +     * Different features may have different setting behaviors, e.g. CDP
> +     * has two values (DATA/CODE) which need us to save input value to
> +     * different position in the array according to type, so we have to
> +     * maintain a callback function.
> +     */
> +    ret = feat->ops.set_new_val(val, feat, type, new_val);
> +
> +    return ret;

Again a case of a pointless intermediate variable.

Jan

_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
https://lists.xen.org/xen-devel

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.