Home | History | Annotate | Line # | Download | only in arm
      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 
     42 uintptr_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 
     63 uint8_t dtrace_fuword8_nocheck(void *);
     64 uint16_t dtrace_fuword16_nocheck(void *);
     65 uint32_t dtrace_fuword32_nocheck(void *);
     66 uint64_t dtrace_fuword64_nocheck(void *);
     67 
     68 void
     69 dtrace_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 
    151 void
    152 dtrace_getupcstack(uint64_t *pcstack, int pcstack_limit)
    153 {
    154 	printf("IMPLEMENT ME: %s\n", __func__);
    155 }
    156 
    157 int
    158 dtrace_getustackdepth(void)
    159 {
    160 	printf("IMPLEMENT ME: %s\n", __func__);
    161 	return (0);
    162 }
    163 
    164 void
    165 dtrace_getufpstack(uint64_t *pcstack, uint64_t *fpstack, int pcstack_limit)
    166 {
    167 	printf("IMPLEMENT ME: %s\n", __func__);
    168 }
    169 
    170 /*ARGSUSED*/
    171 uint64_t
    172 dtrace_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 
    180 int
    181 dtrace_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 
    225 ulong_t
    226 dtrace_getreg(struct trapframe *rp, uint_t reg)
    227 {
    228 	printf("IMPLEMENT ME: %s\n", __func__);
    229 
    230 	return (0);
    231 }
    232 
    233 static int
    234 dtrace_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 
    246 void
    247 dtrace_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 
    254 void
    255 dtrace_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 
    262 void
    263 dtrace_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 
    270 void
    271 dtrace_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 
    278 uint8_t
    279 dtrace_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 
    289 uint16_t
    290 dtrace_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 
    300 uint32_t
    301 dtrace_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 
    311 uint64_t
    312 dtrace_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