@@ -1476,7 +1476,7 @@ Use Virtual Processor ID support if available. This prevents the need for TLB
flushes on VM entry and exit, increasing performance.
### vpmu
-> `= ( bts )`
+> `= ( <boolean> | { bts | ipc | arch [, ...] } )`
> Default: `off`
@@ -1492,6 +1492,19 @@ wrong behaviour (see handle\_pmc\_quirk()).
If 'vpmu=bts' is specified the virtualisation of the Branch Trace Store (BTS)
feature is switched on on Intel processors supporting this feature.
+vpmu=ipc enables performance monitoring, but restricts the counters to the
+most minimum set possible: instructions, cycles, and reference cycles. These
+can be used to calculate instructions per cycle (IPC).
+
+vpmu=arch enables performance monitoring, but restricts the counters to the
+pre-defined architectural events only. These are exposed by cpuid, and listed
+in the Pre-Defined Architectural Performance Events table from the Intel 64
+and IA-32 Architectures Software Developer's Manual, Volume 3B, System
+Programming Guide, Part 2.
+
+If a boolean is not used, combinations of flags are allowed, comma separated.
+For example, vpmu=arch,bts.
+
Note that if **watchdog** option is also specified vpmu will be turned off.
*Warning:*
@@ -43,34 +43,59 @@ CHECK_pmu_data;
CHECK_pmu_params;
/*
- * "vpmu" : vpmu generally enabled
- * "vpmu=off" : vpmu generally disabled
- * "vpmu=bts" : vpmu enabled and Intel BTS feature switched on.
+ * "vpmu" : vpmu generally enabled (all counters)
+ * "vpmu=off" : vpmu generally disabled
+ * "vpmu=bts" : vpmu enabled and Intel BTS feature switched on.
+ * "vpmu=ipc" : vpmu enabled for IPC counters only (most restrictive)
+ * "vpmu=arch" : vpmu enabled for predef arch counters only (restrictive)
+ * flag combinations are allowed, eg, "vpmu=ipc,bts".
*/
static unsigned int __read_mostly opt_vpmu_enabled;
unsigned int __read_mostly vpmu_mode = XENPMU_MODE_OFF;
unsigned int __read_mostly vpmu_features = 0;
-static void parse_vpmu_param(char *s);
-custom_param("vpmu", parse_vpmu_param);
+static void parse_vpmu_params(char *s);
+custom_param("vpmu", parse_vpmu_params);
static DEFINE_SPINLOCK(vpmu_lock);
static unsigned vpmu_count;
static DEFINE_PER_CPU(struct vcpu *, last_vcpu);
-static void __init parse_vpmu_param(char *s)
+static int parse_vpmu_param(char *s, unsigned int len)
{
+ if ( !*s || !len )
+ return 0;
+ if ( !strncmp(s, "bts", len) )
+ vpmu_features |= XENPMU_FEATURE_INTEL_BTS;
+ else if ( !strncmp(s, "ipc", len) )
+ vpmu_features |= XENPMU_FEATURE_IPC_ONLY;
+ else if ( !strncmp(s, "arch", len) )
+ vpmu_features |= XENPMU_FEATURE_ARCH_ONLY;
+ else
+ return 1;
+ return 0;
+}
+
+static void __init parse_vpmu_params(char *s)
+{
+ char *sep, *p = s;
+
switch ( parse_bool(s) )
{
case 0:
break;
default:
- if ( !strcmp(s, "bts") )
- vpmu_features |= XENPMU_FEATURE_INTEL_BTS;
- else if ( *s )
+ while (1)
{
- printk("VPMU: unknown flag: %s - vpmu disabled!\n", s);
- break;
+ sep = strchr(p, ',');
+ if ( sep == NULL )
+ sep = strchr(p, 0);
+ if ( parse_vpmu_param(p, sep - p) )
+ goto error;
+ if ( !*sep )
+ /* reached end of flags */
+ break;
+ p = sep + 1;
}
/* fall through */
case 1:
@@ -79,6 +104,10 @@ static void __init parse_vpmu_param(char *s)
opt_vpmu_enabled = 1;
break;
}
+ return;
+
+ error:
+ printk("VPMU: unknown flags: %s - vpmu disabled!\n", s);
}
void vpmu_lvtpc_update(uint32_t val)
@@ -708,7 +737,9 @@ long do_xenpmu_op(unsigned int op, XEN_GUEST_HANDLE_PARAM(xen_pmu_params_t) arg)
break;
case XENPMU_feature_set:
- if ( pmu_params.val & ~XENPMU_FEATURE_INTEL_BTS )
+ if ( pmu_params.val & ~(XENPMU_FEATURE_INTEL_BTS |
+ XENPMU_FEATURE_IPC_ONLY |
+ XENPMU_FEATURE_ARCH_ONLY))
return -EINVAL;
spin_lock(&vpmu_lock);
@@ -604,12 +604,17 @@ static int core2_vpmu_do_wrmsr(unsigned int msr, uint64_t msr_content,
"MSR_PERF_GLOBAL_STATUS(0x38E)!\n");
return -EINVAL;
case MSR_IA32_PEBS_ENABLE:
+ if ( vpmu_features & (XENPMU_FEATURE_IPC_ONLY |
+ XENPMU_FEATURE_ARCH_ONLY) )
+ return -EINVAL;
if ( msr_content & 1 )
gdprintk(XENLOG_WARNING, "Guest is trying to enable PEBS, "
"which is not supported.\n");
core2_vpmu_cxt->pebs_enable = msr_content;
return 0;
case MSR_IA32_DS_AREA:
+ if ( !(vpmu_features & XENPMU_FEATURE_INTEL_BTS) )
+ return -EINVAL;
if ( vpmu_is_set(vpmu, VPMU_CPU_HAS_DS) )
{
if ( !(has_hvm_container_vcpu(v)
@@ -656,12 +661,51 @@ static int core2_vpmu_do_wrmsr(unsigned int msr, uint64_t msr_content,
tmp = msr - MSR_P6_EVNTSEL(0);
if ( tmp >= 0 && tmp < arch_pmc_cnt )
{
+ bool_t blocked = 0;
+ uint64_t umaskevent;
struct xen_pmu_cntr_pair *xen_pmu_cntr_pair =
vpmu_reg_pointer(core2_vpmu_cxt, arch_counters);
if ( msr_content & ARCH_CTRL_MASK )
return -EINVAL;
+ /* PMC filters */
+ umaskevent = msr_content & MSR_IA32_CMT_EVTSEL_UE_MASK;
+ if ( vpmu_features & (XENPMU_FEATURE_IPC_ONLY |
+ XENPMU_FEATURE_ARCH_ONLY) )
+ {
+ blocked = 1;
+ switch ( umaskevent )
+ {
+ /*
+ * See the Pre-Defined Architectural Performance Events table
+ * from the Intel 64 and IA-32 Architectures Software
+ * Developer's Manual, Volume 3B, System Programming Guide,
+ * Part 2.
+ */
+ case 0x003c: /* UnHalted Core Cycles */
+ case 0x013c: /* UnHalted Reference Cycles */
+ case 0x00c0: /* Instructions Retired */
+ blocked = 0;
+ }
+ }
+
+ if ( vpmu_features & XENPMU_FEATURE_ARCH_ONLY )
+ {
+ /* Additional counters beyond IPC only; blocked already set. */
+ switch ( umaskevent )
+ {
+ case 0x4f2e: /* Last Level Cache References */
+ case 0x412e: /* Last Level Cache Misses */
+ case 0x00c4: /* Branch Instructions Retired */
+ case 0x00c5: /* All Branch Mispredict Retired */
+ blocked = 0;
+ }
+ }
+
+ if ( blocked )
+ return -EINVAL;
+
if ( has_hvm_container_vcpu(v) )
vmx_read_guest_msr(MSR_CORE_PERF_GLOBAL_CTRL,
&core2_vpmu_cxt->global_ctrl);
@@ -329,6 +329,7 @@
/* Platform Shared Resource MSRs */
#define MSR_IA32_CMT_EVTSEL 0x00000c8d
+#define MSR_IA32_CMT_EVTSEL_UE_MASK 0x0000ffff
#define MSR_IA32_CMT_CTR 0x00000c8e
#define MSR_IA32_PSR_ASSOC 0x00000c8f
#define MSR_IA32_PSR_L3_QOS_CFG 0x00000c81
@@ -84,9 +84,19 @@ DEFINE_XEN_GUEST_HANDLE(xen_pmu_params_t);
/*
* PMU features:
- * - XENPMU_FEATURE_INTEL_BTS: Intel BTS support (ignored on AMD)
+ * - XENPMU_FEATURE_INTEL_BTS: Intel BTS support (ignored on AMD)
+ * - XENPMU_FEATURE_IPC_ONLY: Restrict PMCs to the most minimum set possible.
+ * Instructions, cycles, and ref cycles. Can be
+ * used to calculate instructions-per-cycle (IPC)
+ * (ignored on AMD).
+ * - XENPMU_FEATURE_ARCH_ONLY: Restrict PMCs to the Intel Pre-Defined
+ * Architectural Performance Events exposed by
+ * cpuid and listed in the Intel developer's manual
+ * (ignored on AMD).
*/
-#define XENPMU_FEATURE_INTEL_BTS 1
+#define XENPMU_FEATURE_INTEL_BTS (1<<0)
+#define XENPMU_FEATURE_IPC_ONLY (1<<1)
+#define XENPMU_FEATURE_ARCH_ONLY (1<<2)
/*
* Shared PMU data between hypervisor and PV(H) domains.