aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWill Deacon <will.deacon@arm.com>2010-11-13 12:13:56 -0500
committerWill Deacon <will.deacon@arm.com>2010-11-25 11:52:07 -0500
commit84fee97a026ca085f08381054513f9e24689a303 (patch)
treea9cb1205453b4e78741bd26db82e7e7254ebd6c3
parent3561d43fd289f590fdae672e5eb831b8d5cf0bf6 (diff)
ARM: perf: consolidate common PMU behaviour
The functions for mapping PMU events (perf, cache and raw) are common between all PMU types and differ only in the data on which they operate. This patch implements common definitions of these mapping functions and changes the arm_pmu struct to hold pointers to the data which they require. This is in anticipation of separating out the PMU-specific code into separate files. Acked-by: Jamie Iles <jamie.iles@jamieiles.com> Acked-by: Jean Pihet <j-pihet@ti.com> Signed-off-by: Will Deacon <will.deacon@arm.com>
-rw-r--r--arch/arm/kernel/perf_event.c131
1 files changed, 38 insertions, 93 deletions
diff --git a/arch/arm/kernel/perf_event.c b/arch/arm/kernel/perf_event.c
index 07a50357492a..c49e1701a2f6 100644
--- a/arch/arm/kernel/perf_event.c
+++ b/arch/arm/kernel/perf_event.c
@@ -84,14 +84,17 @@ struct arm_pmu {
84 irqreturn_t (*handle_irq)(int irq_num, void *dev); 84 irqreturn_t (*handle_irq)(int irq_num, void *dev);
85 void (*enable)(struct hw_perf_event *evt, int idx); 85 void (*enable)(struct hw_perf_event *evt, int idx);
86 void (*disable)(struct hw_perf_event *evt, int idx); 86 void (*disable)(struct hw_perf_event *evt, int idx);
87 int (*event_map)(int evt);
88 u64 (*raw_event)(u64);
89 int (*get_event_idx)(struct cpu_hw_events *cpuc, 87 int (*get_event_idx)(struct cpu_hw_events *cpuc,
90 struct hw_perf_event *hwc); 88 struct hw_perf_event *hwc);
91 u32 (*read_counter)(int idx); 89 u32 (*read_counter)(int idx);
92 void (*write_counter)(int idx, u32 val); 90 void (*write_counter)(int idx, u32 val);
93 void (*start)(void); 91 void (*start)(void);
94 void (*stop)(void); 92 void (*stop)(void);
93 const unsigned (*cache_map)[PERF_COUNT_HW_CACHE_MAX]
94 [PERF_COUNT_HW_CACHE_OP_MAX]
95 [PERF_COUNT_HW_CACHE_RESULT_MAX];
96 const unsigned (*event_map)[PERF_COUNT_HW_MAX];
97 u32 raw_event_mask;
95 int num_events; 98 int num_events;
96 u64 max_period; 99 u64 max_period;
97}; 100};
@@ -136,10 +139,6 @@ EXPORT_SYMBOL_GPL(perf_num_counters);
136 139
137#define CACHE_OP_UNSUPPORTED 0xFFFF 140#define CACHE_OP_UNSUPPORTED 0xFFFF
138 141
139static unsigned armpmu_perf_cache_map[PERF_COUNT_HW_CACHE_MAX]
140 [PERF_COUNT_HW_CACHE_OP_MAX]
141 [PERF_COUNT_HW_CACHE_RESULT_MAX];
142
143static int 142static int
144armpmu_map_cache_event(u64 config) 143armpmu_map_cache_event(u64 config)
145{ 144{
@@ -157,7 +156,7 @@ armpmu_map_cache_event(u64 config)
157 if (cache_result >= PERF_COUNT_HW_CACHE_RESULT_MAX) 156 if (cache_result >= PERF_COUNT_HW_CACHE_RESULT_MAX)
158 return -EINVAL; 157 return -EINVAL;
159 158
160 ret = (int)armpmu_perf_cache_map[cache_type][cache_op][cache_result]; 159 ret = (int)(*armpmu->cache_map)[cache_type][cache_op][cache_result];
161 160
162 if (ret == CACHE_OP_UNSUPPORTED) 161 if (ret == CACHE_OP_UNSUPPORTED)
163 return -ENOENT; 162 return -ENOENT;
@@ -166,6 +165,19 @@ armpmu_map_cache_event(u64 config)
166} 165}
167 166
168static int 167static int
168armpmu_map_event(u64 config)
169{
170 int mapping = (*armpmu->event_map)[config];
171 return mapping == HW_OP_UNSUPPORTED ? -EOPNOTSUPP : mapping;
172}
173
174static int
175armpmu_map_raw_event(u64 config)
176{
177 return (int)(config & armpmu->raw_event_mask);
178}
179
180static int
169armpmu_event_set_period(struct perf_event *event, 181armpmu_event_set_period(struct perf_event *event,
170 struct hw_perf_event *hwc, 182 struct hw_perf_event *hwc,
171 int idx) 183 int idx)
@@ -458,11 +470,11 @@ __hw_perf_event_init(struct perf_event *event)
458 470
459 /* Decode the generic type into an ARM event identifier. */ 471 /* Decode the generic type into an ARM event identifier. */
460 if (PERF_TYPE_HARDWARE == event->attr.type) { 472 if (PERF_TYPE_HARDWARE == event->attr.type) {
461 mapping = armpmu->event_map(event->attr.config); 473 mapping = armpmu_map_event(event->attr.config);
462 } else if (PERF_TYPE_HW_CACHE == event->attr.type) { 474 } else if (PERF_TYPE_HW_CACHE == event->attr.type) {
463 mapping = armpmu_map_cache_event(event->attr.config); 475 mapping = armpmu_map_cache_event(event->attr.config);
464 } else if (PERF_TYPE_RAW == event->attr.type) { 476 } else if (PERF_TYPE_RAW == event->attr.type) {
465 mapping = armpmu->raw_event(event->attr.config); 477 mapping = armpmu_map_raw_event(event->attr.config);
466 } else { 478 } else {
467 pr_debug("event type %x not supported\n", event->attr.type); 479 pr_debug("event type %x not supported\n", event->attr.type);
468 return -EOPNOTSUPP; 480 return -EOPNOTSUPP;
@@ -1121,30 +1133,6 @@ armv6pmu_stop(void)
1121 spin_unlock_irqrestore(&pmu_lock, flags); 1133 spin_unlock_irqrestore(&pmu_lock, flags);
1122} 1134}
1123 1135
1124static inline int
1125armv6pmu_event_map(int config)
1126{
1127 int mapping = armv6_perf_map[config];
1128 if (HW_OP_UNSUPPORTED == mapping)
1129 mapping = -EOPNOTSUPP;
1130 return mapping;
1131}
1132
1133static inline int
1134armv6mpcore_pmu_event_map(int config)
1135{
1136 int mapping = armv6mpcore_perf_map[config];
1137 if (HW_OP_UNSUPPORTED == mapping)
1138 mapping = -EOPNOTSUPP;
1139 return mapping;
1140}
1141
1142static u64
1143armv6pmu_raw_event(u64 config)
1144{
1145 return config & 0xff;
1146}
1147
1148static int 1136static int
1149armv6pmu_get_event_idx(struct cpu_hw_events *cpuc, 1137armv6pmu_get_event_idx(struct cpu_hw_events *cpuc,
1150 struct hw_perf_event *event) 1138 struct hw_perf_event *event)
@@ -1240,13 +1228,14 @@ static const struct arm_pmu armv6pmu = {
1240 .handle_irq = armv6pmu_handle_irq, 1228 .handle_irq = armv6pmu_handle_irq,
1241 .enable = armv6pmu_enable_event, 1229 .enable = armv6pmu_enable_event,
1242 .disable = armv6pmu_disable_event, 1230 .disable = armv6pmu_disable_event,
1243 .event_map = armv6pmu_event_map,
1244 .raw_event = armv6pmu_raw_event,
1245 .read_counter = armv6pmu_read_counter, 1231 .read_counter = armv6pmu_read_counter,
1246 .write_counter = armv6pmu_write_counter, 1232 .write_counter = armv6pmu_write_counter,
1247 .get_event_idx = armv6pmu_get_event_idx, 1233 .get_event_idx = armv6pmu_get_event_idx,
1248 .start = armv6pmu_start, 1234 .start = armv6pmu_start,
1249 .stop = armv6pmu_stop, 1235 .stop = armv6pmu_stop,
1236 .cache_map = &armv6_perf_cache_map,
1237 .event_map = &armv6_perf_map,
1238 .raw_event_mask = 0xFF,
1250 .num_events = 3, 1239 .num_events = 3,
1251 .max_period = (1LLU << 32) - 1, 1240 .max_period = (1LLU << 32) - 1,
1252}; 1241};
@@ -1263,13 +1252,14 @@ static const struct arm_pmu armv6mpcore_pmu = {
1263 .handle_irq = armv6pmu_handle_irq, 1252 .handle_irq = armv6pmu_handle_irq,
1264 .enable = armv6pmu_enable_event, 1253 .enable = armv6pmu_enable_event,
1265 .disable = armv6mpcore_pmu_disable_event, 1254 .disable = armv6mpcore_pmu_disable_event,
1266 .event_map = armv6mpcore_pmu_event_map,
1267 .raw_event = armv6pmu_raw_event,
1268 .read_counter = armv6pmu_read_counter, 1255 .read_counter = armv6pmu_read_counter,
1269 .write_counter = armv6pmu_write_counter, 1256 .write_counter = armv6pmu_write_counter,
1270 .get_event_idx = armv6pmu_get_event_idx, 1257 .get_event_idx = armv6pmu_get_event_idx,
1271 .start = armv6pmu_start, 1258 .start = armv6pmu_start,
1272 .stop = armv6pmu_stop, 1259 .stop = armv6pmu_stop,
1260 .cache_map = &armv6mpcore_perf_cache_map,
1261 .event_map = &armv6mpcore_perf_map,
1262 .raw_event_mask = 0xFF,
1273 .num_events = 3, 1263 .num_events = 3,
1274 .max_period = (1LLU << 32) - 1, 1264 .max_period = (1LLU << 32) - 1,
1275}; 1265};
@@ -2093,27 +2083,6 @@ static void armv7pmu_stop(void)
2093 spin_unlock_irqrestore(&pmu_lock, flags); 2083 spin_unlock_irqrestore(&pmu_lock, flags);
2094} 2084}
2095 2085
2096static inline int armv7_a8_pmu_event_map(int config)
2097{
2098 int mapping = armv7_a8_perf_map[config];
2099 if (HW_OP_UNSUPPORTED == mapping)
2100 mapping = -EOPNOTSUPP;
2101 return mapping;
2102}
2103
2104static inline int armv7_a9_pmu_event_map(int config)
2105{
2106 int mapping = armv7_a9_perf_map[config];
2107 if (HW_OP_UNSUPPORTED == mapping)
2108 mapping = -EOPNOTSUPP;
2109 return mapping;
2110}
2111
2112static u64 armv7pmu_raw_event(u64 config)
2113{
2114 return config & 0xff;
2115}
2116
2117static int armv7pmu_get_event_idx(struct cpu_hw_events *cpuc, 2086static int armv7pmu_get_event_idx(struct cpu_hw_events *cpuc,
2118 struct hw_perf_event *event) 2087 struct hw_perf_event *event)
2119{ 2088{
@@ -2144,12 +2113,12 @@ static struct arm_pmu armv7pmu = {
2144 .handle_irq = armv7pmu_handle_irq, 2113 .handle_irq = armv7pmu_handle_irq,
2145 .enable = armv7pmu_enable_event, 2114 .enable = armv7pmu_enable_event,
2146 .disable = armv7pmu_disable_event, 2115 .disable = armv7pmu_disable_event,
2147 .raw_event = armv7pmu_raw_event,
2148 .read_counter = armv7pmu_read_counter, 2116 .read_counter = armv7pmu_read_counter,
2149 .write_counter = armv7pmu_write_counter, 2117 .write_counter = armv7pmu_write_counter,
2150 .get_event_idx = armv7pmu_get_event_idx, 2118 .get_event_idx = armv7pmu_get_event_idx,
2151 .start = armv7pmu_start, 2119 .start = armv7pmu_start,
2152 .stop = armv7pmu_stop, 2120 .stop = armv7pmu_stop,
2121 .raw_event_mask = 0xFF,
2153 .max_period = (1LLU << 32) - 1, 2122 .max_period = (1LLU << 32) - 1,
2154}; 2123};
2155 2124
@@ -2318,21 +2287,6 @@ static const unsigned xscale_perf_cache_map[PERF_COUNT_HW_CACHE_MAX]
2318#define XSCALE_PMU_RESET (CCNT_RESET | PMN_RESET) 2287#define XSCALE_PMU_RESET (CCNT_RESET | PMN_RESET)
2319#define XSCALE_PMU_CNT64 0x008 2288#define XSCALE_PMU_CNT64 0x008
2320 2289
2321static inline int
2322xscalepmu_event_map(int config)
2323{
2324 int mapping = xscale_perf_map[config];
2325 if (HW_OP_UNSUPPORTED == mapping)
2326 mapping = -EOPNOTSUPP;
2327 return mapping;
2328}
2329
2330static u64
2331xscalepmu_raw_event(u64 config)
2332{
2333 return config & 0xff;
2334}
2335
2336#define XSCALE1_OVERFLOWED_MASK 0x700 2290#define XSCALE1_OVERFLOWED_MASK 0x700
2337#define XSCALE1_CCOUNT_OVERFLOW 0x400 2291#define XSCALE1_CCOUNT_OVERFLOW 0x400
2338#define XSCALE1_COUNT0_OVERFLOW 0x100 2292#define XSCALE1_COUNT0_OVERFLOW 0x100
@@ -2598,13 +2552,14 @@ static const struct arm_pmu xscale1pmu = {
2598 .handle_irq = xscale1pmu_handle_irq, 2552 .handle_irq = xscale1pmu_handle_irq,
2599 .enable = xscale1pmu_enable_event, 2553 .enable = xscale1pmu_enable_event,
2600 .disable = xscale1pmu_disable_event, 2554 .disable = xscale1pmu_disable_event,
2601 .event_map = xscalepmu_event_map,
2602 .raw_event = xscalepmu_raw_event,
2603 .read_counter = xscale1pmu_read_counter, 2555 .read_counter = xscale1pmu_read_counter,
2604 .write_counter = xscale1pmu_write_counter, 2556 .write_counter = xscale1pmu_write_counter,
2605 .get_event_idx = xscale1pmu_get_event_idx, 2557 .get_event_idx = xscale1pmu_get_event_idx,
2606 .start = xscale1pmu_start, 2558 .start = xscale1pmu_start,
2607 .stop = xscale1pmu_stop, 2559 .stop = xscale1pmu_stop,
2560 .cache_map = &xscale_perf_cache_map,
2561 .event_map = &xscale_perf_map,
2562 .raw_event_mask = 0xFF,
2608 .num_events = 3, 2563 .num_events = 3,
2609 .max_period = (1LLU << 32) - 1, 2564 .max_period = (1LLU << 32) - 1,
2610}; 2565};
@@ -2953,13 +2908,14 @@ static const struct arm_pmu xscale2pmu = {
2953 .handle_irq = xscale2pmu_handle_irq, 2908 .handle_irq = xscale2pmu_handle_irq,
2954 .enable = xscale2pmu_enable_event, 2909 .enable = xscale2pmu_enable_event,
2955 .disable = xscale2pmu_disable_event, 2910 .disable = xscale2pmu_disable_event,
2956 .event_map = xscalepmu_event_map,
2957 .raw_event = xscalepmu_raw_event,
2958 .read_counter = xscale2pmu_read_counter, 2911 .read_counter = xscale2pmu_read_counter,
2959 .write_counter = xscale2pmu_write_counter, 2912 .write_counter = xscale2pmu_write_counter,
2960 .get_event_idx = xscale2pmu_get_event_idx, 2913 .get_event_idx = xscale2pmu_get_event_idx,
2961 .start = xscale2pmu_start, 2914 .start = xscale2pmu_start,
2962 .stop = xscale2pmu_stop, 2915 .stop = xscale2pmu_stop,
2916 .cache_map = &xscale_perf_cache_map,
2917 .event_map = &xscale_perf_map,
2918 .raw_event_mask = 0xFF,
2963 .num_events = 5, 2919 .num_events = 5,
2964 .max_period = (1LLU << 32) - 1, 2920 .max_period = (1LLU << 32) - 1,
2965}; 2921};
@@ -2978,20 +2934,14 @@ init_hw_perf_events(void)
2978 case 0xB560: /* ARM1156 */ 2934 case 0xB560: /* ARM1156 */
2979 case 0xB760: /* ARM1176 */ 2935 case 0xB760: /* ARM1176 */
2980 armpmu = &armv6pmu; 2936 armpmu = &armv6pmu;
2981 memcpy(armpmu_perf_cache_map, armv6_perf_cache_map,
2982 sizeof(armv6_perf_cache_map));
2983 break; 2937 break;
2984 case 0xB020: /* ARM11mpcore */ 2938 case 0xB020: /* ARM11mpcore */
2985 armpmu = &armv6mpcore_pmu; 2939 armpmu = &armv6mpcore_pmu;
2986 memcpy(armpmu_perf_cache_map,
2987 armv6mpcore_perf_cache_map,
2988 sizeof(armv6mpcore_perf_cache_map));
2989 break; 2940 break;
2990 case 0xC080: /* Cortex-A8 */ 2941 case 0xC080: /* Cortex-A8 */
2991 armv7pmu.id = ARM_PERF_PMU_ID_CA8; 2942 armv7pmu.id = ARM_PERF_PMU_ID_CA8;
2992 memcpy(armpmu_perf_cache_map, armv7_a8_perf_cache_map, 2943 armv7pmu.cache_map = &armv7_a8_perf_cache_map;
2993 sizeof(armv7_a8_perf_cache_map)); 2944 armv7pmu.event_map = &armv7_a8_perf_map;
2994 armv7pmu.event_map = armv7_a8_pmu_event_map;
2995 armpmu = &armv7pmu; 2945 armpmu = &armv7pmu;
2996 2946
2997 /* Reset PMNC and read the nb of CNTx counters 2947 /* Reset PMNC and read the nb of CNTx counters
@@ -3000,9 +2950,8 @@ init_hw_perf_events(void)
3000 break; 2950 break;
3001 case 0xC090: /* Cortex-A9 */ 2951 case 0xC090: /* Cortex-A9 */
3002 armv7pmu.id = ARM_PERF_PMU_ID_CA9; 2952 armv7pmu.id = ARM_PERF_PMU_ID_CA9;
3003 memcpy(armpmu_perf_cache_map, armv7_a9_perf_cache_map, 2953 armv7pmu.cache_map = &armv7_a9_perf_cache_map;
3004 sizeof(armv7_a9_perf_cache_map)); 2954 armv7pmu.event_map = &armv7_a9_perf_map;
3005 armv7pmu.event_map = armv7_a9_pmu_event_map;
3006 armpmu = &armv7pmu; 2955 armpmu = &armv7pmu;
3007 2956
3008 /* Reset PMNC and read the nb of CNTx counters 2957 /* Reset PMNC and read the nb of CNTx counters
@@ -3016,13 +2965,9 @@ init_hw_perf_events(void)
3016 switch (part_number) { 2965 switch (part_number) {
3017 case 1: 2966 case 1:
3018 armpmu = &xscale1pmu; 2967 armpmu = &xscale1pmu;
3019 memcpy(armpmu_perf_cache_map, xscale_perf_cache_map,
3020 sizeof(xscale_perf_cache_map));
3021 break; 2968 break;
3022 case 2: 2969 case 2:
3023 armpmu = &xscale2pmu; 2970 armpmu = &xscale2pmu;
3024 memcpy(armpmu_perf_cache_map, xscale_perf_cache_map,
3025 sizeof(xscale_perf_cache_map));
3026 break; 2971 break;
3027 } 2972 }
3028 } 2973 }