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