summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorIgor Nabirushkin <inabirushkin@nvidia.com>2018-04-17 09:20:12 -0400
committermobile promotions <svcmobile_promotions@nvidia.com>2018-04-18 11:43:24 -0400
commitc3c4e00a8ddfcb888f640fc2aec3b69f53eae515 (patch)
tree98907deec98a81a43c4fbc1cfc81becca7a992b8
parente224e866f8b4b814b19ec854b49510507f0a06ae (diff)
misc: tegra-profiler: sample multiple processes
- Sample multiple processes. Add a few new modes. - Fix possible crash in d_path() during multiple execs. Bug 2104957 Bug 2100416 Change-Id: Iab1568de9365e1c719b45c65f490bbd212995b69 Signed-off-by: Igor Nabirushkin <inabirushkin@nvidia.com> Reviewed-on: https://git-master.nvidia.com/r/1696670 Reviewed-by: Automatic_Commit_Validation_User GVS: Gerrit_Virtual_Submit Reviewed-by: Dmitry Antipov <dantipov@nvidia.com> Reviewed-by: Sachin Nikam <snikam@nvidia.com> Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com> Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
-rw-r--r--drivers/misc/tegra-profiler/arm_pmu.h2
-rw-r--r--drivers/misc/tegra-profiler/comm.c10
-rw-r--r--drivers/misc/tegra-profiler/comm.h6
-rw-r--r--drivers/misc/tegra-profiler/hrt.c117
-rw-r--r--drivers/misc/tegra-profiler/hrt.h11
-rw-r--r--drivers/misc/tegra-profiler/main.c101
-rw-r--r--drivers/misc/tegra-profiler/mmap.c250
-rw-r--r--drivers/misc/tegra-profiler/mmap.h10
-rw-r--r--drivers/misc/tegra-profiler/quadd.h47
-rw-r--r--drivers/misc/tegra-profiler/quadd_proc.c2
-rw-r--r--drivers/misc/tegra-profiler/version.h2
-rw-r--r--include/linux/tegra_profiler.h68
12 files changed, 382 insertions, 244 deletions
diff --git a/drivers/misc/tegra-profiler/arm_pmu.h b/drivers/misc/tegra-profiler/arm_pmu.h
index 7e6558414..14aa684cb 100644
--- a/drivers/misc/tegra-profiler/arm_pmu.h
+++ b/drivers/misc/tegra-profiler/arm_pmu.h
@@ -34,7 +34,7 @@ struct quadd_pmu_event_info {
34struct quadd_arch_info { 34struct quadd_arch_info {
35 int type; 35 int type;
36 36
37 int pmuver; 37 unsigned int pmuver;
38 unsigned pmuver_is_set:1; 38 unsigned pmuver_is_set:1;
39 39
40 char name[QUADD_ARCH_NAME_MAX]; 40 char name[QUADD_ARCH_NAME_MAX];
diff --git a/drivers/misc/tegra-profiler/comm.c b/drivers/misc/tegra-profiler/comm.c
index 0f9cf2374..fb78e2542 100644
--- a/drivers/misc/tegra-profiler/comm.c
+++ b/drivers/misc/tegra-profiler/comm.c
@@ -46,6 +46,7 @@ struct quadd_ring_buffer {
46}; 46};
47 47
48struct quadd_comm_ctx { 48struct quadd_comm_ctx {
49 struct quadd_ctx *ctx;
49 struct quadd_comm_control_interface *control; 50 struct quadd_comm_control_interface *control;
50 51
51 atomic_t active; 52 atomic_t active;
@@ -387,7 +388,7 @@ ready_to_profile(void)
387 if (!comm_ctx.params_ok) 388 if (!comm_ctx.params_ok)
388 return 0; 389 return 0;
389 390
390 if (quadd_mode_is_sampling()) { 391 if (quadd_mode_is_sampling(comm_ctx.ctx)) {
391 for_each_possible_cpu(cpuid) { 392 for_each_possible_cpu(cpuid) {
392 is_cpu_present = 393 is_cpu_present =
393 comm_ctx.control->is_cpu_present(cpuid); 394 comm_ctx.control->is_cpu_present(cpuid);
@@ -457,7 +458,7 @@ device_ioctl(struct file *file,
457 } 458 }
458 459
459 if (!comm_ctx.params_ok || 460 if (!comm_ctx.params_ok ||
460 !quadd_mode_is_sampling()) { 461 !quadd_mode_is_sampling(comm_ctx.ctx)) {
461 pr_err("error: incorrect setup ioctl\n"); 462 pr_err("error: incorrect setup ioctl\n");
462 err = -EPERM; 463 err = -EPERM;
463 goto error_out; 464 goto error_out;
@@ -932,10 +933,13 @@ static int comm_init(void)
932} 933}
933 934
934struct quadd_comm_data_interface * 935struct quadd_comm_data_interface *
935quadd_comm_events_init(struct quadd_comm_control_interface *control) 936quadd_comm_events_init(struct quadd_ctx *ctx,
937 struct quadd_comm_control_interface *control)
936{ 938{
937 int err; 939 int err;
938 940
941 comm_ctx.ctx = ctx;
942
939 err = comm_init(); 943 err = comm_init();
940 if (err < 0) 944 if (err < 0)
941 return ERR_PTR(err); 945 return ERR_PTR(err);
diff --git a/drivers/misc/tegra-profiler/comm.h b/drivers/misc/tegra-profiler/comm.h
index eca48a9b6..b3755a82d 100644
--- a/drivers/misc/tegra-profiler/comm.h
+++ b/drivers/misc/tegra-profiler/comm.h
@@ -1,7 +1,7 @@
1/* 1/*
2 * drivers/misc/tegra-profiler/comm.h 2 * drivers/misc/tegra-profiler/comm.h
3 * 3 *
4 * Copyright (c) 2013-2017, NVIDIA CORPORATION. All rights reserved. 4 * Copyright (c) 2013-2018, NVIDIA CORPORATION. All rights reserved.
5 * 5 *
6 * This program is free software; you can redistribute it and/or modify it 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, 7 * under the terms and conditions of the GNU General Public License,
@@ -19,6 +19,7 @@
19 19
20#include <linux/types.h> 20#include <linux/types.h>
21 21
22struct quadd_ctx;
22struct quadd_record_data; 23struct quadd_record_data;
23struct quadd_comm_cap; 24struct quadd_comm_cap;
24struct quadd_module_state; 25struct quadd_module_state;
@@ -85,7 +86,8 @@ struct quadd_comm_data_interface {
85}; 86};
86 87
87struct quadd_comm_data_interface * 88struct quadd_comm_data_interface *
88quadd_comm_events_init(struct quadd_comm_control_interface *control); 89quadd_comm_events_init(struct quadd_ctx *ctx,
90 struct quadd_comm_control_interface *control);
89void quadd_comm_events_exit(void); 91void quadd_comm_events_exit(void);
90 92
91#endif /* __QUADD_COMM_H__ */ 93#endif /* __QUADD_COMM_H__ */
diff --git a/drivers/misc/tegra-profiler/hrt.c b/drivers/misc/tegra-profiler/hrt.c
index ec45b0f4b..126c7f579 100644
--- a/drivers/misc/tegra-profiler/hrt.c
+++ b/drivers/misc/tegra-profiler/hrt.c
@@ -210,10 +210,18 @@ static void put_header(int cpuid)
210 210
211 hdr->reserved |= QUADD_HDR_HAS_CPUID; 211 hdr->reserved |= QUADD_HDR_HAS_CPUID;
212 212
213 if (quadd_mode_is_trace_all()) 213 if (quadd_mode_is_sampling(ctx))
214 hdr->reserved |= QUADD_HDR_MODE_TRACE_ALL;
215 if (quadd_mode_is_sampling())
216 hdr->reserved |= QUADD_HDR_MODE_SAMPLING; 214 hdr->reserved |= QUADD_HDR_MODE_SAMPLING;
215 if (quadd_mode_is_tracing(ctx))
216 hdr->reserved |= QUADD_HDR_MODE_TRACING;
217 if (quadd_mode_is_sample_all(ctx))
218 hdr->reserved |= QUADD_HDR_MODE_SAMPLE_ALL;
219 if (quadd_mode_is_trace_all(ctx))
220 hdr->reserved |= QUADD_HDR_MODE_TRACE_ALL;
221 if (quadd_mode_is_sample_tree(ctx))
222 hdr->reserved |= QUADD_HDR_MODE_SAMPLE_TREE;
223 if (quadd_mode_is_trace_tree(ctx))
224 hdr->reserved |= QUADD_HDR_MODE_TRACE_TREE;
217 225
218 if (pmu) 226 if (pmu)
219 nr_events += pmu->get_current_events(cpuid, events + nr_events, 227 nr_events += pmu->get_current_events(cpuid, events + nr_events,
@@ -373,6 +381,14 @@ get_stack_offset(struct task_struct *task,
373 return vma->vm_end - sp; 381 return vma->vm_end - sp;
374} 382}
375 383
384static inline void
385validate_um_for_task(struct task_struct *task,
386 pid_t param_pid, struct quadd_unw_methods *um)
387{
388 if (task_tgid_nr(task) != param_pid)
389 um->ut = um->dwarf = 0;
390}
391
376static void 392static void
377read_all_sources(struct pt_regs *regs, struct task_struct *task, int is_sched) 393read_all_sources(struct pt_regs *regs, struct task_struct *task, int is_sched)
378{ 394{
@@ -436,6 +452,7 @@ read_all_sources(struct pt_regs *regs, struct task_struct *task, int is_sched)
436 452
437 if (ctx->param.backtrace) { 453 if (ctx->param.backtrace) {
438 cc->um = hrt.um; 454 cc->um = hrt.um;
455 validate_um_for_task(task, ctx->param.pids[0], &cc->um);
439 456
440 bt_size = quadd_get_user_callchain(&event_ctx, cc, ctx); 457 bt_size = quadd_get_user_callchain(&event_ctx, cc, ctx);
441 if (bt_size > 0) { 458 if (bt_size > 0) {
@@ -538,55 +555,69 @@ read_all_sources(struct pt_regs *regs, struct task_struct *task, int is_sched)
538} 555}
539 556
540static inline int 557static inline int
541is_profile_process(struct task_struct *task) 558is_profile_process(struct task_struct *task, int is_trace)
542{ 559{
543 int i; 560 pid_t pid;
544 pid_t pid, profile_pid;
545 struct quadd_ctx *ctx = hrt.quadd_ctx; 561 struct quadd_ctx *ctx = hrt.quadd_ctx;
546 562
547 if (!task) 563 pid = ctx->param.pids[0];
548 return 0; 564
565 if (task_tgid_nr(task) == pid)
566 return 1;
567
568 if ((is_trace && quadd_mode_is_trace_tree(ctx)) ||
569 (!is_trace && quadd_mode_is_sample_tree(ctx))) {
570 struct task_struct *p;
549 571
550 pid = task->tgid; 572 read_lock(&tasklist_lock);
573 for (p = task; p != &init_task;) {
574 if (task_pid_nr(p) == pid) {
575 read_unlock(&tasklist_lock);
576 return 1;
577 }
551 578
552 for (i = 0; i < ctx->param.nr_pids; i++) { 579 rcu_read_lock();
553 profile_pid = ctx->param.pids[i]; 580 p = rcu_dereference(p->real_parent);
554 if (profile_pid == pid) 581 rcu_read_unlock();
555 return 1; 582 }
583 read_unlock(&tasklist_lock);
556 } 584 }
557 585
558 return 0; 586 return 0;
559} 587}
560 588
561static inline int 589static inline int
562is_sample_process(struct task_struct *task) 590is_swapper_task(struct task_struct *task)
563{ 591{
564 return (quadd_mode_is_sampling() && 592 return task_pid_nr(task) == 0;
565 is_profile_process(task));
566} 593}
567 594
568static inline int 595static inline int
569is_swapper_task(struct task_struct *task) 596validate_task(struct task_struct *task)
570{ 597{
571 if (task->pid == 0) 598 return task && task->mm && !is_swapper_task(task);
572 return 1; 599}
573 600
574 return 0; 601static inline int
602is_sample_process(struct task_struct *task)
603{
604 struct quadd_ctx *ctx = hrt.quadd_ctx;
605
606 if (!validate_task(task) || !quadd_mode_is_sampling(ctx))
607 return 0;
608
609 return (quadd_mode_is_sample_all(ctx) || is_profile_process(task, 0));
575} 610}
576 611
577static inline int 612static inline int
578is_trace_process(struct task_struct *task) 613is_trace_process(struct task_struct *task)
579{ 614{
580 if (!task) 615 struct quadd_ctx *ctx = hrt.quadd_ctx;
581 return 0;
582 616
583 if (is_swapper_task(task)) 617 if (!validate_task(task) || !quadd_mode_is_tracing(ctx))
584 return 0; 618 return 0;
585 619
586 if (quadd_mode_is_trace_all()) 620 return (quadd_mode_is_trace_all(ctx) || is_profile_process(task, 1));
587 return 1;
588
589 return is_profile_process(task);
590} 621}
591 622
592static int 623static int
@@ -702,16 +733,13 @@ void __quadd_task_sched_out(struct task_struct *prev,
702 733
703void __quadd_event_mmap(struct vm_area_struct *vma) 734void __quadd_event_mmap(struct vm_area_struct *vma)
704{ 735{
705 struct quadd_parameters *param; 736 if (likely(!atomic_read(&hrt.mmap_active)))
706
707 if (likely(!atomic_read(&hrt.active)))
708 return; 737 return;
709 738
710 if (!is_sample_process(current)) 739 if (!is_sample_process(current))
711 return; 740 return;
712 741
713 param = &hrt.quadd_ctx->param; 742 quadd_process_mmap(vma, current);
714 quadd_process_mmap(vma, param->pids[0]);
715} 743}
716 744
717static void reset_cpu_ctx(void) 745static void reset_cpu_ctx(void)
@@ -733,7 +761,6 @@ static void reset_cpu_ctx(void)
733 761
734int quadd_hrt_start(void) 762int quadd_hrt_start(void)
735{ 763{
736 int err;
737 int cpuid; 764 int cpuid;
738 u64 period; 765 u64 period;
739 long freq; 766 long freq;
@@ -787,14 +814,16 @@ int quadd_hrt_start(void)
787 put_header(cpuid); 814 put_header(cpuid);
788 } 815 }
789 816
790 if (quadd_mode_is_sampling()) { 817 atomic_set(&hrt.mmap_active, 1);
791 if (extra & QUADD_PARAM_EXTRA_GET_MMAP) { 818
792 err = quadd_get_current_mmap(param->pids[0]); 819 /* Enable the mmap events processing before quadd_get_mmaps()
793 if (err) { 820 * otherwise we can miss some events.
794 pr_err("error: quadd_get_current_mmap\n"); 821 */
795 return err; 822 smp_wmb();
796 } 823
797 } 824 if (quadd_mode_is_sampling(ctx)) {
825 if (extra & QUADD_PARAM_EXTRA_GET_MMAP)
826 quadd_get_mmaps(ctx);
798 827
799 if (ctx->pl310) 828 if (ctx->pl310)
800 ctx->pl310->start(); 829 ctx->pl310->start();
@@ -802,6 +831,9 @@ int quadd_hrt_start(void)
802 831
803 quadd_ma_start(&hrt); 832 quadd_ma_start(&hrt);
804 833
834 /* Enable the sampling only after quadd_get_mmaps() */
835 smp_wmb();
836
805 atomic_set(&hrt.active, 1); 837 atomic_set(&hrt.active, 1);
806 838
807 pr_info("Start hrt: freq/period: %ld/%llu\n", freq, period); 839 pr_info("Start hrt: freq/period: %ld/%llu\n", freq, period);
@@ -822,6 +854,7 @@ void quadd_hrt_stop(void)
822 quadd_ma_stop(&hrt); 854 quadd_ma_stop(&hrt);
823 855
824 atomic_set(&hrt.active, 0); 856 atomic_set(&hrt.active, 0);
857 atomic_set(&hrt.mmap_active, 0);
825 858
826 atomic64_set(&hrt.counter_samples, 0); 859 atomic64_set(&hrt.counter_samples, 0);
827 atomic64_set(&hrt.skipped_samples, 0); 860 atomic64_set(&hrt.skipped_samples, 0);
@@ -870,7 +903,9 @@ struct quadd_hrt_ctx *quadd_hrt_init(struct quadd_ctx *ctx)
870 struct quadd_cpu_context *cpu_ctx; 903 struct quadd_cpu_context *cpu_ctx;
871 904
872 hrt.quadd_ctx = ctx; 905 hrt.quadd_ctx = ctx;
906
873 atomic_set(&hrt.active, 0); 907 atomic_set(&hrt.active, 0);
908 atomic_set(&hrt.mmap_active, 0);
874 909
875 freq = ctx->param.freq; 910 freq = ctx->param.freq;
876 freq = max_t(long, QUADD_HRT_MIN_FREQ, freq); 911 freq = max_t(long, QUADD_HRT_MIN_FREQ, freq);
diff --git a/drivers/misc/tegra-profiler/hrt.h b/drivers/misc/tegra-profiler/hrt.h
index 2db0ac8e6..98b591d1e 100644
--- a/drivers/misc/tegra-profiler/hrt.h
+++ b/drivers/misc/tegra-profiler/hrt.h
@@ -50,6 +50,7 @@ struct quadd_hrt_ctx {
50 struct quadd_ctx *quadd_ctx; 50 struct quadd_ctx *quadd_ctx;
51 51
52 atomic_t active; 52 atomic_t active;
53 atomic_t mmap_active;
53 atomic_t nr_active_all_core; 54 atomic_t nr_active_all_core;
54 55
55 atomic64_t counter_samples; 56 atomic64_t counter_samples;
@@ -62,11 +63,11 @@ struct quadd_hrt_ctx {
62 unsigned long rss_size_prev; 63 unsigned long rss_size_prev;
63 64
64 struct timecounter *tc; 65 struct timecounter *tc;
65 int use_arch_timer; 66 unsigned int use_arch_timer:1;
66 int arch_timer_user_access; 67 unsigned int arch_timer_user_access:1;
67 68
68 struct quadd_unw_methods um; 69 struct quadd_unw_methods um;
69 int get_stack_offset; 70 unsigned int get_stack_offset:1;
70}; 71};
71 72
72struct task_struct; 73struct task_struct;
@@ -76,8 +77,8 @@ struct quadd_event_context {
76 struct task_struct *task; 77 struct task_struct *task;
77 struct pt_regs *regs; 78 struct pt_regs *regs;
78 79
79 int user_mode; 80 unsigned int user_mode:1;
80 int is_sched; 81 unsigned int is_sched:1;
81}; 82};
82 83
83#define QUADD_HRT_MIN_FREQ 100 84#define QUADD_HRT_MIN_FREQ 100
diff --git a/drivers/misc/tegra-profiler/main.c b/drivers/misc/tegra-profiler/main.c
index 1e5a5d3d2..8d76225c5 100644
--- a/drivers/misc/tegra-profiler/main.c
+++ b/drivers/misc/tegra-profiler/main.c
@@ -60,16 +60,6 @@ static struct quadd_comm_cap_for_cpu *get_capabilities_for_cpu_int(int cpuid)
60 return &per_cpu(per_cpu_caps, cpuid); 60 return &per_cpu(per_cpu_caps, cpuid);
61} 61}
62 62
63int quadd_mode_is_trace_all(void)
64{
65 return ctx.mode_is_trace_all;
66}
67
68int quadd_mode_is_sampling(void)
69{
70 return ctx.mode_is_sampling;
71}
72
73int tegra_profiler_try_lock(void) 63int tegra_profiler_try_lock(void)
74{ 64{
75 return atomic_cmpxchg(&ctx.tegra_profiler_lock, 0, 1); 65 return atomic_cmpxchg(&ctx.tegra_profiler_lock, 0, 1);
@@ -92,14 +82,12 @@ static int start(void)
92 } 82 }
93 83
94 if (!atomic_cmpxchg(&ctx.started, 0, 1)) { 84 if (!atomic_cmpxchg(&ctx.started, 0, 1)) {
95 preempt_disable(); 85 if (quadd_mode_is_sampling(&ctx)) {
96
97 if (quadd_mode_is_sampling()) {
98 if (ctx.pmu) { 86 if (ctx.pmu) {
99 err = ctx.pmu->enable(); 87 err = ctx.pmu->enable();
100 if (err) { 88 if (err) {
101 pr_err("error: pmu enable\n"); 89 pr_err("error: pmu enable\n");
102 goto errout_preempt; 90 goto errout;
103 } 91 }
104 } 92 }
105 93
@@ -107,7 +95,7 @@ static int start(void)
107 err = ctx.pl310->enable(); 95 err = ctx.pl310->enable();
108 if (err) { 96 if (err) {
109 pr_err("error: pl310 enable\n"); 97 pr_err("error: pl310 enable\n");
110 goto errout_preempt; 98 goto errout;
111 } 99 }
112 } 100 }
113 } 101 }
@@ -117,11 +105,9 @@ static int start(void)
117 err = quadd_hrt_start(); 105 err = quadd_hrt_start();
118 if (err) { 106 if (err) {
119 pr_err("error: hrt start\n"); 107 pr_err("error: hrt start\n");
120 goto errout_preempt; 108 goto errout;
121 } 109 }
122 110
123 preempt_enable();
124
125 err = quadd_power_clk_start(); 111 err = quadd_power_clk_start();
126 if (err < 0) { 112 if (err < 0) {
127 pr_err("error: power_clk start\n"); 113 pr_err("error: power_clk start\n");
@@ -131,9 +117,6 @@ static int start(void)
131 117
132 return 0; 118 return 0;
133 119
134errout_preempt:
135 preempt_enable();
136
137errout: 120errout:
138 atomic_set(&ctx.started, 0); 121 atomic_set(&ctx.started, 0);
139 tegra_profiler_unlock(); 122 tegra_profiler_unlock();
@@ -268,10 +251,10 @@ static int verify_app(struct quadd_parameters *p, uid_t task_uid)
268static int 251static int
269set_parameters(struct quadd_parameters *p) 252set_parameters(struct quadd_parameters *p)
270{ 253{
271 int i, err, nr_pl310 = 0; 254 int i, err = 0, nr_pl310 = 0;
272 uid_t task_uid, current_uid; 255 uid_t task_uid, current_uid;
273 struct quadd_event *pl310_events; 256 struct quadd_event *pl310_events;
274 struct task_struct *task; 257 struct task_struct *task = NULL;
275 u64 *low_addr_p; 258 u64 *low_addr_p;
276 u32 extra; 259 u32 extra;
277 260
@@ -279,49 +262,61 @@ set_parameters(struct quadd_parameters *p)
279 262
280 ctx.mode_is_sampling = 263 ctx.mode_is_sampling =
281 extra & QUADD_PARAM_EXTRA_SAMPLING ? 1 : 0; 264 extra & QUADD_PARAM_EXTRA_SAMPLING ? 1 : 0;
265 ctx.mode_is_tracing =
266 extra & QUADD_PARAM_EXTRA_TRACING ? 1 : 0;
267 ctx.mode_is_sample_all =
268 extra & QUADD_PARAM_EXTRA_SAMPLE_ALL_TASKS ? 1 : 0;
282 ctx.mode_is_trace_all = p->trace_all_tasks; 269 ctx.mode_is_trace_all = p->trace_all_tasks;
283 270 ctx.mode_is_sample_tree =
284 pr_info("flag: sampling: %s\n", 271 extra & QUADD_PARAM_EXTRA_SAMPLE_TREE ? 1 : 0;
285 ctx.mode_is_sampling ? "yes" : "no"); 272 ctx.mode_is_trace_tree =
286 pr_info("flag: trace all: %s\n", 273 extra & QUADD_PARAM_EXTRA_TRACE_TREE ? 1 : 0;
287 ctx.mode_is_trace_all ? "yes" : "no"); 274
288 275 pr_info("flags: s/t/sa/ta/st/tt: %u/%u/%u/%u/%u/%u\n",
289 if (ctx.mode_is_trace_all && !capable(CAP_SYS_ADMIN)) { 276 ctx.mode_is_sampling,
290 pr_err("error: trace all tasks mode is allowed only for root\n"); 277 ctx.mode_is_tracing,
278 ctx.mode_is_sample_all,
279 ctx.mode_is_trace_all,
280 ctx.mode_is_sample_tree,
281 ctx.mode_is_trace_tree);
282
283 if ((ctx.mode_is_trace_all || ctx.mode_is_sample_all) &&
284 !capable(CAP_SYS_ADMIN)) {
285 pr_err("error: \"all tasks\" modes are allowed only for root\n");
291 return -EACCES; 286 return -EACCES;
292 } 287 }
293 288
294 p->package_name[sizeof(p->package_name) - 1] = '\0'; 289 p->package_name[sizeof(p->package_name) - 1] = '\0';
295 ctx.param = *p; 290 ctx.param = *p;
296 291
297 if (!ctx.mode_is_trace_all || ctx.mode_is_sampling) { 292 current_uid = from_kuid(&init_user_ns, current_fsuid());
298 if (!validate_freq(p->freq)) { 293 pr_info("owner uid: %u\n", current_uid);
294
295 if ((ctx.mode_is_tracing && !ctx.mode_is_trace_all) ||
296 (ctx.mode_is_sampling && !ctx.mode_is_sample_all)) {
297 if (ctx.mode_is_sampling && !validate_freq(p->freq)) {
299 pr_err("error: incorrect frequency: %u\n", p->freq); 298 pr_err("error: incorrect frequency: %u\n", p->freq);
300 return -EINVAL; 299 return -EINVAL;
301 } 300 }
302 301
303 /* Currently only one process */ 302 /* Currently only first process */
304 if (p->nr_pids != 1) 303 if (p->nr_pids != 1)
305 return -EINVAL; 304 return -EINVAL;
306 305
307 rcu_read_lock(); 306 task = get_pid_task(find_vpid(p->pids[0]), PIDTYPE_PID);
308 task = pid_task(find_vpid(p->pids[0]), PIDTYPE_PID);
309 rcu_read_unlock();
310 if (!task) { 307 if (!task) {
311 pr_err("error: process not found: %u\n", p->pids[0]); 308 pr_err("error: process not found: %u\n", p->pids[0]);
312 return -ESRCH; 309 return -ESRCH;
313 } 310 }
314 311
315 current_uid = from_kuid(&init_user_ns, current_fsuid());
316 task_uid = from_kuid(&init_user_ns, task_uid(task)); 312 task_uid = from_kuid(&init_user_ns, task_uid(task));
317 313 pr_info("task uid: %u\n", task_uid);
318 pr_info("owner/task uids: %u/%u\n", current_uid, task_uid);
319 314
320 if (!capable(CAP_SYS_ADMIN)) { 315 if (!capable(CAP_SYS_ADMIN)) {
321 if (current_uid != task_uid) { 316 if (current_uid != task_uid) {
322 err = verify_app(p, task_uid); 317 err = verify_app(p, task_uid);
323 if (err < 0) 318 if (err < 0)
324 return err; 319 goto out_put_task;
325 } 320 }
326 ctx.collect_kernel_ips = 0; 321 ctx.collect_kernel_ips = 0;
327 } else { 322 } else {
@@ -335,8 +330,10 @@ set_parameters(struct quadd_parameters *p)
335 type = event->type; 330 type = event->type;
336 id = event->id; 331 id = event->id;
337 332
338 if (type != QUADD_EVENT_TYPE_HARDWARE) 333 if (type != QUADD_EVENT_TYPE_HARDWARE) {
339 return -EINVAL; 334 err = -EINVAL;
335 goto out_put_task;
336 }
340 337
341 if (ctx.pl310 && 338 if (ctx.pl310 &&
342 ctx.pl310_info.nr_supp_events > 0 && 339 ctx.pl310_info.nr_supp_events > 0 &&
@@ -348,12 +345,14 @@ set_parameters(struct quadd_parameters *p)
348 345
349 if (nr_pl310++ > 1) { 346 if (nr_pl310++ > 1) {
350 pr_err("error: multiply pl310 events\n"); 347 pr_err("error: multiply pl310 events\n");
351 return -EINVAL; 348 err = -EINVAL;
349 goto out_put_task;
352 } 350 }
353 } else { 351 } else {
354 pr_err("Bad event: %s\n", 352 pr_err("Bad event: %s\n",
355 quadd_get_hw_event_str(id)); 353 quadd_get_hw_event_str(id));
356 return -EINVAL; 354 err = -EINVAL;
355 goto out_put_task;
357 } 356 }
358 } 357 }
359 358
@@ -365,7 +364,7 @@ set_parameters(struct quadd_parameters *p)
365 pl310_events, 1); 364 pl310_events, 1);
366 if (err) { 365 if (err) {
367 pr_info("pl310 set_parameters: error\n"); 366 pr_info("pl310 set_parameters: error\n");
368 return err; 367 goto out_put_task;
369 } 368 }
370 ctx.pl310_info.active = 1; 369 ctx.pl310_info.active = 1;
371 } else { 370 } else {
@@ -381,12 +380,16 @@ set_parameters(struct quadd_parameters *p)
381 380
382 err = quadd_unwind_start(task); 381 err = quadd_unwind_start(task);
383 if (err) 382 if (err)
384 return err; 383 goto out_put_task;
385 } 384 }
386 385
387 pr_info("New parameters have been applied\n"); 386 pr_info("New parameters have been applied\n");
388 387
389 return 0; 388out_put_task:
389 if (task)
390 put_task_struct(task);
391
392 return err;
390} 393}
391 394
392static void 395static void
@@ -734,7 +737,7 @@ static int __init quadd_module_init(void)
734 return err; 737 return err;
735 } 738 }
736 739
737 ctx.comm = quadd_comm_events_init(&control); 740 ctx.comm = quadd_comm_events_init(&ctx, &control);
738 if (IS_ERR(ctx.comm)) { 741 if (IS_ERR(ctx.comm)) {
739 pr_err("error: COMM init failed\n"); 742 pr_err("error: COMM init failed\n");
740 return PTR_ERR(ctx.comm); 743 return PTR_ERR(ctx.comm);
diff --git a/drivers/misc/tegra-profiler/mmap.c b/drivers/misc/tegra-profiler/mmap.c
index 43b7648b6..3e8a5c729 100644
--- a/drivers/misc/tegra-profiler/mmap.c
+++ b/drivers/misc/tegra-profiler/mmap.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * drivers/misc/tegra-profiler/mmap.c 2 * drivers/misc/tegra-profiler/mmap.c
3 * 3 *
4 * Copyright (c) 2015-2016, NVIDIA CORPORATION. All rights reserved. 4 * Copyright (c) 2015-2018, NVIDIA CORPORATION. All rights reserved.
5 * 5 *
6 * This program is free software; you can redistribute it and/or modify it 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, 7 * under the terms and conditions of the GNU General Public License,
@@ -24,20 +24,24 @@
24 24
25#include <linux/tegra_profiler.h> 25#include <linux/tegra_profiler.h>
26 26
27#include "quadd.h"
27#include "mmap.h" 28#include "mmap.h"
28#include "comm.h" 29#include "comm.h"
29#include "hrt.h" 30#include "hrt.h"
30 31
31#define TMP_BUFFER_SIZE (PATH_MAX + sizeof(u64)) 32#define TMP_BUFFER_SIZE (PATH_MAX + sizeof(u64))
33#define QUADD_MMAP_TREE_MAX_LEVEL 32
32 34
33static void 35static void
34put_mmap_sample(struct quadd_mmap_data *s, char *filename, 36put_mmap_sample(struct quadd_mmap_data *s, char *filename,
35 size_t length, unsigned long pgoff, int is_file_exists) 37 size_t length, unsigned long pgoff,
38 int is_file_exists, pid_t __tgid)
36{ 39{
37 u64 mmap_ed = 0; 40 u64 mmap_ed = 0;
38 struct quadd_record_data r; 41 struct quadd_record_data r;
39 struct quadd_iovec vec[3]; 42 struct quadd_iovec vec[4];
40 u64 pgoff_val = (u64)pgoff << PAGE_SHIFT; 43 u64 pgoff_val = (u64)pgoff << PAGE_SHIFT;
44 u32 tgid = (u32)__tgid;
41 45
42 r.record_type = QUADD_RECORD_TYPE_MMAP; 46 r.record_type = QUADD_RECORD_TYPE_MMAP;
43 47
@@ -58,39 +62,35 @@ put_mmap_sample(struct quadd_mmap_data *s, char *filename,
58 vec[2].base = filename; 62 vec[2].base = filename;
59 vec[2].len = length; 63 vec[2].len = length;
60 64
61 pr_debug("MMAP: pid: %u, file_name: '%s', addr: %#llx - %#llx, len: %llx, pgoff: %#llx\n", 65 vec[3].base = &tgid;
62 s->pid, filename, 66 vec[3].len = sizeof(tgid);
67
68 pr_debug("[%d] MMAP: tid: %u,pid: %u,'%s',%#llx-%#llx(%llx,%#llx)\n",
69 smp_processor_id(), s->pid, tgid, filename,
63 s->addr, s->addr + s->len, s->len, pgoff_val); 70 s->addr, s->addr + s->len, s->len, pgoff_val);
64 71
65 quadd_put_sample(&r, vec, ARRAY_SIZE(vec)); 72 quadd_put_sample_this_cpu(&r, vec, ARRAY_SIZE(vec));
66} 73}
67 74
68void quadd_process_mmap(struct vm_area_struct *vma, pid_t pid) 75static void
76process_mmap(struct vm_area_struct *vma, struct task_struct *task,
77 char *buf, size_t buf_size)
69{ 78{
79 pid_t tgid;
70 int is_file_exists; 80 int is_file_exists;
71 struct file *vm_file; 81 struct file *vm_file;
72 struct path *path; 82 char *file_name;
73 char *file_name, *tmp_buf = NULL;
74 struct quadd_mmap_data sample; 83 struct quadd_mmap_data sample;
75 size_t length, length_aligned; 84 size_t length, length_aligned;
76 85
77 if (!vma)
78 return;
79
80 if (!(vma->vm_flags & VM_EXEC)) 86 if (!(vma->vm_flags & VM_EXEC))
81 return; 87 return;
82 88
83 tmp_buf = kzalloc(TMP_BUFFER_SIZE, GFP_ATOMIC);
84 if (!tmp_buf)
85 return;
86
87 vm_file = vma->vm_file; 89 vm_file = vma->vm_file;
88 if (vm_file) { 90 if (vm_file) {
89 path = &vm_file->f_path; 91 file_name = file_path(vm_file, buf, PATH_MAX);
90
91 file_name = d_path(path, tmp_buf, PATH_MAX);
92 if (IS_ERR(file_name)) 92 if (IS_ERR(file_name))
93 goto out; 93 return;
94 94
95 length = strlen(file_name) + 1; 95 length = strlen(file_name) + 1;
96 is_file_exists = 1; 96 is_file_exists = 1;
@@ -113,12 +113,12 @@ void quadd_process_mmap(struct vm_area_struct *vma, pid_t pid)
113 } 113 }
114 114
115 if (name) 115 if (name)
116 strlcpy(tmp_buf, name, TMP_BUFFER_SIZE); 116 strlcpy(buf, name, buf_size);
117 else 117 else
118 snprintf(tmp_buf, TMP_BUFFER_SIZE, "[vma:%08lx-%08lx]", 118 snprintf(buf, buf_size, "[vma:%08lx-%08lx]",
119 vma->vm_start, vma->vm_end); 119 vma->vm_start, vma->vm_end);
120 120
121 file_name = tmp_buf; 121 file_name = buf;
122 length = strlen(file_name) + 1; 122 length = strlen(file_name) + 1;
123 123
124 is_file_exists = 0; 124 is_file_exists = 0;
@@ -126,110 +126,160 @@ void quadd_process_mmap(struct vm_area_struct *vma, pid_t pid)
126 126
127 length_aligned = ALIGN(length, sizeof(u64)); 127 length_aligned = ALIGN(length, sizeof(u64));
128 128
129 sample.pid = pid; 129 sample.pid = task_pid_nr(task);
130 tgid = task_tgid_nr(task);
130 sample.user_mode = 1; 131 sample.user_mode = 1;
131 132
132 sample.addr = vma->vm_start; 133 sample.addr = vma->vm_start;
133 sample.len = vma->vm_end - vma->vm_start; 134 sample.len = vma->vm_end - vma->vm_start;
134 135
135 put_mmap_sample(&sample, file_name, length_aligned, 136 put_mmap_sample(&sample, file_name, length_aligned,
136 vma->vm_pgoff, is_file_exists); 137 vma->vm_pgoff, is_file_exists, tgid);
138}
137 139
138out: 140void quadd_process_mmap(struct vm_area_struct *vma, struct task_struct *task)
139 kfree(tmp_buf); 141{
142 char *buf;
143
144 buf = kzalloc(TMP_BUFFER_SIZE, GFP_ATOMIC);
145 if (!buf)
146 return;
147
148 preempt_disable();
149 process_mmap(vma, task, buf, TMP_BUFFER_SIZE);
150 preempt_enable();
151
152 kfree(buf);
140} 153}
141 154
142int quadd_get_current_mmap(pid_t pid) 155static void get_process_vmas(struct task_struct *task)
143{ 156{
144 int is_file_exists; 157 char *buf;
145 struct vm_area_struct *vma;
146 struct file *vm_file;
147 struct path *path;
148 char *file_name;
149 struct task_struct *task;
150 struct mm_struct *mm; 158 struct mm_struct *mm;
151 struct quadd_mmap_data sample; 159 struct vm_area_struct *vma;
152 size_t length, length_aligned; 160
153 char *tmp_buf; 161 if (!task)
154 162 return;
155 rcu_read_lock(); 163
156 task = pid_task(find_vpid(pid), PIDTYPE_PID); 164 mm = get_task_mm(task);
157 rcu_read_unlock(); 165 if (!mm)
158 if (!task) { 166 return;
159 pr_err("Process not found: %d\n", pid); 167
160 return -ESRCH; 168 down_read(&mm->mmap_sem);
161 } 169
170 buf = kzalloc(TMP_BUFFER_SIZE, GFP_ATOMIC);
171 if (!buf)
172 goto out_put_mm;
173
174 preempt_disable();
175 for (vma = mm->mmap; vma; vma = vma->vm_next)
176 process_mmap(vma, task, buf, TMP_BUFFER_SIZE);
177 preempt_enable();
178
179 kfree(buf);
180
181out_put_mm:
182 up_read(&mm->mmap_sem);
183 mmput(mm);
184}
162 185
163 mm = task->mm; 186static void
164 if (!mm) { 187__get_process_vmas(struct task_struct *task,
165 pr_warn("mm is not existed for task: %d\n", pid); 188 struct mm_struct *mm, char *buf, size_t buf_size)
166 return 0; 189{
190 struct vm_area_struct *vma;
191
192 for (vma = mm->mmap; vma; vma = vma->vm_next)
193 process_mmap(vma, task, buf, buf_size);
194}
195
196static int
197is_sample_process(struct task_struct *from, struct pid *root_pid)
198{
199 struct task_struct *p;
200
201 for (p = from; p != &init_task;) {
202 if (task_pid_nr(p) == pid_nr(root_pid))
203 return 1;
204
205 rcu_read_lock();
206 p = rcu_dereference(p->real_parent);
207 rcu_read_unlock();
167 } 208 }
168 209
169 pr_info("Get mapped memory objects\n"); 210 return 0;
211}
212
213static void get_all_processes(struct pid *root_pid)
214{
215 char *buf;
216 struct task_struct *p;
217
218 buf = kzalloc(TMP_BUFFER_SIZE, GFP_ATOMIC);
219 if (!buf)
220 return;
170 221
171 tmp_buf = kzalloc(TMP_BUFFER_SIZE, GFP_ATOMIC); 222 read_lock(&tasklist_lock);
172 if (!tmp_buf) 223 for_each_process(p) {
173 return -ENOMEM; 224 struct mm_struct *mm;
174 225
175 for (vma = mm->mmap; vma; vma = vma->vm_next) { 226 if (p->flags & PF_KTHREAD)
176 if (!(vma->vm_flags & VM_EXEC))
177 continue; 227 continue;
178 228
179 vm_file = vma->vm_file; 229 if (root_pid && !is_sample_process(p, root_pid))
180 if (vm_file) { 230 continue;
181 path = &vm_file->f_path;
182
183 file_name = d_path(path, tmp_buf, PATH_MAX);
184 if (IS_ERR(file_name))
185 continue;
186 231
187 length = strlen(file_name) + 1; 232 rcu_read_lock();
188 is_file_exists = 1; 233 task_lock(p);
234 if (likely(p->mm)) {
235 mm = p->mm;
189 } else { 236 } else {
190 const char *name = NULL; 237 mm = NULL;
191 238 task_unlock(p);
192 name = arch_vma_name(vma); 239 }
193 if (!name) { 240 rcu_read_unlock();
194 mm = vma->vm_mm; 241
195 242 if (!mm)
196 if (!mm) { 243 continue;
197 name = "[vdso]";
198 } else if (vma->vm_start <= mm->start_brk &&
199 vma->vm_end >= mm->brk) {
200 name = "[heap]";
201 } else if (vma->vm_start <= mm->start_stack &&
202 vma->vm_end >= mm->start_stack) {
203 name = "[stack]";
204 }
205 }
206 244
207 if (name) 245 if (!down_read_trylock(&mm->mmap_sem))
208 strlcpy(tmp_buf, name, TMP_BUFFER_SIZE); 246 goto __continue;
209 else
210 snprintf(tmp_buf, TMP_BUFFER_SIZE,
211 "[vma:%08lx-%08lx]",
212 vma->vm_start, vma->vm_end);
213 247
214 file_name = tmp_buf; 248 __get_process_vmas(p, mm, buf, TMP_BUFFER_SIZE);
215 length = strlen(file_name) + 1;
216 249
217 is_file_exists = 0; 250 up_read(&mm->mmap_sem);
218 } 251__continue:
252 task_unlock(p);
253 }
254 read_unlock(&tasklist_lock);
219 255
220 length_aligned = ALIGN(length, sizeof(u64)); 256 kfree(buf);
257}
221 258
222 sample.pid = pid; 259void quadd_get_mmaps(struct quadd_ctx *ctx)
223 sample.user_mode = 1; 260{
261 struct pid *pid;
262 struct task_struct *task;
263 struct quadd_parameters *param = &ctx->param;
224 264
225 sample.addr = vma->vm_start; 265 if (!quadd_mode_is_sampling(ctx))
226 sample.len = vma->vm_end - vma->vm_start; 266 return;
227 267
228 put_mmap_sample(&sample, file_name, length_aligned, 268 if (quadd_mode_is_sample_all(ctx)) {
229 vma->vm_pgoff, is_file_exists); 269 get_all_processes(NULL);
270 return;
230 } 271 }
231 272
232 kfree(tmp_buf); 273 pid = find_vpid(param->pids[0]);
233 274
234 return 0; 275 task = get_pid_task(pid, PIDTYPE_PID);
276 if (!task)
277 return;
278
279 if (quadd_mode_is_sample_tree(ctx))
280 get_all_processes(pid);
281 else
282 get_process_vmas(task);
283
284 put_task_struct(task);
235} 285}
diff --git a/drivers/misc/tegra-profiler/mmap.h b/drivers/misc/tegra-profiler/mmap.h
index 4928f939f..993a38c0c 100644
--- a/drivers/misc/tegra-profiler/mmap.h
+++ b/drivers/misc/tegra-profiler/mmap.h
@@ -1,7 +1,7 @@
1/* 1/*
2 * drivers/misc/tegra-profiler/mmap.h 2 * drivers/misc/tegra-profiler/mmap.h
3 * 3 *
4 * Copyright (c) 2014, NVIDIA CORPORATION. All rights reserved. 4 * Copyright (c) 2014-2018, NVIDIA CORPORATION. All rights reserved.
5 * 5 *
6 * This program is free software; you can redistribute it and/or modify it 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, 7 * under the terms and conditions of the GNU General Public License,
@@ -17,9 +17,11 @@
17#ifndef __QUADD_MMAP_H 17#ifndef __QUADD_MMAP_H
18#define __QUADD_MMAP_H 18#define __QUADD_MMAP_H
19 19
20#include <linux/types.h> 20struct vm_area_struct;
21struct task_struct;
22struct quadd_ctx;
21 23
22void quadd_process_mmap(struct vm_area_struct *vma, pid_t pid); 24void quadd_process_mmap(struct vm_area_struct *vma, struct task_struct *task);
23int quadd_get_current_mmap(pid_t pid); 25void quadd_get_mmaps(struct quadd_ctx *ctx);
24 26
25#endif /* __QUADD_MMAP_H */ 27#endif /* __QUADD_MMAP_H */
diff --git a/drivers/misc/tegra-profiler/quadd.h b/drivers/misc/tegra-profiler/quadd.h
index 7af3dfbb2..f85599c78 100644
--- a/drivers/misc/tegra-profiler/quadd.h
+++ b/drivers/misc/tegra-profiler/quadd.h
@@ -56,8 +56,8 @@ struct source_info {
56 56
57 unsigned int raw_event_mask; 57 unsigned int raw_event_mask;
58 58
59 int is_present; 59 unsigned int is_present:1;
60 int active; 60 unsigned int active:1;
61}; 61};
62 62
63struct quadd_ctx { 63struct quadd_ctx {
@@ -77,18 +77,49 @@ struct quadd_ctx {
77 atomic_t started; 77 atomic_t started;
78 atomic_t tegra_profiler_lock; 78 atomic_t tegra_profiler_lock;
79 79
80 int collect_kernel_ips; 80 unsigned int collect_kernel_ips:1;
81 81
82 int mode_is_trace_all; 82 unsigned int mode_is_sampling:1;
83 int mode_is_sampling; 83 unsigned int mode_is_tracing:1;
84 unsigned int mode_is_sample_all:1;
85 unsigned int mode_is_trace_all:1;
86 unsigned int mode_is_sample_tree:1;
87 unsigned int mode_is_trace_tree:1;
84}; 88};
85 89
90static inline int quadd_mode_is_sampling(struct quadd_ctx *ctx)
91{
92 return ctx->mode_is_sampling;
93}
94
95static inline int quadd_mode_is_tracing(struct quadd_ctx *ctx)
96{
97 return ctx->mode_is_tracing;
98}
99
100static inline int quadd_mode_is_sample_all(struct quadd_ctx *ctx)
101{
102 return ctx->mode_is_sample_all;
103}
104
105static inline int quadd_mode_is_trace_all(struct quadd_ctx *ctx)
106{
107 return ctx->mode_is_trace_all;
108}
109
110static inline int quadd_mode_is_sample_tree(struct quadd_ctx *ctx)
111{
112 return ctx->mode_is_sample_tree;
113}
114
115static inline int quadd_mode_is_trace_tree(struct quadd_ctx *ctx)
116{
117 return ctx->mode_is_trace_tree;
118}
119
86void quadd_get_state(struct quadd_module_state *state); 120void quadd_get_state(struct quadd_module_state *state);
87 121
88int tegra_profiler_try_lock(void); 122int tegra_profiler_try_lock(void);
89void tegra_profiler_unlock(void); 123void tegra_profiler_unlock(void);
90 124
91int quadd_mode_is_trace_all(void);
92int quadd_mode_is_sampling(void);
93
94#endif /* __QUADD_H */ 125#endif /* __QUADD_H */
diff --git a/drivers/misc/tegra-profiler/quadd_proc.c b/drivers/misc/tegra-profiler/quadd_proc.c
index 0dc0490fe..8eb25558f 100644
--- a/drivers/misc/tegra-profiler/quadd_proc.c
+++ b/drivers/misc/tegra-profiler/quadd_proc.c
@@ -89,7 +89,7 @@ static int show_capabilities(struct seq_file *f, void *offset)
89 seq_printf(f, "pmu arch: %s\n", 89 seq_printf(f, "pmu arch: %s\n",
90 arch->name); 90 arch->name);
91 if (arch->pmuver_is_set) 91 if (arch->pmuver_is_set)
92 seq_printf(f, "pmu arch version: %d\n", 92 seq_printf(f, "pmu arch version: %u\n",
93 arch->pmuver); 93 arch->pmuver);
94 94
95 seq_printf(f, "l2 cache: %s\n", 95 seq_printf(f, "l2 cache: %s\n",
diff --git a/drivers/misc/tegra-profiler/version.h b/drivers/misc/tegra-profiler/version.h
index e1b72d69e..6b620d727 100644
--- a/drivers/misc/tegra-profiler/version.h
+++ b/drivers/misc/tegra-profiler/version.h
@@ -17,7 +17,7 @@
17#ifndef __QUADD_VERSION_H 17#ifndef __QUADD_VERSION_H
18#define __QUADD_VERSION_H 18#define __QUADD_VERSION_H
19 19
20#define QUADD_MODULE_VERSION "1.121" 20#define QUADD_MODULE_VERSION "1.122"
21#define QUADD_MODULE_BRANCH "Dev" 21#define QUADD_MODULE_BRANCH "Dev"
22 22
23#endif /* __QUADD_VERSION_H */ 23#endif /* __QUADD_VERSION_H */
diff --git a/include/linux/tegra_profiler.h b/include/linux/tegra_profiler.h
index d101ccc1a..2b08a2f90 100644
--- a/include/linux/tegra_profiler.h
+++ b/include/linux/tegra_profiler.h
@@ -19,8 +19,8 @@
19 19
20#include <linux/ioctl.h> 20#include <linux/ioctl.h>
21 21
22#define QUADD_SAMPLES_VERSION 42 22#define QUADD_SAMPLES_VERSION 43
23#define QUADD_IO_VERSION 24 23#define QUADD_IO_VERSION 25
24 24
25#define QUADD_IO_VERSION_DYNAMIC_RB 5 25#define QUADD_IO_VERSION_DYNAMIC_RB 5
26#define QUADD_IO_VERSION_RB_MAX_FILL_COUNT 6 26#define QUADD_IO_VERSION_RB_MAX_FILL_COUNT 6
@@ -42,33 +42,35 @@
42#define QUADD_IO_VERSION_RAW_EVENTS 22 42#define QUADD_IO_VERSION_RAW_EVENTS 22
43#define QUADD_IO_VERSION_SAMPLING_MODE 23 43#define QUADD_IO_VERSION_SAMPLING_MODE 23
44#define QUADD_IO_VERSION_FORCE_ARCH_TIMER 24 44#define QUADD_IO_VERSION_FORCE_ARCH_TIMER 24
45 45#define QUADD_IO_VERSION_SAMPLE_ALL_TASKS 25
46#define QUADD_SAMPLE_VERSION_THUMB_MODE_FLAG 17 46
47#define QUADD_SAMPLE_VERSION_GROUP_SAMPLES 18 47#define QUADD_SAMPLE_VERSION_THUMB_MODE_FLAG 17
48#define QUADD_SAMPLE_VERSION_THREAD_STATE_FLD 19 48#define QUADD_SAMPLE_VERSION_GROUP_SAMPLES 18
49#define QUADD_SAMPLE_VERSION_BT_UNWIND_TABLES 22 49#define QUADD_SAMPLE_VERSION_THREAD_STATE_FLD 19
50#define QUADD_SAMPLE_VERSION_SUPPORT_IP64 23 50#define QUADD_SAMPLE_VERSION_BT_UNWIND_TABLES 22
51#define QUADD_SAMPLE_VERSION_SPECIAL_MMAP 24 51#define QUADD_SAMPLE_VERSION_SUPPORT_IP64 23
52#define QUADD_SAMPLE_VERSION_UNWIND_MIXED 25 52#define QUADD_SAMPLE_VERSION_SPECIAL_MMAP 24
53#define QUADD_SAMPLE_VERSION_UNW_ENTRY_TYPE 26 53#define QUADD_SAMPLE_VERSION_UNWIND_MIXED 25
54#define QUADD_SAMPLE_VERSION_USE_ARCH_TIMER 27 54#define QUADD_SAMPLE_VERSION_UNW_ENTRY_TYPE 26
55#define QUADD_SAMPLE_VERSION_SCHED_SAMPLES 28 55#define QUADD_SAMPLE_VERSION_USE_ARCH_TIMER 27
56#define QUADD_SAMPLE_VERSION_HDR_UNW_METHOD 29 56#define QUADD_SAMPLE_VERSION_SCHED_SAMPLES 28
57#define QUADD_SAMPLE_VERSION_HDR_ARCH_TIMER 30 57#define QUADD_SAMPLE_VERSION_HDR_UNW_METHOD 29
58#define QUADD_SAMPLE_VERSION_STACK_OFFSET 31 58#define QUADD_SAMPLE_VERSION_HDR_ARCH_TIMER 30
59#define QUADD_SAMPLE_VERSION_SCHED_TASK_STATE 32 59#define QUADD_SAMPLE_VERSION_STACK_OFFSET 31
60#define QUADD_SAMPLE_VERSION_URCS 33 60#define QUADD_SAMPLE_VERSION_SCHED_TASK_STATE 32
61#define QUADD_SAMPLE_VERSION_HOTPLUG 34 61#define QUADD_SAMPLE_VERSION_URCS 33
62#define QUADD_SAMPLE_VERSION_PER_CPU_SETUP 35 62#define QUADD_SAMPLE_VERSION_HOTPLUG 34
63#define QUADD_SAMPLE_VERSION_REPORT_TGID 36 63#define QUADD_SAMPLE_VERSION_PER_CPU_SETUP 35
64#define QUADD_SAMPLE_VERSION_MMAP_TS 37 64#define QUADD_SAMPLE_VERSION_REPORT_TGID 36
65#define QUADD_SAMPLE_VERSION_RAW_EVENTS 38 65#define QUADD_SAMPLE_VERSION_MMAP_TS 37
66#define QUADD_SAMPLE_VERSION_OVERHEAD_INFO 39 66#define QUADD_SAMPLE_VERSION_RAW_EVENTS 38
67#define QUADD_SAMPLE_VERSION_REPORT_VPID 40 67#define QUADD_SAMPLE_VERSION_OVERHEAD_INFO 39
68#define QUADD_SAMPLE_VERSION_SCHED_REPORT_VPID 41 68#define QUADD_SAMPLE_VERSION_REPORT_VPID 40
69#define QUADD_SAMPLE_VERSION_SAMPLING_MODE 42 69#define QUADD_SAMPLE_VERSION_SCHED_REPORT_VPID 41
70 70#define QUADD_SAMPLE_VERSION_SAMPLING_MODE 42
71#define QUADD_MMAP_HEADER_VERSION 1 71#define QUADD_SAMPLE_VERSION_SAMPLE_ALL_TASKS 43
72
73#define QUADD_MMAP_HEADER_VERSION 1
72 74
73#define QUADD_MAX_COUNTERS 32 75#define QUADD_MAX_COUNTERS 32
74#define QUADD_MAX_PROCESS 64 76#define QUADD_MAX_PROCESS 64
@@ -359,6 +361,10 @@ struct quadd_debug_data {
359#define QUADD_HDR_HAS_CPUID (1 << 6) 361#define QUADD_HDR_HAS_CPUID (1 << 6)
360#define QUADD_HDR_MODE_TRACE_ALL (1 << 7) 362#define QUADD_HDR_MODE_TRACE_ALL (1 << 7)
361#define QUADD_HDR_MODE_SAMPLING (1 << 8) 363#define QUADD_HDR_MODE_SAMPLING (1 << 8)
364#define QUADD_HDR_MODE_TRACING (1 << 9)
365#define QUADD_HDR_MODE_SAMPLE_ALL (1 << 10)
366#define QUADD_HDR_MODE_SAMPLE_TREE (1 << 11)
367#define QUADD_HDR_MODE_TRACE_TREE (1 << 12)
362 368
363struct quadd_header_data { 369struct quadd_header_data {
364 u16 magic; 370 u16 magic;
@@ -419,6 +425,10 @@ enum {
419#define QUADD_PARAM_EXTRA_PER_PMU_SETUP (1 << 8) 425#define QUADD_PARAM_EXTRA_PER_PMU_SETUP (1 << 8)
420#define QUADD_PARAM_EXTRA_SAMPLING (1 << 9) 426#define QUADD_PARAM_EXTRA_SAMPLING (1 << 9)
421#define QUADD_PARAM_EXTRA_FORCE_ARCH_TIMER (1 << 10) 427#define QUADD_PARAM_EXTRA_FORCE_ARCH_TIMER (1 << 10)
428#define QUADD_PARAM_EXTRA_SAMPLE_ALL_TASKS (1 << 11)
429#define QUADD_PARAM_EXTRA_SAMPLE_TREE (1 << 12)
430#define QUADD_PARAM_EXTRA_TRACING (1 << 13)
431#define QUADD_PARAM_EXTRA_TRACE_TREE (1 << 14)
422 432
423enum { 433enum {
424 QUADD_EVENT_TYPE_RAW = 0, 434 QUADD_EVENT_TYPE_RAW = 0,