aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaul Mackerras <paulus@samba.org>2009-02-23 07:01:28 -0500
committerPaul Mackerras <paulus@samba.org>2009-02-23 07:01:28 -0500
commitd095cd46dac104e4d2a4967c7c19b55a12f78240 (patch)
tree032528a3e23b2fe1b8998e7064101394108ce870
parentcebb469ba242f7ce476e378c8cd3b0c6c63a4c54 (diff)
perfcounters/powerpc: Make exclude_kernel bit work on Apple G5 processors
Currently, setting hw_event.exclude_kernel does nothing on the PPC970 variants used in Apple G5 machines, because they have the HV (hypervisor) bit in the MSR forced to 1, so as far as the PMU is concerned, the kernel runs in hypervisor mode. Thus we have to use the MMCR0_FCHV (freeze counters in hypervisor mode) bit rather than the MMCR0_FCS (freeze counters in supervisor mode) bit. This checks the MSR.HV bit at startup, and if it is set, we set the freeze_counters_kernel variable to MMCR0_FCHV (it was initialized to MMCR0_FCS). We then use that whenever we need to exclude kernel events. Signed-off-by: Paul Mackerras <paulus@samba.org>
-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);
32 32
33struct power_pmu *ppmu; 33struct power_pmu *ppmu;
34 34
35/*
36 * Normally, to ignore kernel events we set the FCS (freeze counters
37 * in supervisor mode) bit in MMCR0, but if the kernel runs with the
38 * hypervisor bit set in the MSR, or if we are running on a processor
39 * where the hypervisor bit is forced to 1 (as on Apple G5 processors),
40 * then we need to use the FCHV bit to ignore kernel events.
41 */
42static unsigned int freeze_counters_kernel = MMCR0_FCS;
43
35void perf_counter_print_debug(void) 44void perf_counter_print_debug(void)
36{ 45{
37} 46}
@@ -364,7 +373,7 @@ void hw_perf_restore(u64 disable)
364 if (counter->hw_event.exclude_user) 373 if (counter->hw_event.exclude_user)
365 cpuhw->mmcr[0] |= MMCR0_FCP; 374 cpuhw->mmcr[0] |= MMCR0_FCP;
366 if (counter->hw_event.exclude_kernel) 375 if (counter->hw_event.exclude_kernel)
367 cpuhw->mmcr[0] |= MMCR0_FCS; 376 cpuhw->mmcr[0] |= freeze_counters_kernel;
368 if (counter->hw_event.exclude_hv) 377 if (counter->hw_event.exclude_hv)
369 cpuhw->mmcr[0] |= MMCR0_FCHV; 378 cpuhw->mmcr[0] |= MMCR0_FCHV;
370 379
@@ -606,10 +615,7 @@ hw_perf_counter_init(struct perf_counter *counter)
606 /* 615 /*
607 * If we are not running on a hypervisor, force the 616 * If we are not running on a hypervisor, force the
608 * exclude_hv bit to 0 so that we don't care what 617 * exclude_hv bit to 0 so that we don't care what
609 * the user set it to. This also means that we don't 618 * the user set it to.
610 * set the MMCR0_FCHV bit, which unconditionally freezes
611 * the counters on the PPC970 variants used in Apple G5
612 * machines (since MSR.HV is always 1 on those machines).
613 */ 619 */
614 if (!firmware_has_feature(FW_FEATURE_LPAR)) 620 if (!firmware_has_feature(FW_FEATURE_LPAR))
615 counter->hw_event.exclude_hv = 0; 621 counter->hw_event.exclude_hv = 0;
@@ -841,6 +847,13 @@ static int init_perf_counters(void)
841 ppmu = &power6_pmu; 847 ppmu = &power6_pmu;
842 break; 848 break;
843 } 849 }
850
851 /*
852 * Use FCHV to ignore kernel events if MSR.HV is set.
853 */
854 if (mfmsr() & MSR_HV)
855 freeze_counters_kernel = MMCR0_FCHV;
856
844 return 0; 857 return 0;
845} 858}
846 859