]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/cddl/dev/dtrace/arm/dtrace_isa.c
MFV c144cc54795d: zlib 1.2.12.
[FreeBSD/FreeBSD.git] / sys / cddl / dev / dtrace / arm / dtrace_isa.c
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 }