xen-devel.lists.xenproject.org archive mirror
 help / color / mirror / Atom feed
From: Chao Peng <chao.p.peng@linux.intel.com>
To: xen-devel@lists.xen.org
Cc: keir@xen.org, Ian.Campbell@citrix.com,
	stefano.stabellini@eu.citrix.com, andrew.cooper3@citrix.com,
	dario.faggioli@citrix.com, Ian.Jackson@eu.citrix.com,
	will.auld@intel.com, JBeulich@suse.com, wei.liu2@citrix.com,
	dgdegra@tycho.nsa.gov
Subject: [PATCH v9 06/13] x86: dynamically get/set CBM for a domain
Date: Wed,  3 Jun 2015 12:53:03 +0800	[thread overview]
Message-ID: <1433307190-6381-7-git-send-email-chao.p.peng@linux.intel.com> (raw)
In-Reply-To: <1433307190-6381-1-git-send-email-chao.p.peng@linux.intel.com>

For CAT, COS is maintained in hypervisor only while CBM is exposed to
user space directly to allow getting/setting domain's cache capacity.
For each specified CBM, hypervisor will either use a existed COS which
has the same CBM or allocate a new one if the same CBM is not found. If
the allocation fails because of no enough COS available then error is
returned. The getting/setting are always operated on a specified socket.
For multiple sockets system, the interface may be called several times.

Signed-off-by: Chao Peng <chao.p.peng@linux.intel.com>
Reviewed-by: Dario Faggioli <dario.faggioli@citrix.com>
Acked-by: Jan Beulich <jbeulich@suse.com>
---
Changes in v9:
* Initialize 'info' explictly so that compiler would not complain.
* Simplify the code and remove multiple return points.
* Remove confused comment for 'target'.
* Add an additional check for cbm to make sure at least one bit is set(which is required).
Changes in v8:
* Add likely for 'socket < nr_sockets' in get_socket_cpu.
Changes in v7:
* find => found in psr_set_l3_cbm().
Changes in v6:
* Correct spin_lock scope.
Changes in v5:
* Add spin_lock to protect cbm_map.
---
 xen/arch/x86/domctl.c           |  20 ++++++
 xen/arch/x86/psr.c              | 139 ++++++++++++++++++++++++++++++++++++++++
 xen/include/asm-x86/msr-index.h |   1 +
 xen/include/asm-x86/psr.h       |   2 +
 xen/include/public/domctl.h     |  12 ++++
 5 files changed, 174 insertions(+)

diff --git a/xen/arch/x86/domctl.c b/xen/arch/x86/domctl.c
index e9f76d0..84baec0 100644
--- a/xen/arch/x86/domctl.c
+++ b/xen/arch/x86/domctl.c
@@ -1130,6 +1130,26 @@ long arch_do_domctl(
         }
         break;
 
+    case XEN_DOMCTL_psr_cat_op:
+        switch ( domctl->u.psr_cat_op.cmd )
+        {
+        case XEN_DOMCTL_PSR_CAT_OP_SET_L3_CBM:
+            ret = psr_set_l3_cbm(d, domctl->u.psr_cat_op.target,
+                                 domctl->u.psr_cat_op.data);
+            break;
+
+        case XEN_DOMCTL_PSR_CAT_OP_GET_L3_CBM:
+            ret = psr_get_l3_cbm(d, domctl->u.psr_cat_op.target,
+                                 &domctl->u.psr_cat_op.data);
+            copyback = 1;
+            break;
+
+        default:
+            ret = -EOPNOTSUPP;
+            break;
+        }
+        break;
+
     default:
         ret = iommu_do_domctl(domctl, d, u_domctl);
         break;
diff --git a/xen/arch/x86/psr.c b/xen/arch/x86/psr.c
index 10c4cdd..fce5bca 100644
--- a/xen/arch/x86/psr.c
+++ b/xen/arch/x86/psr.c
@@ -48,6 +48,14 @@ static unsigned int __read_mostly opt_cos_max = 255;
 static uint64_t rmid_mask;
 static DEFINE_PER_CPU(struct psr_assoc, psr_assoc);
 
+static unsigned int get_socket_cpu(unsigned int socket)
+{
+    if ( likely(socket < nr_sockets) )
+        return cpumask_any(socket_cpumask[socket]);
+
+    return nr_cpu_ids;
+}
+
 static void __init parse_psr_bool(char *s, char *value, char *feature,
                                   unsigned int mask)
 {
@@ -248,6 +256,137 @@ int psr_get_cat_l3_info(unsigned int socket, uint32_t *cbm_len,
     return ret;
 }
 
+int psr_get_l3_cbm(struct domain *d, unsigned int socket, uint64_t *cbm)
+{
+    struct psr_cat_socket_info *info = NULL;
+    int ret = get_cat_socket_info(socket, &info);
+
+    if ( !ret )
+        *cbm = info->cos_to_cbm[d->arch.psr_cos_ids[socket]].cbm;
+
+    return ret;
+}
+
+static bool_t psr_check_cbm(unsigned int cbm_len, uint64_t cbm)
+{
+    unsigned int first_bit, zero_bit;
+
+    /* Set bits should only in the range of [0, cbm_len). */
+    if ( cbm & (~0ull << cbm_len) )
+        return 0;
+
+    /* At least one bit need to be set. */
+    if ( hweight_long(cbm) < 1 )
+        return 0;
+
+    first_bit = find_first_bit(&cbm, cbm_len);
+    zero_bit = find_next_zero_bit(&cbm, cbm_len, first_bit);
+
+    /* Set bits should be contiguous. */
+    if ( zero_bit < cbm_len &&
+         find_next_bit(&cbm, cbm_len, zero_bit) < cbm_len )
+        return 0;
+
+    return 1;
+}
+
+struct cos_cbm_info
+{
+    unsigned int cos;
+    uint64_t cbm;
+};
+
+static void do_write_l3_cbm(void *data)
+{
+    struct cos_cbm_info *info = data;
+
+    wrmsrl(MSR_IA32_PSR_L3_MASK(info->cos), info->cbm);
+}
+
+static int write_l3_cbm(unsigned int socket, unsigned int cos, uint64_t cbm)
+{
+    struct cos_cbm_info info = { .cos = cos, .cbm = cbm };
+
+    if ( socket == cpu_to_socket(smp_processor_id()) )
+        do_write_l3_cbm(&info);
+    else
+    {
+        unsigned int cpu = get_socket_cpu(socket);
+
+        if ( cpu >= nr_cpu_ids )
+            return -EBADSLT;
+        on_selected_cpus(cpumask_of(cpu), do_write_l3_cbm, &info, 1);
+    }
+
+    return 0;
+}
+
+int psr_set_l3_cbm(struct domain *d, unsigned int socket, uint64_t cbm)
+{
+    unsigned int old_cos, cos;
+    struct psr_cat_cbm *map, *found = NULL;
+    struct psr_cat_socket_info *info = NULL;
+    int ret = get_cat_socket_info(socket, &info);
+
+    if ( ret )
+        return ret;
+
+    if ( !psr_check_cbm(info->cbm_len, cbm) )
+        return -EINVAL;
+
+    old_cos = d->arch.psr_cos_ids[socket];
+    map = info->cos_to_cbm;
+
+    spin_lock(&info->cbm_lock);
+
+    for ( cos = 0; cos <= info->cos_max; cos++ )
+    {
+        /* 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 )
+        {
+            if ( unlikely(cos == old_cos) )
+            {
+                spin_unlock(&info->cbm_lock);
+                return 0;
+            }
+            found = map + cos;
+            break;
+        }
+    }
+
+    /* If old cos is referred only by the domain, then use it. */
+    if ( !found && map[old_cos].ref == 1 )
+        found = map + old_cos;
+
+    if ( !found )
+    {
+        spin_unlock(&info->cbm_lock);
+        return -EUSERS;
+    }
+
+    cos = found - map;
+    if ( found->cbm != cbm )
+    {
+        ret = write_l3_cbm(socket, cos, cbm);
+        if ( ret )
+        {
+            spin_unlock(&info->cbm_lock);
+            return ret;
+        }
+        found->cbm = cbm;
+    }
+
+    found->ref++;
+    map[old_cos].ref--;
+    spin_unlock(&info->cbm_lock);
+
+    d->arch.psr_cos_ids[socket] = cos;
+
+    return 0;
+}
+
 /* Called with domain lock held, no extra lock needed for 'psr_cos_ids' */
 static void psr_free_cos(struct domain *d)
 {
diff --git a/xen/include/asm-x86/msr-index.h b/xen/include/asm-x86/msr-index.h
index 83f2f70..5425f77 100644
--- a/xen/include/asm-x86/msr-index.h
+++ b/xen/include/asm-x86/msr-index.h
@@ -327,6 +327,7 @@
 #define MSR_IA32_CMT_EVTSEL		0x00000c8d
 #define MSR_IA32_CMT_CTR		0x00000c8e
 #define MSR_IA32_PSR_ASSOC		0x00000c8f
+#define MSR_IA32_PSR_L3_MASK(n)	(0x00000c90 + (n))
 
 /* Intel Model 6 */
 #define MSR_P6_PERFCTR(n)		(0x000000c1 + (n))
diff --git a/xen/include/asm-x86/psr.h b/xen/include/asm-x86/psr.h
index d364e8c..081750f 100644
--- a/xen/include/asm-x86/psr.h
+++ b/xen/include/asm-x86/psr.h
@@ -53,6 +53,8 @@ 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);
+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);
diff --git a/xen/include/public/domctl.h b/xen/include/public/domctl.h
index 53cdf08..936cf3e 100644
--- a/xen/include/public/domctl.h
+++ b/xen/include/public/domctl.h
@@ -1039,6 +1039,16 @@ struct xen_domctl_monitor_op {
 typedef struct xen_domctl__op xen_domctl_monitor_op_t;
 DEFINE_XEN_GUEST_HANDLE(xen_domctl_monitor_op_t);
 
+struct xen_domctl_psr_cat_op {
+#define XEN_DOMCTL_PSR_CAT_OP_SET_L3_CBM     0
+#define XEN_DOMCTL_PSR_CAT_OP_GET_L3_CBM     1
+    uint32_t cmd;       /* IN: XEN_DOMCTL_PSR_CAT_OP_* */
+    uint32_t target;    /* IN */
+    uint64_t data;      /* IN/OUT */
+};
+typedef struct xen_domctl_psr_cat_op xen_domctl_psr_cat_op_t;
+DEFINE_XEN_GUEST_HANDLE(xen_domctl_psr_cat_op_t);
+
 struct xen_domctl {
     uint32_t cmd;
 #define XEN_DOMCTL_createdomain                   1
@@ -1114,6 +1124,7 @@ struct xen_domctl {
 #define XEN_DOMCTL_setvnumainfo                  74
 #define XEN_DOMCTL_psr_cmt_op                    75
 #define XEN_DOMCTL_monitor_op                    77
+#define XEN_DOMCTL_psr_cat_op                    78
 #define XEN_DOMCTL_gdbsx_guestmemio            1000
 #define XEN_DOMCTL_gdbsx_pausevcpu             1001
 #define XEN_DOMCTL_gdbsx_unpausevcpu           1002
@@ -1175,6 +1186,7 @@ struct xen_domctl {
         struct xen_domctl_vnuma             vnuma;
         struct xen_domctl_psr_cmt_op        psr_cmt_op;
         struct xen_domctl_monitor_op        monitor_op;
+        struct xen_domctl_psr_cat_op        psr_cat_op;
         uint8_t                             pad[128];
     } u;
 };
-- 
1.9.1

  parent reply	other threads:[~2015-06-03  4:53 UTC|newest]

Thread overview: 26+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-06-03  4:52 [PATCH v9 00/13] enable Cache Allocation Technology (CAT) for VMs Chao Peng
2015-06-03  4:52 ` [PATCH v9 01/13] x86: add socket_cpumask Chao Peng
2015-06-15 15:59   ` Jan Beulich
2015-06-03  4:52 ` [PATCH v9 02/13] x86: detect and initialize Intel CAT feature Chao Peng
2015-06-15 15:56   ` Jan Beulich
2015-06-03  4:53 ` [PATCH v9 03/13] x86: maintain COS to CBM mapping for each socket Chao Peng
2015-06-15 16:02   ` Jan Beulich
2015-06-23  7:08     ` Chao Peng
2015-06-23  8:27       ` Jan Beulich
2015-06-03  4:53 ` [PATCH v9 04/13] x86: add COS information for each domain Chao Peng
2015-06-16  6:55   ` Jan Beulich
2015-06-03  4:53 ` [PATCH v9 05/13] x86: expose CBM length and COS number information Chao Peng
2015-06-16  6:58   ` Jan Beulich
2015-06-03  4:53 ` Chao Peng [this message]
2015-06-16  7:08   ` [PATCH v9 06/13] x86: dynamically get/set CBM for a domain Jan Beulich
2015-06-23  7:19     ` Chao Peng
2015-06-23  8:35       ` Jan Beulich
2015-06-23  9:03         ` Chao Peng
2015-06-23  9:14           ` Jan Beulich
2015-06-03  4:53 ` [PATCH v9 07/13] x86: add scheduling support for Intel CAT Chao Peng
2015-06-03  4:53 ` [PATCH v9 08/13] xsm: add CAT related xsm policies Chao Peng
2015-06-03  4:53 ` [PATCH v9 09/13] tools/libxl: minor name changes for CMT commands Chao Peng
2015-06-03  4:53 ` [PATCH v9 10/13] tools/libxl: add command to show PSR hardware info Chao Peng
2015-06-03  4:53 ` [PATCH v9 11/13] tools/libxl: introduce some socket helpers Chao Peng
2015-06-03  4:53 ` [PATCH v9 12/13] tools: add tools support for Intel CAT Chao Peng
2015-06-03  4:53 ` [PATCH v9 13/13] docs: add xl-psr.markdown Chao Peng

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=1433307190-6381-7-git-send-email-chao.p.peng@linux.intel.com \
    --to=chao.p.peng@linux.intel.com \
    --cc=Ian.Campbell@citrix.com \
    --cc=Ian.Jackson@eu.citrix.com \
    --cc=JBeulich@suse.com \
    --cc=andrew.cooper3@citrix.com \
    --cc=dario.faggioli@citrix.com \
    --cc=dgdegra@tycho.nsa.gov \
    --cc=keir@xen.org \
    --cc=stefano.stabellini@eu.citrix.com \
    --cc=wei.liu2@citrix.com \
    --cc=will.auld@intel.com \
    --cc=xen-devel@lists.xen.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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).