[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Xen-devel] [PATCH v12 for-xen-4.5 12/20] x86/VPMU: Initialize PMU for PV(H) guests



>>> On 25.09.14 at 21:28, <boris.ostrovsky@xxxxxxxxxx> wrote:
> @@ -389,14 +390,26 @@ static int amd_vpmu_initialise(struct vcpu *v)
>        }
>      }
>  
> -    ctxt = xzalloc_bytes(sizeof(struct xen_pmu_amd_ctxt) +
> -                         2 * sizeof(uint64_t) * AMD_MAX_COUNTERS);
> -    if ( !ctxt )
> +    regs_size = 2 * sizeof(uint64_t) * AMD_MAX_COUNTERS;
> +    if ( is_hvm_domain(v->domain) )
>      {
> -        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 = xzalloc_bytes(sizeof(struct xen_pmu_amd_ctxt) + regs_size);
> +        if ( !ctxt )
> +        {
> +            gdprintk(XENLOG_WARNING, "Insufficient memory for PMU, "
> +                "PMU feature is unavailable\n");
> +            return -ENOMEM;
> +        }
> +    }
> +    else
> +    {
> +        if ( sizeof(struct xen_pmu_data) + regs_size > PAGE_SIZE )

This is a compile time constant condition - no reason to issue a
message and return failure at runtime, just BUILD_BUG_ON() instead.

> --- a/xen/arch/x86/hvm/vmx/vpmu_core2.c
> +++ b/xen/arch/x86/hvm/vmx/vpmu_core2.c
> @@ -356,25 +356,45 @@ static int core2_vpmu_alloc_resource(struct vcpu *v)
>      struct vpmu_struct *vpmu = vcpu_vpmu(v);
>      struct xen_pmu_intel_ctxt *core2_vpmu_cxt = NULL;
>      uint64_t *p = NULL;
> +    unsigned int regs_size;
>  
> -    if ( !acquire_pmu_ownership(PMU_OWNER_HVM) )
> -        return 0;
> -
> -    wrmsrl(MSR_CORE_PERF_GLOBAL_CTRL, 0);
> -    if ( vmx_add_host_load_msr(MSR_CORE_PERF_GLOBAL_CTRL) )
> +    p = xzalloc_bytes(sizeof(uint64_t));
> +    if ( !p )
>          goto out_err;
>  
> -    if ( vmx_add_guest_msr(MSR_CORE_PERF_GLOBAL_CTRL) )
> -        goto out_err;
> -    vmx_write_guest_msr(MSR_CORE_PERF_GLOBAL_CTRL, 0);
> -
> -    core2_vpmu_cxt = xzalloc_bytes(sizeof(struct xen_pmu_intel_ctxt) +
> -                                   sizeof(uint64_t) * fixed_pmc_cnt +
> -                                   sizeof(struct xen_pmu_cntr_pair) *
> -                                   arch_pmc_cnt);
> -    p = xzalloc(uint64_t);
> -    if ( !core2_vpmu_cxt || !p )
> -        goto out_err;
> +    if ( has_hvm_container_domain(v->domain) )
> +    {
> +        if ( is_hvm_domain(v->domain) && 
> !acquire_pmu_ownership(PMU_OWNER_HVM) )
> +            goto out_err;
> +
> +        wrmsrl(MSR_CORE_PERF_GLOBAL_CTRL, 0);
> +        if ( vmx_add_host_load_msr(MSR_CORE_PERF_GLOBAL_CTRL) )
> +            goto out_err_hvm;
> +        if ( vmx_add_guest_msr(MSR_CORE_PERF_GLOBAL_CTRL) )
> +            goto out_err_hvm;
> +        vmx_write_guest_msr(MSR_CORE_PERF_GLOBAL_CTRL, 0);
> +    }
> +
> +    regs_size = sizeof(uint64_t) * fixed_pmc_cnt +
> +                sizeof(struct xen_pmu_cntr_pair) * arch_pmc_cnt;
> +    if ( is_hvm_domain(v->domain) )
> +    {
> +        core2_vpmu_cxt = xzalloc_bytes(sizeof(struct xen_pmu_intel_ctxt) +
> +                                       regs_size);
> +        if ( !core2_vpmu_cxt )
> +            goto out_err_hvm;
> +    }
> +    else
> +    {
> +        if ( sizeof(struct xen_pmu_data) + regs_size > PAGE_SIZE )
> +        {
> +            printk(XENLOG_WARNING

XENLOG_G_WARNING

Also, with the constituents of regs_size not changing at runtime,
issuing the message just once (and then perhaps in some __init
function) would seem the better approach.

> +static int pvpmu_init(struct domain *d, xen_pmu_params_t *params)
> +{
> +    struct vcpu *v;
> +    struct page_info *page;
> +    uint64_t gfn = params->val;
> +
> +    if ( (params->vcpu >= d->max_vcpus) || (d->vcpu == NULL) ||
> +         (d->vcpu[params->vcpu] == NULL) )
> +        return -EINVAL;
> +
> +    page = get_page_from_gfn(d, gfn, NULL, P2M_ALLOC);
> +    if ( !page )
> +        return -EINVAL;
> +
> +    if ( !get_page_type(page, PGT_writable_page) )
> +    {
> +        put_page(page);
> +        return -EINVAL;
> +    }
> +
> +    v = d->vcpu[params->vcpu];
> +    v->arch.vpmu.xenpmu_data = __map_domain_page_global(page);
> +    if ( !v->arch.vpmu.xenpmu_data )
> +    {
> +        put_page_and_type(page);
> +        return -EINVAL;
> +    }
> +
> +    vpmu_initialise(v);
> +
> +    return 0;
> +}
> +
> +static void pvpmu_finish(struct domain *d, xen_pmu_params_t *params)
> +{
> +    struct vcpu *v;
> +    uint64_t mfn;
> +
> +    if ( (params->vcpu >= d->max_vcpus) || (d->vcpu == NULL) ||
> +         (d->vcpu[params->vcpu] == NULL) )
> +        return;
> +
> +    v = d->vcpu[params->vcpu];
> +    if ( v != current )
> +        vcpu_pause(v);
> +
> +    if ( v->arch.vpmu.xenpmu_data )
> +    {
> +        mfn = domain_page_map_to_mfn(v->arch.vpmu.xenpmu_data);
> +        if ( mfn_valid(mfn) )

Isn't this a must knowing that v->arch.vpmu.xenpmu_data is not
NULL? I.e. ASSERT()?

Jan

_______________________________________________
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®.