dtrace_isa.c revision 1.4
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
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
42uintptr_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
63uint8_t dtrace_fuword8_nocheck(void *);
64uint16_t dtrace_fuword16_nocheck(void *);
65uint32_t dtrace_fuword32_nocheck(void *);
66uint64_t dtrace_fuword64_nocheck(void *);
67
68void
69dtrace_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		printf("--> %08x\n", (uint32_t)scp);
104
105		if (aframes > 0) {
106			aframes--;
107			if ((aframes == 0) && (caller != 0)) {
108				pcstack[depth++] = caller;
109			}
110		}
111		else {
112			printf("++ --> %08x\n", (uint32_t)scp);
113			pcstack[depth++] = scp;
114		}
115
116#if 0
117		savecode = ((uint32_t *)scp)[scp_offset];
118		if ((savecode & 0x0e100000) == 0x08000000) {
119			/* Looks like an STM */
120			rp = frame - 4;
121			for (r = 10; r >= 0; r--) {
122				if (savecode & (1 << r)) {
123					/* register r == *rp-- */
124				}
125			}
126		}
127#endif
128
129		/*
130		 * Switch to next frame up
131		 */
132		if (frame[FR_RFP] == 0)
133			break; /* Top of stack */
134
135		lastframe = frame;
136		frame = (uint32_t *)(frame[FR_RFP]);
137
138		if (INKERNEL((int)frame)) {
139			/* staying in kernel */
140			if (frame <= lastframe) {
141				/* bad frame pointer */
142				break;
143			}
144		}
145		else
146			break;
147	}
148
149	for (; depth < pcstack_limit; depth++) {
150		pcstack[depth] = 0;
151	}
152}
153
154void
155dtrace_getupcstack(uint64_t *pcstack, int pcstack_limit)
156{
157	printf("unimplemented\n");
158}
159
160int
161dtrace_getustackdepth(void)
162{
163	printf("unimplemented\n");
164	return (0);
165}
166
167void
168dtrace_getufpstack(uint64_t *pcstack, uint64_t *fpstack, int pcstack_limit)
169{
170	printf("IMPLEMENT ME: %s\n", __func__);
171}
172
173/*ARGSUSED*/
174uint64_t
175dtrace_getarg(int arg, int aframes)
176{
177	printf("unimplemented\n");
178
179	return (0);
180}
181
182int
183dtrace_getstackdepth(int aframes)
184{
185	uint32_t	*frame, *lastframe;
186	int	depth = 1;
187
188	frame = (uint32_t *)__builtin_frame_address(0);;
189	lastframe = NULL;
190
191	while (frame != NULL) {
192#if 0
193		uint32_t	savecode;
194		int		r;
195		uint32_t	*rp;
196#endif
197
198		depth++;
199
200		/*
201		 * Switch to next frame up
202		 */
203		if (frame[FR_RFP] == 0)
204			break; /* Top of stack */
205
206		lastframe = frame;
207		frame = (uint32_t *)(frame[FR_RFP]);
208
209		if (INKERNEL((int)frame)) {
210			/* staying in kernel */
211			if (frame <= lastframe) {
212				/* bad frame pointer */
213				break;
214			}
215		}
216		else
217			break;
218	}
219
220	if (depth < aframes)
221		return 0;
222	else
223		return depth - aframes;
224
225}
226
227ulong_t
228dtrace_getreg(struct regs *regs, uint_t reg)
229{
230
231	return (0);
232}
233
234static int
235dtrace_copycheck(uintptr_t uaddr, uintptr_t kaddr, size_t size)
236{
237
238	if (uaddr + size > VM_MAXUSER_ADDRESS || uaddr + size < uaddr) {
239		DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR);
240		cpu_core[cpu_number()].cpuc_dtrace_illval = uaddr;
241		return (0);
242	}
243
244	return (1);
245}
246
247void
248dtrace_copyin(uintptr_t uaddr, uintptr_t kaddr, size_t size,
249    volatile uint16_t *flags)
250{
251	if (dtrace_copycheck(uaddr, kaddr, size))
252		dtrace_copy(uaddr, kaddr, size);
253}
254
255void
256dtrace_copyout(uintptr_t kaddr, uintptr_t uaddr, size_t size,
257    volatile uint16_t *flags)
258{
259	if (dtrace_copycheck(uaddr, kaddr, size))
260		dtrace_copy(kaddr, uaddr, size);
261}
262
263void
264dtrace_copyinstr(uintptr_t uaddr, uintptr_t kaddr, size_t size,
265    volatile uint16_t *flags)
266{
267	if (dtrace_copycheck(uaddr, kaddr, size))
268		dtrace_copystr(uaddr, kaddr, size, flags);
269}
270
271void
272dtrace_copyoutstr(uintptr_t kaddr, uintptr_t uaddr, size_t size,
273    volatile uint16_t *flags)
274{
275	if (dtrace_copycheck(uaddr, kaddr, size))
276		dtrace_copystr(kaddr, uaddr, size, flags);
277}
278
279uint8_t
280dtrace_fuword8(void *uaddr)
281{
282	if ((uintptr_t)uaddr > VM_MAXUSER_ADDRESS) {
283		DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR);
284		cpu_core[cpu_number()].cpuc_dtrace_illval = (uintptr_t)uaddr;
285		return (0);
286	}
287	return (dtrace_fuword8_nocheck(uaddr));
288}
289
290uint16_t
291dtrace_fuword16(void *uaddr)
292{
293	if ((uintptr_t)uaddr > VM_MAXUSER_ADDRESS) {
294		DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR);
295		cpu_core[cpu_number()].cpuc_dtrace_illval = (uintptr_t)uaddr;
296		return (0);
297	}
298	return (dtrace_fuword16_nocheck(uaddr));
299}
300
301uint32_t
302dtrace_fuword32(void *uaddr)
303{
304	if ((uintptr_t)uaddr > VM_MAXUSER_ADDRESS) {
305		DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR);
306		cpu_core[cpu_number()].cpuc_dtrace_illval = (uintptr_t)uaddr;
307		return (0);
308	}
309	return (dtrace_fuword32_nocheck(uaddr));
310}
311
312uint64_t
313dtrace_fuword64(void *uaddr)
314{
315	if ((uintptr_t)uaddr > VM_MAXUSER_ADDRESS) {
316		DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR);
317		cpu_core[cpu_number()].cpuc_dtrace_illval = (uintptr_t)uaddr;
318		return (0);
319	}
320	return (dtrace_fuword64_nocheck(uaddr));
321}
322