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 62uint8_t dtrace_fuword8_nocheck(void *); 63uint16_t dtrace_fuword16_nocheck(void *); 64uint32_t dtrace_fuword32_nocheck(void *); 65uint64_t dtrace_fuword64_nocheck(void *); 66 67void 68dtrace_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 113void 114dtrace_getupcstack(uint64_t *pcstack, int pcstack_limit) 115{ 116 printf("IMPLEMENT ME: %s\n", __func__); 117} 118 119int 120dtrace_getustackdepth(void) 121{ 122 printf("IMPLEMENT ME: %s\n", __func__); 123 return (0); 124} 125 126void 127dtrace_getufpstack(uint64_t *pcstack, uint64_t *fpstack, int pcstack_limit) 128{ 129 printf("IMPLEMENT ME: %s\n", __func__); 130} 131 132/*ARGSUSED*/ 133uint64_t 134dtrace_getarg(int arg, int aframes) 135{ 136/* struct arm_frame *fp = (struct arm_frame *)dtrace_getfp();*/ 137 138 return (0); 139} 140 141int 142dtrace_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 168ulong_t 169dtrace_getreg(struct trapframe *rp, uint_t reg) 170{ 171 printf("IMPLEMENT ME: %s\n", __func__); 172 173 return (0); 174} 175 176static int 177dtrace_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 189void 190dtrace_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 197void 198dtrace_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 205void 206dtrace_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 213void 214dtrace_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 221uint8_t 222dtrace_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 232uint16_t 233dtrace_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 243uint32_t 244dtrace_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 254uint64_t 255dtrace_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