diff options
author | Paul Mackerras <paulus@samba.org> | 2009-06-11 00:55:42 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2009-06-11 10:48:37 -0400 |
commit | 106b506c3a8b74daa5751e83ed3e46438fcf9a52 (patch) | |
tree | ad141aa86b020501823c7e2c7ac0abb9f27cf5a1 /arch/powerpc/kernel/perf_counter.c | |
parent | 4da52960fd1ae3ddd14901bc88b608cbeaa4b9a6 (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.c | 42 |
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 | */ | ||
862 | static 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 | |||
859 | const struct pmu *hw_perf_counter_init(struct perf_counter *counter) | 889 | const 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; |