dtrace_isa.c revision 1.2
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#include <machine/reg.h>
39
40#include <vm/vm.h>
41#include <vm/vm_param.h>
42#include <vm/pmap.h>
43
44#include <machine/db_machdep.h>
45#include <machine/md_var.h>
46#include <machine/vmparam.h>
47#include <machine/stack.h>
48#include <ddb/db_sym.h>
49#include <ddb/ddb.h>
50#include <sys/kdb.h>
51
52#include "regset.h"
53
54/*
55 * Wee need some reasonable default to prevent backtrace code
56 * from wandering too far
57 */
58#define	MAX_FUNCTION_SIZE 0x10000
59#define	MAX_PROLOGUE_SIZE 0x100
60
61
62uint8_t dtrace_fuword8_nocheck(void *);
63uint16_t dtrace_fuword16_nocheck(void *);
64uint32_t dtrace_fuword32_nocheck(void *);
65uint64_t dtrace_fuword64_nocheck(void *);
66
67void
68dtrace_getpcstack(pc_t *pcstack, int pcstack_limit, int aframes,
69    uint32_t *intrpc)
70{
71	uint32_t	*frame, *lastframe;
72	int	scp_offset;
73	int	depth = 0;
74	pc_t caller = (pc_t) solaris_cpu[curcpu].cpu_dtrace_caller;
75
76	if (intrpc != 0)
77		pcstack[depth++] = (pc_t) intrpc;
78
79	aframes++;
80
81	frame = (uint32_t *)__builtin_frame_address(0);;
82	lastframe = NULL;
83	scp_offset = -(get_pc_str_offset() >> 2);
84
85	while ((frame != NULL) && (depth < pcstack_limit)) {
86		db_addr_t	scp;
87#if 0
88		uint32_t	savecode;
89		int		r;
90		uint32_t	*rp;
91#endif
92
93		/*
94		 * In theory, the SCP isn't guaranteed to be in the function
95		 * that generated the stack frame.  We hope for the best.
96		 */
97		scp = frame[FR_SCP];
98		printf("--> %08x\n", (uint32_t)scp);
99
100		if (aframes > 0) {
101			aframes--;
102			if ((aframes == 0) && (caller != 0)) {
103				pcstack[depth++] = caller;
104			}
105		}
106		else {
107			printf("++ --> %08x\n", (uint32_t)scp);
108			pcstack[depth++] = scp;
109		}
110
111#if 0
112		savecode = ((uint32_t *)scp)[scp_offset];
113		if ((savecode & 0x0e100000) == 0x08000000) {
114			/* Looks like an STM */
115			rp = frame - 4;
116			for (r = 10; r >= 0; r--) {
117				if (savecode & (1 << r)) {
118					/* register r == *rp-- */
119				}
120			}
121		}
122#endif
123
124		/*
125		 * Switch to next frame up
126		 */
127		if (frame[FR_RFP] == 0)
128			break; /* Top of stack */
129
130		lastframe = frame;
131		frame = (uint32_t *)(frame[FR_RFP]);
132
133		if (INKERNEL((int)frame)) {
134			/* staying in kernel */
135			if (frame <= lastframe) {
136				/* bad frame pointer */
137				break;
138			}
139		}
140		else
141			break;
142	}
143
144	for (; depth < pcstack_limit; depth++) {
145		pcstack[depth] = 0;
146	}
147}
148
149void
150dtrace_getupcstack(uint64_t *pcstack, int pcstack_limit)
151{
152	printf("unimplemented\n");
153}
154
155int
156dtrace_getustackdepth(void)
157{
158	printf("unimplemented\n");
159	return (0);
160}
161
162void
163dtrace_getufpstack(uint64_t *pcstack, uint64_t *fpstack, int pcstack_limit)
164{
165	printf("IMPLEMENT ME: %s\n", __func__);
166}
167
168/*ARGSUSED*/
169uint64_t
170dtrace_getarg(int arg, int aframes)
171{
172	printf("unimplemented\n");
173
174	return (0);
175}
176
177int
178dtrace_getstackdepth(int aframes)
179{
180	uint32_t	*frame, *lastframe;
181	int	scp_offset;
182	int	depth = 1;
183
184	frame = (uint32_t *)__builtin_frame_address(0);;
185	lastframe = NULL;
186	scp_offset = -(get_pc_str_offset() >> 2);
187
188	while (frame != NULL) {
189		db_addr_t	scp;
190#if 0
191		uint32_t	savecode;
192		int		r;
193		uint32_t	*rp;
194#endif
195
196		/*
197		 * In theory, the SCP isn't guaranteed to be in the function
198		 * that generated the stack frame.  We hope for the best.
199		 */
200		scp = frame[FR_SCP];
201
202		depth++;
203
204		/*
205		 * Switch to next frame up
206		 */
207		if (frame[FR_RFP] == 0)
208			break; /* Top of stack */
209
210		lastframe = frame;
211		frame = (uint32_t *)(frame[FR_RFP]);
212
213		if (INKERNEL((int)frame)) {
214			/* staying in kernel */
215			if (frame <= lastframe) {
216				/* bad frame pointer */
217				break;
218			}
219		}
220		else
221			break;
222	}
223
224	if (depth < aframes)
225		return 0;
226	else
227		return depth - aframes;
228
229}
230
231ulong_t
232dtrace_getreg(struct trapframe *rp, uint_t reg)
233{
234
235	return (0);
236}
237
238static int
239dtrace_copycheck(uintptr_t uaddr, uintptr_t kaddr, size_t size)
240{
241
242	if (uaddr + size > VM_MAXUSER_ADDRESS || uaddr + size < uaddr) {
243		DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR);
244		cpu_core[curcpu].cpuc_dtrace_illval = uaddr;
245		return (0);
246	}
247
248	return (1);
249}
250
251void
252dtrace_copyin(uintptr_t uaddr, uintptr_t kaddr, size_t size,
253    volatile uint16_t *flags)
254{
255	if (dtrace_copycheck(uaddr, kaddr, size))
256		dtrace_copy(uaddr, kaddr, size);
257}
258
259void
260dtrace_copyout(uintptr_t kaddr, uintptr_t uaddr, size_t size,
261    volatile uint16_t *flags)
262{
263	if (dtrace_copycheck(uaddr, kaddr, size))
264		dtrace_copy(kaddr, uaddr, size);
265}
266
267void
268dtrace_copyinstr(uintptr_t uaddr, uintptr_t kaddr, size_t size,
269    volatile uint16_t *flags)
270{
271	if (dtrace_copycheck(uaddr, kaddr, size))
272		dtrace_copystr(uaddr, kaddr, size, flags);
273}
274
275void
276dtrace_copyoutstr(uintptr_t kaddr, uintptr_t uaddr, size_t size,
277    volatile uint16_t *flags)
278{
279	if (dtrace_copycheck(uaddr, kaddr, size))
280		dtrace_copystr(kaddr, uaddr, size, flags);
281}
282
283uint8_t
284dtrace_fuword8(void *uaddr)
285{
286	if ((uintptr_t)uaddr > VM_MAXUSER_ADDRESS) {
287		DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR);
288		cpu_core[curcpu].cpuc_dtrace_illval = (uintptr_t)uaddr;
289		return (0);
290	}
291	return (dtrace_fuword8_nocheck(uaddr));
292}
293
294uint16_t
295dtrace_fuword16(void *uaddr)
296{
297	if ((uintptr_t)uaddr > VM_MAXUSER_ADDRESS) {
298		DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR);
299		cpu_core[curcpu].cpuc_dtrace_illval = (uintptr_t)uaddr;
300		return (0);
301	}
302	return (dtrace_fuword16_nocheck(uaddr));
303}
304
305uint32_t
306dtrace_fuword32(void *uaddr)
307{
308	if ((uintptr_t)uaddr > VM_MAXUSER_ADDRESS) {
309		DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR);
310		cpu_core[curcpu].cpuc_dtrace_illval = (uintptr_t)uaddr;
311		return (0);
312	}
313	return (dtrace_fuword32_nocheck(uaddr));
314}
315
316uint64_t
317dtrace_fuword64(void *uaddr)
318{
319	if ((uintptr_t)uaddr > VM_MAXUSER_ADDRESS) {
320		DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR);
321		cpu_core[curcpu].cpuc_dtrace_illval = (uintptr_t)uaddr;
322		return (0);
323	}
324	return (dtrace_fuword64_nocheck(uaddr));
325}
326