[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [PATCH v10 14/20] x86/VPMU: Add support for PMU register handling on PV guests
Intercept accesses to PMU MSRs and process them in VPMU module. Dump VPMU state for all domains (HVM and PV) when requested. Signed-off-by: Boris Ostrovsky <boris.ostrovsky@xxxxxxxxxx> Acked-by: Kevin Tian <kevin.tian@xxxxxxxxx> Reviewed-by: Dietmar Hahn <dietmar.hahn@xxxxxxxxxxxxxx> Tested-by: Dietmar Hahn <dietmar.hahn@xxxxxxxxxxxxxx> --- xen/arch/x86/domain.c | 3 +-- xen/arch/x86/hvm/vmx/vpmu_core2.c | 45 +++++++++++++++++++++++++++++------ xen/arch/x86/hvm/vpmu.c | 7 ++++++ xen/arch/x86/traps.c | 50 +++++++++++++++++++++++++++++++++++++-- xen/include/public/pmu.h | 1 + 5 files changed, 95 insertions(+), 11 deletions(-) diff --git a/xen/arch/x86/domain.c b/xen/arch/x86/domain.c index 64d4a83..ecbb3df 100644 --- a/xen/arch/x86/domain.c +++ b/xen/arch/x86/domain.c @@ -2028,8 +2028,7 @@ void arch_dump_vcpu_info(struct vcpu *v) { paging_dump_vcpu_info(v); - if ( is_hvm_vcpu(v) ) - vpmu_dump(v); + vpmu_dump(v); } void domain_cpuid( diff --git a/xen/arch/x86/hvm/vmx/vpmu_core2.c b/xen/arch/x86/hvm/vmx/vpmu_core2.c index 8d8ce97..37bafea 100644 --- a/xen/arch/x86/hvm/vmx/vpmu_core2.c +++ b/xen/arch/x86/hvm/vmx/vpmu_core2.c @@ -27,6 +27,7 @@ #include <asm/regs.h> #include <asm/types.h> #include <asm/apic.h> +#include <asm/traps.h> #include <asm/msr.h> #include <asm/msr-index.h> #include <asm/hvm/support.h> @@ -294,12 +295,18 @@ static inline void __core2_vpmu_save(struct vcpu *v) rdmsrl(MSR_CORE_PERF_FIXED_CTR0 + i, fixed_counters[i]); for ( i = 0; i < arch_pmc_cnt; i++ ) rdmsrl(MSR_IA32_PERFCTR0 + i, xen_pmu_cntr_pair[i].counter); + + if ( !has_hvm_container_domain(v->domain) ) + rdmsrl(MSR_CORE_PERF_GLOBAL_STATUS, core2_vpmu_cxt->global_status); } static int core2_vpmu_save(struct vcpu *v) { struct vpmu_struct *vpmu = vcpu_vpmu(v); + if ( !has_hvm_container_domain(v->domain) ) + wrmsrl(MSR_CORE_PERF_GLOBAL_CTRL, 0); + if ( !vpmu_are_all_set(vpmu, VPMU_CONTEXT_SAVE | VPMU_CONTEXT_LOADED) ) return 0; @@ -337,6 +344,13 @@ static inline void __core2_vpmu_load(struct vcpu *v) wrmsrl(MSR_CORE_PERF_FIXED_CTR_CTRL, core2_vpmu_cxt->fixed_ctrl); wrmsrl(MSR_IA32_DS_AREA, core2_vpmu_cxt->ds_area); wrmsrl(MSR_IA32_PEBS_ENABLE, core2_vpmu_cxt->pebs_enable); + + if ( !has_hvm_container_domain(v->domain) ) + { + wrmsrl(MSR_CORE_PERF_GLOBAL_OVF_CTRL, core2_vpmu_cxt->global_ovf_ctrl); + core2_vpmu_cxt->global_ovf_ctrl = 0; + wrmsrl(MSR_CORE_PERF_GLOBAL_CTRL, core2_vpmu_cxt->global_ctrl); + } } static void core2_vpmu_load(struct vcpu *v) @@ -447,7 +461,6 @@ static int core2_vpmu_msr_common_check(u32 msr_index, int *type, int *index) static int core2_vpmu_do_wrmsr(unsigned int msr, uint64_t msr_content, uint64_t supported) { - u64 global_ctrl; int i, tmp; int type = -1, index = -1; struct vcpu *v = current; @@ -492,6 +505,7 @@ static int core2_vpmu_do_wrmsr(unsigned int msr, uint64_t msr_content, { case MSR_CORE_PERF_GLOBAL_OVF_CTRL: core2_vpmu_cxt->global_status &= ~msr_content; + wrmsrl(MSR_CORE_PERF_GLOBAL_OVF_CTRL, msr_content); return 0; case MSR_CORE_PERF_GLOBAL_STATUS: gdprintk(XENLOG_INFO, "Can not write readonly MSR: " @@ -519,14 +533,18 @@ static int core2_vpmu_do_wrmsr(unsigned int msr, uint64_t msr_content, gdprintk(XENLOG_WARNING, "Guest setting of DTS is ignored.\n"); return 0; case MSR_CORE_PERF_GLOBAL_CTRL: - global_ctrl = msr_content; + core2_vpmu_cxt->global_ctrl = msr_content; break; case MSR_CORE_PERF_FIXED_CTR_CTRL: if ( msr_content & ( ~((1ull << (fixed_pmc_cnt * FIXED_CTR_CTRL_BITS)) - 1)) ) return 1; - vmx_read_guest_msr(MSR_CORE_PERF_GLOBAL_CTRL, &global_ctrl); + if ( has_hvm_container_domain(v->domain) ) + vmx_read_guest_msr(MSR_CORE_PERF_GLOBAL_CTRL, + &core2_vpmu_cxt->global_ctrl); + else + rdmsrl(MSR_CORE_PERF_GLOBAL_CTRL, core2_vpmu_cxt->global_ctrl); *enabled_cntrs &= ~(((1ULL << fixed_pmc_cnt) - 1) << 32); if ( msr_content != 0 ) { @@ -551,7 +569,11 @@ static int core2_vpmu_do_wrmsr(unsigned int msr, uint64_t msr_content, if ( msr_content & (~((1ull << 32) - 1)) ) return 1; - vmx_read_guest_msr(MSR_CORE_PERF_GLOBAL_CTRL, &global_ctrl); + if ( has_hvm_container_domain(v->domain) ) + vmx_read_guest_msr(MSR_CORE_PERF_GLOBAL_CTRL, + &core2_vpmu_cxt->global_ctrl); + else + rdmsrl(MSR_CORE_PERF_GLOBAL_CTRL, core2_vpmu_cxt->global_ctrl); if ( msr_content & (1ULL << 22) ) *enabled_cntrs |= 1ULL << tmp; @@ -565,9 +587,15 @@ static int core2_vpmu_do_wrmsr(unsigned int msr, uint64_t msr_content, if ( type != MSR_TYPE_GLOBAL ) wrmsrl(msr, msr_content); else - vmx_write_guest_msr(MSR_CORE_PERF_GLOBAL_CTRL, msr_content); + { + if ( has_hvm_container_domain(v->domain) ) + vmx_write_guest_msr(MSR_CORE_PERF_GLOBAL_CTRL, msr_content); + else + wrmsrl(MSR_CORE_PERF_GLOBAL_CTRL, msr_content); + } - if ( (global_ctrl & *enabled_cntrs) || (core2_vpmu_cxt->ds_area != 0) ) + if ( (core2_vpmu_cxt->global_ctrl & *enabled_cntrs) || + (core2_vpmu_cxt->ds_area != 0) ) vpmu_set(vpmu, VPMU_RUNNING); else vpmu_reset(vpmu, VPMU_RUNNING); @@ -594,7 +622,10 @@ static int core2_vpmu_do_rdmsr(unsigned int msr, uint64_t *msr_content) *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); + if ( has_hvm_container_domain(v->domain) ) + vmx_read_guest_msr(MSR_CORE_PERF_GLOBAL_CTRL, msr_content); + else + rdmsrl(MSR_CORE_PERF_GLOBAL_CTRL, *msr_content); break; default: rdmsrl(msr, *msr_content); diff --git a/xen/arch/x86/hvm/vpmu.c b/xen/arch/x86/hvm/vpmu.c index 9c3cf7c..8316f14 100644 --- a/xen/arch/x86/hvm/vpmu.c +++ b/xen/arch/x86/hvm/vpmu.c @@ -549,6 +549,13 @@ long do_xenpmu_op(int op, XEN_GUEST_HANDLE_PARAM(xen_pmu_params_t) arg) return -EFAULT; pvpmu_finish(current->domain, &pmu_params); break; + + case XENPMU_lvtpc_set: + if ( current->arch.vpmu.xenpmu_data == NULL ) + return -EINVAL; + vpmu_lvtpc_update(current->arch.vpmu.xenpmu_data->pmu.l.lapic_lvtpc); + ret = 0; + break; } return ret; diff --git a/xen/arch/x86/traps.c b/xen/arch/x86/traps.c index 7f5306f..bc0c9c3 100644 --- a/xen/arch/x86/traps.c +++ b/xen/arch/x86/traps.c @@ -72,6 +72,7 @@ #include <asm/apic.h> #include <asm/mc146818rtc.h> #include <asm/hpet.h> +#include <asm/hvm/vpmu.h> #include <public/arch-x86/cpuid.h> #include <xsm/xsm.h> @@ -895,8 +896,10 @@ void pv_cpuid(struct cpu_user_regs *regs) __clear_bit(X86_FEATURE_TOPOEXT % 32, &c); break; + case 0x0000000a: /* Architectural Performance Monitor Features (Intel) */ + break; + case 0x00000005: /* MONITOR/MWAIT */ - case 0x0000000a: /* Architectural Performance Monitor Features */ case 0x0000000b: /* Extended Topology Enumeration */ case 0x8000000a: /* SVM revision and features */ case 0x8000001b: /* Instruction Based Sampling */ @@ -912,6 +915,9 @@ void pv_cpuid(struct cpu_user_regs *regs) } out: + /* VPMU may decide to modify some of the leaves */ + vpmu_do_cpuid(regs->eax, &a, &b, &c, &d); + regs->eax = a; regs->ebx = b; regs->ecx = c; @@ -1934,6 +1940,7 @@ static int emulate_privileged_op(struct cpu_user_regs *regs) char io_emul_stub[32]; void (*io_emul)(struct cpu_user_regs *) __attribute__((__regparm__(1))); uint64_t val, msr_content; + bool_t vpmu_msr; if ( !read_descriptor(regs->cs, v, regs, &code_base, &code_limit, &ar, @@ -2424,6 +2431,7 @@ static int emulate_privileged_op(struct cpu_user_regs *regs) uint32_t eax = regs->eax; uint32_t edx = regs->edx; msr_content = ((uint64_t)edx << 32) | eax; + vpmu_msr = 0; switch ( (u32)regs->ecx ) { case MSR_FS_BASE: @@ -2560,7 +2568,22 @@ static int emulate_privileged_op(struct cpu_user_regs *regs) if ( v->arch.debugreg[7] & DR7_ACTIVE_MASK ) wrmsrl(regs->_ecx, msr_content); break; - + case MSR_P6_PERFCTR0...MSR_P6_PERFCTR1: + case MSR_P6_EVNTSEL0...MSR_P6_EVNTSEL1: + case MSR_CORE_PERF_FIXED_CTR0...MSR_CORE_PERF_FIXED_CTR2: + case MSR_CORE_PERF_FIXED_CTR_CTRL...MSR_CORE_PERF_GLOBAL_OVF_CTRL: + if ( boot_cpu_data.x86_vendor == X86_VENDOR_INTEL ) + { + vpmu_msr = 1; + case MSR_AMD_FAM15H_EVNTSEL0...MSR_AMD_FAM15H_PERFCTR5: + if ( vpmu_msr || (boot_cpu_data.x86_vendor == X86_VENDOR_AMD) ) + { + if ( vpmu_do_wrmsr(regs->ecx, msr_content, 0) ) + goto fail; + } + break; + } + /*FALLTHROUGH*/ default: if ( wrmsr_hypervisor_regs(regs->ecx, msr_content) == 1 ) break; @@ -2592,6 +2615,7 @@ static int emulate_privileged_op(struct cpu_user_regs *regs) break; case 0x32: /* RDMSR */ + vpmu_msr = 0; switch ( (u32)regs->ecx ) { case MSR_FS_BASE: @@ -2662,7 +2686,29 @@ static int emulate_privileged_op(struct cpu_user_regs *regs) [regs->_ecx - MSR_AMD64_DR1_ADDRESS_MASK + 1]; regs->edx = 0; break; + case MSR_IA32_PERF_CAPABILITIES: + /* No extra capabilities are supported */ + regs->eax = regs->edx = 0; + break; + case MSR_P6_PERFCTR0...MSR_P6_PERFCTR1: + case MSR_P6_EVNTSEL0...MSR_P6_EVNTSEL1: + case MSR_CORE_PERF_FIXED_CTR0...MSR_CORE_PERF_FIXED_CTR2: + case MSR_CORE_PERF_FIXED_CTR_CTRL...MSR_CORE_PERF_GLOBAL_OVF_CTRL: + if ( boot_cpu_data.x86_vendor == X86_VENDOR_INTEL ) + { + vpmu_msr = 1; + case MSR_AMD_FAM15H_EVNTSEL0...MSR_AMD_FAM15H_PERFCTR5: + if ( vpmu_msr || (boot_cpu_data.x86_vendor == X86_VENDOR_AMD) ) + { + if ( vpmu_do_rdmsr(regs->ecx, &msr_content) ) + goto fail; + regs->eax = (uint32_t)msr_content; + regs->edx = (uint32_t)(msr_content >> 32); + } + break; + } + /*FALLTHROUGH*/ default: if ( rdmsr_hypervisor_regs(regs->ecx, &val) ) { diff --git a/xen/include/public/pmu.h b/xen/include/public/pmu.h index 3d55eb6..92f3683 100644 --- a/xen/include/public/pmu.h +++ b/xen/include/public/pmu.h @@ -27,6 +27,7 @@ #define XENPMU_feature_set 3 #define XENPMU_init 4 #define XENPMU_finish 5 +#define XENPMU_lvtpc_set 6 /* ` } */ /* Parameters structure for HYPERVISOR_xenpmu_op call */ -- 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 |