[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [xen-unstable] x86/vpmu: Add the BTS extension
# HG changeset patch # User Dietmar Hahn <dietmar.hahn@xxxxxxxxxxxxxx> # Date 1331820780 -3600 # Node ID bd685bff45b3f973e4ce979a89defdac1961925b # Parent 28f5f047d060a0c8e831fb4e693a8509a2b62bd8 x86/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> Committed-by: Jan Beulich <jbeulich@xxxxxxxx> --- diff -r 28f5f047d060 -r bd685bff45b3 xen/arch/x86/hvm/svm/vpmu.c --- a/xen/arch/x86/hvm/svm/vpmu.c Thu Mar 15 15:11:30 2012 +0100 +++ b/xen/arch/x86/hvm/svm/vpmu.c Thu Mar 15 15:13:00 2012 +0100 @@ -363,10 +363,11 @@ .arch_vpmu_load = amd_vpmu_restore }; -int svm_vpmu_initialise(struct vcpu *v) +int svm_vpmu_initialise(struct vcpu *v, unsigned int vpmu_flags) { struct vpmu_struct *vpmu = vcpu_vpmu(v); uint8_t family = current_cpu_data.x86; + int ret = 0; switch ( family ) { @@ -374,8 +375,10 @@ case 0x12: case 0x14: case 0x15: - vpmu->arch_vpmu_ops = &amd_vpmu_ops; - return amd_vpmu_initialise(v); + ret = amd_vpmu_initialise(v); + if ( !ret ) + vpmu->arch_vpmu_ops = &amd_vpmu_ops; + return ret; } printk("VPMU: Initialization failed. " diff -r 28f5f047d060 -r bd685bff45b3 xen/arch/x86/hvm/vmx/vmx.c --- a/xen/arch/x86/hvm/vmx/vmx.c Thu Mar 15 15:11:30 2012 +0100 +++ b/xen/arch/x86/hvm/vmx/vmx.c Thu Mar 15 15:13:00 2012 +0100 @@ -1833,6 +1833,9 @@ /* 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) ) @@ -1960,9 +1963,14 @@ 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 28f5f047d060 -r bd685bff45b3 xen/arch/x86/hvm/vmx/vpmu_core2.c --- a/xen/arch/x86/hvm/vmx/vpmu_core2.c Thu Mar 15 15:11:30 2012 +0100 +++ b/xen/arch/x86/hvm/vmx/vpmu_core2.c Thu Mar 15 15:13:00 2012 +0100 @@ -406,7 +406,27 @@ 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) ) + return 1; + gdprintk(XENLOG_WARNING, "Debug Store is not supported on this cpu\n"); + vmx_inject_hw_exception(TRAP_gp_fault, 0); + return 0; + } + } return 0; + } core2_vpmu_cxt = vpmu->context; switch ( msr ) @@ -425,6 +445,19 @@ "which is not supported.\n"); return 1; case MSR_IA32_DS_AREA: + if ( vpmu_is_set(vpmu, VPMU_CPU_HAS_DS) ) + { + if ( !is_canonical_address(msr_content) ) + { + gdprintk(XENLOG_WARNING, + "Illegal address for IA32_DS_AREA: %#" PRIx64 "x\n", + msr_content); + vmx_inject_hw_exception(TRAP_gp_fault, 0); + return 1; + } + core2_vpmu_cxt->pmu_enable->ds_area_enable = msr_content ? 1 : 0; + break; + } gdprintk(XENLOG_WARNING, "Guest setting of DTS is ignored.\n"); return 1; case MSR_CORE_PERF_GLOBAL_CTRL: @@ -471,6 +504,7 @@ 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 @@ -496,6 +530,8 @@ 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) @@ -525,25 +561,35 @@ 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; } @@ -551,6 +597,16 @@ 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 int core2_vpmu_do_interrupt(struct cpu_user_regs *regs) @@ -564,15 +620,21 @@ struct vlapic *vlapic = vcpu_vlapic(v); rdmsrl(MSR_CORE_PERF_GLOBAL_STATUS, msr_content); - if ( !msr_content ) - return 0; - - 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); + if ( 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); + } + 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); @@ -589,8 +651,53 @@ return 1; } -static int core2_vpmu_initialise(struct vcpu *v) +static int core2_vpmu_initialise(struct vcpu *v, unsigned int vpmu_flags) { + struct vpmu_struct *vpmu = vcpu_vpmu(v); + u64 msr_content; + struct cpuinfo_x86 *c = ¤t_cpu_data; + + if ( !(vpmu_flags & VPMU_BOOT_BTS) ) + goto func_out; + /* Check the 'Debug Store' feature in the CPUID.EAX[1]:EDX[21] */ + if ( cpu_has(c, X86_FEATURE_DS) ) + { +#ifdef __x86_64__ + if ( !cpu_has(c, X86_FEATURE_DTES64) ) + { + printk(XENLOG_G_WARNING "CPU doesn't support 64-bit DS Area" + " - Debug Store disabled for d%d:v%d\n", + v->domain->domain_id, v->vcpu_id); + goto func_out; + } +#endif + 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); + printk(XENLOG_G_WARNING "CPU has set BTS_UNAVAIL" + " - Debug Store disabled for d%d:v%d\n", + v->domain->domain_id, v->vcpu_id); + } + else + { + vpmu_set(vpmu, VPMU_CPU_HAS_BTS); + if ( !cpu_has(c, X86_FEATURE_DSCPL) ) + printk(XENLOG_G_INFO + "vpmu: CPU doesn't support CPL-Qualified BTS\n"); + printk("******************************************************\n"); + printk("** WARNING: Emulation of BTS Feature is switched on **\n"); + printk("** Using this processor feature in a virtualized **\n"); + printk("** environment is not 100%% safe. **\n"); + printk("** Setting the DS buffer address with wrong values **\n"); + printk("** may lead to hypervisor hangs or crashes. **\n"); + printk("** It is NOT recommended for production use! **\n"); + printk("******************************************************\n"); + } + } +func_out: check_pmc_quirk(); return 0; } @@ -620,11 +727,12 @@ .arch_vpmu_load = core2_vpmu_load }; -int vmx_vpmu_initialise(struct vcpu *v) +int vmx_vpmu_initialise(struct vcpu *v, unsigned int vpmu_flags) { struct vpmu_struct *vpmu = vcpu_vpmu(v); uint8_t family = current_cpu_data.x86; uint8_t cpu_model = current_cpu_data.x86_model; + int ret = 0; if ( family == 6 ) { @@ -639,8 +747,10 @@ case 46: case 47: case 58: - vpmu->arch_vpmu_ops = &core2_vpmu_ops; - return core2_vpmu_initialise(v); + ret = core2_vpmu_initialise(v, vpmu_flags); + if ( !ret ) + vpmu->arch_vpmu_ops = &core2_vpmu_ops; + return ret; } } diff -r 28f5f047d060 -r bd685bff45b3 xen/arch/x86/hvm/vpmu.c --- a/xen/arch/x86/hvm/vpmu.c Thu Mar 15 15:11:30 2012 +0100 +++ b/xen/arch/x86/hvm/vpmu.c Thu Mar 15 15:13:00 2012 +0100 @@ -32,8 +32,36 @@ #include <asm/hvm/svm/svm.h> #include <asm/hvm/svm/vmcb.h> -static bool_t __read_mostly opt_vpmu_enabled; -boolean_param("vpmu", opt_vpmu_enabled); + +/* + * "vpmu" : vpmu generally enabled + * "vpmu=off" : vpmu generally disabled + * "vpmu=bts" : vpmu enabled and Intel BTS feature switched on. + */ +static unsigned int __read_mostly opt_vpmu_enabled; +static void parse_vpmu_param(char *s); +custom_param("vpmu", parse_vpmu_param); + +static void __init parse_vpmu_param(char *s) +{ + switch ( parse_bool(s) ) + { + case 0: + break; + default: + if ( !strcmp(s, "bts") ) + opt_vpmu_enabled |= VPMU_BOOT_BTS; + else if ( *s ) + { + printk("VPMU: unknown flag: %s - vpmu disabled!\n", s); + break; + } + /* fall through */ + case 1: + opt_vpmu_enabled |= VPMU_BOOT_ENABLED; + break; + } +} int vpmu_do_wrmsr(unsigned int msr, uint64_t msr_content) { @@ -104,12 +132,12 @@ switch ( vendor ) { case X86_VENDOR_AMD: - if ( svm_vpmu_initialise(v) != 0 ) + if ( svm_vpmu_initialise(v, opt_vpmu_enabled) != 0 ) opt_vpmu_enabled = 0; break; case X86_VENDOR_INTEL: - if ( vmx_vpmu_initialise(v) != 0 ) + if ( vmx_vpmu_initialise(v, opt_vpmu_enabled) != 0 ) opt_vpmu_enabled = 0; break; diff -r 28f5f047d060 -r bd685bff45b3 xen/include/asm-x86/hvm/vmx/vpmu_core2.h --- a/xen/include/asm-x86/hvm/vmx/vpmu_core2.h Thu Mar 15 15:11:30 2012 +0100 +++ b/xen/include/asm-x86/hvm/vmx/vpmu_core2.h Thu Mar 15 15:13:00 2012 +0100 @@ -29,6 +29,7 @@ }; struct core2_pmu_enable { + char ds_area_enable; char fixed_ctr_enable[3]; char arch_pmc_enable[1]; }; diff -r 28f5f047d060 -r bd685bff45b3 xen/include/asm-x86/hvm/vpmu.h --- a/xen/include/asm-x86/hvm/vpmu.h Thu Mar 15 15:11:30 2012 +0100 +++ b/xen/include/asm-x86/hvm/vpmu.h Thu Mar 15 15:13:00 2012 +0100 @@ -22,6 +22,14 @@ #ifndef __ASM_X86_HVM_VPMU_H_ #define __ASM_X86_HVM_VPMU_H_ +/* + * Flag bits given as a string on the hypervisor boot parameter 'vpmu'. + * See arch/x86/hvm/vpmu.c. + */ +#define VPMU_BOOT_ENABLED 0x1 /* vpmu generally enabled. */ +#define VPMU_BOOT_BTS 0x2 /* Intel BTS feature wanted. */ + + #define msraddr_to_bitpos(x) (((x)&0xffff) + ((x)>>31)*0x2000) #define vcpu_vpmu(vcpu) (&((vcpu)->arch.hvm_vcpu.vpmu)) #define vpmu_vcpu(vpmu) (container_of((vpmu), struct vcpu, \ @@ -48,8 +56,8 @@ void (*arch_vpmu_load)(struct vcpu *v); }; -int vmx_vpmu_initialise(struct vcpu *v); -int svm_vpmu_initialise(struct vcpu *v); +int vmx_vpmu_initialise(struct vcpu *, unsigned int flags); +int svm_vpmu_initialise(struct vcpu *, unsigned int flags); struct vpmu_struct { u32 flags; @@ -61,6 +69,9 @@ #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 Branch Trace Store */ + #define vpmu_set(_vpmu, _x) ((_vpmu)->flags |= (_x)) #define vpmu_reset(_vpmu, _x) ((_vpmu)->flags &= ~(_x)) diff -r 28f5f047d060 -r bd685bff45b3 xen/include/asm-x86/msr-index.h --- a/xen/include/asm-x86/msr-index.h Thu Mar 15 15:11:30 2012 +0100 +++ b/xen/include/asm-x86/msr-index.h Thu Mar 15 15:13:00 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 _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |