Merge branch 'v3.10/topic/dm-crypt' into linux-linaro-lsk-v3.10
[firefly-linux-kernel-4.4.55.git] / drivers / gator / gator_events_perf_pmu.c
1 /**
2  * Copyright (C) ARM Limited 2010-2015. All rights reserved.
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License version 2 as
6  * published by the Free Software Foundation.
7  */
8
9 #include "gator.h"
10
11 /* gator_events_armvX.c is used for Linux 2.6.x */
12 #if GATOR_PERF_PMU_SUPPORT
13
14 #include <linux/io.h>
15 #ifdef CONFIG_OF
16 #include <linux/of_address.h>
17 #endif
18 #include <linux/perf_event.h>
19 #include <linux/slab.h>
20
21 extern bool event_based_sampling;
22
23 /* Maximum number of per-core counters - currently reserves enough space for two full hardware PMUs for big.LITTLE */
24 #define CNTMAX 16
25 #define CCI_400 4
26 #define CCI_500 8
27 #define CCN_5XX 8
28 /* Maximum number of uncore counters */
29 /* + 1 for the cci-400 cycles counter */
30 /* cci-500 has no cycles counter */
31 /* + 1 for the CCN-5xx cycles counter */
32 #define UCCNT (CCI_400 + 1 + CCI_500 + CCN_5XX + 1)
33
34 /* Default to 0 if unable to probe the revision which was the previous behavior */
35 #define DEFAULT_CCI_REVISION 0
36
37 /* A gator_attr is needed for every counter */
38 struct gator_attr {
39         /* Set once in gator_events_perf_pmu_*_init - the name of the event in the gatorfs */
40         char name[40];
41         /* Exposed in gatorfs - set by gatord to enable this counter */
42         unsigned long enabled;
43         /* Set once in gator_events_perf_pmu_*_init - the perf type to use, see perf_type_id in the perf_event.h header file. */
44         unsigned long type;
45         /* Exposed in gatorfs - set by gatord to select the event to collect */
46         unsigned long event;
47         /* Exposed in gatorfs - set by gatord with the sample period to use and enable EBS for this counter */
48         unsigned long count;
49         /* Exposed as read only in gatorfs - set once in __attr_init as the key to use in the APC data */
50         unsigned long key;
51 };
52
53 /* Per-core counter attributes */
54 static struct gator_attr attrs[CNTMAX];
55 /* Number of initialized per-core counters */
56 static int attr_count;
57 /* Uncore counter attributes */
58 static struct gator_attr uc_attrs[UCCNT];
59 /* Number of initialized uncore counters */
60 static int uc_attr_count;
61
62 struct gator_event {
63         uint32_t curr;
64         uint32_t prev;
65         uint32_t prev_delta;
66         bool zero;
67         struct perf_event *pevent;
68         struct perf_event_attr *pevent_attr;
69 };
70
71 static DEFINE_PER_CPU(struct gator_event[CNTMAX], events);
72 static struct gator_event uc_events[UCCNT];
73 static DEFINE_PER_CPU(int[(CNTMAX + UCCNT)*2], perf_cnt);
74
75 static void gator_events_perf_pmu_stop(void);
76
77 static int __create_files(struct super_block *sb, struct dentry *root, struct gator_attr *const attr)
78 {
79         struct dentry *dir;
80
81         if (attr->name[0] == '\0')
82                 return 0;
83         dir = gatorfs_mkdir(sb, root, attr->name);
84         if (!dir)
85                 return -1;
86         gatorfs_create_ulong(sb, dir, "enabled", &attr->enabled);
87         gatorfs_create_ulong(sb, dir, "count", &attr->count);
88         gatorfs_create_ro_ulong(sb, dir, "key", &attr->key);
89         gatorfs_create_ulong(sb, dir, "event", &attr->event);
90
91         return 0;
92 }
93
94 static int gator_events_perf_pmu_create_files(struct super_block *sb, struct dentry *root)
95 {
96         int cnt;
97
98         for (cnt = 0; cnt < attr_count; cnt++) {
99                 if (__create_files(sb, root, &attrs[cnt]) != 0)
100                         return -1;
101         }
102
103         for (cnt = 0; cnt < uc_attr_count; cnt++) {
104                 if (__create_files(sb, root, &uc_attrs[cnt]) != 0)
105                         return -1;
106         }
107
108         return 0;
109 }
110
111 #if LINUX_VERSION_CODE < KERNEL_VERSION(3, 1, 0)
112 static void ebs_overflow_handler(struct perf_event *event, int unused, struct perf_sample_data *data, struct pt_regs *regs)
113 #else
114 static void ebs_overflow_handler(struct perf_event *event, struct perf_sample_data *data, struct pt_regs *regs)
115 #endif
116 {
117         gator_backtrace_handler(regs);
118 }
119
120 #if LINUX_VERSION_CODE < KERNEL_VERSION(3, 1, 0)
121 static void dummy_handler(struct perf_event *event, int unused, struct perf_sample_data *data, struct pt_regs *regs)
122 #else
123 static void dummy_handler(struct perf_event *event, struct perf_sample_data *data, struct pt_regs *regs)
124 #endif
125 {
126         /* Required as perf_event_create_kernel_counter() requires an overflow handler, even though all we do is poll */
127 }
128
129 static int gator_events_perf_pmu_read(int **buffer, bool sched_switch);
130
131 static int gator_events_perf_pmu_online(int **buffer, bool migrate)
132 {
133         return gator_events_perf_pmu_read(buffer, false);
134 }
135
136 static void __online_dispatch(int cpu, bool migrate, struct gator_attr *const attr, struct gator_event *const event)
137 {
138         perf_overflow_handler_t handler;
139
140         event->zero = true;
141
142         if (event->pevent != NULL || event->pevent_attr == 0 || migrate)
143                 return;
144
145         if (attr->count > 0)
146                 handler = ebs_overflow_handler;
147         else
148                 handler = dummy_handler;
149
150 #if LINUX_VERSION_CODE < KERNEL_VERSION(3, 1, 0)
151         event->pevent = perf_event_create_kernel_counter(event->pevent_attr, cpu, 0, handler);
152 #else
153         event->pevent = perf_event_create_kernel_counter(event->pevent_attr, cpu, 0, handler, 0);
154 #endif
155         if (IS_ERR(event->pevent)) {
156                 pr_debug("gator: unable to online a counter on cpu %d\n", cpu);
157                 event->pevent = NULL;
158                 return;
159         }
160
161         if (event->pevent->state != PERF_EVENT_STATE_ACTIVE) {
162                 pr_debug("gator: inactive counter on cpu %d\n", cpu);
163                 perf_event_release_kernel(event->pevent);
164                 event->pevent = NULL;
165                 return;
166         }
167 }
168
169 static void gator_events_perf_pmu_online_dispatch(int cpu, bool migrate)
170 {
171         int cnt;
172
173         cpu = pcpu_to_lcpu(cpu);
174
175         for (cnt = 0; cnt < attr_count; cnt++)
176                 __online_dispatch(cpu, migrate, &attrs[cnt], &per_cpu(events, cpu)[cnt]);
177
178         if (cpu == 0) {
179                 for (cnt = 0; cnt < uc_attr_count; cnt++)
180                         __online_dispatch(cpu, migrate, &uc_attrs[cnt], &uc_events[cnt]);
181         }
182 }
183
184 static void __offline_dispatch(int cpu, struct gator_event *const event)
185 {
186         struct perf_event *pe = NULL;
187
188         if (event->pevent) {
189                 pe = event->pevent;
190                 event->pevent = NULL;
191         }
192
193         if (pe)
194                 perf_event_release_kernel(pe);
195 }
196
197 static void gator_events_perf_pmu_offline_dispatch(int cpu, bool migrate)
198 {
199         int cnt;
200
201         if (migrate)
202                 return;
203         cpu = pcpu_to_lcpu(cpu);
204
205         for (cnt = 0; cnt < attr_count; cnt++)
206                 __offline_dispatch(cpu, &per_cpu(events, cpu)[cnt]);
207
208         if (cpu == 0) {
209                 for (cnt = 0; cnt < uc_attr_count; cnt++)
210                         __offline_dispatch(cpu, &uc_events[cnt]);
211         }
212 }
213
214 static int __check_ebs(struct gator_attr *const attr)
215 {
216         if (attr->count > 0) {
217                 if (!event_based_sampling) {
218                         event_based_sampling = true;
219                 } else {
220                         pr_warning("gator: Only one ebs counter is allowed\n");
221                         return -1;
222                 }
223         }
224
225         return 0;
226 }
227
228 static int __start(struct gator_attr *const attr, struct gator_event *const event)
229 {
230         u32 size = sizeof(struct perf_event_attr);
231
232         event->pevent = NULL;
233         /* Skip disabled counters */
234         if (!attr->enabled)
235                 return 0;
236
237         event->prev = 0;
238         event->curr = 0;
239         event->prev_delta = 0;
240         event->pevent_attr = kmalloc(size, GFP_KERNEL);
241         if (!event->pevent_attr) {
242                 gator_events_perf_pmu_stop();
243                 return -1;
244         }
245
246         memset(event->pevent_attr, 0, size);
247         event->pevent_attr->type = attr->type;
248         event->pevent_attr->size = size;
249         event->pevent_attr->config = attr->event;
250         event->pevent_attr->sample_period = attr->count;
251         event->pevent_attr->pinned = 1;
252
253         return 0;
254 }
255
256 static int gator_events_perf_pmu_start(void)
257 {
258         int cnt, cpu;
259
260         event_based_sampling = false;
261         for (cnt = 0; cnt < attr_count; cnt++) {
262                 if (__check_ebs(&attrs[cnt]) != 0)
263                         return -1;
264         }
265
266         for (cnt = 0; cnt < uc_attr_count; cnt++) {
267                 if (__check_ebs(&uc_attrs[cnt]) != 0)
268                         return -1;
269         }
270
271         for_each_present_cpu(cpu) {
272                 for (cnt = 0; cnt < attr_count; cnt++) {
273                         if (__start(&attrs[cnt], &per_cpu(events, cpu)[cnt]) != 0)
274                                 return -1;
275                 }
276         }
277
278         for (cnt = 0; cnt < uc_attr_count; cnt++) {
279                 if (__start(&uc_attrs[cnt], &uc_events[cnt]) != 0)
280                         return -1;
281         }
282
283         return 0;
284 }
285
286 static void __event_stop(struct gator_event *const event)
287 {
288         kfree(event->pevent_attr);
289         event->pevent_attr = NULL;
290 }
291
292 static void __attr_stop(struct gator_attr *const attr)
293 {
294         attr->enabled = 0;
295         attr->event = 0;
296         attr->count = 0;
297 }
298
299 static void gator_events_perf_pmu_stop(void)
300 {
301         unsigned int cnt, cpu;
302
303         for_each_present_cpu(cpu) {
304                 for (cnt = 0; cnt < attr_count; cnt++)
305                         __event_stop(&per_cpu(events, cpu)[cnt]);
306         }
307
308         for (cnt = 0; cnt < uc_attr_count; cnt++)
309                 __event_stop(&uc_events[cnt]);
310
311         for (cnt = 0; cnt < attr_count; cnt++)
312                 __attr_stop(&attrs[cnt]);
313
314         for (cnt = 0; cnt < uc_attr_count; cnt++)
315                 __attr_stop(&uc_attrs[cnt]);
316 }
317
318 static void __read(int *const len, int cpu, struct gator_attr *const attr, struct gator_event *const event)
319 {
320         uint32_t delta;
321         struct perf_event *const ev = event->pevent;
322
323         if (ev != NULL && ev->state == PERF_EVENT_STATE_ACTIVE) {
324                 /* After creating the perf counter in __online_dispatch, there
325                  * is a race condition between gator_events_perf_pmu_online and
326                  * gator_events_perf_pmu_read. So have
327                  * gator_events_perf_pmu_online call gator_events_perf_pmu_read
328                  * and in __read check to see if it's the first call after
329                  * __online_dispatch and if so, run the online code.
330                  */
331                 if (event->zero) {
332                         ev->pmu->read(ev);
333                         event->prev = event->curr = local64_read(&ev->count);
334                         event->prev_delta = 0;
335                         per_cpu(perf_cnt, cpu)[(*len)++] = attr->key;
336                         per_cpu(perf_cnt, cpu)[(*len)++] = 0;
337                         event->zero = false;
338                 } else {
339                         ev->pmu->read(ev);
340                         event->curr = local64_read(&ev->count);
341                         delta = event->curr - event->prev;
342                         if (delta != 0 || delta != event->prev_delta) {
343                                 event->prev_delta = delta;
344                                 event->prev = event->curr;
345                                 per_cpu(perf_cnt, cpu)[(*len)++] = attr->key;
346                                 per_cpu(perf_cnt, cpu)[(*len)++] = delta;
347                         }
348                 }
349         }
350 }
351
352 static int gator_events_perf_pmu_read(int **buffer, bool sched_switch)
353 {
354         int cnt, len = 0;
355         const int cpu = get_logical_cpu();
356
357         for (cnt = 0; cnt < attr_count; cnt++)
358                 __read(&len, cpu, &attrs[cnt], &per_cpu(events, cpu)[cnt]);
359
360         if (cpu == 0) {
361                 for (cnt = 0; cnt < uc_attr_count; cnt++)
362                         __read(&len, cpu, &uc_attrs[cnt], &uc_events[cnt]);
363         }
364
365         if (buffer)
366                 *buffer = per_cpu(perf_cnt, cpu);
367
368         return len;
369 }
370
371 static struct gator_interface gator_events_perf_pmu_interface = {
372         .create_files = gator_events_perf_pmu_create_files,
373         .start = gator_events_perf_pmu_start,
374         .stop = gator_events_perf_pmu_stop,
375         .online = gator_events_perf_pmu_online,
376         .online_dispatch = gator_events_perf_pmu_online_dispatch,
377         .offline_dispatch = gator_events_perf_pmu_offline_dispatch,
378         .read = gator_events_perf_pmu_read,
379 };
380
381 static void __attr_init(struct gator_attr *const attr)
382 {
383         attr->name[0] = '\0';
384         attr->enabled = 0;
385         attr->type = 0;
386         attr->event = 0;
387         attr->count = 0;
388         attr->key = gator_events_get_key();
389 }
390
391 #ifdef CONFIG_OF
392
393 static const struct of_device_id arm_cci_matches[] = {
394         {.compatible = "arm,cci-400" },
395         {},
396 };
397
398 static int probe_cci_revision(void)
399 {
400         struct device_node *np;
401         struct resource res;
402         void __iomem *cci_ctrl_base;
403         int rev;
404         int ret = DEFAULT_CCI_REVISION;
405
406         np = of_find_matching_node(NULL, arm_cci_matches);
407         if (!np)
408                 return ret;
409
410         if (of_address_to_resource(np, 0, &res))
411                 goto node_put;
412
413         cci_ctrl_base = ioremap(res.start, resource_size(&res));
414
415         rev = (readl_relaxed(cci_ctrl_base + 0xfe8) >> 4) & 0xf;
416
417         if (rev <= 4)
418                 ret = 0;
419         else if (rev <= 6)
420                 ret = 1;
421
422         iounmap(cci_ctrl_base);
423
424  node_put:
425         of_node_put(np);
426
427         return ret;
428 }
429
430 #else
431
432 static int probe_cci_revision(void)
433 {
434         return DEFAULT_CCI_REVISION;
435 }
436
437 #endif
438
439 static void gator_events_perf_pmu_uncore_init(const char *const name, const int type, const int count, const bool has_cycles_counter)
440 {
441         int cnt;
442
443         if (has_cycles_counter) {
444                 snprintf(uc_attrs[uc_attr_count].name, sizeof(uc_attrs[uc_attr_count].name), "%s_ccnt", name);
445                 uc_attrs[uc_attr_count].type = type;
446                 ++uc_attr_count;
447         }
448
449         for (cnt = 0; cnt < count; ++cnt, ++uc_attr_count) {
450                 struct gator_attr *const attr = &uc_attrs[uc_attr_count];
451
452                 snprintf(attr->name, sizeof(attr->name), "%s_cnt%d", name, cnt);
453                 attr->type = type;
454         }
455 }
456
457 static void gator_events_perf_pmu_cci_400_init(const int type)
458 {
459         const char *cci_name;
460
461         switch (probe_cci_revision()) {
462         case 0:
463                 cci_name = "CCI_400";
464                 break;
465         case 1:
466                 cci_name = "CCI_400-r1";
467                 break;
468         default:
469                 pr_debug("gator: unrecognized cci-400 revision\n");
470                 return;
471         }
472
473         gator_events_perf_pmu_uncore_init(cci_name, type, CCI_400, true);
474 }
475
476 static void gator_events_perf_pmu_cpu_init(const struct gator_cpu *const gator_cpu, const int type)
477 {
478         int cnt;
479
480         snprintf(attrs[attr_count].name, sizeof(attrs[attr_count].name), "%s_ccnt", gator_cpu->pmnc_name);
481         attrs[attr_count].type = type;
482         ++attr_count;
483
484         for (cnt = 0; cnt < gator_cpu->pmnc_counters; ++cnt, ++attr_count) {
485                 struct gator_attr *const attr = &attrs[attr_count];
486
487                 snprintf(attr->name, sizeof(attr->name), "%s_cnt%d", gator_cpu->pmnc_name, cnt);
488                 attr->type = type;
489         }
490 }
491
492 int gator_events_perf_pmu_init(void)
493 {
494         struct perf_event_attr pea;
495         struct perf_event *pe;
496         const struct gator_cpu *gator_cpu;
497         int type;
498         int cpu;
499         int cnt;
500         bool found_cpu = false;
501
502         for (cnt = 0; cnt < CNTMAX; cnt++)
503                 __attr_init(&attrs[cnt]);
504         for (cnt = 0; cnt < UCCNT; cnt++)
505                 __attr_init(&uc_attrs[cnt]);
506
507         memset(&pea, 0, sizeof(pea));
508         pea.size = sizeof(pea);
509         pea.config = 0xFF;
510         attr_count = 0;
511         uc_attr_count = 0;
512         for (type = PERF_TYPE_MAX; type < 0x20; ++type) {
513                 pea.type = type;
514
515                 /* A particular PMU may work on some but not all cores, so try on each core */
516                 pe = NULL;
517                 for_each_present_cpu(cpu) {
518 #if LINUX_VERSION_CODE < KERNEL_VERSION(3, 1, 0)
519                         pe = perf_event_create_kernel_counter(&pea, cpu, 0, dummy_handler);
520 #else
521                         pe = perf_event_create_kernel_counter(&pea, cpu, 0, dummy_handler, 0);
522 #endif
523                         if (!IS_ERR(pe))
524                                 break;
525                 }
526                 /* Assume that valid PMUs are contiguous */
527                 if (IS_ERR(pe)) {
528                         pea.config = 0xff00;
529 #if LINUX_VERSION_CODE < KERNEL_VERSION(3, 1, 0)
530                         pe = perf_event_create_kernel_counter(&pea, 0, 0, dummy_handler);
531 #else
532                         pe = perf_event_create_kernel_counter(&pea, 0, 0, dummy_handler, 0);
533 #endif
534                         if (IS_ERR(pe))
535                                 break;
536                 }
537
538                 if (pe->pmu != NULL && type == pe->pmu->type) {
539                         if (strcmp("CCI", pe->pmu->name) == 0 || strcmp("CCI_400", pe->pmu->name) == 0 || strcmp("CCI_400-r1", pe->pmu->name) == 0) {
540                                 gator_events_perf_pmu_cci_400_init(type);
541                         } else if (strcmp("CCI_500", pe->pmu->name) == 0) {
542                                 gator_events_perf_pmu_uncore_init("CCI_500", type, CCI_500, false);
543                         } else if (strcmp("ccn", pe->pmu->name) == 0) {
544                                 gator_events_perf_pmu_uncore_init("ARM_CCN_5XX", type, CCN_5XX, true);
545                         } else if ((gator_cpu = gator_find_cpu_by_pmu_name(pe->pmu->name)) != NULL) {
546                                 found_cpu = true;
547                                 gator_events_perf_pmu_cpu_init(gator_cpu, type);
548                         }
549                         /* Initialize gator_attrs for dynamic PMUs here */
550                 }
551
552                 perf_event_release_kernel(pe);
553         }
554
555         if (!found_cpu) {
556                 const struct gator_cpu *gator_cpu = gator_find_cpu_by_cpuid(gator_cpuid());
557
558                 if (gator_cpu == NULL) {
559                         gator_cpu = gator_find_cpu_by_cpuid(OTHER);
560                         if (gator_cpu == NULL) {
561                                 pr_err("gator: Didn't find cpu\n");
562                                 return -1;
563                         }
564                 }
565                 gator_events_perf_pmu_cpu_init(gator_cpu, PERF_TYPE_RAW);
566         }
567
568         /* Initialize gator_attrs for non-dynamic PMUs here */
569
570         if (attr_count > CNTMAX) {
571                 pr_err("gator: Too many perf counters\n");
572                 return -1;
573         }
574
575         if (uc_attr_count > UCCNT) {
576                 pr_err("gator: Too many perf uncore counters\n");
577                 return -1;
578         }
579
580         return gator_events_install(&gator_events_perf_pmu_interface);
581 }
582
583 #endif