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