All of lore.kernel.org
 help / color / mirror / Atom feed
From: He Chen <he.chen@linux.intel.com>
To: xen-devel@lists.xenproject.org
Cc: wei.liu2@citrix.com, ian.campbell@citrix.com,
	stefano.stabellini@eu.citrix.com, andrew.cooper3@citrix.com,
	He Chen <he.chen@linux.intel.com>,
	ian.jackson@eu.citrix.com, jbeulich@suse.com, keir@xen.org
Subject: [PATCH 2/5] x86: Support enable/disable CDP dynamically and get CDP status
Date: Wed,  2 Sep 2015 16:27:59 +0800	[thread overview]
Message-ID: <1441182482-7688-3-git-send-email-he.chen@linux.intel.com> (raw)
In-Reply-To: <1441182482-7688-1-git-send-email-he.chen@linux.intel.com>

 cdp_enabled is added to CAT socket info to indicate CDP is on or off on
 the socket and struct psr_cat_cbm is extended to support CDP operation.
 IA32_L3_QOS_CFG is a new MSR to enable/disable L3 CDP, when enable or
 disable CDP, all domains will reset to COS0 with fully access all L3
 cache.

 Signed-off-by: He Chen <he.chen@linux.intel.com>
---
 xen/arch/x86/psr.c          | 164 ++++++++++++++++++++++++++++++++++++++++----
 xen/arch/x86/sysctl.c       |   9 ++-
 xen/include/asm-x86/psr.h   |  10 ++-
 xen/include/public/sysctl.h |   5 ++
 4 files changed, 174 insertions(+), 14 deletions(-)

diff --git a/xen/arch/x86/psr.c b/xen/arch/x86/psr.c
index b357816..26596dd 100644
--- a/xen/arch/x86/psr.c
+++ b/xen/arch/x86/psr.c
@@ -17,13 +17,20 @@
 #include <xen/cpu.h>
 #include <xen/err.h>
 #include <xen/sched.h>
+#include <xen/domain.h>
 #include <asm/psr.h>
 
 #define PSR_CMT        (1<<0)
 #define PSR_CAT        (1<<1)
 
 struct psr_cat_cbm {
-    uint64_t cbm;
+    union {
+        uint64_t cbm;
+        struct {
+            uint64_t code;
+            uint64_t data;
+        }cdp;
+    }u;
     unsigned int ref;
 };
 
@@ -32,6 +39,7 @@ struct psr_cat_socket_info {
     unsigned int cos_max;
     struct psr_cat_cbm *cos_to_cbm;
     spinlock_t cbm_lock;
+    bool_t cdp_enabled;
 };
 
 struct psr_assoc {
@@ -263,7 +271,7 @@ static struct psr_cat_socket_info *get_cat_socket_info(unsigned int socket)
 }
 
 int psr_get_cat_l3_info(unsigned int socket, uint32_t *cbm_len,
-                        uint32_t *cos_max)
+                        uint32_t *cos_max, uint8_t *cdp_enabled)
 {
     struct psr_cat_socket_info *info = get_cat_socket_info(socket);
 
@@ -272,6 +280,7 @@ int psr_get_cat_l3_info(unsigned int socket, uint32_t *cbm_len,
 
     *cbm_len = info->cbm_len;
     *cos_max = info->cos_max;
+    *cdp_enabled = (uint8_t)info->cdp_enabled;
 
     return 0;
 }
@@ -283,7 +292,7 @@ int psr_get_l3_cbm(struct domain *d, unsigned int socket, uint64_t *cbm)
     if ( IS_ERR(info) )
         return PTR_ERR(info);
 
-    *cbm = info->cos_to_cbm[d->arch.psr_cos_ids[socket]].cbm;
+    *cbm = info->cos_to_cbm[d->arch.psr_cos_ids[socket]].u.cbm;
 
     return 0;
 }
@@ -314,19 +323,33 @@ static bool_t psr_check_cbm(unsigned int cbm_len, uint64_t cbm)
 struct cos_cbm_info
 {
     unsigned int cos;
-    uint64_t cbm;
+    uint64_t cbm_code;
+    uint64_t cbm_data;
+    bool_t cdp_mode;
 };
 
 static void do_write_l3_cbm(void *data)
 {
     struct cos_cbm_info *info = data;
 
-    wrmsrl(MSR_IA32_PSR_L3_MASK(info->cos), info->cbm);
+    if ( info->cdp_mode == 0 )
+        wrmsrl(MSR_IA32_PSR_L3_MASK(info->cos), info->cbm_code);
+    else
+    {
+        wrmsrl(MSR_IA32_PSR_L3_MASK(info->cos*2+1), info->cbm_code);
+        wrmsrl(MSR_IA32_PSR_L3_MASK(info->cos*2), info->cbm_data);
+    }
 }
 
-static int write_l3_cbm(unsigned int socket, unsigned int cos, uint64_t cbm)
+static int write_l3_cbm(unsigned int socket, unsigned int cos,
+                        uint64_t cbm_code, uint64_t cbm_data, bool_t cdp_mode)
 {
-    struct cos_cbm_info info = { .cos = cos, .cbm = cbm };
+    struct cos_cbm_info info =
+    { .cos = cos,
+      .cbm_code = cbm_code,
+      .cbm_data = cbm_data,
+      .cdp_mode = cdp_mode,
+    };
 
     if ( socket == cpu_to_socket(smp_processor_id()) )
         do_write_l3_cbm(&info);
@@ -364,7 +387,7 @@ int psr_set_l3_cbm(struct domain *d, unsigned int socket, uint64_t cbm)
         /* If still not found, then keep unused one. */
         if ( !found && cos != 0 && map[cos].ref == 0 )
             found = map + cos;
-        else if ( map[cos].cbm == cbm )
+        else if ( map[cos].u.cbm == cbm )
         {
             if ( unlikely(cos == old_cos) )
             {
@@ -388,16 +411,16 @@ int psr_set_l3_cbm(struct domain *d, unsigned int socket, uint64_t cbm)
     }
 
     cos = found - map;
-    if ( found->cbm != cbm )
+    if ( found->u.cbm != cbm )
     {
-        int ret = write_l3_cbm(socket, cos, cbm);
+        int ret = write_l3_cbm(socket, cos, cbm, 0, 0);
 
         if ( ret )
         {
             spin_unlock(&info->cbm_lock);
             return ret;
         }
-        found->cbm = cbm;
+        found->u.cbm = cbm;
     }
 
     found->ref++;
@@ -491,7 +514,7 @@ static void cat_cpu_init(void)
         info->cos_to_cbm = temp_cos_to_cbm;
         temp_cos_to_cbm = NULL;
         /* cos=0 is reserved as default cbm(all ones). */
-        info->cos_to_cbm[0].cbm = (1ull << info->cbm_len) - 1;
+        info->cos_to_cbm[0].u.cbm = (1ull << info->cbm_len) - 1;
 
         spin_lock_init(&info->cbm_lock);
 
@@ -556,6 +579,123 @@ static int psr_cpu_prepare(unsigned int cpu)
     return cat_cpu_prepare(cpu);
 }
 
+static void do_write_l3_config(void *data)
+{
+    uint64_t val;
+    uint64_t *mask = data;
+
+    rdmsrl(PSR_L3_QOS_CFG, val);
+    wrmsrl(PSR_L3_QOS_CFG, val | *mask);
+}
+
+static int config_socket_l3_cdp(unsigned int socket, uint64_t cdp_mask)
+{
+    unsigned int cpu;
+    uint64_t mask = cdp_mask;
+
+    if ( socket == cpu_to_socket(smp_processor_id()) )
+        do_write_l3_config(&mask);
+    else
+    {
+        cpu = get_socket_cpu(socket);
+        if ( cpu >= nr_cpu_ids )
+            return -ENOTSOCK;
+        on_selected_cpus(cpumask_of(cpu), do_write_l3_config, &mask, 1);
+    }
+    return 0;
+}
+
+int psr_cat_enable_cdp(void)
+{
+    int i, ret;
+    struct psr_cat_socket_info *info;
+    unsigned int socket;
+    struct domain *d;
+
+    for_each_set_bit(socket, cat_socket_enable, nr_sockets)
+    {
+        ret = config_socket_l3_cdp(socket, 1 << PSR_L3_QOS_CDP_ENABLE_BIT);
+        if ( ret )
+            return ret;
+
+        info = cat_socket_info + socket;
+        if (info->cdp_enabled)
+            return 0;
+
+        /* Cut half of cos_max when CDP enabled */
+        info->cos_max = info->cos_max / 2;
+
+        spin_lock(&info->cbm_lock);
+
+        /* Reset COS0 code CBM & data CBM for all domain */
+        info->cos_to_cbm[0].u.cdp.code = (1ull << info->cbm_len) - 1;
+        info->cos_to_cbm[0].u.cdp.data = (1ull << info->cbm_len) - 1;
+
+        for ( i = 0; i <= info->cos_max; i++ )
+            info->cos_to_cbm[0].ref = 0;
+
+        /* Only write mask1 since mask0 is always all 1 by CAT. */
+        ret = write_l3_cbm(socket, 1, info->cos_to_cbm[0].u.cdp.code, 0, 0);
+        if ( ret )
+        {
+            spin_unlock(&info->cbm_lock);
+            return ret;
+        }
+
+        /* Reset all domain to COS0 */
+        for_each_domain( d )
+        {
+            d->arch.psr_cos_ids[socket] = 0;
+            info->cos_to_cbm[0].ref++;
+        }
+
+        spin_unlock(&info->cbm_lock);
+        info->cdp_enabled = 1;
+    }
+
+    return 0;
+}
+
+int psr_cat_disable_cdp(void)
+{
+    int i, ret;
+    struct psr_cat_socket_info *info;
+    unsigned int socket;
+    struct domain *d;
+
+    for_each_set_bit(socket, cat_socket_enable, nr_sockets)
+    {
+        ret = config_socket_l3_cdp(socket, 0 << PSR_L3_QOS_CDP_ENABLE_BIT);
+        if ( ret )
+            return ret;
+
+        info = cat_socket_info + socket;
+        if( !info->cdp_enabled )
+            return 0;
+
+        /* Restore CAT cos_max when CDP disabled */
+        info->cos_max = info->cos_max * 2 + 1;
+        spin_lock(&info->cbm_lock);
+
+        /* Reset all CBMs and set fully open COS0 for all domains */
+        info->cos_to_cbm[0].u.cbm = (1ull << info->cbm_len) - 1;
+        for ( i = 0; i <= info->cos_max; i++ )
+            info->cos_to_cbm[i].ref = 0;
+
+        /* Reset all domains to COS0 */
+        for_each_domain( d )
+        {
+            d->arch.psr_cos_ids[socket] = 0;
+            info->cos_to_cbm[0].ref++;
+        }
+
+        spin_unlock(&info->cbm_lock);
+        info->cdp_enabled = 0;
+    }
+
+    return 0;
+}
+
 static void psr_cpu_init(void)
 {
     if ( cat_socket_info )
diff --git a/xen/arch/x86/sysctl.c b/xen/arch/x86/sysctl.c
index f36b52f..51b03a4 100644
--- a/xen/arch/x86/sysctl.c
+++ b/xen/arch/x86/sysctl.c
@@ -177,12 +177,19 @@ long arch_do_sysctl(
         case XEN_SYSCTL_PSR_CAT_get_l3_info:
             ret = psr_get_cat_l3_info(sysctl->u.psr_cat_op.target,
                                       &sysctl->u.psr_cat_op.u.l3_info.cbm_len,
-                                      &sysctl->u.psr_cat_op.u.l3_info.cos_max);
+                                      &sysctl->u.psr_cat_op.u.l3_info.cos_max,
+                                      &sysctl->u.psr_cat_op.u.l3_info.cdp_enabled);
 
             if ( !ret && __copy_field_to_guest(u_sysctl, sysctl, u.psr_cat_op) )
                 ret = -EFAULT;
 
             break;
+        case XEN_SYSCTL_PSR_CAT_enable_cdp:
+            ret = psr_cat_enable_cdp();
+            break;
+        case XEN_SYSCTL_PSR_CAT_disable_cdp:
+            ret = psr_cat_disable_cdp();
+            break;
         default:
             ret = -EOPNOTSUPP;
             break;
diff --git a/xen/include/asm-x86/psr.h b/xen/include/asm-x86/psr.h
index a6b83df..2b79a92 100644
--- a/xen/include/asm-x86/psr.h
+++ b/xen/include/asm-x86/psr.h
@@ -30,6 +30,11 @@
 /* CDP Capability */
 #define PSR_CAT_CDP_CAPABILITY       0x4
 
+/* L3 QoS Config MSR Address */
+#define PSR_L3_QOS_CFG           0xc81
+
+/* L3 CDP Enable bit*/
+#define PSR_L3_QOS_CDP_ENABLE_BIT       0x0
 
 struct psr_cmt_l3 {
     unsigned int features;
@@ -56,13 +61,16 @@ void psr_free_rmid(struct domain *d);
 void psr_ctxt_switch_to(struct domain *d);
 
 int psr_get_cat_l3_info(unsigned int socket, uint32_t *cbm_len,
-                        uint32_t *cos_max);
+                        uint32_t *cos_max, uint8_t *cdp_enabled);
 int psr_get_l3_cbm(struct domain *d, unsigned int socket, uint64_t *cbm);
 int psr_set_l3_cbm(struct domain *d, unsigned int socket, uint64_t cbm);
 
 int psr_domain_init(struct domain *d);
 void psr_domain_free(struct domain *d);
 
+int psr_cat_enable_cdp(void);
+int psr_cat_disable_cdp(void);
+
 #endif /* __ASM_PSR_H__ */
 
 /*
diff --git a/xen/include/public/sysctl.h b/xen/include/public/sysctl.h
index 58c9be2..8b97137 100644
--- a/xen/include/public/sysctl.h
+++ b/xen/include/public/sysctl.h
@@ -697,6 +697,8 @@ typedef struct xen_sysctl_pcitopoinfo xen_sysctl_pcitopoinfo_t;
 DEFINE_XEN_GUEST_HANDLE(xen_sysctl_pcitopoinfo_t);
 
 #define XEN_SYSCTL_PSR_CAT_get_l3_info               0
+#define XEN_SYSCTL_PSR_CAT_enable_cdp                1
+#define XEN_SYSCTL_PSR_CAT_disable_cdp               2
 struct xen_sysctl_psr_cat_op {
     uint32_t cmd;       /* IN: XEN_SYSCTL_PSR_CAT_* */
     uint32_t target;    /* IN */
@@ -704,6 +706,9 @@ struct xen_sysctl_psr_cat_op {
         struct {
             uint32_t cbm_len;   /* OUT: CBM length */
             uint32_t cos_max;   /* OUT: Maximum COS */
+            #define XEN_SYSCTL_PSR_CDP_DISABLED      0
+            #define XEN_SYSCTL_PSR_CDP_ENABLED       1
+            uint8_t cdp_enabled;   /* OUT: CDP status */
         } l3_info;
     } u;
 };
-- 
1.9.1

  parent reply	other threads:[~2015-09-02  8:28 UTC|newest]

Thread overview: 17+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-09-02  8:27 [PATCH 0/5] Intel Code/Data Prioritization(CDP) feature enabling He Chen
2015-09-02  8:27 ` [PATCH 1/5] x86: detect Intel CDP feature He Chen
2015-09-02 11:12   ` Andrew Cooper
2015-09-02  8:27 ` He Chen [this message]
2015-09-02 11:39   ` [PATCH 2/5] x86: Support enable/disable CDP dynamically and get CDP status Andrew Cooper
2015-09-02 14:07     ` Jan Beulich
2015-09-02  8:28 ` [PATCH 3/5] x86: add domctl cmd to set/get CDP code/data CBM He Chen
2015-09-02 11:59   ` Andrew Cooper
2015-09-06  7:15     ` He Chen
2015-09-06 16:29       ` Andrew Cooper
2015-09-02  8:28 ` [PATCH 4/5] tools: add tools support for Intel CDP He Chen
2015-09-02 13:32   ` Wei Liu
2015-09-02  8:28 ` [PATCH 5/5] docs: add document to introduce CDP command He Chen
2015-09-02 13:32   ` Wei Liu
2015-09-02 12:08 ` [PATCH 0/5] Intel Code/Data Prioritization(CDP) feature enabling Andrew Cooper
2015-09-06  1:18   ` Chao Peng
2015-09-06  6:49   ` He Chen

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1441182482-7688-3-git-send-email-he.chen@linux.intel.com \
    --to=he.chen@linux.intel.com \
    --cc=andrew.cooper3@citrix.com \
    --cc=ian.campbell@citrix.com \
    --cc=ian.jackson@eu.citrix.com \
    --cc=jbeulich@suse.com \
    --cc=keir@xen.org \
    --cc=stefano.stabellini@eu.citrix.com \
    --cc=wei.liu2@citrix.com \
    --cc=xen-devel@lists.xenproject.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.