From mboxrd@z Thu Jan 1 00:00:00 1970 From: Boris Ostrovsky Subject: [PATCH v25 05/15] x86/VPMU: Initialize VPMUs with __initcall Date: Fri, 19 Jun 2015 14:44:36 -0400 Message-ID: <1434739486-1611-6-git-send-email-boris.ostrovsky@oracle.com> References: <1434739486-1611-1-git-send-email-boris.ostrovsky@oracle.com> Mime-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Return-path: In-Reply-To: <1434739486-1611-1-git-send-email-boris.ostrovsky@oracle.com> List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Sender: xen-devel-bounces@lists.xen.org Errors-To: xen-devel-bounces@lists.xen.org To: JBeulich@suse.com, kevin.tian@intel.com, suravee.suthikulpanit@amd.com, Aravind.Gopalakrishnan@amd.com, dietmar.hahn@ts.fujitsu.com, dgdegra@tycho.nsa.gov, andrew.cooper3@citrix.com Cc: boris.ostrovsky@oracle.com, xen-devel@lists.xen.org List-Id: xen-devel@lists.xenproject.org Move some VPMU initilization operations into __initcalls to avoid performing same tests and calculations for each vcpu. Signed-off-by: Boris Ostrovsky Acked-by: Jan Beulich --- xen/arch/x86/hvm/svm/vpmu.c | 106 ++++++++++++-------------- 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, 156 insertions(+), 135 deletions(-) diff --git a/xen/arch/x86/hvm/svm/vpmu.c b/xen/arch/x86/hvm/svm/vpmu.c index 481ea7b..b60ca40 100644 --- a/xen/arch/x86/hvm/svm/vpmu.c +++ b/xen/arch/x86/hvm/svm/vpmu.c @@ -356,54 +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 ( 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); @@ -474,30 +426,62 @@ 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 ) 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 cfcdf42..025c970 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); @@ -829,23 +773,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" */ @@ -884,16 +882,21 @@ int vmx_vpmu_initialise(struct vcpu *v) /* next gen Xeon Phi */ case 0x57: - 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 3e65c9b..e7e552e 100644 --- a/xen/arch/x86/hvm/vpmu.c +++ b/xen/arch/x86/hvm/vpmu.c @@ -453,14 +453,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 ( !opt_vpmu_enabled ) + { + printk(XENLOG_INFO "VPMU: disabled\n"); + return 0; + } + /* NMI watchdog uses LVTPC and HW counter */ if ( opt_watchdog && opt_vpmu_enabled ) { printk(XENLOG_WARNING "NMI watchdog is enabled. Turning VPMU off.\n"); opt_vpmu_enabled = 0; vpmu_mode = XENPMU_MODE_OFF; + 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 + opt_vpmu_enabled = 0; + return 0; } __initcall(vpmu_init); diff --git a/xen/include/asm-x86/hvm/vpmu.h b/xen/include/asm-x86/hvm/vpmu.h index 88ffc19..96f7666 100644 --- a/xen/include/asm-x86/hvm/vpmu.h +++ b/xen/include/asm-x86/hvm/vpmu.h @@ -52,7 +52,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 *); struct vpmu_struct { -- 1.8.1.4