aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/kernel/perf_counter.c
diff options
context:
space:
mode:
authorPaul Mackerras <paulus@samba.org>2009-06-11 00:55:42 -0400
committerIngo Molnar <mingo@elte.hu>2009-06-11 10:48:37 -0400
commit106b506c3a8b74daa5751e83ed3e46438fcf9a52 (patch)
treead141aa86b020501823c7e2c7ac0abb9f27cf5a1 /arch/powerpc/kernel/perf_counter.c
parent4da52960fd1ae3ddd14901bc88b608cbeaa4b9a6 (diff)
perf_counter: powerpc: Implement generalized cache events for POWER processors
This adds tables of event codes for the generalized cache events for all the currently supported powerpc processors: POWER{4,5,5+,6,7} and PPC970*, plus powerpc-specific code to use these tables when a generalized cache event is requested. Signed-off-by: Paul Mackerras <paulus@samba.org> Cc: Peter Zijlstra <a.p.zijlstra@chello.nl> LKML-Reference: <18992.36430.933526.742969@drongo.ozlabs.ibm.com> Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'arch/powerpc/kernel/perf_counter.c')
-rw-r--r--arch/powerpc/kernel/perf_counter.c42
1 files changed, 40 insertions, 2 deletions
diff --git a/arch/powerpc/kernel/perf_counter.c b/arch/powerpc/kernel/perf_counter.c
index 5d12e68aac1c..bb202388170e 100644
--- a/arch/powerpc/kernel/perf_counter.c
+++ b/arch/powerpc/kernel/perf_counter.c
@@ -856,6 +856,36 @@ static void hw_perf_counter_destroy(struct perf_counter *counter)
856 } 856 }
857} 857}
858 858
859/*
860 * Translate a generic cache event config to a raw event code.
861 */
862static int hw_perf_cache_event(u64 config, u64 *eventp)
863{
864 unsigned long type, op, result;
865 int ev;
866
867 if (!ppmu->cache_events)
868 return -EINVAL;
869
870 /* unpack config */
871 type = config & 0xff;
872 op = (config >> 8) & 0xff;
873 result = (config >> 16) & 0xff;
874
875 if (type >= PERF_COUNT_HW_CACHE_MAX ||
876 op >= PERF_COUNT_HW_CACHE_OP_MAX ||
877 result >= PERF_COUNT_HW_CACHE_RESULT_MAX)
878 return -EINVAL;
879
880 ev = (*ppmu->cache_events)[type][op][result];
881 if (ev == 0)
882 return -EOPNOTSUPP;
883 if (ev == -1)
884 return -EINVAL;
885 *eventp = ev;
886 return 0;
887}
888
859const struct pmu *hw_perf_counter_init(struct perf_counter *counter) 889const struct pmu *hw_perf_counter_init(struct perf_counter *counter)
860{ 890{
861 u64 ev; 891 u64 ev;
@@ -868,13 +898,21 @@ const struct pmu *hw_perf_counter_init(struct perf_counter *counter)
868 898
869 if (!ppmu) 899 if (!ppmu)
870 return ERR_PTR(-ENXIO); 900 return ERR_PTR(-ENXIO);
871 if (counter->attr.type != PERF_TYPE_RAW) { 901 switch (counter->attr.type) {
902 case PERF_TYPE_HARDWARE:
872 ev = counter->attr.config; 903 ev = counter->attr.config;
873 if (ev >= ppmu->n_generic || ppmu->generic_events[ev] == 0) 904 if (ev >= ppmu->n_generic || ppmu->generic_events[ev] == 0)
874 return ERR_PTR(-EOPNOTSUPP); 905 return ERR_PTR(-EOPNOTSUPP);
875 ev = ppmu->generic_events[ev]; 906 ev = ppmu->generic_events[ev];
876 } else { 907 break;
908 case PERF_TYPE_HW_CACHE:
909 err = hw_perf_cache_event(counter->attr.config, &ev);
910 if (err)
911 return ERR_PTR(err);
912 break;
913 case PERF_TYPE_RAW:
877 ev = counter->attr.config; 914 ev = counter->attr.config;
915 break;
878 } 916 }
879 counter->hw.config_base = ev; 917 counter->hw.config_base = ev;
880 counter->hw.idx = 0; 918 counter->hw.idx = 0;