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