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