[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] [PATCH v24 04/15] x86/VPMU: Interface for setting PMU mode and flags
> From: Boris Ostrovsky [mailto:boris.ostrovsky@xxxxxxxxxx] > Sent: Wednesday, June 10, 2015 11:04 PM > > Add runtime interface for setting PMU mode and flags. Three main modes are > provided: > * XENPMU_MODE_OFF: PMU is not virtualized > * XENPMU_MODE_SELF: Guests can access PMU MSRs and receive PMU interrupts. > * XENPMU_MODE_HV: Same as XENPMU_MODE_SELF for non-proviledged guests, dom0 > can profile itself and the hypervisor. > > Note that PMU modes are different from what can be provided at Xen's boot line > with 'vpmu' argument. An 'off' (or '0') value is equivalent to > XENPMU_MODE_OFF. > Any other value, on the other hand, will cause VPMU mode to be set to > XENPMU_MODE_SELF during boot. > > For feature flags only Intel's BTS is currently supported. > > Mode and flags are set via HYPERVISOR_xenpmu_op hypercall. > > Signed-off-by: Boris Ostrovsky <boris.ostrovsky@xxxxxxxxxx> > Acked-by: Daniel De Graaf <dgdegra@xxxxxxxxxxxxx> > Acked-by: Jan Beulich <jbeulich@xxxxxxxx> > Reviewed-by: Dietmar Hahn <dietmar.hahn@xxxxxxxxxxxxxx> > --- > tools/flask/policy/policy/modules/xen/xen.te | 3 + > xen/arch/x86/domain.c | 4 +- > xen/arch/x86/hvm/svm/vpmu.c | 4 +- > xen/arch/x86/hvm/vmx/vpmu_core2.c | 10 +- > xen/arch/x86/hvm/vpmu.c | 159 > +++++++++++++++++++++++++-- > xen/arch/x86/x86_64/compat/entry.S | 4 + > xen/arch/x86/x86_64/entry.S | 4 + > xen/include/asm-x86/hvm/vpmu.h | 27 +++-- > xen/include/public/pmu.h | 46 ++++++++ > xen/include/public/xen.h | 1 + > xen/include/xen/hypercall.h | 4 + > xen/include/xlat.lst | 1 + > xen/include/xsm/dummy.h | 15 +++ > xen/include/xsm/xsm.h | 6 + > xen/xsm/dummy.c | 1 + > xen/xsm/flask/hooks.c | 18 +++ > xen/xsm/flask/policy/access_vectors | 2 + > 17 files changed, 284 insertions(+), 25 deletions(-) > > diff --git a/xen/arch/x86/hvm/vpmu.c b/xen/arch/x86/hvm/vpmu.c > index d829d68..5cfb2f0 100644 > --- a/xen/arch/x86/hvm/vpmu.c > +++ b/xen/arch/x86/hvm/vpmu.c > @@ -246,28 +266,45 @@ void vpmu_initialise(struct vcpu *v) > > ASSERT(!vpmu->flags && !vpmu->context); > > + /* > + * Count active VPMUs so that we won't try to change vpmu_mode while > + * they are in use. > + */ > + spin_lock(&vpmu_lock); > + vpmu_count++; > + spin_unlock(&vpmu_lock); > + > switch ( vendor ) > { > case X86_VENDOR_AMD: > - ret = svm_vpmu_initialise(v, opt_vpmu_enabled); > + ret = svm_vpmu_initialise(v); > break; > > case X86_VENDOR_INTEL: > - ret = vmx_vpmu_initialise(v, opt_vpmu_enabled); > + ret = vmx_vpmu_initialise(v); > break; > > default: > - if ( opt_vpmu_enabled ) > + if ( vpmu_mode != XENPMU_MODE_OFF ) > { > printk(XENLOG_G_WARNING "VPMU: Unknown CPU vendor %d. " > "Disabling VPMU\n", vendor); > opt_vpmu_enabled = 0; > + vpmu_mode = XENPMU_MODE_OFF; > } > - return; > + return; /* Don't bother restoring vpmu_count, VPMU is off forever */ why not restoring vpmu_count here? There could be a race condition regarding to the mode control path: + if ( (vpmu_count == 0) || (vpmu_mode == pmu_params.val) || + ((vpmu_mode ^ pmu_params.val) == + (XENPMU_MODE_SELF | XENPMU_MODE_HV)) ) + vpmu_mode = pmu_params.val; It's possible "vpmu_mode=pmu_params.val" happens later than "vpmu_mode = XENPMU_MODE_OFF"... It might not be a big problem since opt_vpmu_enabled is 0 then, but then there's pointless to reset vpmu_mode further if the behavior is not guaranteed. > } > > if ( ret ) > printk(XENLOG_G_WARNING "VPMU: Initialization failed for %pv\n", v); > + > + /* Intel needs to initialize VPMU ops even if VPMU is not in use */ > + if ( ret || (vpmu_mode == XENPMU_MODE_OFF) ) > + { > + spin_lock(&vpmu_lock); > + vpmu_count--; > + spin_unlock(&vpmu_lock); > + } > } > > static void vpmu_clear_last(void *arg) > @@ -296,6 +333,10 @@ void vpmu_destroy(struct vcpu *v) > > if ( vpmu->arch_vpmu_ops && vpmu->arch_vpmu_ops->arch_vpmu_destroy ) > vpmu->arch_vpmu_ops->arch_vpmu_destroy(v); > + > + spin_lock(&vpmu_lock); > + vpmu_count--; > + spin_unlock(&vpmu_lock); > } > > /* Dump some vpmu informations on console. Used in keyhandler > dump_domains(). */ > @@ -307,6 +348,109 @@ void vpmu_dump(struct vcpu *v) > vpmu->arch_vpmu_ops->arch_vpmu_dump(v); > } > > +long do_xenpmu_op(unsigned int op, XEN_GUEST_HANDLE_PARAM(xen_pmu_params_t) > arg) > +{ > + int ret; > + struct xen_pmu_params pmu_params = {.val = 0}; > + > + if ( !opt_vpmu_enabled ) > + return -EOPNOTSUPP; > + > + ret = xsm_pmu_op(XSM_OTHER, current->domain, op); > + if ( ret ) > + return ret; > + > + /* Check major version when parameters are specified */ > + switch ( op ) > + { > + case XENPMU_mode_set: > + case XENPMU_feature_set: > + if ( copy_from_guest(&pmu_params, arg, 1) ) > + return -EFAULT; > + > + if ( pmu_params.version.maj != XENPMU_VER_MAJ ) > + return -EINVAL; > + } > + > + switch ( op ) > + { > + case XENPMU_mode_set: > + { > + if ( (pmu_params.val & ~(XENPMU_MODE_SELF | XENPMU_MODE_HV)) || > + (hweight64(pmu_params.val) > 1) ) > + return -EINVAL; > + > + /* 32-bit dom0 can only sample itself. */ > + if ( is_pv_32bit_vcpu(current) && (pmu_params.val & XENPMU_MODE_HV) ) > + return -EINVAL; > + > + spin_lock(&vpmu_lock); > + > + /* > + * We can always safely switch between XENPMU_MODE_SELF and > + * XENPMU_MODE_HV while other VPMUs are active. > + */ > + if ( (vpmu_count == 0) || (vpmu_mode == pmu_params.val) || > + ((vpmu_mode ^ pmu_params.val) == > + (XENPMU_MODE_SELF | XENPMU_MODE_HV)) ) > + vpmu_mode = pmu_params.val; > + else > + { > + printk(XENLOG_WARNING "VPMU: Cannot change mode while" > + " active VPMUs exist\n"); > + ret = -EBUSY; > + } > + > + spin_unlock(&vpmu_lock); > + > + break; > + } > + > + case XENPMU_mode_get: > + memset(&pmu_params, 0, sizeof(pmu_params)); > + pmu_params.val = vpmu_mode; > + > + pmu_params.version.maj = XENPMU_VER_MAJ; > + pmu_params.version.min = XENPMU_VER_MIN; > + > + if ( copy_to_guest(arg, &pmu_params, 1) ) > + return -EFAULT; > + > + break; > + > + case XENPMU_feature_set: > + if ( pmu_params.val & ~XENPMU_FEATURE_INTEL_BTS ) > + return -EINVAL; > + > + spin_lock(&vpmu_lock); > + > + if ( vpmu_count == 0 ) > + vpmu_features = pmu_params.val; > + else > + { > + printk(XENLOG_WARNING "VPMU: Cannot change features while" > + " active VPMUs exist\n"); > + ret = -EBUSY; > + } what about setting same features as existing in vpmu_features? we should do same check as done in mode setting. Thanks Kevin _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxx http://lists.xen.org/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |