On 02/20/2015 11:27 AM, Jan Beulich wrote:
On 20.02.15 at 17:15, <boris.ostrov...@oracle.com> wrote:
On 02/20/2015 09:35 AM, Jan Beulich wrote:
On 16.02.15 at 23:26, <boris.ostrov...@oracle.com> wrote:
--- a/xen/arch/x86/domain.c
+++ b/xen/arch/x86/domain.c
@@ -437,6 +437,8 @@ int vcpu_initialise(struct vcpu *v)
vmce_init_vcpu(v);
}
+ spin_lock_init(&v->arch.vpmu.vpmu_lock);
This would rather seem to belong into vpmu_initialize().
vpmu_initialize() is called under this lock so we can't do this.
Yes, I saw that later on, but it still doesn't look well structured. Can't
you bail early from vpmu_initialize() the first time through for PV(H)
guests, rather than guarding the HVM invocations with is_hvm_...()?
I could but I am not sure how it would allow me to move spin_lock_init()
to vpmu_initialize().
We are protecting xenpmu_data and it is supposed to be set before we get
into vpmu_initialize().
+static int pvpmu_init(struct domain *d, xen_pmu_params_t *params)
+{
+ struct vcpu *v;
+ struct vpmu_struct *vpmu;
+ struct page_info *page;
+ uint64_t gfn = params->val;
+
+ if ( vpmu_mode == XENPMU_MODE_OFF )
+ return -EINVAL;
+
+ if ( (params->vcpu >= d->max_vcpus) || (d->vcpu == NULL) ||
+ (d->vcpu[params->vcpu] == NULL) )
+ return -EINVAL;
+
+ if ( v->arch.vpmu.xenpmu_data )
+ 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];
+ vpmu = vcpu_vpmu(v);
+ spin_lock(&vpmu->vpmu_lock);
+
+ v->arch.vpmu.xenpmu_data = __map_domain_page_global(page);
+ if ( !v->arch.vpmu.xenpmu_data )
+ {
+ put_page_and_type(page);
+ spin_unlock(&vpmu->vpmu_lock);
+ return -EINVAL;
+ }
+
+ vpmu_initialise(v);
+
+ spin_unlock(&vpmu->vpmu_lock);
So what is this lock guarding against here? Certainly not overwriting
of a non-NULL v->arch.vpmu.xenpmu_data (and hence leaking a
page reference)...
This is trying to protect a race with pvmu_finish() that could clear
xenpmu_data.
(I actually think you were the one who suggested it).
But it should also protect against a second pvpmu_init() on another
pCPU.
Right, I will move 'if (v->arch.vpmu.xenpmu_data )' under the lock (and
clean up if it is non-NULL)
-boris
_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
http://lists.xen.org/xen-devel