diff mbox

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

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

Commit Message

Yi Sun Dec. 14, 2016, 4:07 a.m. UTC
Continue with previous patch, 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 | 111 ++++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 110 insertions(+), 1 deletion(-)

Comments

Jan Beulich Jan. 10, 2017, 2:53 p.m. UTC | #1
>>> On 14.12.16 at 05:07, <yi.y.sun@linux.intel.com> wrote:
> Continue with previous patch, we can try to find if there is a

Please take into consideration that a series may be applied in small
steps. References such as "previous patch" are thus possibly
meaningless. Please instead refer to the patch by title. Also I think
you mean "continue from ...".

> @@ -666,7 +724,58 @@ static int find_cos(const uint64_t *val, uint32_t array_len,
>                      enum cbm_type type,
>                      const struct psr_socket_info *info)
>  {
> -    return 0;
> +    unsigned int cos;
> +    const unsigned int *ref = info->cos_ref;
> +    const struct feat_node *feat_tmp;
> +    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_tmp, &info->feat_list, list)
> +    {
> +        cos_max = feat_tmp->ops.get_cos_max_from_type(feat_tmp, type);
> +        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_tmp, &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_tmp->ops.compare_val(val_tmp, feat_tmp, cos, &found);
> +            if ( ret < 0 )
> +                return ret;
> +
> +            /* If fail to match, go to next cos to compare. */
> +            if ( !found )
> +                break;
> +
> +            val_tmp += ret;
> +            if ( val_tmp - val > array_len )
> +                return -EINVAL;
> +        }
> +
> +        /*
> +         * With this cos id, every entry of value array can match. This cos
> +         * is what we find.
> +         */

"can match" seems rather misleading to me. I think you mean
something like "For this COS ID all entries in the values array did
match. Use it."

Other than that various of the comments given for earlier patches
apply here, in particular the fact that the type matching should
move out of the hook functions.

Jan
Yi Sun Jan. 11, 2017, 6:10 a.m. UTC | #2
On 17-01-10 07:53:07, Jan Beulich wrote:
> >>> On 14.12.16 at 05:07, <yi.y.sun@linux.intel.com> wrote:
> > Continue with previous patch, we can try to find if there is a
> 
> Please take into consideration that a series may be applied in small
> steps. References such as "previous patch" are thus possibly
> meaningless. Please instead refer to the patch by title. Also I think
> you mean "continue from ...".
> 
Thank you!

> > @@ -666,7 +724,58 @@ static int find_cos(const uint64_t *val, uint32_t array_len,
> >                      enum cbm_type type,
> >                      const struct psr_socket_info *info)
> >  {
> > -    return 0;
> > +    unsigned int cos;
> > +    const unsigned int *ref = info->cos_ref;
> > +    const struct feat_node *feat_tmp;
> > +    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_tmp, &info->feat_list, list)
> > +    {
> > +        cos_max = feat_tmp->ops.get_cos_max_from_type(feat_tmp, type);
> > +        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_tmp, &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_tmp->ops.compare_val(val_tmp, feat_tmp, cos, &found);
> > +            if ( ret < 0 )
> > +                return ret;
> > +
> > +            /* If fail to match, go to next cos to compare. */
> > +            if ( !found )
> > +                break;
> > +
> > +            val_tmp += ret;
> > +            if ( val_tmp - val > array_len )
> > +                return -EINVAL;
> > +        }
> > +
> > +        /*
> > +         * With this cos id, every entry of value array can match. This cos
> > +         * is what we find.
> > +         */
> 
> "can match" seems rather misleading to me. I think you mean
> something like "For this COS ID all entries in the values array did
> match. Use it."
> 
Yes, sorry for the wording.

> Other than that various of the comments given for earlier patches
> apply here, in particular the fact that the type matching should
> move out of the hook functions.
> 
Will try this. Thanks!

> Jan
> 
> 
> _______________________________________________
> Xen-devel mailing list
> Xen-devel@lists.xen.org
> https://lists.xen.org/xen-devel
diff mbox

Patch

diff --git a/xen/arch/x86/psr.c b/xen/arch/x86/psr.c
index 8fcaa76..6b2b1e0 100644
--- a/xen/arch/x86/psr.c
+++ b/xen/arch/x86/psr.c
@@ -150,6 +150,25 @@  struct feat_ops {
                        unsigned int old_cos,
                        enum cbm_type type,
                        uint64_t m);
+    /*
+     * get_cos_max_from_type is used to get the cos_max value of the feature
+     * according to input type.
+     */
+    unsigned int (*get_cos_max_from_type)(const struct feat_node *feat,
+                                          enum cbm_type type);
+    /*
+     * 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);
 };
 
 
@@ -346,6 +365,43 @@  static int l3_cat_set_new_val(uint64_t val[],
     return 1;
 }
 
+static unsigned int l3_cat_get_cos_max_from_type(const struct feat_node *feat,
+                                                 enum cbm_type type)
+{
+    if ( type != PSR_CBM_TYPE_L3 )
+        return 0;
+
+    return feat->info.l3_cat_info.cos_max;
+}
+
+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]);
+
+    /* L3 CAT uses one COS. */
+    return 1;
+}
 struct feat_ops l3_cat_ops = {
     .init_feature = l3_cat_init_feature,
     .get_max_cos_max = l3_cat_get_max_cos_max,
@@ -354,6 +410,8 @@  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,
+    .get_cos_max_from_type = l3_cat_get_cos_max_from_type,
+    .compare_val = l3_cat_compare_val,
 };
 
 static void __init parse_psr_bool(char *s, char *value, char *feature,
@@ -666,7 +724,58 @@  static int find_cos(const uint64_t *val, uint32_t array_len,
                     enum cbm_type type,
                     const struct psr_socket_info *info)
 {
-    return 0;
+    unsigned int cos;
+    const unsigned int *ref = info->cos_ref;
+    const struct feat_node *feat_tmp;
+    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_tmp, &info->feat_list, list)
+    {
+        cos_max = feat_tmp->ops.get_cos_max_from_type(feat_tmp, type);
+        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_tmp, &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_tmp->ops.compare_val(val_tmp, feat_tmp, cos, &found);
+            if ( ret < 0 )
+                return ret;
+
+            /* If fail to match, go to next cos to compare. */
+            if ( !found )
+                break;
+
+            val_tmp += ret;
+            if ( val_tmp - val > array_len )
+                return -EINVAL;
+        }
+
+        /*
+         * With this cos id, every entry of value array can match. This cos
+         * is what we find.
+         */
+        if ( found )
+            return cos;
+    }
+
+    return -ENOENT;
 }
 
 static int alloc_new_cos(const struct psr_socket_info *info,