[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


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.