From: Andrew Cooper <andrew.cooper3@citrix.com>
To: He Chen <he.chen@linux.intel.com>, xen-devel@lists.xenproject.org
Cc: keir@xen.org, ian.campbell@citrix.com,
stefano.stabellini@eu.citrix.com, ian.jackson@eu.citrix.com,
jbeulich@suse.com, wei.liu2@citrix.com
Subject: Re: [PATCH 2/5] x86: Support enable/disable CDP dynamically and get CDP status
Date: Wed, 2 Sep 2015 12:39:49 +0100 [thread overview]
Message-ID: <55E6E005.1030904@citrix.com> (raw)
In-Reply-To: <1441182482-7688-3-git-send-email-he.chen@linux.intel.com>
On 02/09/15 09:27, He Chen wrote:
> 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;
Spaces after } please.
> 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)
bool_t *cdp_enabled which...
> {
> 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;
... avoids this typecast.
>
> 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;
This should either be plain "cdp" which would be fine, or
"cdp_enabled". The name "_mode" here is misleading.
> };
>
> 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);
Please introduce
MSR_IA32_PSR_L3_MASK_CBM_CODE()
MSR_IA32_PSR_L3_MASK_CBM_DATA()
to abstract away the x * 2 + 1 calculation.
> + }
> }
>
> -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,
Newline here please, so
{
.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)
Style. spaces inside brakces.
> + 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++;
This is a long running operation and must not be done synchronously like
this. Unfortunately, it is not easy to make restartable.
I think it would be perfectly reasonable to have cdp as a boot time
switch only, and have no ability to change it at runtime. I don't see a
reasonable case to change it dynamically at runtime; users will either
want to use it, or not.
Making this a boot-time choice (i.e. psr=cat,cdp) removes all of this
re-juggling logic, and simplifies things greatly.
Thoughts?
> + }
> +
> + 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;
I realise you are copying the existing (incorrect) style, but please
introduce a blank line between break statements and the subsequent
case/default label. It makes the switch statement far easier to read.
> 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 */
Rather than using a whole 8 bits for a boolean, and leaving alignment
fun for the next person to edit this structure, may I recommend
#define XEN_SYSCTL_PSR_CAT_L3_CDP (1u << 0)
uint32_t flags;
Instead. (Also assumes that in the future we might get CDP at the L4 cache)
~Andrew
next prev parent reply other threads:[~2015-09-02 11:49 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 ` [PATCH 2/5] x86: Support enable/disable CDP dynamically and get CDP status He Chen
2015-09-02 11:39 ` Andrew Cooper [this message]
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=55E6E005.1030904@citrix.com \
--to=andrew.cooper3@citrix.com \
--cc=he.chen@linux.intel.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 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).