diff mbox

[v15,13/23] x86: refactor psr: CDP: implement CPU init flow.

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

Commit Message

Yi Sun Aug. 1, 2017, 8:48 a.m. UTC
This patch implements the CPU init flow for CDP. The flow is almost
same as L3 CAT.

Signed-off-by: Yi Sun <yi.y.sun@linux.intel.com>
---
v15:
    - refine process in 'psr_cpu_init' to remove the 'goto'.
      (suggested by Jan Beulich)
v14:
    - remove the 'Notes' in commit message because a stub function is
      implemented to avoid potential issue.
      (suggested by Jan Beulich)
    - remove 'feat_l3_cdp' because it can be replaced by 'feat_l3'.
      (suggested by Jan Beulich)
    - implement stub callback functions for CDP to avoid system crash if
      not full CDP patches applied.
      (suggested by Jan Beulich)
    - directly assign correct value to 'alt_type' of CDP.
      (suggested by Jan Beulich)
    - goto L3 CAT init process if CDP init fails.
      (suggested by Jan Beulich)
v13:
    - add commit message.
      (suggested by Jan Beulich)
    - fix comment issue.
      (suggested by Jan Beulich)
    - set CDP default value before enabling it.
      (suggested by Jan Beulich)
    - remove unnecessary check.
      (suggested by Jan Beulich)
    - set 'alt_type' for CDP.
      (suggested by Jan Beulich)
    - check 'cos_max' and substract 1 before right shift it to get correct
      value.
      (suggested by Jan Beulich)
v12:
    - move 'type[]' assignment into l3_cdp_props declaration to make it be
      'const'.
      (suggested by Jan Beulich)
    - remove "L2 CAT" indication in printk.
      (suggested by Jan Beulich)
    - fix coding style issue.
      (suggested by Jan Beulich)
    - change 'val' type to uint64_t.
      (suggested by Jan Beulich)
    - use 1ull.
      (suggested by Jan Beulich)
    - restore mask(0) MSR to default value.
      (suggested by Jan Beulich)
v11:
    - changes about 'feat_props'.
      (suggested by Jan Beulich)
    - remove MSR restore action which is unnecessary.
      (suggested by Jan Beulich)
    - modify commit message.
v10:
    - fix comment.
      (suggested by Jan Beulich)
    - use swith in 'cat_init_feature' to handle different feature types.
      (suggested by Jan Beulich)
    - changes about 'props'.
      (suggested by Jan Beulich)
    - restore MSRs to default value when cpu online.
      (suggested by Jan Beulich)
    - remove feat_mask.
      (suggested by Jan Beulich)
v9:
    - modify commit message to describe flow clearer.
    - handle cpu offline and online again case to read MSRs registers values
      back and save them into cos array to make user can get real data.
    - modify error handling process in 'psr_cpu_prepare' to reduce redundant
      codes.
    - modify 'get_cdp_data' and 'get_cdp_code' to make them standard.
      (suggested by Roger Pau and Jan Beulich)
    - encapsulate CDP operations into 'cat_init_feature' to reduce redundant
      codes.
      (suggested by Roger Pau)
    - reuse 'cat_get_cos_max' for CDP.
      (suggested by Roger Pau)
    - handle 'PSR_CDP' in psr_presmp_init to make init work can be done when
      there is only 'psr=cdp' in cmdline.
    - remove unnecessary comment.
      (suggested by Jan Beulich)
    - move CDP related codes in 'cpu_init_work' into 'psr_cpu_init'.
      (suggested by Jan Beulich)
    - add codes to handle CDP's 'cos_num'.
      (suggested by Jan Beulich)
    - fix coding style issue.
      (suggested by Jan Beulich)
    - do not free resources when allocation fails in 'psr_cpu_prepare'.
      (suggested by Jan Beulich)
    - changes about 'uint64_t' to 'uint32_t'.
      (suggested by Jan Beulich)
v7:
    - initialize 'l3_cdp'.
      (suggested by Konrad Rzeszutek Wilk)
v6:
    - use 'cpuid_leaf'.
      (suggested by Konrad Rzeszutek Wilk and Jan Beulich)
v5:
    - remove codes to free 'feat_l3_cdp' in 'free_feature'.
      (suggested by Jan Beulich)
    - encapsulate cpuid registers into 'struct cpuid_leaf_regs'.
      (suggested by Jan Beulich)
    - print socket info when 'opt_cpu_info' is true.
      (suggested by Jan Beulich)
    - rename 'l3_cdp_get_max_cos_max' to 'l3_cdp_get_cos_max'.
      (suggested by Jan Beulich)
    - rename 'dat[]' to 'data[]'.
      (suggested by Jan Beulich)
    - move 'cpu_prepare_work' contents into 'psr_cpu_prepare'.
      (suggested by Jan Beulich)
v4:
    - create this patch to make codes easier to understand.
      (suggested by Jan Beulich)
---
 xen/arch/x86/psr.c | 89 ++++++++++++++++++++++++++++++++++++++++++++++++++----
 1 file changed, 83 insertions(+), 6 deletions(-)

Comments

Wei Liu Aug. 1, 2017, 9:20 a.m. UTC | #1
On Tue, Aug 01, 2017 at 04:48:44PM +0800, Yi Sun wrote:
> This patch implements the CPU init flow for CDP. The flow is almost
> same as L3 CAT.
> 
> Signed-off-by: Yi Sun <yi.y.sun@linux.intel.com>

As far as I can tell, Jan's comment is addressed.

FWIW:

Reviewed-by: Wei Liu <wei.liu2@citrix.com>
Jan Beulich Aug. 2, 2017, 12:35 p.m. UTC | #2
>>> Yi Sun <yi.y.sun@linux.intel.com> 08/01/17 11:04 AM >>>
>@@ -1278,15 +1339,31 @@ static void psr_cpu_init(void)
>cpuid_count_leaf(PSR_CPUID_LEVEL_CAT, 0, ®s);
>if ( regs.b & PSR_RESOURCE_TYPE_L3 )
>{
>+        bool do_l3_cat_init = true;
>+
>cpuid_count_leaf(PSR_CPUID_LEVEL_CAT, 1, ®s);
 >
>feat = feat_l3;
>feat_l3 = NULL;
 >
>-        if ( !cat_init_feature(®s, feat, info, FEAT_TYPE_L3_CAT) )
>-            feat_props[FEAT_TYPE_L3_CAT] = &l3_cat_props;
>-        else
>-            feat_l3 = feat;
>+        if ( (regs.c & PSR_CAT_CDP_CAPABILITY) && (opt_psr & PSR_CDP) )
>+        {
>+            /* If CDP init fails, try to work as L3 CAT. */
>+            if ( !cat_init_feature(®s, feat, info, FEAT_TYPE_L3_CDP) )
>+            {
>+                feat_props[FEAT_TYPE_L3_CDP] = &l3_cdp_props;
>+                /* CDP init succeeds, no need to do L3 CAT init. */
>+                do_l3_cat_init = false;
>+            }
>+        }

The comment ahead of the inner if() now really describes the (implicit)
else case. That's somewhat misleading. How about putting feat back
into feat_l3 in an actual "else", and using that at once instead of the
somewhat clumsily named "do_l3_cat_init" local variable? That would
additionally avoid the need for me to ask you to fold the two if()s. Plus
the resulting code would become more similar ...

>+        if ( do_l3_cat_init )
>+        {
>+            if ( !cat_init_feature(®s, feat, info, FEAT_TYPE_L3_CAT) )
>+                feat_props[FEAT_TYPE_L3_CAT] = &l3_cat_props;
>+            else
>+                feat_l3 = feat;
>+        }

... to this.

And btw, to avoid spamming the list with another full version of this
series, I'd be fine with you just submitting v15.1 of this one patch.

Jan
Yi Sun Aug. 2, 2017, 3:11 p.m. UTC | #3
On 17-08-02 06:35:46, Jan Beulich wrote:
> >>> Yi Sun <yi.y.sun@linux.intel.com> 08/01/17 11:04 AM >>>
> >@@ -1278,15 +1339,31 @@ static void psr_cpu_init(void)
> >cpuid_count_leaf(PSR_CPUID_LEVEL_CAT, 0, ®s);
> >if ( regs.b & PSR_RESOURCE_TYPE_L3 )
> >{
> >+        bool do_l3_cat_init = true;
> >+
> >cpuid_count_leaf(PSR_CPUID_LEVEL_CAT, 1, ®s);
>  >
> >feat = feat_l3;
> >feat_l3 = NULL;
>  >
> >-        if ( !cat_init_feature(®s, feat, info, FEAT_TYPE_L3_CAT) )
> >-            feat_props[FEAT_TYPE_L3_CAT] = &l3_cat_props;
> >-        else
> >-            feat_l3 = feat;
> >+        if ( (regs.c & PSR_CAT_CDP_CAPABILITY) && (opt_psr & PSR_CDP) )
> >+        {
> >+            /* If CDP init fails, try to work as L3 CAT. */
> >+            if ( !cat_init_feature(®s, feat, info, FEAT_TYPE_L3_CDP) )
> >+            {
> >+                feat_props[FEAT_TYPE_L3_CDP] = &l3_cdp_props;
> >+                /* CDP init succeeds, no need to do L3 CAT init. */
> >+                do_l3_cat_init = false;
> >+            }
> >+        }
> 
> The comment ahead of the inner if() now really describes the (implicit)
> else case. That's somewhat misleading. How about putting feat back
> into feat_l3 in an actual "else", and using that at once instead of the
> somewhat clumsily named "do_l3_cat_init" local variable? That would
> additionally avoid the need for me to ask you to fold the two if()s. Plus
> the resulting code would become more similar ...
> 
> >+        if ( do_l3_cat_init )
> >+        {
> >+            if ( !cat_init_feature(®s, feat, info, FEAT_TYPE_L3_CAT) )
> >+                feat_props[FEAT_TYPE_L3_CAT] = &l3_cat_props;
> >+            else
> >+                feat_l3 = feat;
> >+        }
> 
> ... to this.
> 
Thanks for the comment! But I do not understand the intention to put feat
back into feat_l3 in else. After putting feat back into feat_l3, how to
handle L3 CAT init? The L3 CAT init should be entered under two cases:
1. No CDP capability in regs.c. In such case, the feat equals feat_l3 and
   feat_l3 has been NULL at above step.
2. CDP init fails. In such case, the feat equals feat_l3. If we put feat
   back into feat_l3, then they are equal.

So, we cannot use feat or feat_l3 to decide entering L3 CAT init or not.

I think we may check if 'feat_props[FEAT_TYPE_L3_CDP]' is NULL to decide
entering L3 CAT init or not. Because under above two cases, it is NULL.
E.g.
    feat = feat_l3;
    feat_l3 = NULL;
    if ( (regs.c & PSR_CAT_CDP_CAPABILITY) && (opt_psr & PSR_CDP) )
    {
        /* If CDP init fails, try to work as L3 CAT. */
        if ( !cat_init_feature(®s, feat, info, FEAT_TYPE_L3_CDP) )
            feat_props[FEAT_TYPE_L3_CDP] = &l3_cdp_props;
    } 

    if ( !feat_props[FEAT_TYPE_L3_CDP] )
    {
        if ( !cat_init_feature(®s, feat, info, FEAT_TYPE_L3_CAT) )
            feat_props[FEAT_TYPE_L3_CAT] = &l3_cat_props;
        else
            feat_l3 = feat;
    }

How do you think? Thanks!

> And btw, to avoid spamming the list with another full version of this
> series, I'd be fine with you just submitting v15.1 of this one patch.
> 
> Jan
Jan Beulich Aug. 2, 2017, 3:19 p.m. UTC | #4
>>> Yi Sun <yi.y.sun@linux.intel.com> 08/02/17 5:12 PM >>>
>On 17-08-02 06:35:46, Jan Beulich wrote:
>> >>> Yi Sun <yi.y.sun@linux.intel.com> 08/01/17 11:04 AM >>>
>> >@@ -1278,15 +1339,31 @@ static void psr_cpu_init(void)
>> >cpuid_count_leaf(PSR_CPUID_LEVEL_CAT, 0, ®s);
>> >if ( regs.b & PSR_RESOURCE_TYPE_L3 )
>> >{
>> >+        bool do_l3_cat_init = true;
>> >+
>> >cpuid_count_leaf(PSR_CPUID_LEVEL_CAT, 1, ®s);
>>  >
>> >feat = feat_l3;
>> >feat_l3 = NULL;
>>  >
>> >-        if ( !cat_init_feature(®s, feat, info, FEAT_TYPE_L3_CAT) )
>> >-            feat_props[FEAT_TYPE_L3_CAT] = &l3_cat_props;
>> >-        else
>> >-            feat_l3 = feat;
>> >+        if ( (regs.c & PSR_CAT_CDP_CAPABILITY) && (opt_psr & PSR_CDP) )
>> >+        {
>> >+            /* If CDP init fails, try to work as L3 CAT. */
>> >+            if ( !cat_init_feature(®s, feat, info, FEAT_TYPE_L3_CDP) )
>> >+            {
>> >+                feat_props[FEAT_TYPE_L3_CDP] = &l3_cdp_props;
>> >+                /* CDP init succeeds, no need to do L3 CAT init. */
>> >+                do_l3_cat_init = false;
>> >+            }
>> >+        }
>> 
>> The comment ahead of the inner if() now really describes the (implicit)
>> else case. That's somewhat misleading. How about putting feat back
>> into feat_l3 in an actual "else", and using that at once instead of the
>> somewhat clumsily named "do_l3_cat_init" local variable? That would
>> additionally avoid the need for me to ask you to fold the two if()s. Plus
>> the resulting code would become more similar ...
>> 
>> >+        if ( do_l3_cat_init )
>> >+        {
>> >+            if ( !cat_init_feature(®s, feat, info, FEAT_TYPE_L3_CAT) )
>> >+                feat_props[FEAT_TYPE_L3_CAT] = &l3_cat_props;
>> >+            else
>> >+                feat_l3 = feat;
>> >+        }
>> 
>> ... to this.
>> 
>Thanks for the comment! But I do not understand the intention to put feat
>back into feat_l3 in else. After putting feat back into feat_l3, how to
>handle L3 CAT init? The L3 CAT init should be entered under two cases:
>1. No CDP capability in regs.c. In such case, the feat equals feat_l3 and
>feat_l3 has been NULL at above step.
>2. CDP init fails. In such case, the feat equals feat_l3. If we put feat
>back into feat_l3, then they are equal.
>
>So, we cannot use feat or feat_l3 to decide entering L3 CAT init or not.

You could pull the copying of feat_l3 into feat inside the if() checking
the capability. But your alternative doesn't look too bad as well.

Jan
diff mbox

Patch

diff --git a/xen/arch/x86/psr.c b/xen/arch/x86/psr.c
index 6ea2e4e..083e253 100644
--- a/xen/arch/x86/psr.c
+++ b/xen/arch/x86/psr.c
@@ -62,6 +62,7 @@ 
 
 enum psr_feat_type {
     FEAT_TYPE_L3_CAT,
+    FEAT_TYPE_L3_CDP,
     FEAT_TYPE_NUM,
     FEAT_TYPE_UNKNOWN,
 };
@@ -163,6 +164,22 @@  static struct feat_node *feat_l3;
 #define cat_default_val(len) (0xffffffff >> (32 - (len)))
 
 /*
+ * get_cdp_data - get DATA COS register value from input COS ID.
+ * @feat:        the feature node.
+ * @cos:         the COS ID.
+ */
+#define get_cdp_data(feat, cos)              \
+            ((feat)->cos_reg_val[(cos) * 2])
+
+/*
+ * get_cdp_code - get CODE COS register value from input COS ID.
+ * @feat:        the feature node.
+ * @cos:         the COS ID.
+ */
+#define get_cdp_code(feat, cos)              \
+            ((feat)->cos_reg_val[(cos) * 2 + 1])
+
+/*
  * Use this function to check if any allocation feature has been enabled
  * in cmdline.
  */
@@ -262,6 +279,29 @@  static int cat_init_feature(const struct cpuid_leaf *regs,
 
         break;
 
+    case FEAT_TYPE_L3_CDP:
+    {
+        uint64_t val;
+
+        if ( feat->cos_max < 3 )
+            return -ENOENT;
+
+        /* Cut half of cos_max when CDP is enabled. */
+        feat->cos_max = (feat->cos_max - 1) >> 1;
+
+        /* We reserve cos=0 as default cbm (all bits within cbm_len are 1). */
+        get_cdp_code(feat, 0) = cat_default_val(feat->cbm_len);
+        get_cdp_data(feat, 0) = cat_default_val(feat->cbm_len);
+
+        wrmsrl(MSR_IA32_PSR_L3_MASK(0), cat_default_val(feat->cbm_len));
+        wrmsrl(MSR_IA32_PSR_L3_MASK(1), cat_default_val(feat->cbm_len));
+        rdmsrl(MSR_IA32_PSR_L3_QOS_CFG, val);
+        wrmsrl(MSR_IA32_PSR_L3_QOS_CFG,
+               val | (1ull << PSR_L3_QOS_CDP_ENABLE_BIT));
+
+        break;
+    }
+
     default:
         return -ENOENT;
     }
@@ -272,7 +312,8 @@  static int cat_init_feature(const struct cpuid_leaf *regs,
     if ( !opt_cpu_info )
         return 0;
 
-    printk(XENLOG_INFO "CAT: enabled on socket %u, cos_max:%u, cbm_len:%u\n",
+    printk(XENLOG_INFO "%s: enabled on socket %u, cos_max:%u, cbm_len:%u\n",
+           ((type == FEAT_TYPE_L3_CDP) ? "L3 CDP" : "L3 CAT"),
            cpu_to_socket(smp_processor_id()), feat->cos_max, feat->cbm_len);
 
     return 0;
@@ -305,6 +346,26 @@  static const struct feat_props l3_cat_props = {
     .write_msr = l3_cat_write_msr,
 };
 
+/* L3 CDP props */
+static bool l3_cdp_get_feat_info(const struct feat_node *feat,
+                                 uint32_t data[], uint32_t array_len)
+{
+    return false;
+}
+
+static void l3_cdp_write_msr(unsigned int cos, uint32_t val, enum cbm_type type)
+{
+}
+
+static const struct feat_props l3_cdp_props = {
+    .cos_num = 2,
+    .type[0] = PSR_CBM_TYPE_L3_DATA,
+    .type[1] = PSR_CBM_TYPE_L3_CODE,
+    .alt_type = PSR_CBM_TYPE_L3,
+    .get_feat_info = l3_cdp_get_feat_info,
+    .write_msr = l3_cdp_write_msr,
+};
+
 static void __init parse_psr_bool(char *s, char *value, char *feature,
                                   unsigned int mask)
 {
@@ -1278,15 +1339,31 @@  static void psr_cpu_init(void)
     cpuid_count_leaf(PSR_CPUID_LEVEL_CAT, 0, &regs);
     if ( regs.b & PSR_RESOURCE_TYPE_L3 )
     {
+        bool do_l3_cat_init = true;
+
         cpuid_count_leaf(PSR_CPUID_LEVEL_CAT, 1, &regs);
 
         feat = feat_l3;
         feat_l3 = NULL;
 
-        if ( !cat_init_feature(&regs, feat, info, FEAT_TYPE_L3_CAT) )
-            feat_props[FEAT_TYPE_L3_CAT] = &l3_cat_props;
-        else
-            feat_l3 = feat;
+        if ( (regs.c & PSR_CAT_CDP_CAPABILITY) && (opt_psr & PSR_CDP) )
+        {
+            /* If CDP init fails, try to work as L3 CAT. */
+            if ( !cat_init_feature(&regs, feat, info, FEAT_TYPE_L3_CDP) )
+            {
+                feat_props[FEAT_TYPE_L3_CDP] = &l3_cdp_props;
+                /* CDP init succeeds, no need to do L3 CAT init. */
+                do_l3_cat_init = false;
+            }
+        }
+
+        if ( do_l3_cat_init )
+        {
+            if ( !cat_init_feature(&regs, feat, info, FEAT_TYPE_L3_CAT) )
+                feat_props[FEAT_TYPE_L3_CAT] = &l3_cat_props;
+            else
+                feat_l3 = feat;
+        }
     }
 
     info->feat_init = true;
@@ -1348,7 +1425,7 @@  static int __init psr_presmp_init(void)
     if ( (opt_psr & PSR_CMT) && opt_rmid_max )
         init_psr_cmt(opt_rmid_max);
 
-    if ( opt_psr & PSR_CAT )
+    if ( opt_psr & (PSR_CAT | PSR_CDP) )
         init_psr();
 
     if ( psr_cpu_prepare() )