[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [PATCH 2 of 2] vpmu: Add the BTS extension
Add the BTS functionality to the existing vpmu implementation for Intel cpus. Signed-off-by: Dietmar Hahn <dietmar.hahn@xxxxxxxxxxxxxx> xen/arch/x86/hvm/vmx/vmx.c | 12 +- xen/arch/x86/hvm/vmx/vpmu_core2.c | 156 +++++++++++++++++++++++++----- xen/include/asm-x86/hvm/vmx/vpmu_core2.h | 1 + xen/include/asm-x86/hvm/vpmu.h | 3 + xen/include/asm-x86/msr-index.h | 5 + 5 files changed, 148 insertions(+), 29 deletions(-) diff -r 6c666c08cf0d xen/arch/x86/hvm/vmx/vmx.c --- a/xen/arch/x86/hvm/vmx/vmx.c Mon Feb 13 12:36:09 2012 +0100 +++ b/xen/arch/x86/hvm/vmx/vmx.c Mon Feb 13 13:51:51 2012 +0100 @@ -1823,6 +1823,9 @@ static int vmx_msr_read_intercept(unsign /* Debug Trace Store is not supported. */ *msr_content |= MSR_IA32_MISC_ENABLE_BTS_UNAVAIL | MSR_IA32_MISC_ENABLE_PEBS_UNAVAIL; + /* Perhaps vpmu will change some bits. */ + if ( vpmu_do_rdmsr(msr, msr_content) ) + goto done; break; default: if ( vpmu_do_rdmsr(msr, msr_content) ) @@ -1950,9 +1953,14 @@ static int vmx_msr_write_intercept(unsig int i, rc = 0; uint64_t supported = IA32_DEBUGCTLMSR_LBR | IA32_DEBUGCTLMSR_BTF; - if ( !msr_content || (msr_content & ~supported) ) + if ( !msr_content ) break; - + if ( msr_content & ~supported ) + { + /* Perhaps some other bits are supported in vpmu. */ + if ( !vpmu_do_wrmsr(msr, msr_content) ) + break; + } if ( msr_content & IA32_DEBUGCTLMSR_LBR ) { const struct lbr_info *lbr = last_branch_msr_get(); diff -r 6c666c08cf0d xen/arch/x86/hvm/vmx/vpmu_core2.c --- a/xen/arch/x86/hvm/vmx/vpmu_core2.c Mon Feb 13 12:36:09 2012 +0100 +++ b/xen/arch/x86/hvm/vmx/vpmu_core2.c Mon Feb 13 13:51:51 2012 +0100 @@ -401,7 +401,31 @@ static int core2_vpmu_do_wrmsr(unsigned struct core2_vpmu_context *core2_vpmu_cxt = NULL; if ( !core2_vpmu_msr_common_check(msr, &type, &index) ) + { + /* Special handling for BTS */ + if ( msr == MSR_IA32_DEBUGCTLMSR ) + { + uint64_t supported = IA32_DEBUGCTLMSR_TR | IA32_DEBUGCTLMSR_BTS | + IA32_DEBUGCTLMSR_BTINT; + + if ( cpu_has(¤t_cpu_data, X86_FEATURE_DSCPL) ) + { + supported |= IA32_DEBUGCTLMSR_BTS_OFF_OS | + IA32_DEBUGCTLMSR_BTS_OFF_USR; + } + if ( msr_content & supported ) + { + if ( !vpmu_is_set(vpmu, VPMU_CPU_HAS_BTS) ) + { + gdprintk(XENLOG_WARNING, "Debug Store is not supported on this cpu\n"); + vmx_inject_hw_exception(TRAP_gp_fault, 0); + return 0; + } + return 1; + } + } return 0; + } core2_vpmu_cxt = vpmu->context; switch ( msr ) @@ -420,8 +444,26 @@ static int core2_vpmu_do_wrmsr(unsigned "which is not supported.\n"); return 1; case MSR_IA32_DS_AREA: - gdprintk(XENLOG_WARNING, "Guest setting of DTS is ignored.\n"); - return 1; + if ( vpmu_is_set(vpmu, VPMU_CPU_HAS_DS) ) + { + if (!msr_content || !is_canonical_address(msr_content)) + { + gdprintk(XENLOG_WARNING, "Illegal address for IA32_DS_AREA: 0x%lx\n", + msr_content); + vmx_inject_hw_exception(TRAP_gp_fault, 0); + return 1; + } + else + { + core2_vpmu_cxt->pmu_enable->ds_area_enable = msr_content ? 1 : 0; + break; + } + } + else + { + gdprintk(XENLOG_WARNING, "Guest setting of DTS is ignored.\n"); + return 1; + } case MSR_CORE_PERF_GLOBAL_CTRL: global_ctrl = msr_content; for ( i = 0; i < core2_get_pmc_count(); i++ ) @@ -466,6 +508,7 @@ static int core2_vpmu_do_wrmsr(unsigned pmu_enable |= core2_vpmu_cxt->pmu_enable->fixed_ctr_enable[i]; for ( i = 0; i < core2_get_pmc_count(); i++ ) pmu_enable |= core2_vpmu_cxt->pmu_enable->arch_pmc_enable[i]; + pmu_enable |= core2_vpmu_cxt->pmu_enable->ds_area_enable; if ( pmu_enable ) vpmu_set(vpmu, VPMU_RUNNING); else @@ -491,6 +534,8 @@ static int core2_vpmu_do_wrmsr(unsigned inject_gp = 1; break; case MSR_TYPE_CTRL: /* IA32_FIXED_CTR_CTRL */ + if ( msr == MSR_IA32_DS_AREA ) + break; /* 4 bits per counter, currently 3 fixed counters implemented. */ mask = ~((1ull << (3 * 4)) - 1); if (msr_content & mask) @@ -520,25 +565,35 @@ static int core2_vpmu_do_rdmsr(unsigned struct vpmu_struct *vpmu = vcpu_vpmu(v); struct core2_vpmu_context *core2_vpmu_cxt = NULL; - if ( !core2_vpmu_msr_common_check(msr, &type, &index) ) - return 0; - - core2_vpmu_cxt = vpmu->context; - switch ( msr ) + if ( core2_vpmu_msr_common_check(msr, &type, &index) ) { - case MSR_CORE_PERF_GLOBAL_OVF_CTRL: - *msr_content = 0; - break; - case MSR_CORE_PERF_GLOBAL_STATUS: - *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); - break; - default: - rdmsrl(msr, *msr_content); + core2_vpmu_cxt = vpmu->context; + switch ( msr ) + { + case MSR_CORE_PERF_GLOBAL_OVF_CTRL: + *msr_content = 0; + break; + case MSR_CORE_PERF_GLOBAL_STATUS: + *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); + break; + default: + rdmsrl(msr, *msr_content); + } } - + else + { + /* Extension for BTS */ + if ( msr == MSR_IA32_MISC_ENABLE) + { + if ( vpmu_is_set(vpmu, VPMU_CPU_HAS_BTS) ) + *msr_content &= ~MSR_IA32_MISC_ENABLE_BTS_UNAVAIL; + } + else + return 0; + } return 1; } @@ -553,15 +608,24 @@ static int core2_vpmu_do_interrupt(struc struct vlapic *vlapic = vcpu_vlapic(v); rdmsrl(MSR_CORE_PERF_GLOBAL_STATUS, msr_content); - if ( !msr_content ) - return 0; + if ( msr_content ) + { + if ( is_pmc_quirk ) + handle_pmc_quirk(msr_content); - if ( is_pmc_quirk ) - handle_pmc_quirk(msr_content); - - core2_vpmu_cxt->global_ovf_status |= msr_content; - msr_content = 0xC000000700000000 | ((1 << core2_get_pmc_count()) - 1); - wrmsrl(MSR_CORE_PERF_GLOBAL_OVF_CTRL, msr_content); + core2_vpmu_cxt->global_ovf_status |= msr_content; + msr_content = 0xC000000700000000 | ((1 << core2_get_pmc_count()) - 1); + wrmsrl(MSR_CORE_PERF_GLOBAL_OVF_CTRL, msr_content); + } + else + { + /* No PMC overflow but perhaps a Trace Message interrupt. */ + msr_content = __vmread(GUEST_IA32_DEBUGCTL); + if ( !(msr_content & IA32_DEBUGCTLMSR_TR) ) + { + return 0; + } + } apic_write_around(APIC_LVTPC, apic_read(APIC_LVTPC) & ~APIC_LVT_MASKED); @@ -582,10 +646,48 @@ static void core2_vpmu_do_cpuid(unsigned unsigned int *eax, unsigned int *ebx, unsigned int *ecx, unsigned int *edx) { + if (input == 0x1) + { + struct vpmu_struct *vpmu = vcpu_vpmu(current); + + if ( vpmu_is_set(vpmu, VPMU_CPU_HAS_DS) ) + { + /* Switch on the 'Debug Store' feature in CPUID.EAX[1]:EDX[21] */ + *edx |= cpufeat_mask(X86_FEATURE_DS); + } + } } static void core2_vpmu_initialise(struct vcpu *v) { + struct vpmu_struct *vpmu = vcpu_vpmu(v); + u64 msr_content; + struct cpuinfo_x86 *c = ¤t_cpu_data; + + /* Check the 'Debug Store' feature in the CPUID.EAX[1]:EDX[21] */ + if ( cpu_has(c, X86_FEATURE_DS) ) + { + if ( !cpu_has(c, X86_FEATURE_DTES64) ) + { + gdprintk(XENLOG_WARNING, "CPU doesn't support 64-bit DS Area - Debug Store disabled\n"); + goto func_out; + } + vpmu_set(vpmu, VPMU_CPU_HAS_DS); + rdmsrl(MSR_IA32_MISC_ENABLE, msr_content); + if ( msr_content & MSR_IA32_MISC_ENABLE_BTS_UNAVAIL ) + { + /* If BTS_UNAVAIL is set reset the DS feature. */ + vpmu_reset(vpmu, VPMU_CPU_HAS_DS); + gdprintk(XENLOG_WARNING, "CPU has set BTS_UNAVAIL - Debug Store disabled\n"); + } + else + vpmu_set(vpmu, VPMU_CPU_HAS_BTS); + if ( !cpu_has(c, X86_FEATURE_DSCPL) ) + { + gdprintk(XENLOG_WARNING, "vpmu: cpu doesn't support CPL-Qualified BTS\n"); + } + } +func_out: check_pmc_quirk(); } diff -r 6c666c08cf0d xen/include/asm-x86/hvm/vmx/vpmu_core2.h --- a/xen/include/asm-x86/hvm/vmx/vpmu_core2.h Mon Feb 13 12:36:09 2012 +0100 +++ b/xen/include/asm-x86/hvm/vmx/vpmu_core2.h Mon Feb 13 13:51:51 2012 +0100 @@ -29,6 +29,7 @@ struct arch_msr_pair { }; struct core2_pmu_enable { + char ds_area_enable; char fixed_ctr_enable[3]; char arch_pmc_enable[1]; }; diff -r 6c666c08cf0d xen/include/asm-x86/hvm/vpmu.h --- a/xen/include/asm-x86/hvm/vpmu.h Mon Feb 13 12:36:09 2012 +0100 +++ b/xen/include/asm-x86/hvm/vpmu.h Mon Feb 13 13:51:51 2012 +0100 @@ -72,6 +72,9 @@ struct vpmu_struct { #define VPMU_CONTEXT_LOADED 0x2 #define VPMU_RUNNING 0x4 #define VPMU_PASSIVE_DOMAIN_ALLOCATED 0x8 +#define VPMU_CPU_HAS_DS 0x10 /* Has Debug Store */ +#define VPMU_CPU_HAS_BTS 0x20 /* Has Branche Trace Store */ + #define vpmu_set(_vpmu, _x) ((_vpmu)->flags |= (_x)) #define vpmu_reset(_vpmu, _x) ((_vpmu)->flags &= ~(_x)) diff -r 6c666c08cf0d xen/include/asm-x86/msr-index.h --- a/xen/include/asm-x86/msr-index.h Mon Feb 13 12:36:09 2012 +0100 +++ b/xen/include/asm-x86/msr-index.h Mon Feb 13 13:51:51 2012 +0100 @@ -67,6 +67,11 @@ #define MSR_IA32_DEBUGCTLMSR 0x000001d9 #define IA32_DEBUGCTLMSR_LBR (1<<0) /* Last Branch Record */ #define IA32_DEBUGCTLMSR_BTF (1<<1) /* Single Step on Branches */ +#define IA32_DEBUGCTLMSR_TR (1<<6) /* Trace Message Enable */ +#define IA32_DEBUGCTLMSR_BTS (1<<7) /* Branch Trace Store */ +#define IA32_DEBUGCTLMSR_BTINT (1<<8) /* Branch Trace Interrupt */ +#define IA32_DEBUGCTLMSR_BTS_OFF_OS (1<<9) /* BTS off if CPL 0 */ +#define IA32_DEBUGCTLMSR_BTS_OFF_USR (1<<10) /* BTS off if CPL > 0 */ #define MSR_IA32_LASTBRANCHFROMIP 0x000001db #define MSR_IA32_LASTBRANCHTOIP 0x000001dc -- Company details: http://ts.fujitsu.com/imprint.html _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |