]> rtime.felk.cvut.cz Git - sojka/nv-tegra/linux-3.10.git/blob - drivers/misc/tegra-profiler/main.c
misc: tegra-profiler: fix debug preempt warnings
[sojka/nv-tegra/linux-3.10.git] / drivers / misc / tegra-profiler / main.c
1 /*
2  * drivers/misc/tegra-profiler/main.c
3  *
4  * Copyright (c) 2015, NVIDIA CORPORATION.  All rights reserved.
5  *
6  * This program is free software; you can redistribute it and/or modify it
7  * under the terms and conditions of the GNU General Public License,
8  * version 2, as published by the Free Software Foundation.
9  *
10  * This program is distributed in the hope it will be useful, but WITHOUT
11  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
13  * more details.
14  *
15  */
16
17 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
18
19 #include <linux/init.h>
20 #include <linux/module.h>
21 #include <linux/err.h>
22 #include <linux/sched.h>
23
24 #include <linux/tegra_profiler.h>
25
26 #include "quadd.h"
27 #include "arm_pmu.h"
28 #include "hrt.h"
29 #include "comm.h"
30 #include "mmap.h"
31 #include "debug.h"
32 #include "tegra.h"
33 #include "power_clk.h"
34 #include "auth.h"
35 #include "version.h"
36 #include "quadd_proc.h"
37 #include "eh_unwind.h"
38
39 #ifdef CONFIG_ARM64
40 #include "armv8_pmu.h"
41 #else
42 #include "armv7_pmu.h"
43 #endif
44
45 #ifdef CONFIG_CACHE_L2X0
46 #include "pl310.h"
47 #endif
48
49 static struct quadd_ctx ctx;
50
51 static int get_default_properties(void)
52 {
53         ctx.param.freq = 100;
54         ctx.param.ma_freq = 50;
55         ctx.param.backtrace = 1;
56         ctx.param.use_freq = 1;
57         ctx.param.system_wide = 1;
58         ctx.param.power_rate_freq = 0;
59         ctx.param.debug_samples = 0;
60
61         ctx.param.pids[0] = 0;
62         ctx.param.nr_pids = 1;
63
64         return 0;
65 }
66
67 int tegra_profiler_try_lock(void)
68 {
69         return atomic_cmpxchg(&ctx.tegra_profiler_lock, 0, 1);
70 }
71 EXPORT_SYMBOL_GPL(tegra_profiler_try_lock);
72
73 void tegra_profiler_unlock(void)
74 {
75         atomic_set(&ctx.tegra_profiler_lock, 0);
76 }
77 EXPORT_SYMBOL_GPL(tegra_profiler_unlock);
78
79 static int start(void)
80 {
81         int err;
82
83         if (tegra_profiler_try_lock()) {
84                 pr_err("Error: tegra_profiler lock\n");
85                 return -EBUSY;
86         }
87
88         preempt_disable();
89
90         if (!atomic_cmpxchg(&ctx.started, 0, 1)) {
91                 if (ctx.pmu) {
92                         err = ctx.pmu->enable();
93                         if (err) {
94                                 pr_err("error: pmu enable\n");
95                                 goto errout;
96                         }
97                 }
98
99                 if (ctx.pl310) {
100                         err = ctx.pl310->enable();
101                         if (err) {
102                                 pr_err("error: pl310 enable\n");
103                                 goto errout;
104                         }
105                 }
106
107                 ctx.comm->reset();
108
109                 err = quadd_power_clk_start();
110                 if (err < 0) {
111                         pr_err("error: power_clk start\n");
112                         goto errout;
113                 }
114
115                 err = quadd_hrt_start();
116                 if (err) {
117                         pr_err("error: hrt start\n");
118                         goto errout;
119                 }
120         }
121
122         preempt_enable();
123         return 0;
124
125 errout:
126         atomic_set(&ctx.started, 0);
127         tegra_profiler_unlock();
128         preempt_enable();
129
130         return err;
131 }
132
133 static void stop(void)
134 {
135         preempt_disable();
136
137         if (atomic_cmpxchg(&ctx.started, 1, 0)) {
138                 quadd_hrt_stop();
139
140                 ctx.comm->reset();
141
142                 quadd_power_clk_stop();
143                 quadd_unwind_stop();
144
145                 if (ctx.pmu)
146                         ctx.pmu->disable();
147
148                 if (ctx.pl310)
149                         ctx.pl310->disable();
150
151                 tegra_profiler_unlock();
152         }
153
154         preempt_enable();
155 }
156
157 static inline int is_event_supported(struct source_info *si, int event)
158 {
159         int i;
160         int nr = si->nr_supported_events;
161         int *events = si->supported_events;
162
163         for (i = 0; i < nr; i++) {
164                 if (event == events[i])
165                         return 1;
166         }
167         return 0;
168 }
169
170 static int
171 validate_freq(unsigned int freq)
172 {
173         return freq >= 100 && freq <= 100000;
174 }
175
176 static int
177 set_parameters(struct quadd_parameters *p, uid_t *debug_app_uid)
178 {
179         int i, err, uid = 0;
180         int pmu_events_id[QUADD_MAX_COUNTERS];
181         int pl310_events_id;
182         int nr_pmu = 0, nr_pl310 = 0;
183         struct task_struct *task;
184         unsigned int extra;
185         u64 *low_addr_p;
186
187         if (!validate_freq(p->freq)) {
188                 pr_err("%s: incorrect frequency: %u\n", __func__, p->freq);
189                 return -EINVAL;
190         }
191
192         ctx.param = *p;
193
194         for (i = 0; i < ARRAY_SIZE(p->reserved); i++)
195                 ctx.param.reserved[i] = p->reserved[i];
196
197         /* Currently only one process */
198         if (p->nr_pids != 1)
199                 return -EINVAL;
200
201         p->package_name[sizeof(p->package_name) - 1] = '\0';
202
203         rcu_read_lock();
204         task = pid_task(find_vpid(p->pids[0]), PIDTYPE_PID);
205         rcu_read_unlock();
206         if (!task) {
207                 pr_err("Process not found: %u\n", p->pids[0]);
208                 return -ESRCH;
209         }
210
211         pr_info("owner/task uids: %u/%u\n", current_fsuid(), task_uid(task));
212         if (!capable(CAP_SYS_ADMIN)) {
213                 if (current_fsuid() != task_uid(task)) {
214                         uid = quadd_auth_is_debuggable((char *)p->package_name);
215                         if (uid < 0) {
216                                 pr_err("Error: QuadD security service\n");
217                                 return uid;
218                         } else if (uid == 0) {
219                                 pr_err("Error: app is not debuggable\n");
220                                 return -EACCES;
221                         }
222
223                         *debug_app_uid = uid;
224                         pr_info("debug_app_uid: %u\n", uid);
225                 }
226                 ctx.collect_kernel_ips = 0;
227         } else {
228                 ctx.collect_kernel_ips = 1;
229         }
230
231         for (i = 0; i < p->nr_pids; i++)
232                 ctx.param.pids[i] = p->pids[i];
233
234         ctx.param.nr_pids = p->nr_pids;
235
236         for (i = 0; i < p->nr_events; i++) {
237                 int event = p->events[i];
238
239                 if (ctx.pmu && ctx.pmu_info.nr_supported_events > 0
240                         && is_event_supported(&ctx.pmu_info, event)) {
241                         pmu_events_id[nr_pmu++] = p->events[i];
242
243                         pr_info("PMU active event: %s\n",
244                                 quadd_get_event_str(event));
245                 } else if (ctx.pl310 &&
246                            ctx.pl310_info.nr_supported_events > 0 &&
247                            is_event_supported(&ctx.pl310_info, event)) {
248                         pl310_events_id = p->events[i];
249
250                         pr_info("PL310 active event: %s\n",
251                                 quadd_get_event_str(event));
252
253                         if (nr_pl310++ > 1) {
254                                 pr_err("error: multiply pl310 events\n");
255                                 return -EINVAL;
256                         }
257                 } else {
258                         pr_err("Bad event: %s\n",
259                                quadd_get_event_str(event));
260                         return -EINVAL;
261                 }
262         }
263
264         if (ctx.pmu) {
265                 if (nr_pmu > 0) {
266                         err = ctx.pmu->set_events(pmu_events_id, nr_pmu);
267                         if (err) {
268                                 pr_err("PMU set parameters: error\n");
269                                 return err;
270                         }
271                         ctx.pmu_info.active = 1;
272                 } else {
273                         ctx.pmu_info.active = 0;
274                         ctx.pmu->set_events(NULL, 0);
275                 }
276         }
277
278         if (ctx.pl310) {
279                 if (nr_pl310 == 1) {
280                         err = ctx.pl310->set_events(&pl310_events_id, 1);
281                         if (err) {
282                                 pr_info("pl310 set_parameters: error\n");
283                                 return err;
284                         }
285                         ctx.pl310_info.active = 1;
286                 } else {
287                         ctx.pl310_info.active = 0;
288                         ctx.pl310->set_events(NULL, 0);
289                 }
290         }
291
292         extra = p->reserved[QUADD_PARAM_IDX_EXTRA];
293
294         if (extra & QUADD_PARAM_EXTRA_BT_UNWIND_TABLES)
295                 pr_info("unwinding: exception-handling tables\n");
296
297         if (extra & QUADD_PARAM_EXTRA_BT_FP)
298                 pr_info("unwinding: frame pointers\n");
299
300         if (extra & QUADD_PARAM_EXTRA_BT_MIXED)
301                 pr_info("unwinding: mixed mode\n");
302
303         low_addr_p = (u64 *)&p->reserved[QUADD_PARAM_IDX_BT_LOWER_BOUND];
304         ctx.hrt->low_addr = (unsigned long)*low_addr_p;
305         pr_info("bt lower bound: %#lx\n", ctx.hrt->low_addr);
306
307         err = quadd_unwind_start(task);
308         if (err)
309                 return err;
310
311         pr_info("New parameters have been applied\n");
312
313         return 0;
314 }
315
316 static void get_capabilities(struct quadd_comm_cap *cap)
317 {
318         int i, event;
319         unsigned int extra = 0;
320         struct quadd_events_cap *events_cap = &cap->events_cap;
321
322         cap->pmu = ctx.pmu ? 1 : 0;
323
324         cap->l2_cache = 0;
325         if (ctx.pl310) {
326                 cap->l2_cache = 1;
327                 cap->l2_multiple_events = 0;
328         } else if (ctx.pmu) {
329                 struct source_info *s = &ctx.pmu_info;
330                 for (i = 0; i < s->nr_supported_events; i++) {
331                         event = s->supported_events[i];
332                         if (event == QUADD_EVENT_TYPE_L2_DCACHE_READ_MISSES ||
333                             event == QUADD_EVENT_TYPE_L2_DCACHE_WRITE_MISSES ||
334                             event == QUADD_EVENT_TYPE_L2_ICACHE_MISSES) {
335                                 cap->l2_cache = 1;
336                                 cap->l2_multiple_events = 1;
337                                 break;
338                         }
339                 }
340         }
341
342         events_cap->cpu_cycles = 0;
343         events_cap->l1_dcache_read_misses = 0;
344         events_cap->l1_dcache_write_misses = 0;
345         events_cap->l1_icache_misses = 0;
346
347         events_cap->instructions = 0;
348         events_cap->branch_instructions = 0;
349         events_cap->branch_misses = 0;
350         events_cap->bus_cycles = 0;
351
352         events_cap->l2_dcache_read_misses = 0;
353         events_cap->l2_dcache_write_misses = 0;
354         events_cap->l2_icache_misses = 0;
355
356         if (ctx.pl310) {
357                 struct source_info *s = &ctx.pl310_info;
358                 for (i = 0; i < s->nr_supported_events; i++) {
359                         int event = s->supported_events[i];
360
361                         switch (event) {
362                         case QUADD_EVENT_TYPE_L2_DCACHE_READ_MISSES:
363                                 events_cap->l2_dcache_read_misses = 1;
364                                 break;
365                         case QUADD_EVENT_TYPE_L2_DCACHE_WRITE_MISSES:
366                                 events_cap->l2_dcache_write_misses = 1;
367                                 break;
368                         case QUADD_EVENT_TYPE_L2_ICACHE_MISSES:
369                                 events_cap->l2_icache_misses = 1;
370                                 break;
371
372                         default:
373                                 pr_err_once("%s: error: invalid event\n",
374                                             __func__);
375                                 return;
376                         }
377                 }
378         }
379
380         if (ctx.pmu) {
381                 struct source_info *s = &ctx.pmu_info;
382                 for (i = 0; i < s->nr_supported_events; i++) {
383                         int event = s->supported_events[i];
384
385                         switch (event) {
386                         case QUADD_EVENT_TYPE_CPU_CYCLES:
387                                 events_cap->cpu_cycles = 1;
388                                 break;
389                         case QUADD_EVENT_TYPE_INSTRUCTIONS:
390                                 events_cap->instructions = 1;
391                                 break;
392                         case QUADD_EVENT_TYPE_BRANCH_INSTRUCTIONS:
393                                 events_cap->branch_instructions = 1;
394                                 break;
395                         case QUADD_EVENT_TYPE_BRANCH_MISSES:
396                                 events_cap->branch_misses = 1;
397                                 break;
398                         case QUADD_EVENT_TYPE_BUS_CYCLES:
399                                 events_cap->bus_cycles = 1;
400                                 break;
401
402                         case QUADD_EVENT_TYPE_L1_DCACHE_READ_MISSES:
403                                 events_cap->l1_dcache_read_misses = 1;
404                                 break;
405                         case QUADD_EVENT_TYPE_L1_DCACHE_WRITE_MISSES:
406                                 events_cap->l1_dcache_write_misses = 1;
407                                 break;
408                         case QUADD_EVENT_TYPE_L1_ICACHE_MISSES:
409                                 events_cap->l1_icache_misses = 1;
410                                 break;
411
412                         case QUADD_EVENT_TYPE_L2_DCACHE_READ_MISSES:
413                                 events_cap->l2_dcache_read_misses = 1;
414                                 break;
415                         case QUADD_EVENT_TYPE_L2_DCACHE_WRITE_MISSES:
416                                 events_cap->l2_dcache_write_misses = 1;
417                                 break;
418                         case QUADD_EVENT_TYPE_L2_ICACHE_MISSES:
419                                 events_cap->l2_icache_misses = 1;
420                                 break;
421
422                         default:
423                                 pr_err_once("%s: error: invalid event\n",
424                                             __func__);
425                                 return;
426                         }
427                 }
428         }
429
430         cap->tegra_lp_cluster = quadd_is_cpu_with_lp_cluster();
431         cap->power_rate = 1;
432         cap->blocked_read = 1;
433
434         extra |= QUADD_COMM_CAP_EXTRA_BT_KERNEL_CTX;
435         extra |= QUADD_COMM_CAP_EXTRA_GET_MMAP;
436         extra |= QUADD_COMM_CAP_EXTRA_GROUP_SAMPLES;
437         extra |= QUADD_COMM_CAP_EXTRA_BT_UNWIND_TABLES;
438         extra |= QUADD_COMM_CAP_EXTRA_SUPPORT_AARCH64;
439         extra |= QUADD_COMM_CAP_EXTRA_SPECIAL_ARCH_MMAP;
440         extra |= QUADD_COMM_CAP_EXTRA_UNWIND_MIXED;
441         extra |= QUADD_COMM_CAP_EXTRA_UNW_ENTRY_TYPE;
442         extra |= QUADD_COMM_CAP_EXTRA_RB_MMAP_OP;
443
444         if (ctx.hrt->tc)
445                 extra |= QUADD_COMM_CAP_EXTRA_ARCH_TIMER;
446
447         cap->reserved[QUADD_COMM_CAP_IDX_EXTRA] = extra;
448 }
449
450 void quadd_get_state(struct quadd_module_state *state)
451 {
452         unsigned int status = 0;
453
454         quadd_hrt_get_state(state);
455
456         if (ctx.comm->is_active())
457                 status |= QUADD_MOD_STATE_STATUS_IS_ACTIVE;
458
459         if (quadd_auth_is_auth_open())
460                 status |= QUADD_MOD_STATE_STATUS_IS_AUTH_OPEN;
461
462         state->reserved[QUADD_MOD_STATE_IDX_STATUS] = status;
463 }
464
465 static int
466 set_extab(struct quadd_extables *extabs,
467           struct quadd_mmap_area *mmap)
468 {
469         return quadd_unwind_set_extab(extabs, mmap);
470 }
471
472 static void
473 delete_mmap(struct quadd_mmap_area *mmap)
474 {
475         quadd_unwind_delete_mmap(mmap);
476 }
477
478 static struct quadd_comm_control_interface control = {
479         .start                  = start,
480         .stop                   = stop,
481         .set_parameters         = set_parameters,
482         .get_capabilities       = get_capabilities,
483         .get_state              = quadd_get_state,
484         .set_extab              = set_extab,
485         .delete_mmap            = delete_mmap,
486 };
487
488 static int __init quadd_module_init(void)
489 {
490         int i, nr_events, err;
491         int *events;
492
493         pr_info("Branch: %s\n", QUADD_MODULE_BRANCH);
494         pr_info("Version: %s\n", QUADD_MODULE_VERSION);
495         pr_info("Samples version: %d\n", QUADD_SAMPLES_VERSION);
496         pr_info("IO version: %d\n", QUADD_IO_VERSION);
497
498 #ifdef QM_DEBUG_SAMPLES_ENABLE
499         pr_info("############## DEBUG VERSION! ##############\n");
500 #endif
501
502         atomic_set(&ctx.started, 0);
503         atomic_set(&ctx.tegra_profiler_lock, 0);
504
505         get_default_properties();
506
507         ctx.pmu_info.active = 0;
508         ctx.pl310_info.active = 0;
509
510 #ifdef CONFIG_ARM64
511         ctx.pmu = quadd_armv8_pmu_init();
512 #else
513         ctx.pmu = quadd_armv7_pmu_init();
514 #endif
515         if (!ctx.pmu) {
516                 pr_err("PMU init failed\n");
517                 return -ENODEV;
518         } else {
519                 events = ctx.pmu_info.supported_events;
520                 nr_events = ctx.pmu->get_supported_events(events,
521                                                           QUADD_MAX_COUNTERS);
522                 ctx.pmu_info.nr_supported_events = nr_events;
523
524                 pr_debug("PMU: amount of events: %d\n", nr_events);
525
526                 for (i = 0; i < nr_events; i++)
527                         pr_debug("PMU event: %s\n",
528                                  quadd_get_event_str(events[i]));
529         }
530
531 #ifdef CONFIG_CACHE_L2X0
532         ctx.pl310 = quadd_l2x0_events_init();
533 #else
534         ctx.pl310 = NULL;
535 #endif
536         if (ctx.pl310) {
537                 events = ctx.pl310_info.supported_events;
538                 nr_events = ctx.pl310->get_supported_events(events,
539                                                             QUADD_MAX_COUNTERS);
540                 ctx.pl310_info.nr_supported_events = nr_events;
541
542                 pr_info("pl310 success, amount of events: %d\n",
543                         nr_events);
544
545                 for (i = 0; i < nr_events; i++)
546                         pr_info("pl310 event: %s\n",
547                                 quadd_get_event_str(events[i]));
548         } else {
549                 pr_debug("PL310 not found\n");
550         }
551
552         ctx.hrt = quadd_hrt_init(&ctx);
553         if (IS_ERR(ctx.hrt)) {
554                 pr_err("error: HRT init failed\n");
555                 return PTR_ERR(ctx.hrt);
556         }
557
558         err = quadd_power_clk_init(&ctx);
559         if (err < 0) {
560                 pr_err("error: POWER CLK init failed\n");
561                 return err;
562         }
563
564         ctx.comm = quadd_comm_events_init(&control);
565         if (IS_ERR(ctx.comm)) {
566                 pr_err("error: COMM init failed\n");
567                 return PTR_ERR(ctx.comm);
568         }
569
570         err = quadd_auth_init(&ctx);
571         if (err < 0) {
572                 pr_err("error: auth failed\n");
573                 return err;
574         }
575
576         err = quadd_unwind_init();
577         if (err < 0) {
578                 pr_err("error: EH unwinding init failed\n");
579                 return err;
580         }
581
582         get_capabilities(&ctx.cap);
583         quadd_proc_init(&ctx);
584
585         return 0;
586 }
587
588 static void __exit quadd_module_exit(void)
589 {
590         pr_info("QuadD module exit\n");
591
592         quadd_hrt_deinit();
593         quadd_power_clk_deinit();
594         quadd_comm_events_exit();
595         quadd_auth_deinit();
596         quadd_proc_deinit();
597         quadd_unwind_deinit();
598
599 #ifdef CONFIG_ARM64
600         quadd_armv8_pmu_deinit();
601 #else
602         quadd_armv7_pmu_deinit();
603 #endif
604 }
605
606 module_init(quadd_module_init);
607 module_exit(quadd_module_exit);
608
609 MODULE_LICENSE("GPL");
610
611 MODULE_AUTHOR("Nvidia Ltd");
612 MODULE_DESCRIPTION("Tegra profiler");