|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] [PATCH v2 10/13] x86/PMU: Add support for PMU registes handling on PV guests
Am Freitag 20 September 2013, 05:42:09 schrieb Boris Ostrovsky:
> Intercept accesses to PMU MSRs and LVTPC APIC vector (only
> APIC_LVT_MASKED bit is processed) 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>
> ---
> xen/arch/x86/domain.c | 3 +-
> xen/arch/x86/hvm/vmx/vpmu_core2.c | 90
> ++++++++++++++++++++++++++++++---------
> xen/arch/x86/hvm/vpmu.c | 16 +++++++
> xen/arch/x86/traps.c | 39 ++++++++++++++++-
> xen/include/public/xenpmu.h | 1 +
> 5 files changed, 125 insertions(+), 24 deletions(-)
>
> diff --git a/xen/arch/x86/domain.c b/xen/arch/x86/domain.c
> index e119d7b..36f4192 100644
> --- a/xen/arch/x86/domain.c
> +++ b/xen/arch/x86/domain.c
> @@ -1940,8 +1940,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 5726610..ebbb516 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>
> @@ -281,6 +282,9 @@ static inline void __core2_vpmu_save(struct vcpu *v)
> rdmsrl(MSR_CORE_PERF_FIXED_CTR0 + i,
> core2_vpmu_cxt->fix_counters[i]);
> for ( i = 0; i < arch_pmc_cnt; i++ )
> rdmsrl(MSR_IA32_PERFCTR0 + i,
> core2_vpmu_cxt->arch_msr_pair[i].counter);
> +
> + if ( !is_hvm_domain(v->domain) )
> + rdmsrl(MSR_CORE_PERF_GLOBAL_STATUS, core2_vpmu_cxt->global_status);
> }
>
> static int core2_vpmu_save(struct vcpu *v)
> @@ -290,10 +294,14 @@ static int core2_vpmu_save(struct vcpu *v)
> if ( !vpmu_is_set_all(vpmu, VPMU_CONTEXT_SAVE | VPMU_CONTEXT_LOADED) )
> return 0;
>
> + if ( !is_hvm_domain(v->domain) )
> + wrmsrl(MSR_CORE_PERF_GLOBAL_CTRL, 0);
> +
> __core2_vpmu_save(v);
>
> /* Unset PMU MSR bitmap to trap lazy load. */
> - if ( !vpmu_is_set(vpmu, VPMU_RUNNING) && cpu_has_vmx_msr_bitmap )
> + if ( !vpmu_is_set(vpmu, VPMU_RUNNING) && cpu_has_vmx_msr_bitmap
> + && is_hvm_domain(v->domain) )
> core2_vpmu_unset_msr_bitmap(v->arch.hvm_vmx.msr_bitmap);
>
> return 1;
> @@ -315,6 +323,12 @@ static inline void __core2_vpmu_load(struct vcpu *v)
>
> for ( i = 0; i < arch_pmc_cnt; i++ )
> wrmsrl(MSR_P6_EVNTSEL0+i, core2_vpmu_cxt->arch_msr_pair[i].control);
> +
> + if ( !is_hvm_domain(v->domain) )
> + {
> + wrmsrl(MSR_CORE_PERF_GLOBAL_OVF_CTRL,
> core2_vpmu_cxt->global_ovf_ctrl);
> + wrmsrl(MSR_CORE_PERF_GLOBAL_CTRL, core2_vpmu_cxt->global_ctrl);
> + }
> }
>
> static void core2_vpmu_load(struct vcpu *v)
> @@ -421,7 +435,12 @@ 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);
> +
> + if ( is_hvm_domain(v->domain) )
> + hvm_inject_hw_exception(TRAP_gp_fault, 0);
> + else
> + send_guest_trap(v->domain, v->vcpu_id, TRAP_gp_fault);
Maybe use a macro or function for these 4 lines?
> +
> return 0;
> }
> }
> @@ -433,11 +452,15 @@ static int core2_vpmu_do_wrmsr(unsigned int msr,
> uint64_t msr_content)
> {
> case MSR_CORE_PERF_GLOBAL_OVF_CTRL:
> core2_vpmu_cxt->global_ovf_status &= ~msr_content;
> + core2_vpmu_cxt->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);
> + if ( is_hvm_domain(v->domain) )
> + hvm_inject_hw_exception(TRAP_gp_fault, 0);
> + else
> + send_guest_trap(v->domain, v->vcpu_id, TRAP_gp_fault);
Macro/function?
> return 1;
> case MSR_IA32_PEBS_ENABLE:
> if ( msr_content & 1 )
> @@ -453,7 +476,10 @@ 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);
> + if ( is_hvm_domain(v->domain) )
> + hvm_inject_hw_exception(TRAP_gp_fault, 0);
> + else
> + send_guest_trap(v->domain, v->vcpu_id, TRAP_gp_fault);
>
Macro/function and trailing spaces?
> return 1;
> }
> core2_vpmu_cxt->ds_area = msr_content;
> @@ -478,10 +504,14 @@ static int core2_vpmu_do_wrmsr(unsigned int msr,
> uint64_t msr_content)
> non_global_ctrl >>= FIXED_CTR_CTRL_BITS;
> global_ctrl >>= 1;
> }
> + core2_vpmu_cxt->global_ctrl = msr_content;
> break;
> case MSR_CORE_PERF_FIXED_CTR_CTRL:
> non_global_ctrl = msr_content;
> - vmx_read_guest_msr(MSR_CORE_PERF_GLOBAL_CTRL, &global_ctrl);
> + if ( is_hvm_domain(v->domain) )
> + vmx_read_guest_msr(MSR_CORE_PERF_GLOBAL_CTRL, &global_ctrl);
> + else
> + rdmsrl(MSR_CORE_PERF_GLOBAL_CTRL, global_ctrl);
> global_ctrl >>= 32;
> for ( i = 0; i < fixed_pmc_cnt; i++ )
> {
> @@ -495,7 +525,10 @@ static int core2_vpmu_do_wrmsr(unsigned int msr,
> uint64_t msr_content)
> tmp = msr - MSR_P6_EVNTSEL0;
> if ( tmp >= 0 && tmp < arch_pmc_cnt )
> {
> - vmx_read_guest_msr(MSR_CORE_PERF_GLOBAL_CTRL, &global_ctrl);
> + if ( is_hvm_domain(v->domain) )
> + vmx_read_guest_msr(MSR_CORE_PERF_GLOBAL_CTRL, &global_ctrl);
> + else
> + rdmsrl(MSR_CORE_PERF_GLOBAL_CTRL, global_ctrl);
> core2_vpmu_cxt->arch_msr_pair[tmp].control = msr_content;
> for ( i = 0; i < arch_pmc_cnt && !pmu_enable; i++ )
> pmu_enable += (global_ctrl >> i) &
> @@ -509,17 +542,20 @@ static int core2_vpmu_do_wrmsr(unsigned int msr,
> uint64_t msr_content)
> else
> vpmu_reset(vpmu, VPMU_RUNNING);
>
> - /* Setup LVTPC in local apic */
> - if ( vpmu_is_set(vpmu, VPMU_RUNNING) &&
> - is_vlapic_lvtpc_enabled(vcpu_vlapic(v)) )
> - {
> - apic_write_around(APIC_LVTPC, PMU_APIC_VECTOR);
> - vpmu->hw_lapic_lvtpc = PMU_APIC_VECTOR;
> - }
> - else
> + if ( is_hvm_domain(v->domain) )
> {
> - apic_write_around(APIC_LVTPC, PMU_APIC_VECTOR | APIC_LVT_MASKED);
> - vpmu->hw_lapic_lvtpc = PMU_APIC_VECTOR | APIC_LVT_MASKED;
> + /* Setup LVTPC in local apic */
> + if ( vpmu_is_set(vpmu, VPMU_RUNNING) &&
> + is_vlapic_lvtpc_enabled(vcpu_vlapic(v)) )
> + {
> + apic_write_around(APIC_LVTPC, PMU_APIC_VECTOR);
> + vpmu->hw_lapic_lvtpc = PMU_APIC_VECTOR;
> + }
> + else
> + {
> + apic_write_around(APIC_LVTPC, PMU_APIC_VECTOR | APIC_LVT_MASKED);
> + vpmu->hw_lapic_lvtpc = PMU_APIC_VECTOR | APIC_LVT_MASKED;
> + }
> }
>
> if ( type != MSR_TYPE_GLOBAL )
> @@ -547,13 +583,24 @@ 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)
> + {
> + if ( is_hvm_domain(v->domain) )
> + hvm_inject_hw_exception(TRAP_gp_fault, 0);
> + else
> + send_guest_trap(v->domain, v->vcpu_id, TRAP_gp_fault);
Macro/function?
Dietmar.
> + }
> else
> wrmsrl(msr, msr_content);
> }
> else
> - vmx_write_guest_msr(MSR_CORE_PERF_GLOBAL_CTRL, msr_content);
> + {
> + if ( is_hvm_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;
> }
> @@ -577,7 +624,10 @@ static int core2_vpmu_do_rdmsr(unsigned int msr,
> uint64_t *msr_content)
> *msr_content = core2_vpmu_cxt->global_ovf_status;
> break;
> case MSR_CORE_PERF_GLOBAL_CTRL:
> - vmx_read_guest_msr(MSR_CORE_PERF_GLOBAL_CTRL, msr_content);
> + if ( is_hvm_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 69aaa7b..4638193 100644
> --- a/xen/arch/x86/hvm/vpmu.c
> +++ b/xen/arch/x86/hvm/vpmu.c
> @@ -70,6 +70,14 @@ static void __init parse_vpmu_param(char *s)
> }
> }
>
> +static void vpmu_lvtpc_update(uint32_t val)
> +{
> + struct vpmu_struct *vpmu = vcpu_vpmu(current);
> +
> + vpmu->hw_lapic_lvtpc = PMU_APIC_VECTOR | (val & APIC_LVT_MASKED);
> + apic_write(APIC_LVTPC, vpmu->hw_lapic_lvtpc);
> +}
> +
> int vpmu_do_wrmsr(unsigned int msr, uint64_t msr_content)
> {
> struct vpmu_struct *vpmu = vcpu_vpmu(current);
> @@ -428,6 +436,14 @@ long do_xenpmu_op(int op, XEN_GUEST_HANDLE_PARAM(void)
> arg)
> return -EFAULT;
> pvpmu_finish(current->domain, &pmu_params);
> break;
> +
> + case XENPMU_lvtpc_set:
> + if ( copy_from_guest(&pmu_params, arg, 1) )
> + return -EFAULT;
> +
> + vpmu_lvtpc_update((uint32_t)pmu_params.val);
> + ret = 0;
> + break;
> }
>
> return ret;
> diff --git a/xen/arch/x86/traps.c b/xen/arch/x86/traps.c
> index 57dbd0c..f378a24 100644
> --- a/xen/arch/x86/traps.c
> +++ b/xen/arch/x86/traps.c
> @@ -71,6 +71,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>
>
> @@ -871,7 +872,6 @@ static void pv_cpuid(struct cpu_user_regs *regs)
> 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 */
> @@ -880,7 +880,9 @@ static void pv_cpuid(struct cpu_user_regs *regs)
> unsupported:
> a = b = c = d = 0;
> break;
> -
> + case 0x0000000a: /* Architectural Performance Monitor Features (Intel) */
> + vpmu_do_cpuid(0xa, &a, &b, &c, &d);
> + break;
> default:
> (void)cpuid_hypervisor_leaves(regs->eax, 0, &a, &b, &c, &d);
> break;
> @@ -2486,6 +2488,17 @@ static int emulate_privileged_op(struct cpu_user_regs
> *regs)
> if ( wrmsr_safe(regs->ecx, msr_content) != 0 )
> goto fail;
> 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) )
> + {
> + if ( (vpmu_mode & XENPMU_MODE_PRIV) && (v->domain == dom0) )
> + goto invalid;
> + }
> + break;
> default:
> if ( wrmsr_hypervisor_regs(regs->ecx, msr_content) == 1 )
> break;
> @@ -2574,6 +2587,24 @@ static int emulate_privileged_op(struct cpu_user_regs
> *regs)
> regs->eax = (uint32_t)msr_content;
> regs->edx = (uint32_t)(msr_content >> 32);
> break;
> + case MSR_IA32_PERF_CAPABILITIES:
> + if ( rdmsr_safe(regs->ecx, msr_content) )
> + goto fail;
> + /* Full-Width Writes not supported */
> + regs->eax = (uint32_t)msr_content & ~(1 << 13);
> + regs->edx = (uint32_t)(msr_content >> 32);
> + 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) )
> {
> @@ -2606,6 +2637,10 @@ static int emulate_privileged_op(struct cpu_user_regs
> *regs)
> pv_cpuid(regs);
> break;
>
> + case 0x33: /* RDPMC */
> + rdpmc(regs->ecx, regs->eax, regs->edx);
> + break;
> +
> default:
> goto fail;
> }
> diff --git a/xen/include/public/xenpmu.h b/xen/include/public/xenpmu.h
> index ec49097..0060670 100644
> --- a/xen/include/public/xenpmu.h
> +++ b/xen/include/public/xenpmu.h
> @@ -27,6 +27,7 @@
> #define XENPMU_flags_set 3
> #define XENPMU_init 4
> #define XENPMU_finish 5
> +#define XENPMU_lvtpc_set 6
> /* ` } */
>
> /* Parameters structure for HYPERVISOR_xenpmu_op call */
>
--
Company details: http://ts.fujitsu.com/imprint.html
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
http://lists.xen.org/xen-devel
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |