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/atomic.h> 45 #include <machine/db_machdep.h> 46 #include <machine/md_var.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 uint8_t dtrace_fuword8_nocheck(void *); 62 uint16_t dtrace_fuword16_nocheck(void *); 63 uint32_t dtrace_fuword32_nocheck(void *); 64 uint64_t dtrace_fuword64_nocheck(void *); 65 66 void 67 dtrace_getpcstack(pc_t *pcstack, int pcstack_limit, int aframes, 68 uint32_t *intrpc) 69 { 70 struct unwind_state state; 71 int scp_offset; 72 register_t sp; 73 int depth; 74 75 depth = 0; 76 77 if (intrpc != 0) { 78 pcstack[depth++] = (pc_t) intrpc; 79 } 80 81 aframes++; 82 83 __asm __volatile("mov %0, sp" : "=&r" (sp)); 84 85 state.fp = (uint64_t)__builtin_frame_address(0); 86 state.sp = sp; 87 state.pc = (uint64_t)dtrace_getpcstack; 88 89 while (depth < pcstack_limit) { 90 if (unwind_frame(&state)) 91 break; 92 93 if (!INKERNEL(state.pc) || !INKERNEL(state.fp)) 94 break; 95 96 /* 97 * NB: Unlike some other architectures, we don't need to 98 * explicitly insert cpu_dtrace_caller as it appears in the 99 * normal kernel stack trace rather than a special trap frame. 100 */ 101 if (aframes > 0) { 102 aframes--; 103 } else { 104 pcstack[depth++] = state.pc; 105 } 106 107 } 108 109 for (; depth < pcstack_limit; depth++) { 110 pcstack[depth] = 0; 111 } 112 } 113 114 void 115 dtrace_getupcstack(uint64_t *pcstack, int pcstack_limit) 116 { 117 118 printf("IMPLEMENT ME: %s\n", __func__); 119 } 120 121 int 122 dtrace_getustackdepth(void) 123 { 124 125 printf("IMPLEMENT ME: %s\n", __func__); 126 127 return (0); 128 } 129 130 void 131 dtrace_getufpstack(uint64_t *pcstack, uint64_t *fpstack, int pcstack_limit) 132 { 133 134 printf("IMPLEMENT ME: %s\n", __func__); 135 } 136 137 /*ARGSUSED*/ 138 uint64_t 139 dtrace_getarg(int arg, int aframes) 140 { 141 142 printf("IMPLEMENT ME: %s\n", __func__); 143 144 return (0); 145 } 146 147 int 148 dtrace_getstackdepth(int aframes) 149 { 150 struct unwind_state state; 151 int scp_offset; 152 register_t sp; 153 int depth; 154 int done; 155 156 depth = 1; 157 done = 0; 158 159 __asm __volatile("mov %0, sp" : "=&r" (sp)); 160 161 state.fp = (uint64_t)__builtin_frame_address(0); 162 state.sp = sp; 163 state.pc = (uint64_t)dtrace_getstackdepth; 164 165 do { 166 done = unwind_frame(&state); 167 if (!INKERNEL(state.pc) || !INKERNEL(state.fp)) 168 break; 169 depth++; 170 } while (!done); 171 172 if (depth < aframes) 173 return (0); 174 else 175 return (depth - aframes); 176 } 177 178 ulong_t 179 dtrace_getreg(struct trapframe *rp, uint_t reg) 180 { 181 182 printf("IMPLEMENT ME: %s\n", __func__); 183 184 return (0); 185 } 186 187 static int 188 dtrace_copycheck(uintptr_t uaddr, uintptr_t kaddr, size_t size) 189 { 190 191 if (uaddr + size > VM_MAXUSER_ADDRESS || uaddr + size < uaddr) { 192 DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR); 193 cpu_core[curcpu].cpuc_dtrace_illval = uaddr; 194 return (0); 195 } 196 197 return (1); 198 } 199 200 void 201 dtrace_copyin(uintptr_t uaddr, uintptr_t kaddr, size_t size, 202 volatile uint16_t *flags) 203 { 204 205 if (dtrace_copycheck(uaddr, kaddr, size)) 206 dtrace_copy(uaddr, kaddr, size); 207 } 208 209 void 210 dtrace_copyout(uintptr_t kaddr, uintptr_t uaddr, size_t size, 211 volatile uint16_t *flags) 212 { 213 214 if (dtrace_copycheck(uaddr, kaddr, size)) 215 dtrace_copy(kaddr, uaddr, size); 216 } 217 218 void 219 dtrace_copyinstr(uintptr_t uaddr, uintptr_t kaddr, size_t size, 220 volatile uint16_t *flags) 221 { 222 223 if (dtrace_copycheck(uaddr, kaddr, size)) 224 dtrace_copystr(uaddr, kaddr, size, flags); 225 } 226 227 void 228 dtrace_copyoutstr(uintptr_t kaddr, uintptr_t uaddr, size_t size, 229 volatile uint16_t *flags) 230 { 231 232 if (dtrace_copycheck(uaddr, kaddr, size)) 233 dtrace_copystr(kaddr, uaddr, size, flags); 234 } 235 236 uint8_t 237 dtrace_fuword8(void *uaddr) 238 { 239 240 if ((uintptr_t)uaddr > VM_MAXUSER_ADDRESS) { 241 DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR); 242 cpu_core[curcpu].cpuc_dtrace_illval = (uintptr_t)uaddr; 243 return (0); 244 } 245 246 return (dtrace_fuword8_nocheck(uaddr)); 247 } 248 249 uint16_t 250 dtrace_fuword16(void *uaddr) 251 { 252 253 if ((uintptr_t)uaddr > VM_MAXUSER_ADDRESS) { 254 DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR); 255 cpu_core[curcpu].cpuc_dtrace_illval = (uintptr_t)uaddr; 256 return (0); 257 } 258 259 return (dtrace_fuword16_nocheck(uaddr)); 260 } 261 262 uint32_t 263 dtrace_fuword32(void *uaddr) 264 { 265 266 if ((uintptr_t)uaddr > VM_MAXUSER_ADDRESS) { 267 DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR); 268 cpu_core[curcpu].cpuc_dtrace_illval = (uintptr_t)uaddr; 269 return (0); 270 } 271 272 return (dtrace_fuword32_nocheck(uaddr)); 273 } 274 275 uint64_t 276 dtrace_fuword64(void *uaddr) 277 { 278 279 if ((uintptr_t)uaddr > VM_MAXUSER_ADDRESS) { 280 DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR); 281 cpu_core[curcpu].cpuc_dtrace_illval = (uintptr_t)uaddr; 282 return (0); 283 } 284 285 return (dtrace_fuword64_nocheck(uaddr)); 286 } 287