misc: tegra-profiler: fix sleep inside atomic
[linux-3.10.git] / drivers / misc / tegra-profiler / backtrace.h
1 /*
2  * drivers/misc/tegra-profiler/backtrace.h
3  *
4  * Copyright (c) 2013-2016, 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 #ifndef __QUADD_BACKTRACE_H
18 #define __QUADD_BACKTRACE_H
19
20 #include <linux/mm.h>
21 #include <linux/bitops.h>
22 #include <linux/uaccess.h>
23
24 #include <linux/tegra_profiler.h>
25
26 #define QUADD_MAX_STACK_DEPTH           64
27
28 #define QUADD_UNW_TYPES_SIZE \
29         DIV_ROUND_UP(QUADD_MAX_STACK_DEPTH * 4, sizeof(u32) * BITS_PER_BYTE)
30
31 struct quadd_hrt_ctx;
32
33 struct quadd_unw_methods {
34         unsigned int
35                 fp:1,
36                 ut:1,
37                 ut_ce:1,
38                 dwarf:1;
39 };
40
41 struct quadd_callchain {
42         int nr;
43
44         union {
45                 u32 ip_32[QUADD_MAX_STACK_DEPTH];
46                 u64 ip_64[QUADD_MAX_STACK_DEPTH];
47         };
48
49         u32 types[QUADD_UNW_TYPES_SIZE];
50
51         int cs_64;
52
53         struct quadd_unw_methods um;
54
55         unsigned int urc_fp;
56         unsigned int urc_ut;
57         unsigned int urc_dwarf;
58
59         unsigned long curr_sp;
60         unsigned long curr_fp;
61         unsigned long curr_fp_thumb;
62         unsigned long curr_pc;
63         unsigned long curr_lr;
64
65         struct quadd_hrt_ctx *hrt;
66 };
67
68 struct quadd_ctx;
69 struct pt_regs;
70
71 unsigned int
72 quadd_get_user_callchain(struct pt_regs *regs,
73                          struct quadd_callchain *cc_data,
74                          struct quadd_ctx *ctx,
75                          struct task_struct *task);
76
77 int
78 quadd_callchain_store(struct quadd_callchain *cc,
79                       unsigned long ip, unsigned int type);
80
81 unsigned long
82 quadd_user_stack_pointer(struct pt_regs *regs);
83
84 unsigned long
85 quadd_get_user_frame_pointer(struct pt_regs *regs);
86
87 unsigned long
88 quadd_user_link_register(struct pt_regs *regs);
89
90 static inline int
91 is_vma_addr(unsigned long addr, struct vm_area_struct *vma,
92             unsigned long nbytes)
93 {
94         return  vma &&
95                 addr >= vma->vm_start &&
96                 addr < vma->vm_end - nbytes;
97 }
98
99 static inline int
100 validate_pc_addr(unsigned long addr, unsigned long nbytes)
101 {
102         return addr && addr < TASK_SIZE - nbytes;
103 }
104
105 static inline int
106 validate_stack_addr(unsigned long addr,
107                     struct vm_area_struct *vma,
108                     unsigned long nbytes)
109 {
110         if (addr & 0x03)
111                 return 0;
112
113         return is_vma_addr(addr, vma, nbytes);
114 }
115
116 static inline long
117 read_user_data(void *dst, const void __user *src, unsigned long n)
118 {
119         long err;
120
121         pagefault_disable();
122         err = __copy_from_user_inatomic(dst, src, n);
123         pagefault_enable();
124
125         if (unlikely(err)) {
126                 pr_debug("%s: failed for address: %p\n",
127                          __func__, src);
128                 err = -QUADD_URC_EACCESS;
129         }
130
131         return err;
132 }
133
134 #endif  /* __QUADD_BACKTRACE_H */