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 /* 23 * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 #include <sys/cdefs.h> 27 28 #include <sys/param.h> 29 #include <sys/systm.h> 30 #include <sys/dtrace_impl.h> 31 #include <sys/kernel.h> 32 #include <sys/stack.h> 33 #include <sys/pcpu.h> 34 35 #include <machine/frame.h> 36 #include <machine/md_var.h> 37 38 #include <vm/vm.h> 39 #include <vm/vm_param.h> 40 #include <vm/pmap.h> 41 42 #include <machine/atomic.h> 43 #include <machine/db_machdep.h> 44 #include <machine/md_var.h> 45 #include <machine/stack.h> 46 #include <ddb/db_sym.h> 47 #include <ddb/ddb.h> 48 #include <sys/kdb.h> 49 50 #include "regset.h" 51 52 uint8_t dtrace_fuword8_nocheck(void *); 53 uint16_t dtrace_fuword16_nocheck(void *); 54 uint32_t dtrace_fuword32_nocheck(void *); 55 uint64_t dtrace_fuword64_nocheck(void *); 56 57 void 58 dtrace_getpcstack(pc_t *pcstack, int pcstack_limit, int aframes, 59 uint32_t *intrpc) 60 { 61 struct unwind_state state; 62 register_t sp; 63 int scp_offset; 64 int depth = 0; 65 66 if (intrpc != 0) 67 pcstack[depth++] = (pc_t) intrpc; 68 69 aframes++; 70 71 __asm __volatile("mov %0, sp" : "=&r" (sp)); 72 73 state.registers[FP] = (uint32_t)__builtin_frame_address(0); 74 state.registers[SP] = sp; 75 state.registers[LR] = (uint32_t)__builtin_return_address(0); 76 state.registers[PC] = (uint32_t)dtrace_getpcstack; 77 78 while (depth < pcstack_limit) { 79 int done; 80 81 done = unwind_stack_one(&state, 1); 82 83 /* 84 * NB: Unlike some other architectures, we don't need to 85 * explicitly insert cpu_dtrace_caller as it appears in the 86 * normal kernel stack trace rather than a special trap frame. 87 */ 88 if (aframes > 0) { 89 aframes--; 90 } else { 91 pcstack[depth++] = state.registers[PC]; 92 } 93 94 if (done) 95 break; 96 } 97 98 for (; depth < pcstack_limit; depth++) { 99 pcstack[depth] = 0; 100 } 101 } 102 103 void 104 dtrace_getupcstack(uint64_t *pcstack, int pcstack_limit) 105 { 106 printf("IMPLEMENT ME: %s\n", __func__); 107 } 108 109 int 110 dtrace_getustackdepth(void) 111 { 112 printf("IMPLEMENT ME: %s\n", __func__); 113 return (0); 114 } 115 116 void 117 dtrace_getufpstack(uint64_t *pcstack, uint64_t *fpstack, int pcstack_limit) 118 { 119 printf("IMPLEMENT ME: %s\n", __func__); 120 } 121 122 /*ARGSUSED*/ 123 uint64_t 124 dtrace_getarg(int arg, int aframes) 125 { 126 /* struct arm_frame *fp = (struct arm_frame *)dtrace_getfp();*/ 127 128 return (0); 129 } 130 131 int 132 dtrace_getstackdepth(int aframes) 133 { 134 struct unwind_state state; 135 register_t sp; 136 int scp_offset; 137 int done = 0; 138 int depth = 1; 139 140 __asm __volatile("mov %0, sp" : "=&r" (sp)); 141 142 state.registers[FP] = (uint32_t)__builtin_frame_address(0); 143 state.registers[SP] = sp; 144 state.registers[LR] = (uint32_t)__builtin_return_address(0); 145 state.registers[PC] = (uint32_t)dtrace_getstackdepth; 146 147 do { 148 done = unwind_stack_one(&state, 1); 149 depth++; 150 } while (!done); 151 152 if (depth < aframes) 153 return 0; 154 else 155 return depth - aframes; 156 } 157 158 ulong_t 159 dtrace_getreg(struct trapframe *frame, uint_t reg) 160 { 161 printf("IMPLEMENT ME: %s\n", __func__); 162 163 return (0); 164 } 165 166 static int 167 dtrace_copycheck(uintptr_t uaddr, uintptr_t kaddr, size_t size) 168 { 169 170 if (uaddr + size > VM_MAXUSER_ADDRESS || uaddr + size < uaddr) { 171 DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR); 172 cpu_core[curcpu].cpuc_dtrace_illval = uaddr; 173 return (0); 174 } 175 176 return (1); 177 } 178 179 void 180 dtrace_copyin(uintptr_t uaddr, uintptr_t kaddr, size_t size, 181 volatile uint16_t *flags) 182 { 183 if (dtrace_copycheck(uaddr, kaddr, size)) 184 dtrace_copy(uaddr, kaddr, size); 185 } 186 187 void 188 dtrace_copyout(uintptr_t kaddr, uintptr_t uaddr, size_t size, 189 volatile uint16_t *flags) 190 { 191 if (dtrace_copycheck(uaddr, kaddr, size)) 192 dtrace_copy(kaddr, uaddr, size); 193 } 194 195 void 196 dtrace_copyinstr(uintptr_t uaddr, uintptr_t kaddr, size_t size, 197 volatile uint16_t *flags) 198 { 199 if (dtrace_copycheck(uaddr, kaddr, size)) 200 dtrace_copystr(uaddr, kaddr, size, flags); 201 } 202 203 void 204 dtrace_copyoutstr(uintptr_t kaddr, uintptr_t uaddr, size_t size, 205 volatile uint16_t *flags) 206 { 207 if (dtrace_copycheck(uaddr, kaddr, size)) 208 dtrace_copystr(kaddr, uaddr, size, flags); 209 } 210 211 uint8_t 212 dtrace_fuword8(void *uaddr) 213 { 214 if ((uintptr_t)uaddr > VM_MAXUSER_ADDRESS) { 215 DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR); 216 cpu_core[curcpu].cpuc_dtrace_illval = (uintptr_t)uaddr; 217 return (0); 218 } 219 return (dtrace_fuword8_nocheck(uaddr)); 220 } 221 222 uint16_t 223 dtrace_fuword16(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_fuword16_nocheck(uaddr)); 231 } 232 233 uint32_t 234 dtrace_fuword32(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_fuword32_nocheck(uaddr)); 242 } 243 244 uint64_t 245 dtrace_fuword64(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_fuword64_nocheck(uaddr)); 253 } 254