[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [PATCH v18 06/16] x86/VPMU: Initialize VPMUs 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 | 112 ++++++++++++---------------- xen/arch/x86/hvm/vmx/vpmu_core2.c | 151 +++++++++++++++++++------------------- xen/arch/x86/hvm/vpmu.c | 32 ++++++++ xen/include/asm-x86/hvm/vpmu.h | 2 + 4 files changed, 157 insertions(+), 140 deletions(-) diff --git a/xen/arch/x86/hvm/svm/vpmu.c b/xen/arch/x86/hvm/svm/vpmu.c index 2cfdf08..03474a3 100644 --- a/xen/arch/x86/hvm/svm/vpmu.c +++ b/xen/arch/x86/hvm/svm/vpmu.c @@ -375,57 +375,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(*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(*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); @@ -497,30 +446,63 @@ 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(*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(*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; +} + +int __init amd_vpmu_init(void) +{ + 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); + return -EINVAL; } - printk("VPMU: Initialization failed. " - "AMD processor family %d has not " - "been supported\n", family); - return -EINVAL; + return 0; } diff --git a/xen/arch/x86/hvm/vmx/vpmu_core2.c b/xen/arch/x86/hvm/vmx/vpmu_core2.c index 4d08d1b..6c78323 100644 --- a/xen/arch/x86/hvm/vmx/vpmu_core2.c +++ b/xen/arch/x86/hvm/vmx/vpmu_core2.c @@ -724,62 +724,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); @@ -846,23 +790,77 @@ 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; +} + +int __init core2_vpmu_init(void) +{ + u64 caps; + + if ( current_cpu_data.x86 != 6 ) + { + printk(XENLOG_WARNING "VPMU: only family 6 is supported\n"); + return -EINVAL; + } + + 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" */ @@ -894,16 +892,19 @@ 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); + return -EINVAL; } - 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; +} diff --git a/xen/arch/x86/hvm/vpmu.c b/xen/arch/x86/hvm/vpmu.c index 40a89d9..f62fa80 100644 --- a/xen/arch/x86/hvm/vpmu.c +++ b/xen/arch/x86/hvm/vpmu.c @@ -528,14 +528,46 @@ long do_xenpmu_op(unsigned int op, XEN_GUEST_HANDLE_PARAM(xen_pmu_params_t) arg) static int __init vpmu_init(void) { + int vendor = current_cpu_data.x86_vendor; + + if ( vpmu_disabled ) + { + printk(XENLOG_INFO "VPMU: disabled\n"); + return 0; + } + /* NMI watchdog uses LVTPC and HW counter */ if ( opt_watchdog && !vpmu_disabled ) { printk(XENLOG_WARNING "NMI watchdog is enabled. Turning VPMU off.\n"); vpmu_mode = XENPMU_MODE_OFF; vpmu_disabled = 1; + return 0; + } + + switch ( vendor ) + { + case X86_VENDOR_AMD: + if ( amd_vpmu_init() ) + vpmu_mode = XENPMU_MODE_OFF; + break; + case X86_VENDOR_INTEL: + if ( core2_vpmu_init() ) + vpmu_mode = XENPMU_MODE_OFF; + break; + default: + printk(XENLOG_WARNING "VPMU: Unknown CPU vendor: %d. " + "Turning VPMU off.\n", vendor); + vpmu_mode = XENPMU_MODE_OFF; + break; } + if ( vpmu_mode != XENPMU_MODE_OFF ) + printk(XENLOG_INFO "VPMU: version " __stringify(XENPMU_VER_MAJ) "." + __stringify(XENPMU_VER_MIN) "\n"); + else + vpmu_disabled = 1; + return 0; } __initcall(vpmu_init); diff --git a/xen/include/asm-x86/hvm/vpmu.h b/xen/include/asm-x86/hvm/vpmu.h index 1171b2a..cf32f82 100644 --- a/xen/include/asm-x86/hvm/vpmu.h +++ b/xen/include/asm-x86/hvm/vpmu.h @@ -62,7 +62,9 @@ struct arch_vpmu_ops { void (*arch_vpmu_dump)(const struct vcpu *); }; +int core2_vpmu_init(void); int vmx_vpmu_initialise(struct vcpu *); +int amd_vpmu_init(void); int svm_vpmu_initialise(struct vcpu *); /* VPMU states */ -- 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 |