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