diff options
author | Will Deacon <will.deacon@arm.com> | 2013-01-23 12:17:52 -0500 |
---|---|---|
committer | Will Deacon <will.deacon@arm.com> | 2013-01-23 12:17:52 -0500 |
commit | 6abc749f635005be78dfcb562c2235511965db6d (patch) | |
tree | 885c469162ee1e518ca8715cef9dd58536991bf3 | |
parent | 9931faca02c604c22335f5a935a501bb2ace6e20 (diff) | |
parent | 9dcbf466559f6f2f55d60eb5a1bbebc8e694b52a (diff) |
Merge branch 'for-rmk/perf' into for-rmk/virt/kvm/core
-rw-r--r-- | arch/arm/include/asm/cputype.h | 33 | ||||
-rw-r--r-- | arch/arm/kernel/perf_event.c | 16 | ||||
-rw-r--r-- | arch/arm/kernel/perf_event_cpu.c | 51 | ||||
-rw-r--r-- | arch/arm/kernel/perf_event_v6.c | 4 | ||||
-rw-r--r-- | arch/arm/kernel/perf_event_v7.c | 18 | ||||
-rw-r--r-- | arch/arm/kernel/perf_event_xscale.c | 2 |
6 files changed, 75 insertions, 49 deletions
diff --git a/arch/arm/include/asm/cputype.h b/arch/arm/include/asm/cputype.h index a59dcb5ab5fc..ad41ec2471e8 100644 --- a/arch/arm/include/asm/cputype.h +++ b/arch/arm/include/asm/cputype.h | |||
@@ -64,6 +64,24 @@ extern unsigned int processor_id; | |||
64 | #define read_cpuid_ext(reg) 0 | 64 | #define read_cpuid_ext(reg) 0 |
65 | #endif | 65 | #endif |
66 | 66 | ||
67 | #define ARM_CPU_IMP_ARM 0x41 | ||
68 | #define ARM_CPU_IMP_INTEL 0x69 | ||
69 | |||
70 | #define ARM_CPU_PART_ARM1136 0xB360 | ||
71 | #define ARM_CPU_PART_ARM1156 0xB560 | ||
72 | #define ARM_CPU_PART_ARM1176 0xB760 | ||
73 | #define ARM_CPU_PART_ARM11MPCORE 0xB020 | ||
74 | #define ARM_CPU_PART_CORTEX_A8 0xC080 | ||
75 | #define ARM_CPU_PART_CORTEX_A9 0xC090 | ||
76 | #define ARM_CPU_PART_CORTEX_A5 0xC050 | ||
77 | #define ARM_CPU_PART_CORTEX_A15 0xC0F0 | ||
78 | #define ARM_CPU_PART_CORTEX_A7 0xC070 | ||
79 | |||
80 | #define ARM_CPU_XSCALE_ARCH_MASK 0xe000 | ||
81 | #define ARM_CPU_XSCALE_ARCH_V1 0x2000 | ||
82 | #define ARM_CPU_XSCALE_ARCH_V2 0x4000 | ||
83 | #define ARM_CPU_XSCALE_ARCH_V3 0x6000 | ||
84 | |||
67 | /* | 85 | /* |
68 | * The CPU ID never changes at run time, so we might as well tell the | 86 | * The CPU ID never changes at run time, so we might as well tell the |
69 | * compiler that it's constant. Use this function to read the CPU ID | 87 | * compiler that it's constant. Use this function to read the CPU ID |
@@ -74,6 +92,21 @@ static inline unsigned int __attribute_const__ read_cpuid_id(void) | |||
74 | return read_cpuid(CPUID_ID); | 92 | return read_cpuid(CPUID_ID); |
75 | } | 93 | } |
76 | 94 | ||
95 | static inline unsigned int __attribute_const__ read_cpuid_implementor(void) | ||
96 | { | ||
97 | return (read_cpuid_id() & 0xFF000000) >> 24; | ||
98 | } | ||
99 | |||
100 | static inline unsigned int __attribute_const__ read_cpuid_part_number(void) | ||
101 | { | ||
102 | return read_cpuid_id() & 0xFFF0; | ||
103 | } | ||
104 | |||
105 | static inline unsigned int __attribute_const__ xscale_cpu_arch_version(void) | ||
106 | { | ||
107 | return read_cpuid_part_number() & ARM_CPU_XSCALE_ARCH_MASK; | ||
108 | } | ||
109 | |||
77 | static inline unsigned int __attribute_const__ read_cpuid_cachetype(void) | 110 | static inline unsigned int __attribute_const__ read_cpuid_cachetype(void) |
78 | { | 111 | { |
79 | return read_cpuid(CPUID_CACHETYPE); | 112 | return read_cpuid(CPUID_CACHETYPE); |
diff --git a/arch/arm/kernel/perf_event.c b/arch/arm/kernel/perf_event.c index f9e8657dd241..31e0eb353cd8 100644 --- a/arch/arm/kernel/perf_event.c +++ b/arch/arm/kernel/perf_event.c | |||
@@ -149,12 +149,6 @@ again: | |||
149 | static void | 149 | static void |
150 | armpmu_read(struct perf_event *event) | 150 | armpmu_read(struct perf_event *event) |
151 | { | 151 | { |
152 | struct hw_perf_event *hwc = &event->hw; | ||
153 | |||
154 | /* Don't read disabled counters! */ | ||
155 | if (hwc->idx < 0) | ||
156 | return; | ||
157 | |||
158 | armpmu_event_update(event); | 152 | armpmu_event_update(event); |
159 | } | 153 | } |
160 | 154 | ||
@@ -207,8 +201,6 @@ armpmu_del(struct perf_event *event, int flags) | |||
207 | struct hw_perf_event *hwc = &event->hw; | 201 | struct hw_perf_event *hwc = &event->hw; |
208 | int idx = hwc->idx; | 202 | int idx = hwc->idx; |
209 | 203 | ||
210 | WARN_ON(idx < 0); | ||
211 | |||
212 | armpmu_stop(event, PERF_EF_UPDATE); | 204 | armpmu_stop(event, PERF_EF_UPDATE); |
213 | hw_events->events[idx] = NULL; | 205 | hw_events->events[idx] = NULL; |
214 | clear_bit(idx, hw_events->used_mask); | 206 | clear_bit(idx, hw_events->used_mask); |
@@ -358,7 +350,7 @@ __hw_perf_event_init(struct perf_event *event) | |||
358 | { | 350 | { |
359 | struct arm_pmu *armpmu = to_arm_pmu(event->pmu); | 351 | struct arm_pmu *armpmu = to_arm_pmu(event->pmu); |
360 | struct hw_perf_event *hwc = &event->hw; | 352 | struct hw_perf_event *hwc = &event->hw; |
361 | int mapping, err; | 353 | int mapping; |
362 | 354 | ||
363 | mapping = armpmu->map_event(event); | 355 | mapping = armpmu->map_event(event); |
364 | 356 | ||
@@ -407,14 +399,12 @@ __hw_perf_event_init(struct perf_event *event) | |||
407 | local64_set(&hwc->period_left, hwc->sample_period); | 399 | local64_set(&hwc->period_left, hwc->sample_period); |
408 | } | 400 | } |
409 | 401 | ||
410 | err = 0; | ||
411 | if (event->group_leader != event) { | 402 | if (event->group_leader != event) { |
412 | err = validate_group(event); | 403 | if (validate_group(event) != 0); |
413 | if (err) | ||
414 | return -EINVAL; | 404 | return -EINVAL; |
415 | } | 405 | } |
416 | 406 | ||
417 | return err; | 407 | return 0; |
418 | } | 408 | } |
419 | 409 | ||
420 | static int armpmu_event_init(struct perf_event *event) | 410 | static int armpmu_event_init(struct perf_event *event) |
diff --git a/arch/arm/kernel/perf_event_cpu.c b/arch/arm/kernel/perf_event_cpu.c index 5f6620684e25..1f2740e3dbc0 100644 --- a/arch/arm/kernel/perf_event_cpu.c +++ b/arch/arm/kernel/perf_event_cpu.c | |||
@@ -147,7 +147,7 @@ static void cpu_pmu_init(struct arm_pmu *cpu_pmu) | |||
147 | cpu_pmu->free_irq = cpu_pmu_free_irq; | 147 | cpu_pmu->free_irq = cpu_pmu_free_irq; |
148 | 148 | ||
149 | /* Ensure the PMU has sane values out of reset. */ | 149 | /* Ensure the PMU has sane values out of reset. */ |
150 | if (cpu_pmu && cpu_pmu->reset) | 150 | if (cpu_pmu->reset) |
151 | on_each_cpu(cpu_pmu->reset, cpu_pmu, 1); | 151 | on_each_cpu(cpu_pmu->reset, cpu_pmu, 1); |
152 | } | 152 | } |
153 | 153 | ||
@@ -201,48 +201,46 @@ static struct platform_device_id cpu_pmu_plat_device_ids[] = { | |||
201 | static int probe_current_pmu(struct arm_pmu *pmu) | 201 | static int probe_current_pmu(struct arm_pmu *pmu) |
202 | { | 202 | { |
203 | int cpu = get_cpu(); | 203 | int cpu = get_cpu(); |
204 | unsigned long cpuid = read_cpuid_id(); | 204 | unsigned long implementor = read_cpuid_implementor(); |
205 | unsigned long implementor = (cpuid & 0xFF000000) >> 24; | 205 | unsigned long part_number = read_cpuid_part_number(); |
206 | unsigned long part_number = (cpuid & 0xFFF0); | ||
207 | int ret = -ENODEV; | 206 | int ret = -ENODEV; |
208 | 207 | ||
209 | pr_info("probing PMU on CPU %d\n", cpu); | 208 | pr_info("probing PMU on CPU %d\n", cpu); |
210 | 209 | ||
211 | /* ARM Ltd CPUs. */ | 210 | /* ARM Ltd CPUs. */ |
212 | if (0x41 == implementor) { | 211 | if (implementor == ARM_CPU_IMP_ARM) { |
213 | switch (part_number) { | 212 | switch (part_number) { |
214 | case 0xB360: /* ARM1136 */ | 213 | case ARM_CPU_PART_ARM1136: |
215 | case 0xB560: /* ARM1156 */ | 214 | case ARM_CPU_PART_ARM1156: |
216 | case 0xB760: /* ARM1176 */ | 215 | case ARM_CPU_PART_ARM1176: |
217 | ret = armv6pmu_init(pmu); | 216 | ret = armv6pmu_init(pmu); |
218 | break; | 217 | break; |
219 | case 0xB020: /* ARM11mpcore */ | 218 | case ARM_CPU_PART_ARM11MPCORE: |
220 | ret = armv6mpcore_pmu_init(pmu); | 219 | ret = armv6mpcore_pmu_init(pmu); |
221 | break; | 220 | break; |
222 | case 0xC080: /* Cortex-A8 */ | 221 | case ARM_CPU_PART_CORTEX_A8: |
223 | ret = armv7_a8_pmu_init(pmu); | 222 | ret = armv7_a8_pmu_init(pmu); |
224 | break; | 223 | break; |
225 | case 0xC090: /* Cortex-A9 */ | 224 | case ARM_CPU_PART_CORTEX_A9: |
226 | ret = armv7_a9_pmu_init(pmu); | 225 | ret = armv7_a9_pmu_init(pmu); |
227 | break; | 226 | break; |
228 | case 0xC050: /* Cortex-A5 */ | 227 | case ARM_CPU_PART_CORTEX_A5: |
229 | ret = armv7_a5_pmu_init(pmu); | 228 | ret = armv7_a5_pmu_init(pmu); |
230 | break; | 229 | break; |
231 | case 0xC0F0: /* Cortex-A15 */ | 230 | case ARM_CPU_PART_CORTEX_A15: |
232 | ret = armv7_a15_pmu_init(pmu); | 231 | ret = armv7_a15_pmu_init(pmu); |
233 | break; | 232 | break; |
234 | case 0xC070: /* Cortex-A7 */ | 233 | case ARM_CPU_PART_CORTEX_A7: |
235 | ret = armv7_a7_pmu_init(pmu); | 234 | ret = armv7_a7_pmu_init(pmu); |
236 | break; | 235 | break; |
237 | } | 236 | } |
238 | /* Intel CPUs [xscale]. */ | 237 | /* Intel CPUs [xscale]. */ |
239 | } else if (0x69 == implementor) { | 238 | } else if (implementor == ARM_CPU_IMP_INTEL) { |
240 | part_number = (cpuid >> 13) & 0x7; | 239 | switch (xscale_cpu_arch_version()) { |
241 | switch (part_number) { | 240 | case ARM_CPU_XSCALE_ARCH_V1: |
242 | case 1: | ||
243 | ret = xscale1pmu_init(pmu); | 241 | ret = xscale1pmu_init(pmu); |
244 | break; | 242 | break; |
245 | case 2: | 243 | case ARM_CPU_XSCALE_ARCH_V2: |
246 | ret = xscale2pmu_init(pmu); | 244 | ret = xscale2pmu_init(pmu); |
247 | break; | 245 | break; |
248 | } | 246 | } |
@@ -279,17 +277,22 @@ static int cpu_pmu_device_probe(struct platform_device *pdev) | |||
279 | } | 277 | } |
280 | 278 | ||
281 | if (ret) { | 279 | if (ret) { |
282 | pr_info("failed to register PMU devices!"); | 280 | pr_info("failed to probe PMU!"); |
283 | kfree(pmu); | 281 | goto out_free; |
284 | return ret; | ||
285 | } | 282 | } |
286 | 283 | ||
287 | cpu_pmu = pmu; | 284 | cpu_pmu = pmu; |
288 | cpu_pmu->plat_device = pdev; | 285 | cpu_pmu->plat_device = pdev; |
289 | cpu_pmu_init(cpu_pmu); | 286 | cpu_pmu_init(cpu_pmu); |
290 | armpmu_register(cpu_pmu, PERF_TYPE_RAW); | 287 | ret = armpmu_register(cpu_pmu, PERF_TYPE_RAW); |
291 | 288 | ||
292 | return 0; | 289 | if (!ret) |
290 | return 0; | ||
291 | |||
292 | out_free: | ||
293 | pr_info("failed to register PMU devices!"); | ||
294 | kfree(pmu); | ||
295 | return ret; | ||
293 | } | 296 | } |
294 | 297 | ||
295 | static struct platform_driver cpu_pmu_driver = { | 298 | static struct platform_driver cpu_pmu_driver = { |
diff --git a/arch/arm/kernel/perf_event_v6.c b/arch/arm/kernel/perf_event_v6.c index 041d0526a288..03664b0e8fa4 100644 --- a/arch/arm/kernel/perf_event_v6.c +++ b/arch/arm/kernel/perf_event_v6.c | |||
@@ -106,7 +106,7 @@ static const unsigned armv6_perf_cache_map[PERF_COUNT_HW_CACHE_MAX] | |||
106 | }, | 106 | }, |
107 | [C(OP_WRITE)] = { | 107 | [C(OP_WRITE)] = { |
108 | [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, | 108 | [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, |
109 | [C(RESULT_MISS)] = ARMV6_PERFCTR_ICACHE_MISS, | 109 | [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, |
110 | }, | 110 | }, |
111 | [C(OP_PREFETCH)] = { | 111 | [C(OP_PREFETCH)] = { |
112 | [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, | 112 | [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, |
@@ -259,7 +259,7 @@ static const unsigned armv6mpcore_perf_cache_map[PERF_COUNT_HW_CACHE_MAX] | |||
259 | }, | 259 | }, |
260 | [C(OP_WRITE)] = { | 260 | [C(OP_WRITE)] = { |
261 | [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, | 261 | [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, |
262 | [C(RESULT_MISS)] = ARMV6MPCORE_PERFCTR_ICACHE_MISS, | 262 | [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, |
263 | }, | 263 | }, |
264 | [C(OP_PREFETCH)] = { | 264 | [C(OP_PREFETCH)] = { |
265 | [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, | 265 | [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, |
diff --git a/arch/arm/kernel/perf_event_v7.c b/arch/arm/kernel/perf_event_v7.c index 4fbc757d9cff..8c79a9e70b83 100644 --- a/arch/arm/kernel/perf_event_v7.c +++ b/arch/arm/kernel/perf_event_v7.c | |||
@@ -157,8 +157,8 @@ static const unsigned armv7_a8_perf_cache_map[PERF_COUNT_HW_CACHE_MAX] | |||
157 | [C(RESULT_MISS)] = ARMV7_PERFCTR_L1_ICACHE_REFILL, | 157 | [C(RESULT_MISS)] = ARMV7_PERFCTR_L1_ICACHE_REFILL, |
158 | }, | 158 | }, |
159 | [C(OP_WRITE)] = { | 159 | [C(OP_WRITE)] = { |
160 | [C(RESULT_ACCESS)] = ARMV7_A8_PERFCTR_L1_ICACHE_ACCESS, | 160 | [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, |
161 | [C(RESULT_MISS)] = ARMV7_PERFCTR_L1_ICACHE_REFILL, | 161 | [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, |
162 | }, | 162 | }, |
163 | [C(OP_PREFETCH)] = { | 163 | [C(OP_PREFETCH)] = { |
164 | [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, | 164 | [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, |
@@ -282,7 +282,7 @@ static const unsigned armv7_a9_perf_cache_map[PERF_COUNT_HW_CACHE_MAX] | |||
282 | }, | 282 | }, |
283 | [C(OP_WRITE)] = { | 283 | [C(OP_WRITE)] = { |
284 | [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, | 284 | [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, |
285 | [C(RESULT_MISS)] = ARMV7_PERFCTR_L1_ICACHE_REFILL, | 285 | [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, |
286 | }, | 286 | }, |
287 | [C(OP_PREFETCH)] = { | 287 | [C(OP_PREFETCH)] = { |
288 | [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, | 288 | [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, |
@@ -399,8 +399,8 @@ static const unsigned armv7_a5_perf_cache_map[PERF_COUNT_HW_CACHE_MAX] | |||
399 | [C(RESULT_MISS)] = ARMV7_PERFCTR_L1_ICACHE_REFILL, | 399 | [C(RESULT_MISS)] = ARMV7_PERFCTR_L1_ICACHE_REFILL, |
400 | }, | 400 | }, |
401 | [C(OP_WRITE)] = { | 401 | [C(OP_WRITE)] = { |
402 | [C(RESULT_ACCESS)] = ARMV7_PERFCTR_L1_ICACHE_ACCESS, | 402 | [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, |
403 | [C(RESULT_MISS)] = ARMV7_PERFCTR_L1_ICACHE_REFILL, | 403 | [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, |
404 | }, | 404 | }, |
405 | /* | 405 | /* |
406 | * The prefetch counters don't differentiate between the I | 406 | * The prefetch counters don't differentiate between the I |
@@ -527,8 +527,8 @@ static const unsigned armv7_a15_perf_cache_map[PERF_COUNT_HW_CACHE_MAX] | |||
527 | [C(RESULT_MISS)] = ARMV7_PERFCTR_L1_ICACHE_REFILL, | 527 | [C(RESULT_MISS)] = ARMV7_PERFCTR_L1_ICACHE_REFILL, |
528 | }, | 528 | }, |
529 | [C(OP_WRITE)] = { | 529 | [C(OP_WRITE)] = { |
530 | [C(RESULT_ACCESS)] = ARMV7_PERFCTR_L1_ICACHE_ACCESS, | 530 | [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, |
531 | [C(RESULT_MISS)] = ARMV7_PERFCTR_L1_ICACHE_REFILL, | 531 | [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, |
532 | }, | 532 | }, |
533 | [C(OP_PREFETCH)] = { | 533 | [C(OP_PREFETCH)] = { |
534 | [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, | 534 | [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, |
@@ -651,8 +651,8 @@ static const unsigned armv7_a7_perf_cache_map[PERF_COUNT_HW_CACHE_MAX] | |||
651 | [C(RESULT_MISS)] = ARMV7_PERFCTR_L1_ICACHE_REFILL, | 651 | [C(RESULT_MISS)] = ARMV7_PERFCTR_L1_ICACHE_REFILL, |
652 | }, | 652 | }, |
653 | [C(OP_WRITE)] = { | 653 | [C(OP_WRITE)] = { |
654 | [C(RESULT_ACCESS)] = ARMV7_PERFCTR_L1_ICACHE_ACCESS, | 654 | [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, |
655 | [C(RESULT_MISS)] = ARMV7_PERFCTR_L1_ICACHE_REFILL, | 655 | [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, |
656 | }, | 656 | }, |
657 | [C(OP_PREFETCH)] = { | 657 | [C(OP_PREFETCH)] = { |
658 | [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, | 658 | [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, |
diff --git a/arch/arm/kernel/perf_event_xscale.c b/arch/arm/kernel/perf_event_xscale.c index 2b0fe30ec12e..63990c42fac9 100644 --- a/arch/arm/kernel/perf_event_xscale.c +++ b/arch/arm/kernel/perf_event_xscale.c | |||
@@ -83,7 +83,7 @@ static const unsigned xscale_perf_cache_map[PERF_COUNT_HW_CACHE_MAX] | |||
83 | }, | 83 | }, |
84 | [C(OP_WRITE)] = { | 84 | [C(OP_WRITE)] = { |
85 | [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, | 85 | [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, |
86 | [C(RESULT_MISS)] = XSCALE_PERFCTR_ICACHE_MISS, | 86 | [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, |
87 | }, | 87 | }, |
88 | [C(OP_PREFETCH)] = { | 88 | [C(OP_PREFETCH)] = { |
89 | [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, | 89 | [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, |