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)
{
}
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;
/*
* 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;
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;
}