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

[Xen-devel] [PATCH 2/5] x86: Support enable/disable CDP dynamically and get CDP status



 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@xxxxxxxxxxxxxxx>
---
 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


_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
http://lists.xen.org/xen-devel


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.