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