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

Re: [Xen-devel] [PATCH v12 for-xen-4.5 09/20] x86/VPMU: Add public xenpmu.h



> From: Boris Ostrovsky [mailto:boris.ostrovsky@xxxxxxxxxx]
> Sent: Thursday, September 25, 2014 12:29 PM
> 
> Add pmu.h header files, move various macros and structures that will be
> shared between hypervisor and PV guests to it.
> 
> Move MSR banks out of architectural PMU structures to allow for larger sizes
> in the future. The banks are allocated immediately after the context and
> PMU structures store offsets to them.
> 
> Signed-off-by: Boris Ostrovsky <boris.ostrovsky@xxxxxxxxxx>

Acked-by: Kevin Tian <kevin.tian@xxxxxxxxx>

> ---
>  xen/arch/x86/hvm/svm/vpmu.c              |  84
> ++++++++++++----------
>  xen/arch/x86/hvm/vmx/vpmu_core2.c        | 118
> +++++++++++++++++--------------
>  xen/arch/x86/hvm/vpmu.c                  |   6 ++
>  xen/arch/x86/oprofile/op_model_ppro.c    |   6 +-
>  xen/include/asm-x86/hvm/vmx/vpmu_core2.h |  32 ---------
>  xen/include/asm-x86/hvm/vpmu.h           |  16 ++---
>  xen/include/public/arch-arm.h            |   3 +
>  xen/include/public/arch-x86/pmu.h        |  77 ++++++++++++++++++++
>  xen/include/public/arch-x86/xen-x86_32.h |   8 +++
>  xen/include/public/arch-x86/xen-x86_64.h |   8 +++
>  xen/include/public/pmu.h                 |  38 ++++++++++
>  11 files changed, 263 insertions(+), 133 deletions(-)
>  delete mode 100644 xen/include/asm-x86/hvm/vmx/vpmu_core2.h
>  create mode 100644 xen/include/public/arch-x86/pmu.h
>  create mode 100644 xen/include/public/pmu.h
> 
> diff --git a/xen/arch/x86/hvm/svm/vpmu.c b/xen/arch/x86/hvm/svm/vpmu.c
> index 11e9484..124b147 100644
> --- a/xen/arch/x86/hvm/svm/vpmu.c
> +++ b/xen/arch/x86/hvm/svm/vpmu.c
> @@ -30,10 +30,7 @@
>  #include <asm/apic.h>
>  #include <asm/hvm/vlapic.h>
>  #include <asm/hvm/vpmu.h>
> -
> -#define F10H_NUM_COUNTERS 4
> -#define F15H_NUM_COUNTERS 6
> -#define MAX_NUM_COUNTERS F15H_NUM_COUNTERS
> +#include <public/pmu.h>
> 
>  #define MSR_F10H_EVNTSEL_GO_SHIFT   40
>  #define MSR_F10H_EVNTSEL_EN_SHIFT   22
> @@ -49,6 +46,10 @@ static const u32 __read_mostly *counters;
>  static const u32 __read_mostly *ctrls;
>  static bool_t __read_mostly k7_counters_mirrored;
> 
> +#define F10H_NUM_COUNTERS   4
> +#define F15H_NUM_COUNTERS   6
> +#define AMD_MAX_COUNTERS    6
> +
>  /* PMU Counter MSRs. */
>  static const u32 AMD_F10H_COUNTERS[] = {
>      MSR_K7_PERFCTR0,
> @@ -83,12 +84,14 @@ static const u32 AMD_F15H_CTRLS[] = {
>      MSR_AMD_FAM15H_EVNTSEL5
>  };
> 
> -/* storage for context switching */
> -struct amd_vpmu_context {
> -    u64 counters[MAX_NUM_COUNTERS];
> -    u64 ctrls[MAX_NUM_COUNTERS];
> -    bool_t msr_bitmap_set;
> -};
> +/* Use private context as a flag for MSR bitmap */
> +#define msr_bitmap_on(vpmu)    do
> {                                    \
> +                                   (vpmu)->priv_context = (void *)-1L;
> \
> +                               } while (0)
> +#define msr_bitmap_off(vpmu)   do
> {                                    \
> +                                   (vpmu)->priv_context = NULL;
> \
> +                               } while (0)
> +#define is_msr_bitmap_on(vpmu) ((vpmu)->priv_context != NULL)
> 
>  static inline int get_pmu_reg_type(u32 addr)
>  {
> @@ -142,7 +145,6 @@ static void amd_vpmu_set_msr_bitmap(struct vcpu
> *v)
>  {
>      unsigned int i;
>      struct vpmu_struct *vpmu = vcpu_vpmu(v);
> -    struct amd_vpmu_context *ctxt = vpmu->context;
> 
>      for ( i = 0; i < num_counters; i++ )
>      {
> @@ -150,14 +152,13 @@ static void amd_vpmu_set_msr_bitmap(struct vcpu
> *v)
>          svm_intercept_msr(v, ctrls[i], MSR_INTERCEPT_WRITE);
>      }
> 
> -    ctxt->msr_bitmap_set = 1;
> +    msr_bitmap_on(vpmu);
>  }
> 
>  static void amd_vpmu_unset_msr_bitmap(struct vcpu *v)
>  {
>      unsigned int i;
>      struct vpmu_struct *vpmu = vcpu_vpmu(v);
> -    struct amd_vpmu_context *ctxt = vpmu->context;
> 
>      for ( i = 0; i < num_counters; i++ )
>      {
> @@ -165,7 +166,7 @@ static void amd_vpmu_unset_msr_bitmap(struct vcpu
> *v)
>          svm_intercept_msr(v, ctrls[i], MSR_INTERCEPT_RW);
>      }
> 
> -    ctxt->msr_bitmap_set = 0;
> +    msr_bitmap_off(vpmu);
>  }
> 
>  static int amd_vpmu_do_interrupt(struct cpu_user_regs *regs)
> @@ -177,19 +178,22 @@ static inline void context_load(struct vcpu *v)
>  {
>      unsigned int i;
>      struct vpmu_struct *vpmu = vcpu_vpmu(v);
> -    struct amd_vpmu_context *ctxt = vpmu->context;
> +    struct xen_pmu_amd_ctxt *ctxt = vpmu->context;
> +    uint64_t *counter_regs = vpmu_reg_pointer(ctxt, counters);
> +    uint64_t *ctrl_regs = vpmu_reg_pointer(ctxt, ctrls);
> 
>      for ( i = 0; i < num_counters; i++ )
>      {
> -        wrmsrl(counters[i], ctxt->counters[i]);
> -        wrmsrl(ctrls[i], ctxt->ctrls[i]);
> +        wrmsrl(counters[i], counter_regs[i]);
> +        wrmsrl(ctrls[i], ctrl_regs[i]);
>      }
>  }
> 
>  static void amd_vpmu_load(struct vcpu *v)
>  {
>      struct vpmu_struct *vpmu = vcpu_vpmu(v);
> -    struct amd_vpmu_context *ctxt = vpmu->context;
> +    struct xen_pmu_amd_ctxt *ctxt = vpmu->context;
> +    uint64_t *ctrl_regs = vpmu_reg_pointer(ctxt, ctrls);
> 
>      vpmu_reset(vpmu, VPMU_FROZEN);
> 
> @@ -198,7 +202,7 @@ static void amd_vpmu_load(struct vcpu *v)
>          unsigned int i;
> 
>          for ( i = 0; i < num_counters; i++ )
> -            wrmsrl(ctrls[i], ctxt->ctrls[i]);
> +            wrmsrl(ctrls[i], ctrl_regs[i]);
> 
>          return;
>      }
> @@ -212,17 +216,17 @@ static inline void context_save(struct vcpu *v)
>  {
>      unsigned int i;
>      struct vpmu_struct *vpmu = vcpu_vpmu(v);
> -    struct amd_vpmu_context *ctxt = vpmu->context;
> +    struct xen_pmu_amd_ctxt *ctxt = vpmu->context;
> +    uint64_t *counter_regs = vpmu_reg_pointer(ctxt, counters);
> 
>      /* No need to save controls -- they are saved in amd_vpmu_do_wrmsr
> */
>      for ( i = 0; i < num_counters; i++ )
> -        rdmsrl(counters[i], ctxt->counters[i]);
> +        rdmsrl(counters[i], counter_regs[i]);
>  }
> 
>  static int amd_vpmu_save(struct vcpu *v)
>  {
>      struct vpmu_struct *vpmu = vcpu_vpmu(v);
> -    struct amd_vpmu_context *ctx = vpmu->context;
>      unsigned int i;
> 
>      /*
> @@ -245,7 +249,7 @@ static int amd_vpmu_save(struct vcpu *v)
>      context_save(v);
> 
>      if ( !vpmu_is_set(vpmu, VPMU_RUNNING) &&
> -         has_hvm_container_domain(v->domain) &&
> ctx->msr_bitmap_set )
> +         has_hvm_container_domain(v->domain) &&
> is_msr_bitmap_on(vpmu) )
>          amd_vpmu_unset_msr_bitmap(v);
> 
>      return 1;
> @@ -256,7 +260,9 @@ static void context_update(unsigned int msr, u64
> msr_content)
>      unsigned int i;
>      struct vcpu *v = current;
>      struct vpmu_struct *vpmu = vcpu_vpmu(v);
> -    struct amd_vpmu_context *ctxt = vpmu->context;
> +    struct xen_pmu_amd_ctxt *ctxt = vpmu->context;
> +    uint64_t *counter_regs = vpmu_reg_pointer(ctxt, counters);
> +    uint64_t *ctrl_regs = vpmu_reg_pointer(ctxt, ctrls);
> 
>      if ( k7_counters_mirrored &&
>          ((msr >= MSR_K7_EVNTSEL0) && (msr <= MSR_K7_PERFCTR3)) )
> @@ -268,12 +274,12 @@ static void context_update(unsigned int msr, u64
> msr_content)
>      {
>         if ( msr == ctrls[i] )
>         {
> -           ctxt->ctrls[i] = msr_content;
> +           ctrl_regs[i] = msr_content;
>             return;
>         }
>          else if (msr == counters[i] )
>          {
> -            ctxt->counters[i] = msr_content;
> +            counter_regs[i] = msr_content;
>              return;
>          }
>      }
> @@ -303,8 +309,7 @@ static int amd_vpmu_do_wrmsr(unsigned int msr,
> uint64_t msr_content,
>              return 1;
>          vpmu_set(vpmu, VPMU_RUNNING);
> 
> -        if ( has_hvm_container_domain(v->domain) &&
> -             !((struct amd_vpmu_context
> *)vpmu->context)->msr_bitmap_set )
> +        if ( has_hvm_container_domain(v->domain) &&
> is_msr_bitmap_on(vpmu) )
>               amd_vpmu_set_msr_bitmap(v);
>      }
> 
> @@ -313,8 +318,7 @@ static int amd_vpmu_do_wrmsr(unsigned int msr,
> uint64_t msr_content,
>          (is_pmu_enabled(msr_content) == 0) && vpmu_is_set(vpmu,
> VPMU_RUNNING) )
>      {
>          vpmu_reset(vpmu, VPMU_RUNNING);
> -        if ( has_hvm_container_domain(v->domain) &&
> -             ((struct amd_vpmu_context
> *)vpmu->context)->msr_bitmap_set )
> +        if ( has_hvm_container_domain(v->domain) &&
> is_msr_bitmap_on(vpmu) )
>               amd_vpmu_unset_msr_bitmap(v);
>          release_pmu_ownship(PMU_OWNER_HVM);
>      }
> @@ -355,7 +359,7 @@ static int amd_vpmu_do_rdmsr(unsigned int msr,
> uint64_t *msr_content)
> 
>  static int amd_vpmu_initialise(struct vcpu *v)
>  {
> -    struct amd_vpmu_context *ctxt;
> +    struct xen_pmu_amd_ctxt *ctxt;
>      struct vpmu_struct *vpmu = vcpu_vpmu(v);
>      uint8_t family = current_cpu_data.x86;
> 
> @@ -385,7 +389,8 @@ static int amd_vpmu_initialise(struct vcpu *v)
>        }
>      }
> 
> -    ctxt = xzalloc(struct amd_vpmu_context);
> +    ctxt = xzalloc_bytes(sizeof(struct xen_pmu_amd_ctxt) +
> +                         2 * sizeof(uint64_t) * AMD_MAX_COUNTERS);
>      if ( !ctxt )
>      {
>          gdprintk(XENLOG_WARNING, "Insufficient memory for PMU, "
> @@ -394,7 +399,11 @@ static int amd_vpmu_initialise(struct vcpu *v)
>          return -ENOMEM;
>      }
> 
> +    ctxt->counters = sizeof(struct xen_pmu_amd_ctxt);
> +    ctxt->ctrls = ctxt->counters + sizeof(uint64_t) * AMD_MAX_COUNTERS;
> +
>      vpmu->context = ctxt;
> +    vpmu->priv_context = NULL;
>      vpmu_set(vpmu, VPMU_CONTEXT_ALLOCATED);
>      return 0;
>  }
> @@ -406,8 +415,7 @@ static void amd_vpmu_destroy(struct vcpu *v)
>      if ( !vpmu_is_set(vpmu, VPMU_CONTEXT_ALLOCATED) )
>          return;
> 
> -    if ( has_hvm_container_domain(v->domain) &&
> -         ((struct amd_vpmu_context *)vpmu->context)->msr_bitmap_set )
> +    if ( has_hvm_container_domain(v->domain) &&
> is_msr_bitmap_on(vpmu) )
>          amd_vpmu_unset_msr_bitmap(v);
> 
>      xfree(vpmu->context);
> @@ -424,7 +432,9 @@ static void amd_vpmu_destroy(struct vcpu *v)
>  static void amd_vpmu_dump(const struct vcpu *v)
>  {
>      const struct vpmu_struct *vpmu = vcpu_vpmu(v);
> -    const struct amd_vpmu_context *ctxt = vpmu->context;
> +    const struct xen_pmu_amd_ctxt *ctxt = vpmu->context;
> +    const uint64_t *counter_regs = vpmu_reg_pointer(ctxt, counters);
> +    const uint64_t *ctrl_regs = vpmu_reg_pointer(ctxt, ctrls);
>      unsigned int i;
> 
>      printk("    VPMU state: 0x%x ", vpmu->flags);
> @@ -454,8 +464,8 @@ static void amd_vpmu_dump(const struct vcpu *v)
>          rdmsrl(ctrls[i], ctrl);
>          rdmsrl(counters[i], cntr);
>          printk("      %#x: %#lx (%#lx in HW)    %#x: %#lx (%#lx in
> HW)\n",
> -               ctrls[i], ctxt->ctrls[i], ctrl,
> -               counters[i], ctxt->counters[i], cntr);
> +               ctrls[i], ctrl_regs[i], ctrl,
> +               counters[i], counter_regs[i], cntr);
>      }
>  }
> 
> diff --git a/xen/arch/x86/hvm/vmx/vpmu_core2.c
> b/xen/arch/x86/hvm/vmx/vpmu_core2.c
> index 79a82a3..beff5c3 100644
> --- a/xen/arch/x86/hvm/vmx/vpmu_core2.c
> +++ b/xen/arch/x86/hvm/vmx/vpmu_core2.c
> @@ -35,8 +35,8 @@
>  #include <asm/hvm/vmx/vmcs.h>
>  #include <public/sched.h>
>  #include <public/hvm/save.h>
> +#include <public/pmu.h>
>  #include <asm/hvm/vpmu.h>
> -#include <asm/hvm/vmx/vpmu_core2.h>
> 
>  /*
>   * See Intel SDM Vol 2a Instruction Set Reference chapter 3 for CPUID
> @@ -68,6 +68,10 @@
>  #define MSR_PMC_ALIAS_MASK       (~(MSR_IA32_PERFCTR0 ^
> MSR_IA32_A_PERFCTR0))
>  static bool_t __read_mostly full_width_write;
> 
> +/* Intel-specific VPMU features */
> +#define VPMU_CPU_HAS_DS                     0x100 /* Has Debug
> Store */
> +#define VPMU_CPU_HAS_BTS                    0x200 /* Has Branch
> Trace Store */
> +
>  /*
>   * MSR_CORE_PERF_FIXED_CTR_CTRL contains the configuration of all fixed
>   * counters. 4 bits for every counter.
> @@ -75,17 +79,6 @@ static bool_t __read_mostly full_width_write;
>  #define FIXED_CTR_CTRL_BITS 4
>  #define FIXED_CTR_CTRL_MASK ((1 << FIXED_CTR_CTRL_BITS) - 1)
> 
> -#define VPMU_CORE2_MAX_FIXED_PMCS     4
> -struct core2_vpmu_context {
> -    u64 fixed_ctrl;
> -    u64 ds_area;
> -    u64 pebs_enable;
> -    u64 global_ovf_status;
> -    u64 enabled_cntrs;  /* Follows PERF_GLOBAL_CTRL MSR format */
> -    u64 fix_counters[VPMU_CORE2_MAX_FIXED_PMCS];
> -    struct arch_msr_pair arch_msr_pair[1];
> -};
> -
>  /* Number of general-purpose and fixed performance counters */
>  static unsigned int __read_mostly arch_pmc_cnt, fixed_pmc_cnt;
> 
> @@ -222,6 +215,7 @@ static int is_core2_vpmu_msr(u32 msr_index, int
> *type, int *index)
>      }
>  }
> 
> +#define msraddr_to_bitpos(x) (((x)&0xffff) + ((x)>>31)*0x2000)
>  static void core2_vpmu_set_msr_bitmap(unsigned long *msr_bitmap)
>  {
>      int i;
> @@ -291,12 +285,15 @@ static void
> core2_vpmu_unset_msr_bitmap(unsigned long *msr_bitmap)
>  static inline void __core2_vpmu_save(struct vcpu *v)
>  {
>      int i;
> -    struct core2_vpmu_context *core2_vpmu_cxt = vcpu_vpmu(v)->context;
> +    struct xen_pmu_intel_ctxt *core2_vpmu_cxt = vcpu_vpmu(v)->context;
> +    uint64_t *fixed_counters = vpmu_reg_pointer(core2_vpmu_cxt,
> fixed_counters);
> +    struct xen_pmu_cntr_pair *xen_pmu_cntr_pair =
> +        vpmu_reg_pointer(core2_vpmu_cxt, arch_counters);
> 
>      for ( i = 0; i < fixed_pmc_cnt; i++ )
> -        rdmsrl(MSR_CORE_PERF_FIXED_CTR0 + i,
> core2_vpmu_cxt->fix_counters[i]);
> +        rdmsrl(MSR_CORE_PERF_FIXED_CTR0 + i, fixed_counters[i]);
>      for ( i = 0; i < arch_pmc_cnt; i++ )
> -        rdmsrl(MSR_IA32_PERFCTR0 + i,
> core2_vpmu_cxt->arch_msr_pair[i].counter);
> +        rdmsrl(MSR_IA32_PERFCTR0 + i, xen_pmu_cntr_pair[i].counter);
>  }
> 
>  static int core2_vpmu_save(struct vcpu *v)
> @@ -319,10 +316,13 @@ static int core2_vpmu_save(struct vcpu *v)
>  static inline void __core2_vpmu_load(struct vcpu *v)
>  {
>      unsigned int i, pmc_start;
> -    struct core2_vpmu_context *core2_vpmu_cxt = vcpu_vpmu(v)->context;
> +    struct xen_pmu_intel_ctxt *core2_vpmu_cxt = vcpu_vpmu(v)->context;
> +    uint64_t *fixed_counters = vpmu_reg_pointer(core2_vpmu_cxt,
> fixed_counters);
> +    struct xen_pmu_cntr_pair *xen_pmu_cntr_pair =
> +        vpmu_reg_pointer(core2_vpmu_cxt, arch_counters);
> 
>      for ( i = 0; i < fixed_pmc_cnt; i++ )
> -        wrmsrl(MSR_CORE_PERF_FIXED_CTR0 + i,
> core2_vpmu_cxt->fix_counters[i]);
> +        wrmsrl(MSR_CORE_PERF_FIXED_CTR0 + i, fixed_counters[i]);
> 
>      if ( full_width_write )
>          pmc_start = MSR_IA32_A_PERFCTR0;
> @@ -330,8 +330,8 @@ static inline void __core2_vpmu_load(struct vcpu *v)
>          pmc_start = MSR_IA32_PERFCTR0;
>      for ( i = 0; i < arch_pmc_cnt; i++ )
>      {
> -        wrmsrl(pmc_start + i, core2_vpmu_cxt->arch_msr_pair[i].counter);
> -        wrmsrl(MSR_P6_EVNTSEL(i),
> core2_vpmu_cxt->arch_msr_pair[i].control);
> +        wrmsrl(pmc_start + i, xen_pmu_cntr_pair[i].counter);
> +        wrmsrl(MSR_P6_EVNTSEL(i), xen_pmu_cntr_pair[i].control);
>      }
> 
>      wrmsrl(MSR_CORE_PERF_FIXED_CTR_CTRL,
> core2_vpmu_cxt->fixed_ctrl);
> @@ -354,7 +354,8 @@ static void core2_vpmu_load(struct vcpu *v)
>  static int core2_vpmu_alloc_resource(struct vcpu *v)
>  {
>      struct vpmu_struct *vpmu = vcpu_vpmu(v);
> -    struct core2_vpmu_context *core2_vpmu_cxt;
> +    struct xen_pmu_intel_ctxt *core2_vpmu_cxt = NULL;
> +    uint64_t *p = NULL;
> 
>      if ( !acquire_pmu_ownership(PMU_OWNER_HVM) )
>          return 0;
> @@ -367,12 +368,20 @@ static int core2_vpmu_alloc_resource(struct vcpu
> *v)
>          goto out_err;
>      vmx_write_guest_msr(MSR_CORE_PERF_GLOBAL_CTRL, 0);
> 
> -    core2_vpmu_cxt = xzalloc_bytes(sizeof(struct core2_vpmu_context) +
> -                    (arch_pmc_cnt-1)*sizeof(struct arch_msr_pair));
> -    if ( !core2_vpmu_cxt )
> +    core2_vpmu_cxt = xzalloc_bytes(sizeof(struct xen_pmu_intel_ctxt) +
> +                                   sizeof(uint64_t) * fixed_pmc_cnt +
> +                                   sizeof(struct xen_pmu_cntr_pair)
> *
> +                                   arch_pmc_cnt);
> +    p = xzalloc(uint64_t);
> +    if ( !core2_vpmu_cxt || !p )
>          goto out_err;
> 
> -    vpmu->context = (void *)core2_vpmu_cxt;
> +    core2_vpmu_cxt->fixed_counters = sizeof(struct xen_pmu_intel_ctxt);
> +    core2_vpmu_cxt->arch_counters = core2_vpmu_cxt->fixed_counters +
> +                                    sizeof(uint64_t) * fixed_pmc_cnt;
> +
> +    vpmu->context = core2_vpmu_cxt;
> +    vpmu->priv_context = p;
> 
>      vpmu_set(vpmu, VPMU_CONTEXT_ALLOCATED);
> 
> @@ -381,6 +390,9 @@ static int core2_vpmu_alloc_resource(struct vcpu *v)
>  out_err:
>      release_pmu_ownship(PMU_OWNER_HVM);
> 
> +    xfree(core2_vpmu_cxt);
> +    xfree(p);
> +
>      printk("Failed to allocate VPMU resources for domain %u vcpu %u\n",
>             v->vcpu_id, v->domain->domain_id);
> 
> @@ -418,7 +430,8 @@ static int core2_vpmu_do_wrmsr(unsigned int msr,
> uint64_t msr_content,
>      int type = -1, index = -1;
>      struct vcpu *v = current;
>      struct vpmu_struct *vpmu = vcpu_vpmu(v);
> -    struct core2_vpmu_context *core2_vpmu_cxt = NULL;
> +    struct xen_pmu_intel_ctxt *core2_vpmu_cxt = NULL;
> +    uint64_t *enabled_cntrs;
> 
>      if ( !core2_vpmu_msr_common_check(msr, &type, &index) )
>      {
> @@ -446,10 +459,11 @@ static int core2_vpmu_do_wrmsr(unsigned int msr,
> uint64_t msr_content,
>      ASSERT(!supported);
> 
>      core2_vpmu_cxt = vpmu->context;
> +    enabled_cntrs = vpmu->priv_context;
>      switch ( msr )
>      {
>      case MSR_CORE_PERF_GLOBAL_OVF_CTRL:
> -        core2_vpmu_cxt->global_ovf_status &= ~msr_content;
> +        core2_vpmu_cxt->global_status &= ~msr_content;
>          return 1;
>      case MSR_CORE_PERF_GLOBAL_STATUS:
>          gdprintk(XENLOG_INFO, "Can not write readonly MSR: "
> @@ -483,15 +497,14 @@ static int core2_vpmu_do_wrmsr(unsigned int msr,
> uint64_t msr_content,
>          break;
>      case MSR_CORE_PERF_FIXED_CTR_CTRL:
>          vmx_read_guest_msr(MSR_CORE_PERF_GLOBAL_CTRL,
> &global_ctrl);
> -        core2_vpmu_cxt->enabled_cntrs &=
> -                ~(((1ULL << VPMU_CORE2_MAX_FIXED_PMCS) - 1) <<
> 32);
> +        *enabled_cntrs &= ~(((1ULL << fixed_pmc_cnt) - 1) << 32);
>          if ( msr_content != 0 )
>          {
>              u64 val = msr_content;
>              for ( i = 0; i < fixed_pmc_cnt; i++ )
>              {
>                  if ( val & 3 )
> -                    core2_vpmu_cxt->enabled_cntrs |= (1ULL << 32) <<
> i;
> +                    *enabled_cntrs |= (1ULL << 32) << i;
>                  val >>= FIXED_CTR_CTRL_BITS;
>              }
>          }
> @@ -502,19 +515,21 @@ static int core2_vpmu_do_wrmsr(unsigned int msr,
> uint64_t msr_content,
>          tmp = msr - MSR_P6_EVNTSEL(0);
>          if ( tmp >= 0 && tmp < arch_pmc_cnt )
>          {
> +            struct xen_pmu_cntr_pair *xen_pmu_cntr_pair =
> +                vpmu_reg_pointer(core2_vpmu_cxt, arch_counters);
> +
>              vmx_read_guest_msr(MSR_CORE_PERF_GLOBAL_CTRL,
> &global_ctrl);
> 
>              if ( msr_content & (1ULL << 22) )
> -                core2_vpmu_cxt->enabled_cntrs |= 1ULL << tmp;
> +                *enabled_cntrs |= 1ULL << tmp;
>              else
> -                core2_vpmu_cxt->enabled_cntrs &= ~(1ULL << tmp);
> +                *enabled_cntrs &= ~(1ULL << tmp);
> 
> -            core2_vpmu_cxt->arch_msr_pair[tmp].control = msr_content;
> +            xen_pmu_cntr_pair[tmp].control = msr_content;
>          }
>      }
> 
> -    if ( (global_ctrl & core2_vpmu_cxt->enabled_cntrs) ||
> -         (core2_vpmu_cxt->ds_area != 0)  )
> +    if ( (global_ctrl & *enabled_cntrs) || (core2_vpmu_cxt->ds_area != 0) )
>          vpmu_set(vpmu, VPMU_RUNNING);
>      else
>          vpmu_reset(vpmu, VPMU_RUNNING);
> @@ -560,7 +575,7 @@ static int core2_vpmu_do_rdmsr(unsigned int msr,
> uint64_t *msr_content)
>      int type = -1, index = -1;
>      struct vcpu *v = current;
>      struct vpmu_struct *vpmu = vcpu_vpmu(v);
> -    struct core2_vpmu_context *core2_vpmu_cxt = NULL;
> +    struct xen_pmu_intel_ctxt *core2_vpmu_cxt = NULL;
> 
>      if ( core2_vpmu_msr_common_check(msr, &type, &index) )
>      {
> @@ -571,7 +586,7 @@ static int core2_vpmu_do_rdmsr(unsigned int msr,
> uint64_t *msr_content)
>              *msr_content = 0;
>              break;
>          case MSR_CORE_PERF_GLOBAL_STATUS:
> -            *msr_content = core2_vpmu_cxt->global_ovf_status;
> +            *msr_content = core2_vpmu_cxt->global_status;
>              break;
>          case MSR_CORE_PERF_GLOBAL_CTRL:
>              vmx_read_guest_msr(MSR_CORE_PERF_GLOBAL_CTRL,
> msr_content);
> @@ -620,10 +635,12 @@ static void core2_vpmu_dump(const struct vcpu *v)
>  {
>      const struct vpmu_struct *vpmu = vcpu_vpmu(v);
>      unsigned int i;
> -    const struct core2_vpmu_context *core2_vpmu_cxt = NULL;
> +    const struct xen_pmu_intel_ctxt *core2_vpmu_cxt = vpmu->context;
>      u64 val;
> +    uint64_t *fixed_counters;
> +    struct xen_pmu_cntr_pair *cntr_pair;
> 
> -    if ( !vpmu_is_set(vpmu, VPMU_CONTEXT_ALLOCATED) )
> +    if ( !core2_vpmu_cxt || !vpmu_is_set(vpmu,
> VPMU_CONTEXT_ALLOCATED) )
>           return;
> 
>      if ( !vpmu_is_set(vpmu, VPMU_RUNNING) )
> @@ -636,16 +653,15 @@ static void core2_vpmu_dump(const struct vcpu *v)
>      }
> 
>      printk("    vPMU running\n");
> -    core2_vpmu_cxt = vpmu->context;
> +
> +    cntr_pair = vpmu_reg_pointer(core2_vpmu_cxt, arch_counters);
> +    fixed_counters = vpmu_reg_pointer(core2_vpmu_cxt, fixed_counters);
> 
>      /* Print the contents of the counter and its configuration msr. */
>      for ( i = 0; i < arch_pmc_cnt; i++ )
> -    {
> -        const struct arch_msr_pair *msr_pair =
> core2_vpmu_cxt->arch_msr_pair;
> -
>          printk("      general_%d: 0x%016lx ctrl: 0x%016lx\n",
> -               i, msr_pair[i].counter, msr_pair[i].control);
> -    }
> +            i, cntr_pair[i].counter, cntr_pair[i].control);
> +
>      /*
>       * The configuration of the fixed counter is 4 bits each in the
>       * MSR_CORE_PERF_FIXED_CTR_CTRL.
> @@ -654,7 +670,7 @@ static void core2_vpmu_dump(const struct vcpu *v)
>      for ( i = 0; i < fixed_pmc_cnt; i++ )
>      {
>          printk("      fixed_%d:   0x%016lx ctrl: %#lx\n",
> -               i, core2_vpmu_cxt->fix_counters[i],
> +               i, fixed_counters[i],
>                 val & FIXED_CTR_CTRL_MASK);
>          val >>= FIXED_CTR_CTRL_BITS;
>      }
> @@ -665,14 +681,14 @@ static int core2_vpmu_do_interrupt(struct
> cpu_user_regs *regs)
>      struct vcpu *v = current;
>      u64 msr_content;
>      struct vpmu_struct *vpmu = vcpu_vpmu(v);
> -    struct core2_vpmu_context *core2_vpmu_cxt = vpmu->context;
> +    struct xen_pmu_intel_ctxt *core2_vpmu_cxt = vpmu->context;
> 
>      rdmsrl(MSR_CORE_PERF_GLOBAL_STATUS, msr_content);
>      if ( msr_content )
>      {
>          if ( is_pmc_quirk )
>              handle_pmc_quirk(msr_content);
> -        core2_vpmu_cxt->global_ovf_status |= msr_content;
> +        core2_vpmu_cxt->global_status |= msr_content;
>          msr_content = 0xC000000700000000 | ((1 << arch_pmc_cnt) - 1);
>          wrmsrl(MSR_CORE_PERF_GLOBAL_OVF_CTRL, msr_content);
>      }
> @@ -739,13 +755,6 @@ static int core2_vpmu_initialise(struct vcpu *v,
> unsigned int vpmu_flags)
> 
>      arch_pmc_cnt = core2_get_arch_pmc_count();
>      fixed_pmc_cnt = core2_get_fixed_pmc_count();
> -    if ( fixed_pmc_cnt > VPMU_CORE2_MAX_FIXED_PMCS )
> -    {
> -        fixed_pmc_cnt = VPMU_CORE2_MAX_FIXED_PMCS;
> -        printk(XENLOG_G_WARNING "Limiting number of fixed counters
> to %d\n",
> -               fixed_pmc_cnt);
> -    }
> -
>      check_pmc_quirk();
>      return 0;
>  }
> @@ -758,6 +767,7 @@ static void core2_vpmu_destroy(struct vcpu *v)
>          return;
> 
>      xfree(vpmu->context);
> +    xfree(vpmu->priv_context);
>      if ( has_hvm_container_domain(v->domain) &&
> cpu_has_vmx_msr_bitmap )
>          core2_vpmu_unset_msr_bitmap(v->arch.hvm_vmx.msr_bitmap);
>      release_pmu_ownship(PMU_OWNER_HVM);
> diff --git a/xen/arch/x86/hvm/vpmu.c b/xen/arch/x86/hvm/vpmu.c
> index 0210284..071b869 100644
> --- a/xen/arch/x86/hvm/vpmu.c
> +++ b/xen/arch/x86/hvm/vpmu.c
> @@ -31,6 +31,7 @@
>  #include <asm/hvm/svm/svm.h>
>  #include <asm/hvm/svm/vmcb.h>
>  #include <asm/apic.h>
> +#include <public/pmu.h>
> 
>  /*
>   * "vpmu" :     vpmu generally enabled
> @@ -228,6 +229,11 @@ void vpmu_initialise(struct vcpu *v)
>      struct vpmu_struct *vpmu = vcpu_vpmu(v);
>      uint8_t vendor = current_cpu_data.x86_vendor;
> 
> +    BUILD_BUG_ON(sizeof(struct xen_pmu_intel_ctxt) >
> XENPMU_CTXT_PAD_SZ);
> +    BUILD_BUG_ON(sizeof(struct xen_pmu_amd_ctxt) >
> XENPMU_CTXT_PAD_SZ);
> +    BUILD_BUG_ON(sizeof(struct xen_pmu_regs) >
> XENPMU_REGS_PAD_SZ);
> +    BUILD_BUG_ON(sizeof(struct compat_pmu_regs) >
> XENPMU_REGS_PAD_SZ);
> +
>      if ( vpmu_is_set(vpmu, VPMU_CONTEXT_ALLOCATED) )
>          vpmu_destroy(v);
>      vpmu_clear(vpmu);
> diff --git a/xen/arch/x86/oprofile/op_model_ppro.c
> b/xen/arch/x86/oprofile/op_model_ppro.c
> index aa99e4d..ca429a1 100644
> --- a/xen/arch/x86/oprofile/op_model_ppro.c
> +++ b/xen/arch/x86/oprofile/op_model_ppro.c
> @@ -20,11 +20,15 @@
>  #include <asm/regs.h>
>  #include <asm/current.h>
>  #include <asm/hvm/vpmu.h>
> -#include <asm/hvm/vmx/vpmu_core2.h>
> 
>  #include "op_x86_model.h"
>  #include "op_counter.h"
> 
> +struct arch_msr_pair {
> +    u64 counter;
> +    u64 control;
> +};
> +
>  /*
>   * Intel "Architectural Performance Monitoring" CPUID
>   * detection/enumeration details:
> diff --git a/xen/include/asm-x86/hvm/vmx/vpmu_core2.h
> b/xen/include/asm-x86/hvm/vmx/vpmu_core2.h
> deleted file mode 100644
> index 410372d..0000000
> --- a/xen/include/asm-x86/hvm/vmx/vpmu_core2.h
> +++ /dev/null
> @@ -1,32 +0,0 @@
> -
> -/*
> - * vpmu_core2.h: CORE 2 specific PMU virtualization for HVM domain.
> - *
> - * Copyright (c) 2007, Intel Corporation.
> - *
> - * This program is free software; you can redistribute it and/or modify it
> - * under the terms and conditions of the GNU General Public License,
> - * version 2, as published by the Free Software Foundation.
> - *
> - * This program is distributed in the hope it will be useful, but WITHOUT
> - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
> or
> - * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
> License for
> - * more details.
> - *
> - * You should have received a copy of the GNU General Public License along
> with
> - * this program; if not, write to the Free Software Foundation, Inc., 59 
> Temple
> - * Place - Suite 330, Boston, MA 02111-1307 USA.
> - *
> - * Author: Haitao Shan <haitao.shan@xxxxxxxxx>
> - */
> -
> -#ifndef __ASM_X86_HVM_VPMU_CORE_H_
> -#define __ASM_X86_HVM_VPMU_CORE_H_
> -
> -struct arch_msr_pair {
> -    u64 counter;
> -    u64 control;
> -};
> -
> -#endif /* __ASM_X86_HVM_VPMU_CORE_H_ */
> -
> diff --git a/xen/include/asm-x86/hvm/vpmu.h
> b/xen/include/asm-x86/hvm/vpmu.h
> index 761c556..f0b2686 100644
> --- a/xen/include/asm-x86/hvm/vpmu.h
> +++ b/xen/include/asm-x86/hvm/vpmu.h
> @@ -22,6 +22,8 @@
>  #ifndef __ASM_X86_HVM_VPMU_H_
>  #define __ASM_X86_HVM_VPMU_H_
> 
> +#include <public/pmu.h>
> +
>  /*
>   * Flag bits given as a string on the hypervisor boot parameter 'vpmu'.
>   * See arch/x86/hvm/vpmu.c.
> @@ -29,12 +31,9 @@
>  #define VPMU_BOOT_ENABLED 0x1    /* vpmu generally enabled. */
>  #define VPMU_BOOT_BTS     0x2    /* Intel BTS feature wanted. */
> 
> -
> -#define msraddr_to_bitpos(x) (((x)&0xffff) + ((x)>>31)*0x2000)
>  #define vcpu_vpmu(vcpu)   (&((vcpu)->arch.hvm_vcpu.vpmu))
>  #define vpmu_vcpu(vpmu)   (container_of((vpmu), struct vcpu, \
>                                            arch.hvm_vcpu.vpmu))
> -#define vpmu_domain(vpmu) (vpmu_vcpu(vpmu)->domain)
> 
>  #define MSR_TYPE_COUNTER            0
>  #define MSR_TYPE_CTRL               1
> @@ -42,6 +41,9 @@
>  #define MSR_TYPE_ARCH_COUNTER       3
>  #define MSR_TYPE_ARCH_CTRL          4
> 
> +/* Start of PMU register bank */
> +#define vpmu_reg_pointer(ctxt, offset) ((void *)((uintptr_t)ctxt + \
> +
> (uintptr_t)ctxt->offset))
> 
>  /* Arch specific operations shared by all vpmus */
>  struct arch_vpmu_ops {
> @@ -65,7 +67,8 @@ struct vpmu_struct {
>      u32 flags;
>      u32 last_pcpu;
>      u32 hw_lapic_lvtpc;
> -    void *context;
> +    void *context;      /* May be shared with PV guest */
> +    void *priv_context; /* hypervisor-only */
>      struct arch_vpmu_ops *arch_vpmu_ops;
>  };
> 
> @@ -77,11 +80,6 @@ struct vpmu_struct {
>  #define VPMU_FROZEN                         0x10  /* Stop
> counters while VCPU is not running */
>  #define VPMU_PASSIVE_DOMAIN_ALLOCATED       0x20
> 
> -/* VPMU features */
> -#define VPMU_CPU_HAS_DS                     0x100 /* Has Debug
> Store */
> -#define VPMU_CPU_HAS_BTS                    0x200 /* Has Branch
> Trace Store */
> -
> -
>  static inline void vpmu_set(struct vpmu_struct *vpmu, const u32 mask)
>  {
>      vpmu->flags |= mask;
> diff --git a/xen/include/public/arch-arm.h b/xen/include/public/arch-arm.h
> index ac54cd6..9de6d66 100644
> --- a/xen/include/public/arch-arm.h
> +++ b/xen/include/public/arch-arm.h
> @@ -407,6 +407,9 @@ typedef uint64_t xen_callback_t;
> 
>  #endif
> 
> +/* Stub definition of PMU structure */
> +typedef struct xen_pmu_arch {} xen_pmu_arch_t;
> +
>  #endif /*  __XEN_PUBLIC_ARCH_ARM_H__ */
> 
>  /*
> diff --git a/xen/include/public/arch-x86/pmu.h
> b/xen/include/public/arch-x86/pmu.h
> new file mode 100644
> index 0000000..c0cfc6c
> --- /dev/null
> +++ b/xen/include/public/arch-x86/pmu.h
> @@ -0,0 +1,77 @@
> +#ifndef __XEN_PUBLIC_ARCH_X86_PMU_H__
> +#define __XEN_PUBLIC_ARCH_X86_PMU_H__
> +
> +/* x86-specific PMU definitions */
> +
> +/* AMD PMU registers and structures */
> +struct xen_pmu_amd_ctxt {
> +    /* Offsets to counter and control MSRs (relative to
> xen_pmu_arch.c.amd) */
> +    uint32_t counters;
> +    uint32_t ctrls;
> +};
> +typedef struct xen_pmu_amd_ctxt xen_pmu_amd_ctxt_t;
> +DEFINE_XEN_GUEST_HANDLE(xen_pmu_amd_ctxt_t);
> +
> +/* Intel PMU registers and structures */
> +struct xen_pmu_cntr_pair {
> +    uint64_t counter;
> +    uint64_t control;
> +};
> +typedef struct xen_pmu_cntr_pair xen_pmu_cntr_pair_t;
> +DEFINE_XEN_GUEST_HANDLE(xen_pmu_cntr_pair_t);
> +
> +struct xen_pmu_intel_ctxt {
> +    uint64_t global_ctrl;
> +    uint64_t global_ovf_ctrl;
> +    uint64_t global_status;
> +    uint64_t fixed_ctrl;
> +    uint64_t ds_area;
> +    uint64_t pebs_enable;
> +    uint64_t debugctl;
> +    /*
> +     * Offsets to fixed and architectural counter MSRs (relative to
> +     * xen_pmu_arch.c.intel)
> +     */
> +    uint32_t fixed_counters;
> +    uint32_t arch_counters;
> +};
> +typedef struct xen_pmu_intel_ctxt xen_pmu_intel_ctxt_t;
> +DEFINE_XEN_GUEST_HANDLE(xen_pmu_intel_ctxt_t);
> +
> +struct xen_pmu_arch {
> +    union {
> +        struct xen_pmu_regs regs;
> +        /* Padding for adding new registers to xen_pmu_regs in the future
> */
> +#define XENPMU_REGS_PAD_SZ  64
> +        uint8_t pad[XENPMU_REGS_PAD_SZ];
> +    } r;
> +    union {
> +        uint32_t lapic_lvtpc;
> +        uint64_t pad;
> +    } l;
> +    union {
> +        struct xen_pmu_amd_ctxt amd;
> +        struct xen_pmu_intel_ctxt intel;
> +
> +        /*
> +         * Padding for contexts (fixed parts only, does not include MSR
> banks
> +         * that are specified by offsets
> +         */
> +#define XENPMU_CTXT_PAD_SZ  128
> +        uint8_t pad[XENPMU_CTXT_PAD_SZ];
> +    } c;
> +};
> +typedef struct xen_pmu_arch xen_pmu_arch_t;
> +DEFINE_XEN_GUEST_HANDLE(xen_pmu_arch_t);
> +
> +#endif /* __XEN_PUBLIC_ARCH_X86_PMU_H__ */
> +/*
> + * Local variables:
> + * mode: C
> + * c-file-style: "BSD"
> + * c-basic-offset: 4
> + * tab-width: 4
> + * indent-tabs-mode: nil
> + * End:
> + */
> +
> diff --git a/xen/include/public/arch-x86/xen-x86_32.h
> b/xen/include/public/arch-x86/xen-x86_32.h
> index 1504191..5b437cf 100644
> --- a/xen/include/public/arch-x86/xen-x86_32.h
> +++ b/xen/include/public/arch-x86/xen-x86_32.h
> @@ -136,6 +136,14 @@ struct cpu_user_regs {
>  typedef struct cpu_user_regs cpu_user_regs_t;
>  DEFINE_XEN_GUEST_HANDLE(cpu_user_regs_t);
> 
> +struct xen_pmu_regs {
> +    uint32_t eip;
> +    uint32_t esp;
> +    uint16_t cs;
> +};
> +typedef struct xen_pmu_regs xen_pmu_regs_t;
> +DEFINE_XEN_GUEST_HANDLE(xen_pmu_regs_t);
> +
>  /*
>   * Page-directory addresses above 4GB do not fit into architectural %cr3.
>   * When accessing %cr3, or equivalent field in vcpu_guest_context, guests
> diff --git a/xen/include/public/arch-x86/xen-x86_64.h
> b/xen/include/public/arch-x86/xen-x86_64.h
> index 1c4e159..86b6844 100644
> --- a/xen/include/public/arch-x86/xen-x86_64.h
> +++ b/xen/include/public/arch-x86/xen-x86_64.h
> @@ -174,6 +174,14 @@ struct cpu_user_regs {
>  typedef struct cpu_user_regs cpu_user_regs_t;
>  DEFINE_XEN_GUEST_HANDLE(cpu_user_regs_t);
> 
> +struct xen_pmu_regs {
> +    __DECL_REG(ip);
> +    __DECL_REG(sp);
> +    uint16_t cs;
> +};
> +typedef struct xen_pmu_regs xen_pmu_regs_t;
> +DEFINE_XEN_GUEST_HANDLE(xen_pmu_regs_t);
> +
>  #undef __DECL_REG
> 
>  #define xen_pfn_to_cr3(pfn) ((unsigned long)(pfn) << 12)
> diff --git a/xen/include/public/pmu.h b/xen/include/public/pmu.h
> new file mode 100644
> index 0000000..e6f45ee
> --- /dev/null
> +++ b/xen/include/public/pmu.h
> @@ -0,0 +1,38 @@
> +#ifndef __XEN_PUBLIC_PMU_H__
> +#define __XEN_PUBLIC_PMU_H__
> +
> +#include "xen.h"
> +#if defined(__i386__) || defined(__x86_64__)
> +#include "arch-x86/pmu.h"
> +#elif defined (__arm__) || defined (__aarch64__)
> +#include "arch-arm.h"
> +#else
> +#error "Unsupported architecture"
> +#endif
> +
> +#define XENPMU_VER_MAJ    0
> +#define XENPMU_VER_MIN    1
> +
> +
> +/* Shared between hypervisor and PV domain */
> +struct xen_pmu_data {
> +    uint32_t domain_id;
> +    uint32_t vcpu_id;
> +    uint32_t pcpu_id;
> +    uint32_t pmu_flags;
> +
> +    xen_pmu_arch_t pmu;
> +};
> +typedef struct xen_pmu_data xen_pmu_data_t;
> +
> +#endif /* __XEN_PUBLIC_PMU_H__ */
> +
> +/*
> + * Local variables:
> + * mode: C
> + * c-file-style: "BSD"
> + * c-basic-offset: 4
> + * tab-width: 4
> + * indent-tabs-mode: nil
> + * End:
> + */
> --
> 1.8.1.4


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