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