From mboxrd@z Thu Jan 1 00:00:00 1970 From: Boris Ostrovsky Subject: [PATCH v6 12/19] x86/VPMU: Add support for PMU register handling on PV guests Date: Tue, 13 May 2014 11:53:26 -0400 Message-ID: <1399996413-1998-13-git-send-email-boris.ostrovsky@oracle.com> References: <1399996413-1998-1-git-send-email-boris.ostrovsky@oracle.com> Mime-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Return-path: In-Reply-To: <1399996413-1998-1-git-send-email-boris.ostrovsky@oracle.com> List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Sender: xen-devel-bounces@lists.xen.org Errors-To: xen-devel-bounces@lists.xen.org To: JBeulich@suse.com, kevin.tian@intel.com, dietmar.hahn@ts.fujitsu.com, suravee.suthikulpanit@amd.com Cc: keir@xen.org, andrew.cooper3@citrix.com, donald.d.dugger@intel.com, xen-devel@lists.xen.org, jun.nakajima@intel.com, boris.ostrovsky@oracle.com List-Id: xen-devel@lists.xenproject.org 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 Acked-by: Kevin Tian Reviewed-by: Dietmar Hahn Tested-by: Dietmar Hahn --- xen/arch/x86/domain.c | 3 +- xen/arch/x86/hvm/vmx/vpmu_core2.c | 64 +++++++++++++++++++++++++++++++-------- xen/arch/x86/hvm/vpmu.c | 7 +++++ xen/arch/x86/traps.c | 32 ++++++++++++++++++-- xen/include/public/pmu.h | 1 + 5 files changed, 91 insertions(+), 16 deletions(-) diff --git a/xen/arch/x86/domain.c b/xen/arch/x86/domain.c index 483e85b..4a122da 100644 --- a/xen/arch/x86/domain.c +++ b/xen/arch/x86/domain.c @@ -2012,8 +2012,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 b048180..8182dc3 100644 --- a/xen/arch/x86/hvm/vmx/vpmu_core2.c +++ b/xen/arch/x86/hvm/vmx/vpmu_core2.c @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -297,12 +298,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 ( is_pv_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 ( is_pv_domain(v->domain) ) + wrmsrl(MSR_CORE_PERF_GLOBAL_CTRL, 0); + if ( !vpmu_is_set_all(vpmu, VPMU_CONTEXT_SAVE | VPMU_CONTEXT_LOADED) ) return 0; @@ -340,6 +347,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 ( is_pv_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) @@ -436,9 +450,16 @@ static int core2_vpmu_msr_common_check(u32 msr_index, int *type, int *index) return 1; } +static void inject_trap(struct vcpu *v, unsigned int trapno) +{ + if ( !is_pv_domain(v->domain) ) + hvm_inject_hw_exception(trapno, 0); + else + send_guest_trap(v->domain, v->vcpu_id, trapno); +} + static int core2_vpmu_do_wrmsr(unsigned int msr, uint64_t msr_content) { - u64 global_ctrl; int i, tmp; int type = -1, index = -1; struct vcpu *v = current; @@ -462,7 +483,7 @@ static int core2_vpmu_do_wrmsr(unsigned int msr, uint64_t msr_content) if ( vpmu_is_set(vpmu, VPMU_CPU_HAS_BTS) ) return 1; gdprintk(XENLOG_WARNING, "Debug Store is not supported on this cpu\n"); - hvm_inject_hw_exception(TRAP_gp_fault, 0); + inject_trap(v, TRAP_gp_fault); return 0; } } @@ -475,11 +496,12 @@ 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 1; case MSR_CORE_PERF_GLOBAL_STATUS: gdprintk(XENLOG_INFO, "Can not write readonly MSR: " "MSR_PERF_GLOBAL_STATUS(0x38E)!\n"); - hvm_inject_hw_exception(TRAP_gp_fault, 0); + inject_trap(v, TRAP_gp_fault); return 1; case MSR_IA32_PEBS_ENABLE: if ( msr_content & 1 ) @@ -495,7 +517,7 @@ static int core2_vpmu_do_wrmsr(unsigned int msr, uint64_t msr_content) gdprintk(XENLOG_WARNING, "Illegal address for IA32_DS_AREA: %#" PRIx64 "x\n", msr_content); - hvm_inject_hw_exception(TRAP_gp_fault, 0); + inject_trap(v, TRAP_gp_fault); return 1; } core2_vpmu_cxt->ds_area = msr_content; @@ -504,10 +526,14 @@ static int core2_vpmu_do_wrmsr(unsigned int msr, uint64_t msr_content) gdprintk(XENLOG_WARNING, "Guest setting of DTS is ignored.\n"); return 1; 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: - vmx_read_guest_msr(MSR_CORE_PERF_GLOBAL_CTRL, &global_ctrl); + if ( !is_pv_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 ) { @@ -529,7 +555,11 @@ static int core2_vpmu_do_wrmsr(unsigned int msr, uint64_t msr_content) 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 ( !is_pv_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; @@ -540,7 +570,8 @@ static int core2_vpmu_do_wrmsr(unsigned int msr, uint64_t 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); @@ -570,13 +601,19 @@ static int core2_vpmu_do_wrmsr(unsigned int msr, uint64_t msr_content) inject_gp = 1; break; } - if (inject_gp) - hvm_inject_hw_exception(TRAP_gp_fault, 0); + + if (inject_gp) + inject_trap(v, TRAP_gp_fault); else wrmsrl(msr, msr_content); } else - vmx_write_guest_msr(MSR_CORE_PERF_GLOBAL_CTRL, msr_content); + { + if ( !is_pv_domain(v->domain) ) + vmx_write_guest_msr(MSR_CORE_PERF_GLOBAL_CTRL, msr_content); + else + wrmsrl(MSR_CORE_PERF_GLOBAL_CTRL, msr_content); + } return 1; } @@ -600,7 +637,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 ( !is_pv_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 2d152f7..f89e7ff 100644 --- a/xen/arch/x86/hvm/vpmu.c +++ b/xen/arch/x86/hvm/vpmu.c @@ -455,6 +455,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 45070bb..a0d0ba7 100644 --- a/xen/arch/x86/traps.c +++ b/xen/arch/x86/traps.c @@ -72,6 +72,7 @@ #include #include #include +#include #include #include @@ -868,8 +869,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 */ @@ -885,6 +888,8 @@ void pv_cpuid(struct cpu_user_regs *regs) } out: + vpmu_do_cpuid(regs->eax, &a, &b, &c, &d); + regs->eax = a; regs->ebx = b; regs->ecx = c; @@ -2515,7 +2520,14 @@ 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: + case MSR_AMD_FAM15H_EVNTSEL0...MSR_AMD_FAM15H_PERFCTR5: + if ( !vpmu_do_wrmsr(regs->ecx, msr_content) ) + goto invalid; + break; default: if ( wrmsr_hypervisor_regs(regs->ecx, msr_content) == 1 ) break; @@ -2617,6 +2629,22 @@ 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: + case MSR_AMD_FAM15H_EVNTSEL0...MSR_AMD_FAM15H_PERFCTR5: + if ( vpmu_do_rdmsr(regs->ecx, &msr_content) ) + { + regs->eax = (uint32_t)msr_content; + regs->edx = (uint32_t)(msr_content >> 32); + break; + } + goto rdmsr_normal; default: if ( rdmsr_hypervisor_regs(regs->ecx, &val) ) diff --git a/xen/include/public/pmu.h b/xen/include/public/pmu.h index 814e061..81783de 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