xref: /freebsd/sys/cddl/dev/dtrace/arm/dtrace_isa.c (revision 8ddb146abcdf061be9f2c0db7e391697dafad85c)
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$
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 #include <sys/stack.h>
34 #include <sys/pcpu.h>
35 
36 #include <machine/frame.h>
37 #include <machine/md_var.h>
38 
39 #include <vm/vm.h>
40 #include <vm/vm_param.h>
41 #include <vm/pmap.h>
42 
43 #include <machine/atomic.h>
44 #include <machine/db_machdep.h>
45 #include <machine/md_var.h>
46 #include <machine/stack.h>
47 #include <ddb/db_sym.h>
48 #include <ddb/ddb.h>
49 #include <sys/kdb.h>
50 
51 #include "regset.h"
52 
53 /*
54  * Wee need some reasonable default to prevent backtrace code
55  * from wandering too far
56  */
57 #define	MAX_FUNCTION_SIZE 0x10000
58 #define	MAX_PROLOGUE_SIZE 0x100
59 
60 
61 uint8_t dtrace_fuword8_nocheck(void *);
62 uint16_t dtrace_fuword16_nocheck(void *);
63 uint32_t dtrace_fuword32_nocheck(void *);
64 uint64_t dtrace_fuword64_nocheck(void *);
65 
66 void
67 dtrace_getpcstack(pc_t *pcstack, int pcstack_limit, int aframes,
68     uint32_t *intrpc)
69 {
70 	struct unwind_state state;
71 	register_t sp;
72 	int scp_offset;
73 	int depth = 0;
74 
75 	if (intrpc != 0)
76 		pcstack[depth++] = (pc_t) intrpc;
77 
78 	aframes++;
79 
80 	__asm __volatile("mov %0, sp" : "=&r" (sp));
81 
82 	state.registers[FP] = (uint32_t)__builtin_frame_address(0);
83 	state.registers[SP] = sp;
84 	state.registers[LR] = (uint32_t)__builtin_return_address(0);
85 	state.registers[PC] = (uint32_t)dtrace_getpcstack;
86 
87 	while (depth < pcstack_limit) {
88 		int done;
89 
90 		done = unwind_stack_one(&state, 1);
91 
92 		/*
93 		 * NB: Unlike some other architectures, we don't need to
94 		 * explicitly insert cpu_dtrace_caller as it appears in the
95 		 * normal kernel stack trace rather than a special trap frame.
96 		 */
97 		if (aframes > 0) {
98 			aframes--;
99 		} else {
100 			pcstack[depth++] = state.registers[PC];
101 		}
102 
103 		if (done)
104 			break;
105 	}
106 
107 	for (; depth < pcstack_limit; depth++) {
108 		pcstack[depth] = 0;
109 	}
110 }
111 
112 void
113 dtrace_getupcstack(uint64_t *pcstack, int pcstack_limit)
114 {
115 	printf("IMPLEMENT ME: %s\n", __func__);
116 }
117 
118 int
119 dtrace_getustackdepth(void)
120 {
121 	printf("IMPLEMENT ME: %s\n", __func__);
122 	return (0);
123 }
124 
125 void
126 dtrace_getufpstack(uint64_t *pcstack, uint64_t *fpstack, int pcstack_limit)
127 {
128 	printf("IMPLEMENT ME: %s\n", __func__);
129 }
130 
131 /*ARGSUSED*/
132 uint64_t
133 dtrace_getarg(int arg, int aframes)
134 {
135 /*	struct arm_frame *fp = (struct arm_frame *)dtrace_getfp();*/
136 
137 	return (0);
138 }
139 
140 int
141 dtrace_getstackdepth(int aframes)
142 {
143 	struct unwind_state state;
144 	register_t sp;
145 	int scp_offset;
146 	int done = 0;
147 	int depth = 1;
148 
149 	__asm __volatile("mov %0, sp" : "=&r" (sp));
150 
151 	state.registers[FP] = (uint32_t)__builtin_frame_address(0);
152 	state.registers[SP] = sp;
153 	state.registers[LR] = (uint32_t)__builtin_return_address(0);
154 	state.registers[PC] = (uint32_t)dtrace_getstackdepth;
155 
156 	do {
157 		done = unwind_stack_one(&state, 1);
158 		depth++;
159 	} while (!done);
160 
161 	if (depth < aframes)
162 		return 0;
163 	else
164 		return depth - aframes;
165 }
166 
167 ulong_t
168 dtrace_getreg(struct trapframe *rp, uint_t reg)
169 {
170 	printf("IMPLEMENT ME: %s\n", __func__);
171 
172 	return (0);
173 }
174 
175 static int
176 dtrace_copycheck(uintptr_t uaddr, uintptr_t kaddr, size_t size)
177 {
178 
179 	if (uaddr + size > VM_MAXUSER_ADDRESS || uaddr + size < uaddr) {
180 		DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR);
181 		cpu_core[curcpu].cpuc_dtrace_illval = uaddr;
182 		return (0);
183 	}
184 
185 	return (1);
186 }
187 
188 void
189 dtrace_copyin(uintptr_t uaddr, uintptr_t kaddr, size_t size,
190     volatile uint16_t *flags)
191 {
192 	if (dtrace_copycheck(uaddr, kaddr, size))
193 		dtrace_copy(uaddr, kaddr, size);
194 }
195 
196 void
197 dtrace_copyout(uintptr_t kaddr, uintptr_t uaddr, size_t size,
198     volatile uint16_t *flags)
199 {
200 	if (dtrace_copycheck(uaddr, kaddr, size))
201 		dtrace_copy(kaddr, uaddr, size);
202 }
203 
204 void
205 dtrace_copyinstr(uintptr_t uaddr, uintptr_t kaddr, size_t size,
206     volatile uint16_t *flags)
207 {
208 	if (dtrace_copycheck(uaddr, kaddr, size))
209 		dtrace_copystr(uaddr, kaddr, size, flags);
210 }
211 
212 void
213 dtrace_copyoutstr(uintptr_t kaddr, uintptr_t uaddr, size_t size,
214     volatile uint16_t *flags)
215 {
216 	if (dtrace_copycheck(uaddr, kaddr, size))
217 		dtrace_copystr(kaddr, uaddr, size, flags);
218 }
219 
220 uint8_t
221 dtrace_fuword8(void *uaddr)
222 {
223 	if ((uintptr_t)uaddr > VM_MAXUSER_ADDRESS) {
224 		DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR);
225 		cpu_core[curcpu].cpuc_dtrace_illval = (uintptr_t)uaddr;
226 		return (0);
227 	}
228 	return (dtrace_fuword8_nocheck(uaddr));
229 }
230 
231 uint16_t
232 dtrace_fuword16(void *uaddr)
233 {
234 	if ((uintptr_t)uaddr > VM_MAXUSER_ADDRESS) {
235 		DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR);
236 		cpu_core[curcpu].cpuc_dtrace_illval = (uintptr_t)uaddr;
237 		return (0);
238 	}
239 	return (dtrace_fuword16_nocheck(uaddr));
240 }
241 
242 uint32_t
243 dtrace_fuword32(void *uaddr)
244 {
245 	if ((uintptr_t)uaddr > VM_MAXUSER_ADDRESS) {
246 		DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR);
247 		cpu_core[curcpu].cpuc_dtrace_illval = (uintptr_t)uaddr;
248 		return (0);
249 	}
250 	return (dtrace_fuword32_nocheck(uaddr));
251 }
252 
253 uint64_t
254 dtrace_fuword64(void *uaddr)
255 {
256 	if ((uintptr_t)uaddr > VM_MAXUSER_ADDRESS) {
257 		DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR);
258 		cpu_core[curcpu].cpuc_dtrace_illval = (uintptr_t)uaddr;
259 		return (0);
260 	}
261 	return (dtrace_fuword64_nocheck(uaddr));
262 }
263