From: Andrew Cooper <andrew.cooper3@citrix.com>
To: Chao Peng <chao.p.peng@linux.intel.com>, xen-devel@lists.xen.org
Cc: keir@xen.org, Ian.Campbell@citrix.com,
stefano.stabellini@eu.citrix.com, Ian.Jackson@eu.citrix.com,
will.auld@intel.com, JBeulich@suse.com, wei.liu2@citrix.com,
dgdegra@tycho.nsa.gov
Subject: Re: [PATCH v4 08/12] x86: dynamically get/set CBM for a domain
Date: Thu, 09 Apr 2015 23:06:45 +0100 [thread overview]
Message-ID: <5526F7F5.6030508@citrix.com> (raw)
In-Reply-To: <1428571105-3604-9-git-send-email-chao.p.peng@linux.intel.com>
On 09/04/2015 10:18, Chao Peng wrote:
> 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>
> ---
> xen/arch/x86/domctl.c | 18 ++++++
> xen/arch/x86/psr.c | 126 ++++++++++++++++++++++++++++++++++++++++
> xen/include/asm-x86/msr-index.h | 1 +
> xen/include/asm-x86/psr.h | 2 +
> xen/include/public/domctl.h | 12 ++++
> 5 files changed, 159 insertions(+)
>
> diff --git a/xen/arch/x86/domctl.c b/xen/arch/x86/domctl.c
> index d4f6ccf..89a6b33 100644
> --- a/xen/arch/x86/domctl.c
> +++ b/xen/arch/x86/domctl.c
> @@ -1326,6 +1326,24 @@ 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;
As I have just fixed up the style everywhere else in arch_do_domctl(),
could you put a newline in here, just to visually separate the case
statements slightly.
> + 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 e390fd9..5247bcd 100644
> --- a/xen/arch/x86/psr.c
> +++ b/xen/arch/x86/psr.c
> @@ -56,6 +56,17 @@ static unsigned int get_socket_count(void)
> return DIV_ROUND_UP(nr_cpu_ids, cpus_per_socket);
> }
>
> +static unsigned int get_socket_cpu(unsigned int socket)
> +{
> + if ( socket < nr_sockets )
> + {
> + cpumask_t *cpu_mask = cat_socket_info[socket].socket_cpu_mask;
Blank line between variables and code please.
> + ASSERT(cpu_mask != NULL);
> + return cpumask_any(cpu_mask);
> + }
> + return nr_cpu_ids;
> +}
> +
> static void __init parse_psr_bool(char *s, char *value, char *feature,
> unsigned int mask)
> {
> @@ -252,6 +263,121 @@ int psr_get_cat_l3_info(unsigned int socket, uint32_t *cbm_len,
> return 0;
> }
>
> +int psr_get_l3_cbm(struct domain *d, unsigned int socket, uint64_t *cbm)
> +{
> + unsigned int cos;
> + struct psr_cat_socket_info *info;
> + int ret = get_cat_socket_info(socket, &info);
> +
> + if ( ret )
> + return ret;
> +
> + cos = d->arch.psr_cos_ids[socket];
> + *cbm = info->cos_cbm_map[cos].cbm;
> + return 0;
> +}
> +
> +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;
> +
> + 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;
And again here please.
> + 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, *find;
> + struct psr_cat_socket_info *info;
> + 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_cbm_map;
> + find = NULL;
> +
> + for ( cos = 0; cos <= info->cos_max; cos++ )
> + {
> + /* If still not found, then keep unused one. */
> + if ( !find && cos != 0 && map[cos].ref == 0 )
> + find = map + cos;
> + else if ( map[cos].cbm == cbm )
> + {
> + if ( unlikely(cos == old_cos) )
> + return -EEXIST;
> + find = map + cos;
> + break;
> + }
> + }
> +
> + /* If old cos is referred only by the domain, then use it. */
> + if ( !find && map[old_cos].ref == 1 )
> + find = map + old_cos;
> +
> + if ( !find )
> + return -EUSERS;
> +
> + cos = find - map;
> + if ( find->cbm != cbm )
> + {
> + ret = write_l3_cbm(socket, cos, cbm);
> + if ( ret )
> + return ret;
> + find->cbm = cbm;
> + }
> + find->ref++;
> + map[old_cos].ref--;
This can race with psr_free_cos() leading to corruption. It is possible
for two different domains to be holding their own spinlock but using the
same cos index.
You definitely do need a psr/cos spinlock for safety.
~Andrew
> + d->arch.psr_cos_ids[socket] = cos;
> + return 0;
> +}
> +
> /* Called with domain lock held, no psr specific lock needed */
> 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 3a8a406..fb474bb 100644
> --- a/xen/include/asm-x86/psr.h
> +++ b/xen/include/asm-x86/psr.h
> @@ -54,6 +54,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 ca0e51e..9f04836 100644
> --- a/xen/include/public/domctl.h
> +++ b/xen/include/public/domctl.h
> @@ -1005,6 +1005,16 @@ struct xen_domctl_psr_cmt_op {
> typedef struct xen_domctl_psr_cmt_op xen_domctl_psr_cmt_op_t;
> DEFINE_XEN_GUEST_HANDLE(xen_domctl_psr_cmt_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: socket to be operated on */
> + 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
> @@ -1080,6 +1090,7 @@ struct xen_domctl {
> #define XEN_DOMCTL_setvnumainfo 74
> #define XEN_DOMCTL_psr_cmt_op 75
> #define XEN_DOMCTL_arm_configure_domain 76
> +#define XEN_DOMCTL_psr_cat_op 77
> #define XEN_DOMCTL_gdbsx_guestmemio 1000
> #define XEN_DOMCTL_gdbsx_pausevcpu 1001
> #define XEN_DOMCTL_gdbsx_unpausevcpu 1002
> @@ -1145,6 +1156,7 @@ struct xen_domctl {
> struct xen_domctl_gdbsx_domstatus gdbsx_domstatus;
> struct xen_domctl_vnuma vnuma;
> struct xen_domctl_psr_cmt_op psr_cmt_op;
> + struct xen_domctl_psr_cat_op psr_cat_op;
> uint8_t pad[128];
> } u;
> };
next prev parent reply other threads:[~2015-04-09 22:06 UTC|newest]
Thread overview: 37+ messages / expand[flat|nested] mbox.gz Atom feed top
2015-04-09 9:18 [PATCH v4 00/12] enable Cache Allocation Technology (CAT) for VMs Chao Peng
2015-04-09 9:18 ` [PATCH v4 01/12] x86: clean up psr boot parameter parsing Chao Peng
2015-04-09 20:38 ` Andrew Cooper
2015-04-09 9:18 ` [PATCH v4 02/12] x86: improve psr scheduling code Chao Peng
2015-04-09 21:01 ` Andrew Cooper
2015-04-10 7:24 ` Chao Peng
2015-04-10 9:28 ` Andrew Cooper
2015-04-09 9:18 ` [PATCH v4 03/12] x86: detect and initialize Intel CAT feature Chao Peng
2015-04-09 21:30 ` Andrew Cooper
2015-04-09 9:18 ` [PATCH v4 04/12] x86: maintain COS to CBM mapping for each socket Chao Peng
2015-04-09 21:35 ` Andrew Cooper
2015-04-10 7:26 ` Chao Peng
2015-04-09 9:18 ` [PATCH v4 05/12] x86: maintain socket CPU mask for CAT Chao Peng
2015-04-09 21:45 ` Andrew Cooper
2015-04-10 7:33 ` Chao Peng
2015-04-10 9:48 ` Andrew Cooper
2015-04-09 9:18 ` [PATCH v4 06/12] x86: add COS information for each domain Chao Peng
2015-04-09 21:54 ` Andrew Cooper
2015-04-10 7:35 ` Chao Peng
2015-04-09 9:18 ` [PATCH v4 07/12] x86: expose CBM length and COS number information Chao Peng
2015-04-09 21:54 ` Andrew Cooper
2015-04-09 9:18 ` [PATCH v4 08/12] x86: dynamically get/set CBM for a domain Chao Peng
2015-04-09 22:06 ` Andrew Cooper [this message]
2015-04-10 7:37 ` Chao Peng
2015-04-09 9:18 ` [PATCH v4 09/12] x86: add scheduling support for Intel CAT Chao Peng
2015-04-09 22:12 ` Andrew Cooper
2015-04-10 7:41 ` Chao Peng
2015-04-09 9:18 ` [PATCH v4 10/12] xsm: add CAT related xsm policies Chao Peng
2015-04-09 9:18 ` [PATCH v4 11/12] tools: add tools support for Intel CAT Chao Peng
2015-04-09 10:50 ` Wei Liu
2015-04-16 11:20 ` Ian Campbell
2015-04-09 9:18 ` [PATCH v4 12/12] docs: add xl-psr.markdown Chao Peng
2015-04-09 11:29 ` Andrew Cooper
2015-04-10 7:45 ` Chao Peng
2015-04-16 11:58 ` Ian Campbell
2015-04-17 14:39 ` Chao Peng
2015-04-09 22:15 ` [PATCH v4 00/12] enable Cache Allocation Technology (CAT) for VMs Andrew Cooper
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=5526F7F5.6030508@citrix.com \
--to=andrew.cooper3@citrix.com \
--cc=Ian.Campbell@citrix.com \
--cc=Ian.Jackson@eu.citrix.com \
--cc=JBeulich@suse.com \
--cc=chao.p.peng@linux.intel.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 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.