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