diff mbox

[v8,10/24] x86: refactor psr: set value: implement cos finding flow.

Message ID 1487148579-7243-11-git-send-email-yi.y.sun@linux.intel.com (mailing list archive)
State New, archived
Headers show

Commit Message

Yi Sun Feb. 15, 2017, 8:49 a.m. UTC
Continue with patch:
'x86: refactor psr: set value: assemble features value array'

We can try to find if there is a COS ID on which all features' COS registers
values are same as the array assembled before.

Signed-off-by: Yi Sun <yi.y.sun@linux.intel.com>
---
 xen/arch/x86/psr.c | 93 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 93 insertions(+)

Comments

Wei Liu Feb. 26, 2017, 5:43 p.m. UTC | #1
On Wed, Feb 15, 2017 at 04:49:25PM +0800, Yi Sun wrote:
> Continue with patch:
> 'x86: refactor psr: set value: assemble features value array'
> 
> We can try to find if there is a COS ID on which all features' COS registers
> values are same as the array assembled before.
> 
> Signed-off-by: Yi Sun <yi.y.sun@linux.intel.com>
> ---
>  xen/arch/x86/psr.c | 93 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 93 insertions(+)
> 
> diff --git a/xen/arch/x86/psr.c b/xen/arch/x86/psr.c
> index ae108b9..7fab28b 100644
> --- a/xen/arch/x86/psr.c
> +++ b/xen/arch/x86/psr.c
> @@ -145,6 +145,19 @@ struct feat_ops {
>                         const struct feat_node *feat,
>                         enum cbm_type type,
>                         uint64_t m);
> +    /*
> +     * compare_val is used in set value process to compare if the
> +     * input value array can match all the features' COS registers values
> +     * according to input cos id.
> +     *
> +     * The return value is the amount of entries to skip in the value array
> +     * or error.
> +     * 1 - one entry in value array.
> +     * 2 - two entries in value array, e.g. CDP uses two entries.
> +     * negative - error.

This doesn't match the code (yet?).

What about return value 0?

> +     */
> +    int (*compare_val)(const uint64_t val[], const struct feat_node *feat,
> +                        unsigned int cos, bool *found);

Indentation.


Wei.
Yi Sun Feb. 27, 2017, 7:16 a.m. UTC | #2
On 17-02-26 17:43:20, Wei Liu wrote:
> On Wed, Feb 15, 2017 at 04:49:25PM +0800, Yi Sun wrote:
> > Continue with patch:
> > 'x86: refactor psr: set value: assemble features value array'
> > 
> > We can try to find if there is a COS ID on which all features' COS registers
> > values are same as the array assembled before.
> > 
> > Signed-off-by: Yi Sun <yi.y.sun@linux.intel.com>
> > ---
> >  xen/arch/x86/psr.c | 93 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
> >  1 file changed, 93 insertions(+)
> > 
> > diff --git a/xen/arch/x86/psr.c b/xen/arch/x86/psr.c
> > index ae108b9..7fab28b 100644
> > --- a/xen/arch/x86/psr.c
> > +++ b/xen/arch/x86/psr.c
> > @@ -145,6 +145,19 @@ struct feat_ops {
> >                         const struct feat_node *feat,
> >                         enum cbm_type type,
> >                         uint64_t m);
> > +    /*
> > +     * compare_val is used in set value process to compare if the
> > +     * input value array can match all the features' COS registers values
> > +     * according to input cos id.
> > +     *
> > +     * The return value is the amount of entries to skip in the value array
> > +     * or error.
> > +     * 1 - one entry in value array.
> > +     * 2 - two entries in value array, e.g. CDP uses two entries.
> > +     * negative - error.
> 
> This doesn't match the code (yet?).
> 
> What about return value 0?
> 
Oh, sorry, per Jan's suggestion, I have change the type of the function. But I
forgot the modify the comments. Will fix it.

> > +     */
> > +    int (*compare_val)(const uint64_t val[], const struct feat_node *feat,
> > +                        unsigned int cos, bool *found);
> 
> Indentation.
> 
Thanks!

> 
> Wei.
Jan Beulich March 8, 2017, 5:03 p.m. UTC | #3
>>> On 15.02.17 at 09:49, <yi.y.sun@linux.intel.com> wrote:
> Continue with patch:

???

> 'x86: refactor psr: set value: assemble features value array'

Or did you perhaps mean "continue from"?

> --- a/xen/arch/x86/psr.c
> +++ b/xen/arch/x86/psr.c
> @@ -145,6 +145,19 @@ struct feat_ops {
>                         const struct feat_node *feat,
>                         enum cbm_type type,
>                         uint64_t m);
> +    /*
> +     * compare_val is used in set value process to compare if the
> +     * input value array can match all the features' COS registers values
> +     * according to input cos id.
> +     *
> +     * The return value is the amount of entries to skip in the value array
> +     * or error.
> +     * 1 - one entry in value array.
> +     * 2 - two entries in value array, e.g. CDP uses two entries.

Isn't this get_cos_num()'s result again? Or, looking at the function
below, is the comment simply stale?

> @@ -356,6 +369,34 @@ static int l3_cat_set_new_val(uint64_t val[],
>      return 0;
>  }
>  
> +static int l3_cat_compare_val(const uint64_t val[],
> +                              const struct feat_node *feat,
> +                              unsigned int cos, bool *found)
> +{
> +    uint64_t l3_def_cbm;
> +
> +    l3_def_cbm = (1ull << feat->info.l3_cat_info.cbm_len) - 1;

Please only calculate the value on the path you need it. Also this
will again degenerate of cbm_len == 64.

> +    /*
> +     * Different features' cos_max are different. If cos id of the feature
> +     * being set exceeds other feature's cos_max, the val of other feature
> +     * must be default value. HW supports such case.
> +     */
> +    if ( cos > feat->info.l3_cat_info.cos_max )
> +    {
> +        if ( val[0] != l3_def_cbm )
> +        {
> +            *found = false;
> +            return -ENOENT;

What is the difference between this "not found" and ...

> +        }
> +        *found = true;
> +    }
> +    else
> +        *found = (val[0] == feat->cos_reg_val[cos]);
> +
> +    return 0;

... the possible one here? I.e. why once -ENOENT and once 0 as
return value?

> @@ -715,6 +757,57 @@ static int find_cos(const uint64_t *val, uint32_t array_len,
>                      enum psr_feat_type feat_type,
>                      const struct psr_socket_info *info)
>  {
> +    unsigned int cos;
> +    const unsigned int *ref = info->cos_ref;
> +    const struct feat_node *feat;
> +    const uint64_t *val_tmp = val;
> +    int ret;
> +    bool found = false;
> +    unsigned int cos_max = 0;
> +
> +    /* cos_max is the one of the feature which is being set. */
> +    list_for_each_entry(feat, &info->feat_list, list)
> +    {
> +        if ( feat->feature != feat_type )
> +            continue;
> +
> +        cos_max = feat->ops.get_cos_max(feat);
> +        if ( cos_max > 0 )

What's the purpose of this check? I.e. why do you continue the loop
in case you find zero? You won't find another node with the same
feat_type, will you?

> +            break;
> +    }
> +
> +    for ( cos = 0; cos <= cos_max; cos++ )
> +    {
> +        if ( cos && !ref[cos] )
> +            continue;
> +
> +        /* Not found, need find again from beginning. */

You may not even have looked yet, so how can you say "not found"?

Jan
Yi Sun March 10, 2017, 5:35 a.m. UTC | #4
On 17-03-08 10:03:10, Jan Beulich wrote:
> >>> On 15.02.17 at 09:49, <yi.y.sun@linux.intel.com> wrote:
> > Continue with patch:
> 
> ???
> 
> > 'x86: refactor psr: set value: assemble features value array'
> 
> Or did you perhaps mean "continue from"?
> 
Should be 'from'. Thanks!

> > --- a/xen/arch/x86/psr.c
> > +++ b/xen/arch/x86/psr.c
> > @@ -145,6 +145,19 @@ struct feat_ops {
> >                         const struct feat_node *feat,
> >                         enum cbm_type type,
> >                         uint64_t m);
> > +    /*
> > +     * compare_val is used in set value process to compare if the
> > +     * input value array can match all the features' COS registers values
> > +     * according to input cos id.
> > +     *
> > +     * The return value is the amount of entries to skip in the value array
> > +     * or error.
> > +     * 1 - one entry in value array.
> > +     * 2 - two entries in value array, e.g. CDP uses two entries.
> 
> Isn't this get_cos_num()'s result again? Or, looking at the function
> below, is the comment simply stale?
> 
Sorry, forgot to update it.

> > @@ -356,6 +369,34 @@ static int l3_cat_set_new_val(uint64_t val[],
> >      return 0;
> >  }
> >  
> > +static int l3_cat_compare_val(const uint64_t val[],
> > +                              const struct feat_node *feat,
> > +                              unsigned int cos, bool *found)
> > +{
> > +    uint64_t l3_def_cbm;
> > +
> > +    l3_def_cbm = (1ull << feat->info.l3_cat_info.cbm_len) - 1;
> 
> Please only calculate the value on the path you need it. Also this
> will again degenerate of cbm_len == 64.
> 
Sorry, what do you mean? I need get the default value of L3 CAT here
to check if input val equals the default one if cos exceeds cos_max.

As explanation in previous patch, cbm_len is not 64. It means how many bits
the CBM value has. E.g. L3 CAT may have 11 bits. L2 CAT may have 8 bits.

> > +    /*
> > +     * Different features' cos_max are different. If cos id of the feature
> > +     * being set exceeds other feature's cos_max, the val of other feature
> > +     * must be default value. HW supports such case.
> > +     */
> > +    if ( cos > feat->info.l3_cat_info.cos_max )
> > +    {
> > +        if ( val[0] != l3_def_cbm )
> > +        {
> > +            *found = false;
> > +            return -ENOENT;
> 
> What is the difference between this "not found" and ...
> 
This is an error case. If input cos exceeds the cos_max and the input val is
not default value, that means the input parameters exceed HW ability. We should
report error back.

> > +        }
> > +        *found = true;
> > +    }
> > +    else
> > +        *found = (val[0] == feat->cos_reg_val[cos]);
> > +
> > +    return 0;
> 
> ... the possible one here? I.e. why once -ENOENT and once 0 as
> return value?
> 
0 means success. '*found' means if the val is found or not. Per Roger's
suggestion, I will refine this function to use return value to check
if it is found or not.

> > @@ -715,6 +757,57 @@ static int find_cos(const uint64_t *val, uint32_t array_len,
> >                      enum psr_feat_type feat_type,
> >                      const struct psr_socket_info *info)
> >  {
> > +    unsigned int cos;
> > +    const unsigned int *ref = info->cos_ref;
> > +    const struct feat_node *feat;
> > +    const uint64_t *val_tmp = val;
> > +    int ret;
> > +    bool found = false;
> > +    unsigned int cos_max = 0;
> > +
> > +    /* cos_max is the one of the feature which is being set. */
> > +    list_for_each_entry(feat, &info->feat_list, list)
> > +    {
> > +        if ( feat->feature != feat_type )
> > +            continue;
> > +
> > +        cos_max = feat->ops.get_cos_max(feat);
> > +        if ( cos_max > 0 )
> 
> What's the purpose of this check? I.e. why do you continue the loop
> in case you find zero? You won't find another node with the same
> feat_type, will you?
> 
This is corrected in next version. Thanks!

> > +            break;
> > +    }
> > +
> > +    for ( cos = 0; cos <= cos_max; cos++ )
> > +    {
> > +        if ( cos && !ref[cos] )
> > +            continue;
> > +
> > +        /* Not found, need find again from beginning. */
> 
> You may not even have looked yet, so how can you say "not found"?
> 
Sorry, it should be "If not found, need find again...".

> Jan
Jan Beulich March 10, 2017, 9:21 a.m. UTC | #5
>>> On 10.03.17 at 06:35, <yi.y.sun@linux.intel.com> wrote:
> On 17-03-08 10:03:10, Jan Beulich wrote:
>> >>> On 15.02.17 at 09:49, <yi.y.sun@linux.intel.com> wrote:
>> > @@ -356,6 +369,34 @@ static int l3_cat_set_new_val(uint64_t val[],
>> >      return 0;
>> >  }
>> >  
>> > +static int l3_cat_compare_val(const uint64_t val[],
>> > +                              const struct feat_node *feat,
>> > +                              unsigned int cos, bool *found)
>> > +{
>> > +    uint64_t l3_def_cbm;
>> > +
>> > +    l3_def_cbm = (1ull << feat->info.l3_cat_info.cbm_len) - 1;
>> 
>> Please only calculate the value on the path you need it. Also this
>> will again degenerate of cbm_len == 64.
>> 
> Sorry, what do you mean? I need get the default value of L3 CAT here
> to check if input val equals the default one if cos exceeds cos_max.

No, you don't need it at function scope. You only need it ...

>> > +    /*
>> > +     * Different features' cos_max are different. If cos id of the feature
>> > +     * being set exceeds other feature's cos_max, the val of other feature
>> > +     * must be default value. HW supports such case.
>> > +     */
>> > +    if ( cos > feat->info.l3_cat_info.cos_max )
>> > +    {
>> > +        if ( val[0] != l3_def_cbm )

... in this more narrow one. Specifically no code outside the outer
if() needs the variable.

>> > +        {
>> > +            *found = false;
>> > +            return -ENOENT;
>> 
>> What is the difference between this "not found" and ...
>> 
> This is an error case. If input cos exceeds the cos_max and the input val is
> not default value, that means the input parameters exceed HW ability. We should
> report error back.
> 
>> > +        }
>> > +        *found = true;
>> > +    }
>> > +    else
>> > +        *found = (val[0] == feat->cos_reg_val[cos]);
>> > +
>> > +    return 0;
>> 
>> ... the possible one here? I.e. why once -ENOENT and once 0 as
>> return value?
>> 
> 0 means success. '*found' means if the val is found or not.

I still don't understand the difference, but perhaps this will all sort
itself out once the cos_max checks get done in common code and
the default values (suitably stored, as suggested elsewhere) can
also be checked by common code. In fact with that I'm not even
sure you will continue to require this feature dependent actor
anymore.

> Per Roger's
> suggestion, I will refine this function to use return value to check
> if it is found or not.

Well, let's see how this ends up being.

Jan
diff mbox

Patch

diff --git a/xen/arch/x86/psr.c b/xen/arch/x86/psr.c
index ae108b9..7fab28b 100644
--- a/xen/arch/x86/psr.c
+++ b/xen/arch/x86/psr.c
@@ -145,6 +145,19 @@  struct feat_ops {
                        const struct feat_node *feat,
                        enum cbm_type type,
                        uint64_t m);
+    /*
+     * compare_val is used in set value process to compare if the
+     * input value array can match all the features' COS registers values
+     * according to input cos id.
+     *
+     * The return value is the amount of entries to skip in the value array
+     * or error.
+     * 1 - one entry in value array.
+     * 2 - two entries in value array, e.g. CDP uses two entries.
+     * negative - error.
+     */
+    int (*compare_val)(const uint64_t val[], const struct feat_node *feat,
+                        unsigned int cos, bool *found);
 };
 
 /*
@@ -356,6 +369,34 @@  static int l3_cat_set_new_val(uint64_t val[],
     return 0;
 }
 
+static int l3_cat_compare_val(const uint64_t val[],
+                              const struct feat_node *feat,
+                              unsigned int cos, bool *found)
+{
+    uint64_t l3_def_cbm;
+
+    l3_def_cbm = (1ull << feat->info.l3_cat_info.cbm_len) - 1;
+
+    /*
+     * Different features' cos_max are different. If cos id of the feature
+     * being set exceeds other feature's cos_max, the val of other feature
+     * must be default value. HW supports such case.
+     */
+    if ( cos > feat->info.l3_cat_info.cos_max )
+    {
+        if ( val[0] != l3_def_cbm )
+        {
+            *found = false;
+            return -ENOENT;
+        }
+        *found = true;
+    }
+    else
+        *found = (val[0] == feat->cos_reg_val[cos]);
+
+    return 0;
+}
+
 static const struct feat_ops l3_cat_ops = {
     .get_cos_max = l3_cat_get_cos_max,
     .get_feat_info = l3_cat_get_feat_info,
@@ -363,6 +404,7 @@  static const struct feat_ops l3_cat_ops = {
     .get_cos_num = l3_cat_get_cos_num,
     .get_old_val = l3_cat_get_old_val,
     .set_new_val = l3_cat_set_new_val,
+    .compare_val = l3_cat_compare_val,
 };
 
 static void __init parse_psr_bool(char *s, char *value, char *feature,
@@ -715,6 +757,57 @@  static int find_cos(const uint64_t *val, uint32_t array_len,
                     enum psr_feat_type feat_type,
                     const struct psr_socket_info *info)
 {
+    unsigned int cos;
+    const unsigned int *ref = info->cos_ref;
+    const struct feat_node *feat;
+    const uint64_t *val_tmp = val;
+    int ret;
+    bool found = false;
+    unsigned int cos_max = 0;
+
+    /* cos_max is the one of the feature which is being set. */
+    list_for_each_entry(feat, &info->feat_list, list)
+    {
+        if ( feat->feature != feat_type )
+            continue;
+
+        cos_max = feat->ops.get_cos_max(feat);
+        if ( cos_max > 0 )
+            break;
+    }
+
+    for ( cos = 0; cos <= cos_max; cos++ )
+    {
+        if ( cos && !ref[cos] )
+            continue;
+
+        /* Not found, need find again from beginning. */
+        val_tmp = val;
+        list_for_each_entry(feat, &info->feat_list, list)
+        {
+            /*
+             * Compare value according to feature list order.
+             * We must follow this order because value array is assembled
+             * as this order in get_old_set_new().
+             */
+            ret = feat->ops.compare_val(val_tmp, feat, cos, &found);
+            if ( ret < 0 )
+                return ret;
+
+            /* If fail to match, go to next cos to compare. */
+            if ( !found )
+                break;
+
+            val_tmp += feat->ops.get_cos_num(feat);
+            if ( val_tmp - val > array_len )
+                return -EINVAL;
+        }
+
+        /* For this COS ID all entries in the values array did match. Use it. */
+        if ( found )
+            return cos;
+    }
+
     return -ENOENT;
 }