summaryrefslogtreecommitdiffstats
path: root/arch/powerpc/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc/kernel')
-rw-r--r--arch/powerpc/kernel/perf_counter.c23
1 files changed, 18 insertions, 5 deletions
diff --git a/arch/powerpc/kernel/perf_counter.c b/arch/powerpc/kernel/perf_counter.c
index bd6ba85beb54..6e27913ec0d8 100644
--- a/arch/powerpc/kernel/perf_counter.c
+++ b/arch/powerpc/kernel/perf_counter.c
@@ -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;
}
OpenPOWER on IntegriCloud