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