[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
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |