All of lore.kernel.org
 help / color / mirror / Atom feed
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

  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 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.