[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [PATCH v14 for-xen-4.5 12/21] x86/VPMU: Initialize AMD and Intel VPMU with __initcall
Move some VPMU initilization operations into __initcalls to avoid performing same tests and calculations for each vcpu. Signed-off-by: Boris Ostrovsky <boris.ostrovsky@xxxxxxxxxx> --- xen/arch/x86/hvm/svm/vpmu.c | 117 +++++++++++++--------------- xen/arch/x86/hvm/vmx/vpmu_core2.c | 157 ++++++++++++++++++++------------------ 2 files changed, 133 insertions(+), 141 deletions(-) diff --git a/xen/arch/x86/hvm/svm/vpmu.c b/xen/arch/x86/hvm/svm/vpmu.c index 1ae4c1e..e8bb4e2 100644 --- a/xen/arch/x86/hvm/svm/vpmu.c +++ b/xen/arch/x86/hvm/svm/vpmu.c @@ -356,57 +356,6 @@ static int amd_vpmu_do_rdmsr(unsigned int msr, uint64_t *msr_content) return 1; } -static int amd_vpmu_initialise(struct vcpu *v) -{ - struct xen_pmu_amd_ctxt *ctxt; - struct vpmu_struct *vpmu = vcpu_vpmu(v); - uint8_t family = current_cpu_data.x86; - - if ( vpmu_is_set(vpmu, VPMU_CONTEXT_ALLOCATED) ) - return 0; - - if ( counters == NULL ) - { - switch ( family ) - { - case 0x15: - num_counters = F15H_NUM_COUNTERS; - counters = AMD_F15H_COUNTERS; - ctrls = AMD_F15H_CTRLS; - k7_counters_mirrored = 1; - break; - case 0x10: - case 0x12: - case 0x14: - case 0x16: - default: - num_counters = F10H_NUM_COUNTERS; - counters = AMD_F10H_COUNTERS; - ctrls = AMD_F10H_CTRLS; - k7_counters_mirrored = 0; - break; - } - } - - ctxt = xzalloc_bytes(sizeof(struct xen_pmu_amd_ctxt) + - 2 * sizeof(uint64_t) * num_counters); - if ( !ctxt ) - { - gdprintk(XENLOG_WARNING, "Insufficient memory for PMU, " - " PMU feature is unavailable on domain %d vcpu %d.\n", - v->vcpu_id, v->domain->domain_id); - return -ENOMEM; - } - - ctxt->counters = sizeof(struct xen_pmu_amd_ctxt); - ctxt->ctrls = ctxt->counters + sizeof(uint64_t) * num_counters; - - vpmu->context = ctxt; - vpmu->priv_context = NULL; - vpmu_set(vpmu, VPMU_CONTEXT_ALLOCATED); - return 0; -} - static void amd_vpmu_destroy(struct vcpu *v) { struct vpmu_struct *vpmu = vcpu_vpmu(v); @@ -480,30 +429,66 @@ struct arch_vpmu_ops amd_vpmu_ops = { int svm_vpmu_initialise(struct vcpu *v) { + struct xen_pmu_amd_ctxt *ctxt; struct vpmu_struct *vpmu = vcpu_vpmu(v); - uint8_t family = current_cpu_data.x86; - int ret = 0; - /* vpmu enabled? */ - if ( vpmu_mode == XENPMU_MODE_OFF ) + if ( (vpmu_mode == XENPMU_MODE_OFF) || + vpmu_is_set(vpmu, VPMU_CONTEXT_ALLOCATED) ) return 0; - switch ( family ) + if ( !counters ) + return -EINVAL; + + ctxt = xzalloc_bytes(sizeof(struct xen_pmu_amd_ctxt) + + 2 * sizeof(uint64_t) * num_counters); + if ( !ctxt ) { + printk(XENLOG_G_WARNING "Insufficient memory for PMU, " + " PMU feature is unavailable on domain %d vcpu %d.\n", + v->vcpu_id, v->domain->domain_id); + return -ENOMEM; + } + + ctxt->counters = sizeof(struct xen_pmu_amd_ctxt); + ctxt->ctrls = ctxt->counters + sizeof(uint64_t) * num_counters; + + vpmu->context = ctxt; + vpmu->priv_context = NULL; + + vpmu->arch_vpmu_ops = &amd_vpmu_ops; + + vpmu_set(vpmu, VPMU_CONTEXT_ALLOCATED); + return 0; +} + +static int __init amd_vpmu_init(void) +{ + if ( current_cpu_data.x86_vendor != X86_VENDOR_AMD ) + return 0; + + switch ( current_cpu_data.x86 ) + { + case 0x15: + num_counters = F15H_NUM_COUNTERS; + counters = AMD_F15H_COUNTERS; + ctrls = AMD_F15H_CTRLS; + k7_counters_mirrored = 1; + break; case 0x10: case 0x12: case 0x14: - case 0x15: case 0x16: - ret = amd_vpmu_initialise(v); - if ( !ret ) - vpmu->arch_vpmu_ops = &amd_vpmu_ops; - return ret; + num_counters = F10H_NUM_COUNTERS; + counters = AMD_F10H_COUNTERS; + ctrls = AMD_F10H_CTRLS; + k7_counters_mirrored = 0; + break; + default: + printk(XENLOG_WARNING "VPMU: Unsupported CPU family %#x\n", + current_cpu_data.x86); + vpmu_mode = XENPMU_MODE_OFF; } - printk("VPMU: Initialization failed. " - "AMD processor family %d has not " - "been supported\n", family); - return -EINVAL; + return 0; } - +__initcall(amd_vpmu_init); diff --git a/xen/arch/x86/hvm/vmx/vpmu_core2.c b/xen/arch/x86/hvm/vmx/vpmu_core2.c index 9b422c3..0933c67 100644 --- a/xen/arch/x86/hvm/vmx/vpmu_core2.c +++ b/xen/arch/x86/hvm/vmx/vpmu_core2.c @@ -708,62 +708,6 @@ static int core2_vpmu_do_interrupt(struct cpu_user_regs *regs) return 1; } -static int core2_vpmu_initialise(struct vcpu *v) -{ - struct vpmu_struct *vpmu = vcpu_vpmu(v); - u64 msr_content; - static bool_t ds_warned; - - if ( !(vpmu_features & XENPMU_FEATURE_INTEL_BTS) ) - goto func_out; - /* Check the 'Debug Store' feature in the CPUID.EAX[1]:EDX[21] */ - while ( boot_cpu_has(X86_FEATURE_DS) ) - { - if ( !boot_cpu_has(X86_FEATURE_DTES64) ) - { - if ( !ds_warned ) - printk(XENLOG_G_WARNING "CPU doesn't support 64-bit DS Area" - " - Debug Store disabled for guests\n"); - break; - } - 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); - if ( !ds_warned ) - printk(XENLOG_G_WARNING "CPU has set BTS_UNAVAIL" - " - Debug Store disabled for guests\n"); - break; - } - - vpmu_set(vpmu, VPMU_CPU_HAS_BTS); - if ( !ds_warned ) - { - if ( !boot_cpu_has(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"); - } - break; - } - ds_warned = 1; - func_out: - - arch_pmc_cnt = core2_get_arch_pmc_count(); - fixed_pmc_cnt = core2_get_fixed_pmc_count(); - check_pmc_quirk(); - return 0; -} - static void core2_vpmu_destroy(struct vcpu *v) { struct vpmu_struct *vpmu = vcpu_vpmu(v); @@ -832,23 +776,81 @@ struct arch_vpmu_ops core2_no_vpmu_ops = { int vmx_vpmu_initialise(struct vcpu *v) { 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; + u64 msr_content; + static bool_t ds_warned; vpmu->arch_vpmu_ops = &core2_no_vpmu_ops; if ( vpmu_mode == XENPMU_MODE_OFF ) return 0; - if ( family == 6 ) - { - u64 caps; + if ( (arch_pmc_cnt + fixed_pmc_cnt) == 0 ) + return -EINVAL; - rdmsrl(MSR_IA32_PERF_CAPABILITIES, caps); - full_width_write = (caps >> 13) & 1; + if ( !(vpmu_features & XENPMU_FEATURE_INTEL_BTS) ) + goto func_out; + /* Check the 'Debug Store' feature in the CPUID.EAX[1]:EDX[21] */ + while ( boot_cpu_has(X86_FEATURE_DS) ) + { + if ( !boot_cpu_has(X86_FEATURE_DTES64) ) + { + if ( !ds_warned ) + printk(XENLOG_G_WARNING "CPU doesn't support 64-bit DS Area" + " - Debug Store disabled for guests\n"); + break; + } + 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); + if ( !ds_warned ) + printk(XENLOG_G_WARNING "CPU has set BTS_UNAVAIL" + " - Debug Store disabled for guests\n"); + break; + } - switch ( cpu_model ) + vpmu_set(vpmu, VPMU_CPU_HAS_BTS); + if ( !ds_warned ) { + if ( !boot_cpu_has(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"); + } + break; + } + ds_warned = 1; + func_out: + + vpmu->arch_vpmu_ops = &core2_vpmu_ops; + + return 0; +} + +static int __init core2_vpmu_init(void) +{ + u64 caps; + + if ( current_cpu_data.x86_vendor != X86_VENDOR_INTEL ) + return 0; + + if ( current_cpu_data.x86 != 6 ) + { + printk(XENLOG_WARNING "VPMU: only family 6 is supported\n"); + vpmu_mode = XENPMU_MODE_OFF; + return 0; + } + + switch ( current_cpu_data.x86_model ) + { /* Core2: */ case 0x0f: /* original 65 nm celeron/pentium/core2/xeon, "Merom"/"Conroe" */ case 0x16: /* single-core 65 nm celeron/core2solo "Merom-L"/"Conroe-L" */ @@ -880,16 +882,21 @@ int vmx_vpmu_initialise(struct vcpu *v) /* future: */ case 0x3d: case 0x4e: - ret = core2_vpmu_initialise(v); - if ( !ret ) - vpmu->arch_vpmu_ops = &core2_vpmu_ops; - return ret; - } + break; + default: + printk(XENLOG_WARNING "VPMU: Unsupported CPU model %#x\n", + current_cpu_data.x86_model); + vpmu_mode = XENPMU_MODE_OFF; + return 0; } - printk("VPMU: Initialization failed. " - "Intel processor family %d model %d has not " - "been supported\n", family, cpu_model); - return -EINVAL; -} + arch_pmc_cnt = core2_get_arch_pmc_count(); + fixed_pmc_cnt = core2_get_fixed_pmc_count(); + rdmsrl(MSR_IA32_PERF_CAPABILITIES, caps); + full_width_write = (caps >> 13) & 1; + check_pmc_quirk(); + + return 0; +} +__initcall(core2_vpmu_init); -- 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 |