1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
7 * with the License.
8 *
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
13 *
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
19 *
20 * CDDL HEADER END
21 *
22 * $FreeBSD: head/sys/cddl/dev/dtrace/arm/dtrace_isa.c 295882 2016-02-22 09:08:04Z skra $
23 */
24 /*
25 * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
26 * Use is subject to license terms.
27 */
28 #include <sys/cdefs.h>
29
30 #include <sys/param.h>
31 #include <sys/systm.h>
32 #include <sys/kernel.h>
33
34 #include <machine/frame.h>
35 #include <machine/reg.h>
36
37 #include <machine/db_machdep.h>
38 #include <machine/vmparam.h>
39 #include <ddb/db_sym.h>
40 #include <ddb/ddb.h>
41
42 uintptr_t kernelbase = (uintptr_t)KERNEL_BASE;
43
44 /* TODO: support AAPCS */
45 /* XXX: copied from sys/arch/arm/arm/db_trace.c */
46 #define INKERNEL(va) (((vaddr_t)(va)) >= VM_MIN_KERNEL_ADDRESS)
47
48 #define FR_SCP (0)
49 #define FR_RLV (-1)
50 #define FR_RSP (-2)
51 #define FR_RFP (-3)
52
53 #include "regset.h"
54
55 /*
56 * Wee need some reasonable default to prevent backtrace code
57 * from wandering too far
58 */
59 #define MAX_FUNCTION_SIZE 0x10000
60 #define MAX_PROLOGUE_SIZE 0x100
61
62
63 uint8_t dtrace_fuword8_nocheck(void *);
64 uint16_t dtrace_fuword16_nocheck(void *);
65 uint32_t dtrace_fuword32_nocheck(void *);
66 uint64_t dtrace_fuword64_nocheck(void *);
67
68 void
dtrace_getpcstack(pc_t * pcstack,int pcstack_limit,int aframes,uint32_t * intrpc)69 dtrace_getpcstack(pc_t *pcstack, int pcstack_limit, int aframes,
70 uint32_t *intrpc)
71 {
72 uint32_t *frame, *lastframe;
73 #if 0
74 int scp_offset;
75 #endif
76 int depth = 0;
77 pc_t caller = (pc_t) solaris_cpu[cpu_number()].cpu_dtrace_caller;
78
79 if (intrpc != 0)
80 pcstack[depth++] = (pc_t) intrpc;
81
82 aframes++;
83
84 frame = (uint32_t *)__builtin_frame_address(0);;
85 lastframe = NULL;
86 #if 0
87 scp_offset = -(get_pc_str_offset() >> 2);
88 #endif
89
90 while ((frame != NULL) && (depth < pcstack_limit)) {
91 db_addr_t scp;
92 #if 0
93 uint32_t savecode;
94 int r;
95 uint32_t *rp;
96 #endif
97
98 /*
99 * In theory, the SCP isn't guaranteed to be in the function
100 * that generated the stack frame. We hope for the best.
101 */
102 scp = frame[FR_SCP];
103 if (aframes > 0) {
104 aframes--;
105 if ((aframes == 0) && (caller != 0)) {
106 pcstack[depth++] = caller;
107 }
108 }
109 else {
110 pcstack[depth++] = scp;
111 }
112
113 #if 0
114 savecode = ((uint32_t *)scp)[scp_offset];
115 if ((savecode & 0x0e100000) == 0x08000000) {
116 /* Looks like an STM */
117 rp = frame - 4;
118 for (r = 10; r >= 0; r--) {
119 if (savecode & (1 << r)) {
120 /* register r == *rp-- */
121 }
122 }
123 }
124 #endif
125
126 /*
127 * Switch to next frame up
128 */
129 if (frame[FR_RFP] == 0)
130 break; /* Top of stack */
131
132 lastframe = frame;
133 frame = (uint32_t *)(frame[FR_RFP]);
134
135 if (INKERNEL((int)frame)) {
136 /* staying in kernel */
137 if (frame <= lastframe) {
138 /* bad frame pointer */
139 break;
140 }
141 }
142 else
143 break;
144 }
145
146 for (; depth < pcstack_limit; depth++) {
147 pcstack[depth] = 0;
148 }
149 }
150
151 void
dtrace_getupcstack(uint64_t * pcstack,int pcstack_limit)152 dtrace_getupcstack(uint64_t *pcstack, int pcstack_limit)
153 {
154 printf("IMPLEMENT ME: %s\n", __func__);
155 }
156
157 int
dtrace_getustackdepth(void)158 dtrace_getustackdepth(void)
159 {
160 printf("IMPLEMENT ME: %s\n", __func__);
161 return (0);
162 }
163
164 void
dtrace_getufpstack(uint64_t * pcstack,uint64_t * fpstack,int pcstack_limit)165 dtrace_getufpstack(uint64_t *pcstack, uint64_t *fpstack, int pcstack_limit)
166 {
167 printf("IMPLEMENT ME: %s\n", __func__);
168 }
169
170 /*ARGSUSED*/
171 uint64_t
dtrace_getarg(int arg,int aframes)172 dtrace_getarg(int arg, int aframes)
173 {
174 /* struct arm_frame *fp = (struct arm_frame *)dtrace_getfp();*/
175
176 printf("IMPLEMENT ME: %s\n", __func__);
177 return (0);
178 }
179
180 int
dtrace_getstackdepth(int aframes)181 dtrace_getstackdepth(int aframes)
182 {
183 uint32_t *frame, *lastframe;
184 int depth = 1;
185
186 frame = (uint32_t *)__builtin_frame_address(0);;
187 lastframe = NULL;
188
189 while (frame != NULL) {
190 #if 0
191 uint32_t savecode;
192 int r;
193 uint32_t *rp;
194 #endif
195
196 depth++;
197
198 /*
199 * Switch to next frame up
200 */
201 if (frame[FR_RFP] == 0)
202 break; /* Top of stack */
203
204 lastframe = frame;
205 frame = (uint32_t *)(frame[FR_RFP]);
206
207 if (INKERNEL((int)frame)) {
208 /* staying in kernel */
209 if (frame <= lastframe) {
210 /* bad frame pointer */
211 break;
212 }
213 }
214 else
215 break;
216 }
217
218 if (depth < aframes)
219 return 0;
220 else
221 return depth - aframes;
222
223 }
224
225 ulong_t
dtrace_getreg(struct trapframe * rp,uint_t reg)226 dtrace_getreg(struct trapframe *rp, uint_t reg)
227 {
228 printf("IMPLEMENT ME: %s\n", __func__);
229
230 return (0);
231 }
232
233 static int
dtrace_copycheck(uintptr_t uaddr,uintptr_t kaddr,size_t size)234 dtrace_copycheck(uintptr_t uaddr, uintptr_t kaddr, size_t size)
235 {
236
237 if (uaddr + size > VM_MAXUSER_ADDRESS || uaddr + size < uaddr) {
238 DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR);
239 cpu_core[cpu_number()].cpuc_dtrace_illval = uaddr;
240 return (0);
241 }
242
243 return (1);
244 }
245
246 void
dtrace_copyin(uintptr_t uaddr,uintptr_t kaddr,size_t size,volatile uint16_t * flags)247 dtrace_copyin(uintptr_t uaddr, uintptr_t kaddr, size_t size,
248 volatile uint16_t *flags)
249 {
250 if (dtrace_copycheck(uaddr, kaddr, size))
251 dtrace_copy(uaddr, kaddr, size);
252 }
253
254 void
dtrace_copyout(uintptr_t kaddr,uintptr_t uaddr,size_t size,volatile uint16_t * flags)255 dtrace_copyout(uintptr_t kaddr, uintptr_t uaddr, size_t size,
256 volatile uint16_t *flags)
257 {
258 if (dtrace_copycheck(uaddr, kaddr, size))
259 dtrace_copy(kaddr, uaddr, size);
260 }
261
262 void
dtrace_copyinstr(uintptr_t uaddr,uintptr_t kaddr,size_t size,volatile uint16_t * flags)263 dtrace_copyinstr(uintptr_t uaddr, uintptr_t kaddr, size_t size,
264 volatile uint16_t *flags)
265 {
266 if (dtrace_copycheck(uaddr, kaddr, size))
267 dtrace_copystr(uaddr, kaddr, size, flags);
268 }
269
270 void
dtrace_copyoutstr(uintptr_t kaddr,uintptr_t uaddr,size_t size,volatile uint16_t * flags)271 dtrace_copyoutstr(uintptr_t kaddr, uintptr_t uaddr, size_t size,
272 volatile uint16_t *flags)
273 {
274 if (dtrace_copycheck(uaddr, kaddr, size))
275 dtrace_copystr(kaddr, uaddr, size, flags);
276 }
277
278 uint8_t
dtrace_fuword8(void * uaddr)279 dtrace_fuword8(void *uaddr)
280 {
281 if ((uintptr_t)uaddr > VM_MAXUSER_ADDRESS) {
282 DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR);
283 cpu_core[cpu_number()].cpuc_dtrace_illval = (uintptr_t)uaddr;
284 return (0);
285 }
286 return (dtrace_fuword8_nocheck(uaddr));
287 }
288
289 uint16_t
dtrace_fuword16(void * uaddr)290 dtrace_fuword16(void *uaddr)
291 {
292 if ((uintptr_t)uaddr > VM_MAXUSER_ADDRESS) {
293 DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR);
294 cpu_core[cpu_number()].cpuc_dtrace_illval = (uintptr_t)uaddr;
295 return (0);
296 }
297 return (dtrace_fuword16_nocheck(uaddr));
298 }
299
300 uint32_t
dtrace_fuword32(void * uaddr)301 dtrace_fuword32(void *uaddr)
302 {
303 if ((uintptr_t)uaddr > VM_MAXUSER_ADDRESS) {
304 DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR);
305 cpu_core[cpu_number()].cpuc_dtrace_illval = (uintptr_t)uaddr;
306 return (0);
307 }
308 return (dtrace_fuword32_nocheck(uaddr));
309 }
310
311 uint64_t
dtrace_fuword64(void * uaddr)312 dtrace_fuword64(void *uaddr)
313 {
314 if ((uintptr_t)uaddr > VM_MAXUSER_ADDRESS) {
315 DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR);
316 cpu_core[cpu_number()].cpuc_dtrace_illval = (uintptr_t)uaddr;
317 return (0);
318 }
319 return (dtrace_fuword64_nocheck(uaddr));
320 }
321