[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] [PATCH v2 5/6] xen/PMU: Intercept PMU-related MSR and APIC accesses
Am Freitag 06 Juni 2014, 13:44:45 schrieb Boris Ostrovsky: > Provide interfaces for recognizing accesses to PMU-related MSRs and LVTPC APIC > and process these accesses in Xen PMU code. > > Signed-off-by: Boris Ostrovsky <boris.ostrovsky@xxxxxxxxxx> > --- > arch/x86/xen/enlighten.c | 24 ++++++++++-- > arch/x86/xen/pmu.c | 84 > ++++++++++++++++++++++++++++++++++++++++++ > arch/x86/xen/pmu.h | 4 ++ > include/xen/interface/xenpmu.h | 1 + > 4 files changed, 110 insertions(+), 3 deletions(-) > > diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c > index 201d09a..a3e4db6 100644 > --- a/arch/x86/xen/enlighten.c > +++ b/arch/x86/xen/enlighten.c > @@ -82,6 +82,7 @@ > #include "mmu.h" > #include "smp.h" > #include "multicalls.h" > +#include "pmu.h" > > EXPORT_SYMBOL_GPL(hypercall_page); > > @@ -964,6 +965,11 @@ static u32 xen_apic_read(u32 reg) > > static void xen_apic_write(u32 reg, u32 val) > { > + if (reg == APIC_LVTPC) { > + (void)pmu_apic_update(reg); > + return; > + } > + > /* Warn to see if there's any stray references */ > WARN_ON(1); > } > @@ -1068,6 +1074,17 @@ static inline void xen_write_cr8(unsigned long val) > BUG_ON(val); > } > #endif > + > +static u64 xen_read_msr_safe(unsigned int msr, int *err) > +{ > + u64 val; > + > + if (pmu_msr_read(msr, &val, err)) > + return val; > + > + return native_read_msr_safe(msr, err); > +} > + > static int xen_write_msr_safe(unsigned int msr, unsigned low, unsigned high) > { > int ret; > @@ -1108,7 +1125,8 @@ static int xen_write_msr_safe(unsigned int msr, > unsigned low, unsigned high) > break; > > default: > - ret = native_write_msr_safe(msr, low, high); > + if (!pmu_msr_write(msr, low, high, &ret)) > + ret = native_write_msr_safe(msr, low, high); > } > > return ret; > @@ -1244,11 +1262,11 @@ static const struct pv_cpu_ops xen_cpu_ops > __initconst = { > > .wbinvd = native_wbinvd, > > - .read_msr = native_read_msr_safe, > + .read_msr = xen_read_msr_safe, > .write_msr = xen_write_msr_safe, > > .read_tsc = native_read_tsc, > - .read_pmc = native_read_pmc, > + .read_pmc = xen_read_pmc, > > .read_tscp = native_read_tscp, > > diff --git a/arch/x86/xen/pmu.c b/arch/x86/xen/pmu.c > index f1bec27..f92d406 100644 > --- a/arch/x86/xen/pmu.c > +++ b/arch/x86/xen/pmu.c > @@ -160,6 +160,90 @@ static bool is_intel_pmu_msr(u32 msr_index, int *type, > int *index) > return false; > } > > +bool pmu_msr_read(unsigned int msr, uint64_t *val, int *err) > +{ > + > + if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD) { > + if (is_amd_pmu_msr(msr)) { > + *val = native_read_msr_safe(msr, err); > + return true; > + } > + } else { > + int type, index; > + if (is_intel_pmu_msr(msr, &type, &index)) { > + *val = native_read_msr_safe(msr, err); > + return true; > + } > + } > + > + return false; > +} > + > +bool pmu_msr_write(unsigned int msr, uint32_t low, uint32_t high, int *err) > +{ > + if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD) { > + if (is_amd_pmu_msr(msr)) { > + *err = native_write_msr_safe(msr, low, high); > + return true; > + } > + } else { > + int type, index; > + > + if (is_intel_pmu_msr(msr, &type, &index)) { > + *err = native_write_msr_safe(msr, low, high); > + return true; > + } > + } > + > + return false; > +} > + > +unsigned long long xen_amd_read_pmc(int counter) > +{ > + uint32_t msr; > + int err; > + > + msr = amd_counters_base + (counter * amd_msr_step); > + return native_read_msr_safe(msr, &err); > +} > + > +unsigned long long xen_intel_read_pmc(int counter) > +{ > + int err; > + uint32_t msr; > + > + if (counter & (1<<30)) What means the 30? Should be a #define ...? Dietmar. > + msr = MSR_CORE_PERF_FIXED_CTR0 + (counter & 0xffff); > + else > + msr = MSR_IA32_PERFCTR0 + counter; > + > + return native_read_msr_safe(msr, &err); > +} > + > +unsigned long long xen_read_pmc(int counter) > +{ > + if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD) > + return xen_amd_read_pmc(counter); > + else > + return xen_intel_read_pmc(counter); > +} > + > +int pmu_apic_update(uint32_t val) > +{ > + int ret; > + struct xen_pmu_data *xenpmu_data = get_xenpmu_data(); > + > + if (!xenpmu_data) { > + WARN_ONCE(1, "%s: pmudata not initialized\n", __func__); > + return -EINVAL; > + } > + > + xenpmu_data->pmu.lapic_lvtpc = val; > + ret = HYPERVISOR_xenpmu_op(XENPMU_lvtpc_set, NULL); > + > + return ret; > +} > + > /* perf callbacks*/ > int xen_is_in_guest(void) > { > diff --git a/arch/x86/xen/pmu.h b/arch/x86/xen/pmu.h > index d52e8db..30bfbcf 100644 > --- a/arch/x86/xen/pmu.h > +++ b/arch/x86/xen/pmu.h > @@ -7,5 +7,9 @@ irqreturn_t xen_pmu_irq_handler(int irq, void *dev_id); > int xen_pmu_init(int cpu); > void xen_pmu_finish(int cpu); > bool is_xen_pmu(int cpu); > +bool pmu_msr_read(unsigned int msr, uint64_t *val, int *err); > +bool pmu_msr_write(unsigned int msr, uint32_t low, uint32_t high, int *err); > +int pmu_apic_update(uint32_t reg); > +unsigned long long xen_read_pmc(int counter); > > #endif /* __XEN_PMU_H */ > diff --git a/include/xen/interface/xenpmu.h b/include/xen/interface/xenpmu.h > index ed00245..79384e4 100644 > --- a/include/xen/interface/xenpmu.h > +++ b/include/xen/interface/xenpmu.h > @@ -13,6 +13,7 @@ > #define XENPMU_feature_set 3 > #define XENPMU_init 4 > #define XENPMU_finish 5 > +#define XENPMU_lvtpc_set 6 > > /* Parameter structure for HYPERVISOR_xenpmu_op call */ > struct xen_pmu_params { > _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxx http://lists.xen.org/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |