2 * drivers/misc/tegra-profiler/main.c
4 * Copyright (c) 2015, NVIDIA CORPORATION. All rights reserved.
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.
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
17 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
19 #include <linux/init.h>
20 #include <linux/module.h>
21 #include <linux/err.h>
22 #include <linux/sched.h>
24 #include <linux/tegra_profiler.h>
33 #include "power_clk.h"
36 #include "quadd_proc.h"
37 #include "eh_unwind.h"
40 #include "armv8_pmu.h"
42 #include "armv7_pmu.h"
45 #ifdef CONFIG_CACHE_L2X0
49 static struct quadd_ctx ctx;
51 static int get_default_properties(void)
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;
61 ctx.param.pids[0] = 0;
62 ctx.param.nr_pids = 1;
67 int tegra_profiler_try_lock(void)
69 return atomic_cmpxchg(&ctx.tegra_profiler_lock, 0, 1);
71 EXPORT_SYMBOL_GPL(tegra_profiler_try_lock);
73 void tegra_profiler_unlock(void)
75 atomic_set(&ctx.tegra_profiler_lock, 0);
77 EXPORT_SYMBOL_GPL(tegra_profiler_unlock);
79 static int start(void)
83 if (tegra_profiler_try_lock()) {
84 pr_err("Error: tegra_profiler lock\n");
90 if (!atomic_cmpxchg(&ctx.started, 0, 1)) {
92 err = ctx.pmu->enable();
94 pr_err("error: pmu enable\n");
100 err = ctx.pl310->enable();
102 pr_err("error: pl310 enable\n");
109 err = quadd_power_clk_start();
111 pr_err("error: power_clk start\n");
115 err = quadd_hrt_start();
117 pr_err("error: hrt start\n");
126 atomic_set(&ctx.started, 0);
127 tegra_profiler_unlock();
133 static void stop(void)
137 if (atomic_cmpxchg(&ctx.started, 1, 0)) {
142 quadd_power_clk_stop();
149 ctx.pl310->disable();
151 tegra_profiler_unlock();
157 static inline int is_event_supported(struct source_info *si, int event)
160 int nr = si->nr_supported_events;
161 int *events = si->supported_events;
163 for (i = 0; i < nr; i++) {
164 if (event == events[i])
171 validate_freq(unsigned int freq)
173 return freq >= 100 && freq <= 100000;
177 set_parameters(struct quadd_parameters *p, uid_t *debug_app_uid)
180 int pmu_events_id[QUADD_MAX_COUNTERS];
182 int nr_pmu = 0, nr_pl310 = 0;
183 struct task_struct *task;
187 if (!validate_freq(p->freq)) {
188 pr_err("%s: incorrect frequency: %u\n", __func__, p->freq);
194 for (i = 0; i < ARRAY_SIZE(p->reserved); i++)
195 ctx.param.reserved[i] = p->reserved[i];
197 /* Currently only one process */
201 p->package_name[sizeof(p->package_name) - 1] = '\0';
204 task = pid_task(find_vpid(p->pids[0]), PIDTYPE_PID);
207 pr_err("Process not found: %u\n", p->pids[0]);
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);
216 pr_err("Error: QuadD security service\n");
218 } else if (uid == 0) {
219 pr_err("Error: app is not debuggable\n");
223 *debug_app_uid = uid;
224 pr_info("debug_app_uid: %u\n", uid);
226 ctx.collect_kernel_ips = 0;
228 ctx.collect_kernel_ips = 1;
231 for (i = 0; i < p->nr_pids; i++)
232 ctx.param.pids[i] = p->pids[i];
234 ctx.param.nr_pids = p->nr_pids;
236 for (i = 0; i < p->nr_events; i++) {
237 int event = p->events[i];
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];
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];
250 pr_info("PL310 active event: %s\n",
251 quadd_get_event_str(event));
253 if (nr_pl310++ > 1) {
254 pr_err("error: multiply pl310 events\n");
258 pr_err("Bad event: %s\n",
259 quadd_get_event_str(event));
266 err = ctx.pmu->set_events(pmu_events_id, nr_pmu);
268 pr_err("PMU set parameters: error\n");
271 ctx.pmu_info.active = 1;
273 ctx.pmu_info.active = 0;
274 ctx.pmu->set_events(NULL, 0);
280 err = ctx.pl310->set_events(&pl310_events_id, 1);
282 pr_info("pl310 set_parameters: error\n");
285 ctx.pl310_info.active = 1;
287 ctx.pl310_info.active = 0;
288 ctx.pl310->set_events(NULL, 0);
292 extra = p->reserved[QUADD_PARAM_IDX_EXTRA];
294 if (extra & QUADD_PARAM_EXTRA_BT_UNWIND_TABLES)
295 pr_info("unwinding: exception-handling tables\n");
297 if (extra & QUADD_PARAM_EXTRA_BT_FP)
298 pr_info("unwinding: frame pointers\n");
300 if (extra & QUADD_PARAM_EXTRA_BT_MIXED)
301 pr_info("unwinding: mixed mode\n");
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);
307 err = quadd_unwind_start(task);
311 pr_info("New parameters have been applied\n");
316 static void get_capabilities(struct quadd_comm_cap *cap)
319 unsigned int extra = 0;
320 struct quadd_events_cap *events_cap = &cap->events_cap;
322 cap->pmu = ctx.pmu ? 1 : 0;
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) {
336 cap->l2_multiple_events = 1;
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;
347 events_cap->instructions = 0;
348 events_cap->branch_instructions = 0;
349 events_cap->branch_misses = 0;
350 events_cap->bus_cycles = 0;
352 events_cap->l2_dcache_read_misses = 0;
353 events_cap->l2_dcache_write_misses = 0;
354 events_cap->l2_icache_misses = 0;
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];
362 case QUADD_EVENT_TYPE_L2_DCACHE_READ_MISSES:
363 events_cap->l2_dcache_read_misses = 1;
365 case QUADD_EVENT_TYPE_L2_DCACHE_WRITE_MISSES:
366 events_cap->l2_dcache_write_misses = 1;
368 case QUADD_EVENT_TYPE_L2_ICACHE_MISSES:
369 events_cap->l2_icache_misses = 1;
373 pr_err_once("%s: error: invalid event\n",
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];
386 case QUADD_EVENT_TYPE_CPU_CYCLES:
387 events_cap->cpu_cycles = 1;
389 case QUADD_EVENT_TYPE_INSTRUCTIONS:
390 events_cap->instructions = 1;
392 case QUADD_EVENT_TYPE_BRANCH_INSTRUCTIONS:
393 events_cap->branch_instructions = 1;
395 case QUADD_EVENT_TYPE_BRANCH_MISSES:
396 events_cap->branch_misses = 1;
398 case QUADD_EVENT_TYPE_BUS_CYCLES:
399 events_cap->bus_cycles = 1;
402 case QUADD_EVENT_TYPE_L1_DCACHE_READ_MISSES:
403 events_cap->l1_dcache_read_misses = 1;
405 case QUADD_EVENT_TYPE_L1_DCACHE_WRITE_MISSES:
406 events_cap->l1_dcache_write_misses = 1;
408 case QUADD_EVENT_TYPE_L1_ICACHE_MISSES:
409 events_cap->l1_icache_misses = 1;
412 case QUADD_EVENT_TYPE_L2_DCACHE_READ_MISSES:
413 events_cap->l2_dcache_read_misses = 1;
415 case QUADD_EVENT_TYPE_L2_DCACHE_WRITE_MISSES:
416 events_cap->l2_dcache_write_misses = 1;
418 case QUADD_EVENT_TYPE_L2_ICACHE_MISSES:
419 events_cap->l2_icache_misses = 1;
423 pr_err_once("%s: error: invalid event\n",
430 cap->tegra_lp_cluster = quadd_is_cpu_with_lp_cluster();
432 cap->blocked_read = 1;
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;
445 extra |= QUADD_COMM_CAP_EXTRA_ARCH_TIMER;
447 cap->reserved[QUADD_COMM_CAP_IDX_EXTRA] = extra;
450 void quadd_get_state(struct quadd_module_state *state)
452 unsigned int status = 0;
454 quadd_hrt_get_state(state);
456 if (ctx.comm->is_active())
457 status |= QUADD_MOD_STATE_STATUS_IS_ACTIVE;
459 if (quadd_auth_is_auth_open())
460 status |= QUADD_MOD_STATE_STATUS_IS_AUTH_OPEN;
462 state->reserved[QUADD_MOD_STATE_IDX_STATUS] = status;
466 set_extab(struct quadd_extables *extabs,
467 struct quadd_mmap_area *mmap)
469 return quadd_unwind_set_extab(extabs, mmap);
473 delete_mmap(struct quadd_mmap_area *mmap)
475 quadd_unwind_delete_mmap(mmap);
478 static struct quadd_comm_control_interface control = {
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,
488 static int __init quadd_module_init(void)
490 int i, nr_events, err;
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);
498 #ifdef QM_DEBUG_SAMPLES_ENABLE
499 pr_info("############## DEBUG VERSION! ##############\n");
502 atomic_set(&ctx.started, 0);
503 atomic_set(&ctx.tegra_profiler_lock, 0);
505 get_default_properties();
507 ctx.pmu_info.active = 0;
508 ctx.pl310_info.active = 0;
511 ctx.pmu = quadd_armv8_pmu_init();
513 ctx.pmu = quadd_armv7_pmu_init();
516 pr_err("PMU init failed\n");
519 events = ctx.pmu_info.supported_events;
520 nr_events = ctx.pmu->get_supported_events(events,
522 ctx.pmu_info.nr_supported_events = nr_events;
524 pr_debug("PMU: amount of events: %d\n", nr_events);
526 for (i = 0; i < nr_events; i++)
527 pr_debug("PMU event: %s\n",
528 quadd_get_event_str(events[i]));
531 #ifdef CONFIG_CACHE_L2X0
532 ctx.pl310 = quadd_l2x0_events_init();
537 events = ctx.pl310_info.supported_events;
538 nr_events = ctx.pl310->get_supported_events(events,
540 ctx.pl310_info.nr_supported_events = nr_events;
542 pr_info("pl310 success, amount of events: %d\n",
545 for (i = 0; i < nr_events; i++)
546 pr_info("pl310 event: %s\n",
547 quadd_get_event_str(events[i]));
549 pr_debug("PL310 not found\n");
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);
558 err = quadd_power_clk_init(&ctx);
560 pr_err("error: POWER CLK init failed\n");
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);
570 err = quadd_auth_init(&ctx);
572 pr_err("error: auth failed\n");
576 err = quadd_unwind_init();
578 pr_err("error: EH unwinding init failed\n");
582 get_capabilities(&ctx.cap);
583 quadd_proc_init(&ctx);
588 static void __exit quadd_module_exit(void)
590 pr_info("QuadD module exit\n");
593 quadd_power_clk_deinit();
594 quadd_comm_events_exit();
597 quadd_unwind_deinit();
600 quadd_armv8_pmu_deinit();
602 quadd_armv7_pmu_deinit();
606 module_init(quadd_module_init);
607 module_exit(quadd_module_exit);
609 MODULE_LICENSE("GPL");
611 MODULE_AUTHOR("Nvidia Ltd");
612 MODULE_DESCRIPTION("Tegra profiler");