xref: /netbsd-src/external/cddl/osnet/dev/dtrace/arm/dtrace_isa.c (revision ba2539a9805a0544ff82c0003cc02fe1eee5603d)
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