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