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

[Xen-devel] [PATCH v9 14/25] x86: refactor psr: CDP: implement CPU init and free flow.



This patch implements the CPU init and free flow for CDP including L3 CDP
initialization callback function. The flow is almost same as L3 CAT.

Signed-off-by: Yi Sun <yi.y.sun@xxxxxxxxxxxxxxx>
---
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 | 112 ++++++++++++++++++++++++++++++++++++++++++++---------
 1 file changed, 94 insertions(+), 18 deletions(-)

diff --git a/xen/arch/x86/psr.c b/xen/arch/x86/psr.c
index 2bc7f3c..e2a2643 100644
--- a/xen/arch/x86/psr.c
+++ b/xen/arch/x86/psr.c
@@ -55,6 +55,9 @@
 /* CAT features use 1 COS register in one access. */
 #define CAT_COS_NUM      1
 
+/* CDP uses 2 COS registers in one access. */
+#define CDP_COS_NUM      2
+
 enum psr_feat_type {
     PSR_SOCKET_L3_CAT = 0,
     PSR_SOCKET_L3_CDP,
@@ -209,12 +212,29 @@ static DEFINE_PER_CPU(struct psr_assoc, psr_assoc);
  * array creation. It is used to transiently store a spare node.
  */
 static struct feat_node *feat_l3_cat;
+static struct feat_node *feat_l3_cdp;
 
 /* Common functions */
 #define cat_default_val(len)                 \
             ( (uint32_t)((1ul << len) - 1) )
 
 /*
+ * get_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.
  */
@@ -303,20 +323,56 @@ static void cat_init_feature(struct cpuid_leaf regs,
     cat.cbm_len = (regs.a & CAT_CBM_LEN_MASK) + 1;
     cat.cos_max = min(opt_cos_max, regs.d & CAT_COS_MAX_MASK);
 
-    /* cos=0 is reserved as default cbm(all bits within cbm_len are 1). */
-    feat->cos_reg_val[0] = cat_default_val(cat.cbm_len);
-    /*
-     * To handle cpu offline and then online case, we need read MSRs back to
-     * save values into cos_reg_val array.
-     */
-    for ( i = 1; i <= cat.cos_max; i++ )
+    if ( type == PSR_SOCKET_L3_CDP )
+    {
+        uint64_t val_code;
+
+        /* Cut half of cos_max when CDP is enabled. */
+        cat.cos_max >>= 1;
+
+        /* We only write mask1 since mask0 is always all ones by default. */
+        wrmsrl(MSR_IA32_PSR_L3_MASK(1), cat_default_val(cat.cbm_len));
+        rdmsrl(MSR_IA32_PSR_L3_QOS_CFG, val);
+        wrmsrl(MSR_IA32_PSR_L3_QOS_CFG, val | (1 << 
PSR_L3_QOS_CDP_ENABLE_BIT));
+
+        /* cos=0 is reserved as default cbm(all bits within cbm_len are 1). */
+        get_cdp_code(feat, 0) = cat_default_val(cat.cbm_len);
+        get_cdp_data(feat, 0) = cat_default_val(cat.cbm_len);
+
+        feat->cos_num = CDP_COS_NUM;
+
+        /*
+         * To handle cpu offline and then online case, we need read MSRs back 
to
+         * save values into cos_reg_val array. All cpus MSRs values on same 
socket
+         * are same.
+         */
+        for ( i = 1; i <= cat.cos_max; i++ )
+        {
+            rdmsrl(MSR_IA32_PSR_L3_MASK_DATA(i), val);
+            rdmsrl(MSR_IA32_PSR_L3_MASK_CODE(i), val_code);
+            get_cdp_code(feat, i) = (uint32_t)val_code;
+            get_cdp_data(feat, i) = (uint32_t)val;
+        }
+    }
+    else
     {
-        rdmsrl(MSR_IA32_PSR_L3_MASK(i), val);
-        feat->cos_reg_val[i] = (uint32_t)val;
+        /* cos=0 is reserved as default cbm(all bits within cbm_len are 1). */
+        feat->cos_reg_val[0] = cat_default_val(cat.cbm_len);
+
+        feat->cos_num = CAT_COS_NUM;
+
+        /*
+         * To handle cpu offline and then online case, we need read MSRs back 
to
+         * save values into cos_reg_val array.
+         */
+        for ( i = 1; i <= cat.cos_max; i++ )
+        {
+            rdmsrl(MSR_IA32_PSR_L3_MASK(i), val);
+            feat->cos_reg_val[i] = (uint32_t)val;
+        }
     }
 
     feat->info.cat_info = cat;
-    feat->cos_num = CAT_COS_NUM;
 
     /* Add this feature into array. */
     info->features[type] = feat;
@@ -328,8 +384,9 @@ static void cat_init_feature(struct cpuid_leaf regs,
     if ( !opt_cpu_info )
         return;
 
-    printk(XENLOG_INFO "%s CAT: enabled on socket %u, cos_max:%u, 
cbm_len:%u\n",
-           ((type == PSR_SOCKET_L3_CAT) ? "L3" : "L2"),
+    printk(XENLOG_INFO "%s: enabled on socket %u, cos_max:%u, cbm_len:%u\n",
+           ((type == PSR_SOCKET_L3_CDP) ? "CDP" :
+            ((type == PSR_SOCKET_L3_CAT) ? "L3 CAT": "L2 CAT")),
            socket, feat->info.cat_info.cos_max,
            feat->info.cat_info.cbm_len);
 
@@ -448,6 +505,11 @@ static const struct feat_ops l3_cat_ops = {
     .write_msr = l3_cat_write_msr,
 };
 
+/* L3 CDP ops */
+struct feat_ops l3_cdp_ops = {
+    .get_cos_max = cat_get_cos_max,
+};
+
 static void __init parse_psr_bool(char *s, char *value, char *feature,
                                   unsigned int mask)
 {
@@ -1244,6 +1306,10 @@ static int psr_cpu_prepare(void)
          (feat_l3_cat = xzalloc(struct feat_node)) == NULL )
         return -ENOMEM;
 
+    if ( feat_l3_cdp == NULL &&
+         (feat_l3_cdp = xzalloc(struct feat_node)) == NULL )
+        return -ENOMEM;
+
     return 0;
 }
 
@@ -1279,11 +1345,21 @@ static void psr_cpu_init(void)
     {
         cpuid_count_leaf(PSR_CPUID_LEVEL_CAT, 1, &regs);
 
-        feat = feat_l3_cat;
-        feat_l3_cat = NULL;
-        feat->ops = l3_cat_ops;
-
-        cat_init_feature(regs, feat, info, PSR_SOCKET_L3_CAT);
+        if ( (regs.c & PSR_CAT_CDP_CAPABILITY) && (opt_psr & PSR_CDP) &&
+             !test_bit(PSR_SOCKET_L3_CDP, &info->feat_mask) )
+        {
+            feat = feat_l3_cdp;
+            feat_l3_cdp = NULL;
+            feat->ops = l3_cdp_ops;
+            cat_init_feature(regs, feat, info, PSR_SOCKET_L3_CDP);
+        }
+        else
+        {
+            feat = feat_l3_cat;
+            feat_l3_cat = NULL;
+            feat->ops = l3_cat_ops;
+            cat_init_feature(regs, feat, info, PSR_SOCKET_L3_CAT);
+        }
     }
 
 assoc_init:
@@ -1343,7 +1419,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() )
-- 
1.9.1


_______________________________________________
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®.