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