void vpmu_initialise(struct vcpu *v) { struct vpmu_struct *vpmu = vcpu_vpmu(v); uint8_t vendor = current_cpu_data.x86_vendor; if ( is_pvh_vcpu(v) ) return; if ( vpmu_is_set(vpmu, VPMU_CONTEXT_ALLOCATED) ) vpmu_destroy(v); vpmu_clear(vpmu); vpmu->context = NULL; switch ( vendor ) { case X86_VENDOR_AMD: if ( svm_vpmu_initialise(v, opt_vpmu_enabled) != 0 ) opt_vpmu_enabled = 0; break; case X86_VENDOR_INTEL: if ( vmx_vpmu_initialise(v, opt_vpmu_enabled) != 0 ) opt_vpmu_enabled = 0; break; default: printk("VPMU: Initialization failed. " "Unknown CPU vendor %d\n", vendor); opt_vpmu_enabled = 0; break; } }
static int vpmu_arch_initialise(struct vcpu *v) { struct vpmu_struct *vpmu = vcpu_vpmu(v); uint8_t vendor = current_cpu_data.x86_vendor; int ret; BUILD_BUG_ON(sizeof(struct xen_pmu_intel_ctxt) > XENPMU_CTXT_PAD_SZ); BUILD_BUG_ON(sizeof(struct xen_pmu_amd_ctxt) > XENPMU_CTXT_PAD_SZ); BUILD_BUG_ON(sizeof(struct xen_pmu_regs) > XENPMU_REGS_PAD_SZ); BUILD_BUG_ON(sizeof(struct compat_pmu_regs) > XENPMU_REGS_PAD_SZ); ASSERT(!(vpmu->flags & ~VPMU_AVAILABLE) && !vpmu->context); if ( !vpmu_available(v) ) return 0; switch ( vendor ) { case X86_VENDOR_AMD: ret = svm_vpmu_initialise(v); break; case X86_VENDOR_INTEL: ret = vmx_vpmu_initialise(v); break; default: 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 -EINVAL; } vpmu->hw_lapic_lvtpc = PMU_APIC_VECTOR | APIC_LVT_MASKED; if ( ret ) printk(XENLOG_G_WARNING "VPMU: Initialization failed for %pv\n", v); return ret; }
void vpmu_initialise(struct vcpu *v) { struct vpmu_struct *vpmu = vcpu_vpmu(v); uint8_t vendor = current_cpu_data.x86_vendor; int ret; bool_t is_priv_vpmu = is_hardware_domain(v->domain); BUILD_BUG_ON(sizeof(struct xen_pmu_intel_ctxt) > XENPMU_CTXT_PAD_SZ); BUILD_BUG_ON(sizeof(struct xen_pmu_amd_ctxt) > XENPMU_CTXT_PAD_SZ); BUILD_BUG_ON(sizeof(struct xen_pmu_regs) > XENPMU_REGS_PAD_SZ); BUILD_BUG_ON(sizeof(struct compat_pmu_regs) > XENPMU_REGS_PAD_SZ); ASSERT(!vpmu->flags && !vpmu->context); if ( !is_priv_vpmu ) { /* * Count active VPMUs so that we won't try to change vpmu_mode while * they are in use. * vpmu_mode can be safely updated while dom0's VPMUs are active and * so we don't need to include it in the count. */ spin_lock(&vpmu_lock); vpmu_count++; spin_unlock(&vpmu_lock); } switch ( vendor ) { case X86_VENDOR_AMD: ret = svm_vpmu_initialise(v); break; case X86_VENDOR_INTEL: ret = vmx_vpmu_initialise(v); break; default: 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; /* Don't bother restoring vpmu_count, VPMU is off forever */ } 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 ( !is_priv_vpmu && (ret || (vpmu_mode == XENPMU_MODE_OFF) || (vpmu_mode == XENPMU_MODE_ALL)) ) { spin_lock(&vpmu_lock); vpmu_count--; spin_unlock(&vpmu_lock); } }