[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] [PATCH v25 05/15] x86/VPMU: Initialize VPMUs with __initcall
Am Freitag 19 Juni 2015, 14:44:36 schrieb Boris Ostrovsky: > 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> > Acked-by: Jan Beulich <jbeulich@xxxxxxxx> For the Intel/VMX part: Reviewed-by: Dietmar Hahn <dietmar.hahn@xxxxxxxxxxxxxx> > --- > 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 { > -- Company details: http://ts.fujitsu.com/imprint.html _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxx http://lists.xen.org/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |