|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [PATCH v18 06/16] x86/VPMU: Initialize VPMUs with __initcall
Move some VPMU initilization operations into __initcalls to avoid performing
same tests and calculations for each vcpu.
Signed-off-by: Boris Ostrovsky <boris.ostrovsky@xxxxxxxxxx>
---
xen/arch/x86/hvm/svm/vpmu.c | 112 ++++++++++++----------------
xen/arch/x86/hvm/vmx/vpmu_core2.c | 151 +++++++++++++++++++-------------------
xen/arch/x86/hvm/vpmu.c | 32 ++++++++
xen/include/asm-x86/hvm/vpmu.h | 2 +
4 files changed, 157 insertions(+), 140 deletions(-)
diff --git a/xen/arch/x86/hvm/svm/vpmu.c b/xen/arch/x86/hvm/svm/vpmu.c
index 2cfdf08..03474a3 100644
--- a/xen/arch/x86/hvm/svm/vpmu.c
+++ b/xen/arch/x86/hvm/svm/vpmu.c
@@ -375,57 +375,6 @@ static int amd_vpmu_do_rdmsr(unsigned int msr, uint64_t
*msr_content)
return 1;
}
-static int amd_vpmu_initialise(struct vcpu *v)
-{
- struct xen_pmu_amd_ctxt *ctxt;
- struct vpmu_struct *vpmu = vcpu_vpmu(v);
- uint8_t family = current_cpu_data.x86;
-
- if ( vpmu_is_set(vpmu, VPMU_CONTEXT_ALLOCATED) )
- return 0;
-
- if ( counters == NULL )
- {
- switch ( family )
- {
- case 0x15:
- num_counters = F15H_NUM_COUNTERS;
- counters = AMD_F15H_COUNTERS;
- ctrls = AMD_F15H_CTRLS;
- k7_counters_mirrored = 1;
- break;
- case 0x10:
- case 0x12:
- case 0x14:
- case 0x16:
- default:
- num_counters = F10H_NUM_COUNTERS;
- counters = AMD_F10H_COUNTERS;
- ctrls = AMD_F10H_CTRLS;
- k7_counters_mirrored = 0;
- break;
- }
- }
-
- ctxt = xzalloc_bytes(sizeof(*ctxt) +
- 2 * sizeof(uint64_t) * num_counters);
- if ( !ctxt )
- {
- 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->counters = sizeof(*ctxt);
- ctxt->ctrls = ctxt->counters + sizeof(uint64_t) * num_counters;
-
- vpmu->context = ctxt;
- vpmu->priv_context = NULL;
- vpmu_set(vpmu, VPMU_CONTEXT_ALLOCATED);
- return 0;
-}
-
static void amd_vpmu_destroy(struct vcpu *v)
{
struct vpmu_struct *vpmu = vcpu_vpmu(v);
@@ -497,30 +446,63 @@ struct arch_vpmu_ops amd_vpmu_ops = {
int svm_vpmu_initialise(struct vcpu *v)
{
+ struct xen_pmu_amd_ctxt *ctxt;
struct vpmu_struct *vpmu = vcpu_vpmu(v);
- uint8_t family = current_cpu_data.x86;
- int ret = 0;
- /* vpmu enabled? */
- if ( vpmu_mode == XENPMU_MODE_OFF )
+ if ( (vpmu_mode == XENPMU_MODE_OFF) ||
+ vpmu_is_set(vpmu, VPMU_CONTEXT_ALLOCATED) )
return 0;
- switch ( family )
+ if ( !counters )
+ return -EINVAL;
+
+ ctxt = xzalloc_bytes(sizeof(*ctxt) +
+ 2 * sizeof(uint64_t) * num_counters);
+ if ( !ctxt )
+ {
+ printk(XENLOG_G_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->counters = sizeof(*ctxt);
+ ctxt->ctrls = ctxt->counters + sizeof(uint64_t) * num_counters;
+
+ vpmu->context = ctxt;
+ vpmu->priv_context = NULL;
+
+ vpmu->arch_vpmu_ops = &amd_vpmu_ops;
+
+ vpmu_set(vpmu, VPMU_CONTEXT_ALLOCATED);
+ return 0;
+}
+
+int __init amd_vpmu_init(void)
+{
+ switch ( current_cpu_data.x86 )
{
+ case 0x15:
+ num_counters = F15H_NUM_COUNTERS;
+ counters = AMD_F15H_COUNTERS;
+ ctrls = AMD_F15H_CTRLS;
+ k7_counters_mirrored = 1;
+ break;
case 0x10:
case 0x12:
case 0x14:
- case 0x15:
case 0x16:
- ret = amd_vpmu_initialise(v);
- if ( !ret )
- vpmu->arch_vpmu_ops = &amd_vpmu_ops;
- return ret;
+ num_counters = F10H_NUM_COUNTERS;
+ counters = AMD_F10H_COUNTERS;
+ ctrls = AMD_F10H_CTRLS;
+ k7_counters_mirrored = 0;
+ break;
+ default:
+ printk(XENLOG_WARNING "VPMU: Unsupported CPU family %#x\n",
+ current_cpu_data.x86);
+ return -EINVAL;
}
- printk("VPMU: Initialization failed. "
- "AMD processor family %d has not "
- "been supported\n", family);
- return -EINVAL;
+ return 0;
}
diff --git a/xen/arch/x86/hvm/vmx/vpmu_core2.c
b/xen/arch/x86/hvm/vmx/vpmu_core2.c
index 4d08d1b..6c78323 100644
--- a/xen/arch/x86/hvm/vmx/vpmu_core2.c
+++ b/xen/arch/x86/hvm/vmx/vpmu_core2.c
@@ -724,62 +724,6 @@ static int core2_vpmu_do_interrupt(struct cpu_user_regs
*regs)
return 1;
}
-static int core2_vpmu_initialise(struct vcpu *v)
-{
- struct vpmu_struct *vpmu = vcpu_vpmu(v);
- u64 msr_content;
- static bool_t ds_warned;
-
- if ( !(vpmu_features & XENPMU_FEATURE_INTEL_BTS) )
- goto func_out;
- /* Check the 'Debug Store' feature in the CPUID.EAX[1]:EDX[21] */
- while ( boot_cpu_has(X86_FEATURE_DS) )
- {
- if ( !boot_cpu_has(X86_FEATURE_DTES64) )
- {
- if ( !ds_warned )
- printk(XENLOG_G_WARNING "CPU doesn't support 64-bit DS Area"
- " - Debug Store disabled for guests\n");
- break;
- }
- vpmu_set(vpmu, VPMU_CPU_HAS_DS);
- rdmsrl(MSR_IA32_MISC_ENABLE, msr_content);
- if ( msr_content & MSR_IA32_MISC_ENABLE_BTS_UNAVAIL )
- {
- /* If BTS_UNAVAIL is set reset the DS feature. */
- vpmu_reset(vpmu, VPMU_CPU_HAS_DS);
- if ( !ds_warned )
- printk(XENLOG_G_WARNING "CPU has set BTS_UNAVAIL"
- " - Debug Store disabled for guests\n");
- break;
- }
-
- vpmu_set(vpmu, VPMU_CPU_HAS_BTS);
- if ( !ds_warned )
- {
- if ( !boot_cpu_has(X86_FEATURE_DSCPL) )
- printk(XENLOG_G_INFO
- "vpmu: CPU doesn't support CPL-Qualified BTS\n");
- printk("******************************************************\n");
- printk("** WARNING: Emulation of BTS Feature is switched on **\n");
- printk("** Using this processor feature in a virtualized **\n");
- printk("** environment is not 100%% safe.
**\n");
- printk("** Setting the DS buffer address with wrong values **\n");
- printk("** may lead to hypervisor hangs or crashes. **\n");
- printk("** It is NOT recommended for production use! **\n");
- printk("******************************************************\n");
- }
- break;
- }
- ds_warned = 1;
- func_out:
-
- arch_pmc_cnt = core2_get_arch_pmc_count();
- fixed_pmc_cnt = core2_get_fixed_pmc_count();
- check_pmc_quirk();
- return 0;
-}
-
static void core2_vpmu_destroy(struct vcpu *v)
{
struct vpmu_struct *vpmu = vcpu_vpmu(v);
@@ -846,23 +790,77 @@ struct arch_vpmu_ops core2_no_vpmu_ops = {
int vmx_vpmu_initialise(struct vcpu *v)
{
struct vpmu_struct *vpmu = vcpu_vpmu(v);
- uint8_t family = current_cpu_data.x86;
- uint8_t cpu_model = current_cpu_data.x86_model;
- int ret = 0;
+ u64 msr_content;
+ static bool_t ds_warned;
vpmu->arch_vpmu_ops = &core2_no_vpmu_ops;
if ( vpmu_mode == XENPMU_MODE_OFF )
return 0;
- if ( family == 6 )
- {
- u64 caps;
+ if ( (arch_pmc_cnt + fixed_pmc_cnt) == 0 )
+ return -EINVAL;
- rdmsrl(MSR_IA32_PERF_CAPABILITIES, caps);
- full_width_write = (caps >> 13) & 1;
+ if ( !(vpmu_features & XENPMU_FEATURE_INTEL_BTS) )
+ goto func_out;
+ /* Check the 'Debug Store' feature in the CPUID.EAX[1]:EDX[21] */
+ while ( boot_cpu_has(X86_FEATURE_DS) )
+ {
+ if ( !boot_cpu_has(X86_FEATURE_DTES64) )
+ {
+ if ( !ds_warned )
+ printk(XENLOG_G_WARNING "CPU doesn't support 64-bit DS Area"
+ " - Debug Store disabled for guests\n");
+ break;
+ }
+ vpmu_set(vpmu, VPMU_CPU_HAS_DS);
+ rdmsrl(MSR_IA32_MISC_ENABLE, msr_content);
+ if ( msr_content & MSR_IA32_MISC_ENABLE_BTS_UNAVAIL )
+ {
+ /* If BTS_UNAVAIL is set reset the DS feature. */
+ vpmu_reset(vpmu, VPMU_CPU_HAS_DS);
+ if ( !ds_warned )
+ printk(XENLOG_G_WARNING "CPU has set BTS_UNAVAIL"
+ " - Debug Store disabled for guests\n");
+ break;
+ }
- switch ( cpu_model )
+ vpmu_set(vpmu, VPMU_CPU_HAS_BTS);
+ if ( !ds_warned )
{
+ if ( !boot_cpu_has(X86_FEATURE_DSCPL) )
+ printk(XENLOG_G_INFO
+ "vpmu: CPU doesn't support CPL-Qualified BTS\n");
+ printk("******************************************************\n");
+ printk("** WARNING: Emulation of BTS Feature is switched on **\n");
+ printk("** Using this processor feature in a virtualized **\n");
+ printk("** environment is not 100%% safe.
**\n");
+ printk("** Setting the DS buffer address with wrong values **\n");
+ printk("** may lead to hypervisor hangs or crashes. **\n");
+ printk("** It is NOT recommended for production use! **\n");
+ printk("******************************************************\n");
+ }
+ break;
+ }
+ ds_warned = 1;
+ func_out:
+
+ vpmu->arch_vpmu_ops = &core2_vpmu_ops;
+
+ return 0;
+}
+
+int __init core2_vpmu_init(void)
+{
+ u64 caps;
+
+ if ( current_cpu_data.x86 != 6 )
+ {
+ printk(XENLOG_WARNING "VPMU: only family 6 is supported\n");
+ return -EINVAL;
+ }
+
+ switch ( current_cpu_data.x86_model )
+ {
/* Core2: */
case 0x0f: /* original 65 nm celeron/pentium/core2/xeon,
"Merom"/"Conroe" */
case 0x16: /* single-core 65 nm celeron/core2solo "Merom-L"/"Conroe-L"
*/
@@ -894,16 +892,19 @@ int vmx_vpmu_initialise(struct vcpu *v)
/* future: */
case 0x3d:
case 0x4e:
- ret = core2_vpmu_initialise(v);
- if ( !ret )
- vpmu->arch_vpmu_ops = &core2_vpmu_ops;
- return ret;
- }
+ break;
+ default:
+ printk(XENLOG_WARNING "VPMU: Unsupported CPU model %#x\n",
+ current_cpu_data.x86_model);
+ return -EINVAL;
}
- printk("VPMU: Initialization failed. "
- "Intel processor family %d model %d has not "
- "been supported\n", family, cpu_model);
- return -EINVAL;
-}
+ arch_pmc_cnt = core2_get_arch_pmc_count();
+ fixed_pmc_cnt = core2_get_fixed_pmc_count();
+ rdmsrl(MSR_IA32_PERF_CAPABILITIES, caps);
+ full_width_write = (caps >> 13) & 1;
+ check_pmc_quirk();
+
+ return 0;
+}
diff --git a/xen/arch/x86/hvm/vpmu.c b/xen/arch/x86/hvm/vpmu.c
index 40a89d9..f62fa80 100644
--- a/xen/arch/x86/hvm/vpmu.c
+++ b/xen/arch/x86/hvm/vpmu.c
@@ -528,14 +528,46 @@ long do_xenpmu_op(unsigned int op,
XEN_GUEST_HANDLE_PARAM(xen_pmu_params_t) arg)
static int __init vpmu_init(void)
{
+ int vendor = current_cpu_data.x86_vendor;
+
+ if ( vpmu_disabled )
+ {
+ printk(XENLOG_INFO "VPMU: disabled\n");
+ return 0;
+ }
+
/* NMI watchdog uses LVTPC and HW counter */
if ( opt_watchdog && !vpmu_disabled )
{
printk(XENLOG_WARNING "NMI watchdog is enabled. Turning VPMU off.\n");
vpmu_mode = XENPMU_MODE_OFF;
vpmu_disabled = 1;
+ return 0;
+ }
+
+ switch ( vendor )
+ {
+ case X86_VENDOR_AMD:
+ if ( amd_vpmu_init() )
+ vpmu_mode = XENPMU_MODE_OFF;
+ break;
+ case X86_VENDOR_INTEL:
+ if ( core2_vpmu_init() )
+ vpmu_mode = XENPMU_MODE_OFF;
+ break;
+ default:
+ printk(XENLOG_WARNING "VPMU: Unknown CPU vendor: %d. "
+ "Turning VPMU off.\n", vendor);
+ vpmu_mode = XENPMU_MODE_OFF;
+ break;
}
+ if ( vpmu_mode != XENPMU_MODE_OFF )
+ printk(XENLOG_INFO "VPMU: version " __stringify(XENPMU_VER_MAJ) "."
+ __stringify(XENPMU_VER_MIN) "\n");
+ else
+ vpmu_disabled = 1;
+
return 0;
}
__initcall(vpmu_init);
diff --git a/xen/include/asm-x86/hvm/vpmu.h b/xen/include/asm-x86/hvm/vpmu.h
index 1171b2a..cf32f82 100644
--- a/xen/include/asm-x86/hvm/vpmu.h
+++ b/xen/include/asm-x86/hvm/vpmu.h
@@ -62,7 +62,9 @@ struct arch_vpmu_ops {
void (*arch_vpmu_dump)(const struct vcpu *);
};
+int core2_vpmu_init(void);
int vmx_vpmu_initialise(struct vcpu *);
+int amd_vpmu_init(void);
int svm_vpmu_initialise(struct vcpu *);
/* VPMU states */
--
1.8.1.4
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
http://lists.xen.org/xen-devel
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |