|
[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
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |