|
@@ -32,6 +32,15 @@ DEFINE_PER_CPU(struct cpu_hw_counters, cpu_hw_counters);
|
|
|
|
|
|
struct power_pmu *ppmu;
|
|
|
|
|
|
+/*
|
|
|
+ * Normally, to ignore kernel events we set the FCS (freeze counters
|
|
|
+ * in supervisor mode) bit in MMCR0, but if the kernel runs with the
|
|
|
+ * hypervisor bit set in the MSR, or if we are running on a processor
|
|
|
+ * where the hypervisor bit is forced to 1 (as on Apple G5 processors),
|
|
|
+ * then we need to use the FCHV bit to ignore kernel events.
|
|
|
+ */
|
|
|
+static unsigned int freeze_counters_kernel = MMCR0_FCS;
|
|
|
+
|
|
|
void perf_counter_print_debug(void)
|
|
|
{
|
|
|
}
|
|
@@ -364,7 +373,7 @@ void hw_perf_restore(u64 disable)
|
|
|
if (counter->hw_event.exclude_user)
|
|
|
cpuhw->mmcr[0] |= MMCR0_FCP;
|
|
|
if (counter->hw_event.exclude_kernel)
|
|
|
- cpuhw->mmcr[0] |= MMCR0_FCS;
|
|
|
+ cpuhw->mmcr[0] |= freeze_counters_kernel;
|
|
|
if (counter->hw_event.exclude_hv)
|
|
|
cpuhw->mmcr[0] |= MMCR0_FCHV;
|
|
|
|
|
@@ -606,10 +615,7 @@ hw_perf_counter_init(struct perf_counter *counter)
|
|
|
/*
|
|
|
* If we are not running on a hypervisor, force the
|
|
|
* exclude_hv bit to 0 so that we don't care what
|
|
|
- * the user set it to. This also means that we don't
|
|
|
- * set the MMCR0_FCHV bit, which unconditionally freezes
|
|
|
- * the counters on the PPC970 variants used in Apple G5
|
|
|
- * machines (since MSR.HV is always 1 on those machines).
|
|
|
+ * the user set it to.
|
|
|
*/
|
|
|
if (!firmware_has_feature(FW_FEATURE_LPAR))
|
|
|
counter->hw_event.exclude_hv = 0;
|
|
@@ -841,6 +847,13 @@ static int init_perf_counters(void)
|
|
|
ppmu = &power6_pmu;
|
|
|
break;
|
|
|
}
|
|
|
+
|
|
|
+ /*
|
|
|
+ * Use FCHV to ignore kernel events if MSR.HV is set.
|
|
|
+ */
|
|
|
+ if (mfmsr() & MSR_HV)
|
|
|
+ freeze_counters_kernel = MMCR0_FCHV;
|
|
|
+
|
|
|
return 0;
|
|
|
}
|
|
|
|