1*c7570492SJustin Hibbits /* 2*c7570492SJustin Hibbits * CDDL HEADER START 3*c7570492SJustin Hibbits * 4*c7570492SJustin Hibbits * The contents of this file are subject to the terms of the 5*c7570492SJustin Hibbits * Common Development and Distribution License, Version 1.0 only 6*c7570492SJustin Hibbits * (the "License"). You may not use this file except in compliance 7*c7570492SJustin Hibbits * with the License. 8*c7570492SJustin Hibbits * 9*c7570492SJustin Hibbits * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*c7570492SJustin Hibbits * or http://www.opensolaris.org/os/licensing. 11*c7570492SJustin Hibbits * See the License for the specific language governing permissions 12*c7570492SJustin Hibbits * and limitations under the License. 13*c7570492SJustin Hibbits * 14*c7570492SJustin Hibbits * When distributing Covered Code, include this CDDL HEADER in each 15*c7570492SJustin Hibbits * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*c7570492SJustin Hibbits * If applicable, add the following below this CDDL HEADER, with the 17*c7570492SJustin Hibbits * fields enclosed by brackets "[]" replaced with your own identifying 18*c7570492SJustin Hibbits * information: Portions Copyright [yyyy] [name of copyright owner] 19*c7570492SJustin Hibbits * 20*c7570492SJustin Hibbits * CDDL HEADER END 21*c7570492SJustin Hibbits * 22*c7570492SJustin Hibbits * $FreeBSD$ 23*c7570492SJustin Hibbits */ 24*c7570492SJustin Hibbits /* 25*c7570492SJustin Hibbits * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 26*c7570492SJustin Hibbits * Use is subject to license terms. 27*c7570492SJustin Hibbits */ 28*c7570492SJustin Hibbits #include <sys/cdefs.h> 29*c7570492SJustin Hibbits 30*c7570492SJustin Hibbits #include <sys/param.h> 31*c7570492SJustin Hibbits #include <sys/systm.h> 32*c7570492SJustin Hibbits #include <sys/kernel.h> 33*c7570492SJustin Hibbits #include <sys/stack.h> 34*c7570492SJustin Hibbits #include <sys/sysent.h> 35*c7570492SJustin Hibbits #include <sys/pcpu.h> 36*c7570492SJustin Hibbits 37*c7570492SJustin Hibbits #include <machine/frame.h> 38*c7570492SJustin Hibbits #include <machine/md_var.h> 39*c7570492SJustin Hibbits #include <machine/reg.h> 40*c7570492SJustin Hibbits #include <machine/stack.h> 41*c7570492SJustin Hibbits 42*c7570492SJustin Hibbits #include <vm/vm.h> 43*c7570492SJustin Hibbits #include <vm/vm_param.h> 44*c7570492SJustin Hibbits #include <vm/pmap.h> 45*c7570492SJustin Hibbits 46*c7570492SJustin Hibbits #include "regset.h" 47*c7570492SJustin Hibbits 48*c7570492SJustin Hibbits uint8_t dtrace_fuword8_nocheck(void *); 49*c7570492SJustin Hibbits uint16_t dtrace_fuword16_nocheck(void *); 50*c7570492SJustin Hibbits uint32_t dtrace_fuword32_nocheck(void *); 51*c7570492SJustin Hibbits uint64_t dtrace_fuword64_nocheck(void *); 52*c7570492SJustin Hibbits 53*c7570492SJustin Hibbits /* Offset to the LR Save word (ppc32) */ 54*c7570492SJustin Hibbits #define RETURN_OFFSET 4 55*c7570492SJustin Hibbits #define RETURN_OFFSET64 8 56*c7570492SJustin Hibbits 57*c7570492SJustin Hibbits #define INKERNEL(x) ((x) <= VM_MAX_KERNEL_ADDRESS && \ 58*c7570492SJustin Hibbits (x) >= VM_MIN_KERNEL_ADDRESS) 59*c7570492SJustin Hibbits 60*c7570492SJustin Hibbits greg_t 61*c7570492SJustin Hibbits dtrace_getfp(void) 62*c7570492SJustin Hibbits { 63*c7570492SJustin Hibbits return (greg_t)__builtin_frame_address(0); 64*c7570492SJustin Hibbits } 65*c7570492SJustin Hibbits 66*c7570492SJustin Hibbits void 67*c7570492SJustin Hibbits dtrace_getpcstack(pc_t *pcstack, int pcstack_limit, int aframes, 68*c7570492SJustin Hibbits uint32_t *intrpc) 69*c7570492SJustin Hibbits { 70*c7570492SJustin Hibbits int depth = 0; 71*c7570492SJustin Hibbits register_t sp; 72*c7570492SJustin Hibbits vm_offset_t callpc; 73*c7570492SJustin Hibbits pc_t caller = (pc_t) solaris_cpu[curcpu].cpu_dtrace_caller; 74*c7570492SJustin Hibbits 75*c7570492SJustin Hibbits if (intrpc != 0) 76*c7570492SJustin Hibbits pcstack[depth++] = (pc_t) intrpc; 77*c7570492SJustin Hibbits 78*c7570492SJustin Hibbits aframes++; 79*c7570492SJustin Hibbits 80*c7570492SJustin Hibbits sp = dtrace_getfp(); 81*c7570492SJustin Hibbits 82*c7570492SJustin Hibbits while (depth < pcstack_limit) { 83*c7570492SJustin Hibbits if (!INKERNEL((long) sp)) 84*c7570492SJustin Hibbits break; 85*c7570492SJustin Hibbits 86*c7570492SJustin Hibbits callpc = *(uintptr_t *)(sp + RETURN_OFFSET); 87*c7570492SJustin Hibbits 88*c7570492SJustin Hibbits if (!INKERNEL(callpc)) 89*c7570492SJustin Hibbits break; 90*c7570492SJustin Hibbits 91*c7570492SJustin Hibbits if (aframes > 0) { 92*c7570492SJustin Hibbits aframes--; 93*c7570492SJustin Hibbits if ((aframes == 0) && (caller != 0)) { 94*c7570492SJustin Hibbits pcstack[depth++] = caller; 95*c7570492SJustin Hibbits } 96*c7570492SJustin Hibbits } 97*c7570492SJustin Hibbits else { 98*c7570492SJustin Hibbits pcstack[depth++] = callpc; 99*c7570492SJustin Hibbits } 100*c7570492SJustin Hibbits 101*c7570492SJustin Hibbits sp = *(uintptr_t*)sp; 102*c7570492SJustin Hibbits } 103*c7570492SJustin Hibbits 104*c7570492SJustin Hibbits for (; depth < pcstack_limit; depth++) { 105*c7570492SJustin Hibbits pcstack[depth] = 0; 106*c7570492SJustin Hibbits } 107*c7570492SJustin Hibbits } 108*c7570492SJustin Hibbits 109*c7570492SJustin Hibbits static int 110*c7570492SJustin Hibbits dtrace_getustack_common(uint64_t *pcstack, int pcstack_limit, uintptr_t pc, 111*c7570492SJustin Hibbits uintptr_t sp) 112*c7570492SJustin Hibbits { 113*c7570492SJustin Hibbits proc_t *p = curproc; 114*c7570492SJustin Hibbits int ret = 0; 115*c7570492SJustin Hibbits 116*c7570492SJustin Hibbits ASSERT(pcstack == NULL || pcstack_limit > 0); 117*c7570492SJustin Hibbits 118*c7570492SJustin Hibbits while (pc != 0) { 119*c7570492SJustin Hibbits ret++; 120*c7570492SJustin Hibbits if (pcstack != NULL) { 121*c7570492SJustin Hibbits *pcstack++ = (uint64_t)pc; 122*c7570492SJustin Hibbits pcstack_limit--; 123*c7570492SJustin Hibbits if (pcstack_limit <= 0) 124*c7570492SJustin Hibbits break; 125*c7570492SJustin Hibbits } 126*c7570492SJustin Hibbits 127*c7570492SJustin Hibbits if (sp == 0) 128*c7570492SJustin Hibbits break; 129*c7570492SJustin Hibbits 130*c7570492SJustin Hibbits if (SV_PROC_FLAG(p, SV_ILP32)) { 131*c7570492SJustin Hibbits pc = dtrace_fuword32((void *)(sp + RETURN_OFFSET)); 132*c7570492SJustin Hibbits sp = dtrace_fuword32((void *)sp); 133*c7570492SJustin Hibbits } 134*c7570492SJustin Hibbits else { 135*c7570492SJustin Hibbits pc = dtrace_fuword64((void *)(sp + RETURN_OFFSET64)); 136*c7570492SJustin Hibbits sp = dtrace_fuword64((void *)sp); 137*c7570492SJustin Hibbits } 138*c7570492SJustin Hibbits } 139*c7570492SJustin Hibbits 140*c7570492SJustin Hibbits return (ret); 141*c7570492SJustin Hibbits } 142*c7570492SJustin Hibbits 143*c7570492SJustin Hibbits void 144*c7570492SJustin Hibbits dtrace_getupcstack(uint64_t *pcstack, int pcstack_limit) 145*c7570492SJustin Hibbits { 146*c7570492SJustin Hibbits proc_t *p = curproc; 147*c7570492SJustin Hibbits struct trapframe *tf; 148*c7570492SJustin Hibbits uintptr_t pc, sp; 149*c7570492SJustin Hibbits volatile uint16_t *flags = 150*c7570492SJustin Hibbits (volatile uint16_t *)&cpu_core[curcpu].cpuc_dtrace_flags; 151*c7570492SJustin Hibbits int n; 152*c7570492SJustin Hibbits 153*c7570492SJustin Hibbits if (*flags & CPU_DTRACE_FAULT) 154*c7570492SJustin Hibbits return; 155*c7570492SJustin Hibbits 156*c7570492SJustin Hibbits if (pcstack_limit <= 0) 157*c7570492SJustin Hibbits return; 158*c7570492SJustin Hibbits 159*c7570492SJustin Hibbits /* 160*c7570492SJustin Hibbits * If there's no user context we still need to zero the stack. 161*c7570492SJustin Hibbits */ 162*c7570492SJustin Hibbits if (p == NULL || (tf = curthread->td_frame) == NULL) 163*c7570492SJustin Hibbits goto zero; 164*c7570492SJustin Hibbits 165*c7570492SJustin Hibbits *pcstack++ = (uint64_t)p->p_pid; 166*c7570492SJustin Hibbits pcstack_limit--; 167*c7570492SJustin Hibbits 168*c7570492SJustin Hibbits if (pcstack_limit <= 0) 169*c7570492SJustin Hibbits return; 170*c7570492SJustin Hibbits 171*c7570492SJustin Hibbits pc = tf->srr0; 172*c7570492SJustin Hibbits sp = tf->fixreg[1]; 173*c7570492SJustin Hibbits 174*c7570492SJustin Hibbits if (DTRACE_CPUFLAG_ISSET(CPU_DTRACE_ENTRY)) { 175*c7570492SJustin Hibbits /* 176*c7570492SJustin Hibbits * In an entry probe. The frame pointer has not yet been 177*c7570492SJustin Hibbits * pushed (that happens in the function prologue). The 178*c7570492SJustin Hibbits * best approach is to add the current pc as a missing top 179*c7570492SJustin Hibbits * of stack and back the pc up to the caller, which is stored 180*c7570492SJustin Hibbits * at the current stack pointer address since the call 181*c7570492SJustin Hibbits * instruction puts it there right before the branch. 182*c7570492SJustin Hibbits */ 183*c7570492SJustin Hibbits 184*c7570492SJustin Hibbits *pcstack++ = (uint64_t)pc; 185*c7570492SJustin Hibbits pcstack_limit--; 186*c7570492SJustin Hibbits if (pcstack_limit <= 0) 187*c7570492SJustin Hibbits return; 188*c7570492SJustin Hibbits 189*c7570492SJustin Hibbits pc = tf->lr; 190*c7570492SJustin Hibbits } 191*c7570492SJustin Hibbits 192*c7570492SJustin Hibbits n = dtrace_getustack_common(pcstack, pcstack_limit, pc, sp); 193*c7570492SJustin Hibbits ASSERT(n >= 0); 194*c7570492SJustin Hibbits ASSERT(n <= pcstack_limit); 195*c7570492SJustin Hibbits 196*c7570492SJustin Hibbits pcstack += n; 197*c7570492SJustin Hibbits pcstack_limit -= n; 198*c7570492SJustin Hibbits 199*c7570492SJustin Hibbits zero: 200*c7570492SJustin Hibbits while (pcstack_limit-- > 0) 201*c7570492SJustin Hibbits *pcstack++ = 0; 202*c7570492SJustin Hibbits } 203*c7570492SJustin Hibbits 204*c7570492SJustin Hibbits int 205*c7570492SJustin Hibbits dtrace_getustackdepth(void) 206*c7570492SJustin Hibbits { 207*c7570492SJustin Hibbits proc_t *p = curproc; 208*c7570492SJustin Hibbits struct trapframe *tf; 209*c7570492SJustin Hibbits uintptr_t pc, sp; 210*c7570492SJustin Hibbits int n = 0; 211*c7570492SJustin Hibbits 212*c7570492SJustin Hibbits if (p == NULL || (tf = curthread->td_frame) == NULL) 213*c7570492SJustin Hibbits return (0); 214*c7570492SJustin Hibbits 215*c7570492SJustin Hibbits if (DTRACE_CPUFLAG_ISSET(CPU_DTRACE_FAULT)) 216*c7570492SJustin Hibbits return (-1); 217*c7570492SJustin Hibbits 218*c7570492SJustin Hibbits pc = tf->srr0; 219*c7570492SJustin Hibbits sp = tf->fixreg[1]; 220*c7570492SJustin Hibbits 221*c7570492SJustin Hibbits if (DTRACE_CPUFLAG_ISSET(CPU_DTRACE_ENTRY)) { 222*c7570492SJustin Hibbits /* 223*c7570492SJustin Hibbits * In an entry probe. The frame pointer has not yet been 224*c7570492SJustin Hibbits * pushed (that happens in the function prologue). The 225*c7570492SJustin Hibbits * best approach is to add the current pc as a missing top 226*c7570492SJustin Hibbits * of stack and back the pc up to the caller, which is stored 227*c7570492SJustin Hibbits * at the current stack pointer address since the call 228*c7570492SJustin Hibbits * instruction puts it there right before the branch. 229*c7570492SJustin Hibbits */ 230*c7570492SJustin Hibbits 231*c7570492SJustin Hibbits if (SV_PROC_FLAG(p, SV_ILP32)) { 232*c7570492SJustin Hibbits pc = dtrace_fuword32((void *) sp); 233*c7570492SJustin Hibbits } 234*c7570492SJustin Hibbits else 235*c7570492SJustin Hibbits pc = dtrace_fuword64((void *) sp); 236*c7570492SJustin Hibbits n++; 237*c7570492SJustin Hibbits } 238*c7570492SJustin Hibbits 239*c7570492SJustin Hibbits n += dtrace_getustack_common(NULL, 0, pc, sp); 240*c7570492SJustin Hibbits 241*c7570492SJustin Hibbits return (n); 242*c7570492SJustin Hibbits } 243*c7570492SJustin Hibbits 244*c7570492SJustin Hibbits void 245*c7570492SJustin Hibbits dtrace_getufpstack(uint64_t *pcstack, uint64_t *fpstack, int pcstack_limit) 246*c7570492SJustin Hibbits { 247*c7570492SJustin Hibbits proc_t *p = curproc; 248*c7570492SJustin Hibbits struct trapframe *tf; 249*c7570492SJustin Hibbits uintptr_t pc, sp; 250*c7570492SJustin Hibbits volatile uint16_t *flags = 251*c7570492SJustin Hibbits (volatile uint16_t *)&cpu_core[curcpu].cpuc_dtrace_flags; 252*c7570492SJustin Hibbits #ifdef notyet /* XXX signal stack */ 253*c7570492SJustin Hibbits uintptr_t oldcontext; 254*c7570492SJustin Hibbits size_t s1, s2; 255*c7570492SJustin Hibbits #endif 256*c7570492SJustin Hibbits 257*c7570492SJustin Hibbits if (*flags & CPU_DTRACE_FAULT) 258*c7570492SJustin Hibbits return; 259*c7570492SJustin Hibbits 260*c7570492SJustin Hibbits if (pcstack_limit <= 0) 261*c7570492SJustin Hibbits return; 262*c7570492SJustin Hibbits 263*c7570492SJustin Hibbits /* 264*c7570492SJustin Hibbits * If there's no user context we still need to zero the stack. 265*c7570492SJustin Hibbits */ 266*c7570492SJustin Hibbits if (p == NULL || (tf = curthread->td_frame) == NULL) 267*c7570492SJustin Hibbits goto zero; 268*c7570492SJustin Hibbits 269*c7570492SJustin Hibbits *pcstack++ = (uint64_t)p->p_pid; 270*c7570492SJustin Hibbits pcstack_limit--; 271*c7570492SJustin Hibbits 272*c7570492SJustin Hibbits if (pcstack_limit <= 0) 273*c7570492SJustin Hibbits return; 274*c7570492SJustin Hibbits 275*c7570492SJustin Hibbits pc = tf->srr0; 276*c7570492SJustin Hibbits sp = tf->fixreg[1]; 277*c7570492SJustin Hibbits 278*c7570492SJustin Hibbits #ifdef notyet /* XXX signal stack */ 279*c7570492SJustin Hibbits oldcontext = lwp->lwp_oldcontext; 280*c7570492SJustin Hibbits s1 = sizeof (struct xframe) + 2 * sizeof (long); 281*c7570492SJustin Hibbits s2 = s1 + sizeof (siginfo_t); 282*c7570492SJustin Hibbits #endif 283*c7570492SJustin Hibbits 284*c7570492SJustin Hibbits if (DTRACE_CPUFLAG_ISSET(CPU_DTRACE_ENTRY)) { 285*c7570492SJustin Hibbits *pcstack++ = (uint64_t)pc; 286*c7570492SJustin Hibbits *fpstack++ = 0; 287*c7570492SJustin Hibbits pcstack_limit--; 288*c7570492SJustin Hibbits if (pcstack_limit <= 0) 289*c7570492SJustin Hibbits return; 290*c7570492SJustin Hibbits 291*c7570492SJustin Hibbits if (SV_PROC_FLAG(p, SV_ILP32)) { 292*c7570492SJustin Hibbits pc = dtrace_fuword32((void *)sp); 293*c7570492SJustin Hibbits } 294*c7570492SJustin Hibbits else { 295*c7570492SJustin Hibbits pc = dtrace_fuword64((void *)sp); 296*c7570492SJustin Hibbits } 297*c7570492SJustin Hibbits } 298*c7570492SJustin Hibbits 299*c7570492SJustin Hibbits while (pc != 0) { 300*c7570492SJustin Hibbits *pcstack++ = (uint64_t)pc; 301*c7570492SJustin Hibbits *fpstack++ = sp; 302*c7570492SJustin Hibbits pcstack_limit--; 303*c7570492SJustin Hibbits if (pcstack_limit <= 0) 304*c7570492SJustin Hibbits break; 305*c7570492SJustin Hibbits 306*c7570492SJustin Hibbits if (sp == 0) 307*c7570492SJustin Hibbits break; 308*c7570492SJustin Hibbits 309*c7570492SJustin Hibbits #ifdef notyet /* XXX signal stack */ 310*c7570492SJustin Hibbits if (oldcontext == sp + s1 || oldcontext == sp + s2) { 311*c7570492SJustin Hibbits ucontext_t *ucp = (ucontext_t *)oldcontext; 312*c7570492SJustin Hibbits greg_t *gregs = ucp->uc_mcontext.gregs; 313*c7570492SJustin Hibbits 314*c7570492SJustin Hibbits sp = dtrace_fulword(&gregs[REG_FP]); 315*c7570492SJustin Hibbits pc = dtrace_fulword(&gregs[REG_PC]); 316*c7570492SJustin Hibbits 317*c7570492SJustin Hibbits oldcontext = dtrace_fulword(&ucp->uc_link); 318*c7570492SJustin Hibbits } else 319*c7570492SJustin Hibbits #endif /* XXX */ 320*c7570492SJustin Hibbits { 321*c7570492SJustin Hibbits if (SV_PROC_FLAG(p, SV_ILP32)) { 322*c7570492SJustin Hibbits pc = dtrace_fuword32((void *)(sp + RETURN_OFFSET)); 323*c7570492SJustin Hibbits sp = dtrace_fuword32((void *)sp); 324*c7570492SJustin Hibbits } 325*c7570492SJustin Hibbits else { 326*c7570492SJustin Hibbits pc = dtrace_fuword64((void *)(sp + RETURN_OFFSET64)); 327*c7570492SJustin Hibbits sp = dtrace_fuword64((void *)sp); 328*c7570492SJustin Hibbits } 329*c7570492SJustin Hibbits } 330*c7570492SJustin Hibbits 331*c7570492SJustin Hibbits /* 332*c7570492SJustin Hibbits * This is totally bogus: if we faulted, we're going to clear 333*c7570492SJustin Hibbits * the fault and break. This is to deal with the apparently 334*c7570492SJustin Hibbits * broken Java stacks on x86. 335*c7570492SJustin Hibbits */ 336*c7570492SJustin Hibbits if (*flags & CPU_DTRACE_FAULT) { 337*c7570492SJustin Hibbits *flags &= ~CPU_DTRACE_FAULT; 338*c7570492SJustin Hibbits break; 339*c7570492SJustin Hibbits } 340*c7570492SJustin Hibbits } 341*c7570492SJustin Hibbits 342*c7570492SJustin Hibbits zero: 343*c7570492SJustin Hibbits while (pcstack_limit-- > 0) 344*c7570492SJustin Hibbits *pcstack++ = 0; 345*c7570492SJustin Hibbits } 346*c7570492SJustin Hibbits 347*c7570492SJustin Hibbits /*ARGSUSED*/ 348*c7570492SJustin Hibbits uint64_t 349*c7570492SJustin Hibbits dtrace_getarg(int arg, int aframes) 350*c7570492SJustin Hibbits { 351*c7570492SJustin Hibbits return (0); 352*c7570492SJustin Hibbits } 353*c7570492SJustin Hibbits 354*c7570492SJustin Hibbits #ifdef notyet 355*c7570492SJustin Hibbits { 356*c7570492SJustin Hibbits int depth = 0; 357*c7570492SJustin Hibbits register_t sp; 358*c7570492SJustin Hibbits vm_offset_t callpc; 359*c7570492SJustin Hibbits pc_t caller = (pc_t) solaris_cpu[curcpu].cpu_dtrace_caller; 360*c7570492SJustin Hibbits 361*c7570492SJustin Hibbits if (intrpc != 0) 362*c7570492SJustin Hibbits pcstack[depth++] = (pc_t) intrpc; 363*c7570492SJustin Hibbits 364*c7570492SJustin Hibbits aframes++; 365*c7570492SJustin Hibbits 366*c7570492SJustin Hibbits sp = dtrace_getfp(); 367*c7570492SJustin Hibbits 368*c7570492SJustin Hibbits while (depth < pcstack_limit) { 369*c7570492SJustin Hibbits if (!INKERNEL((long) frame)) 370*c7570492SJustin Hibbits break; 371*c7570492SJustin Hibbits 372*c7570492SJustin Hibbits callpc = *(void **)(sp + RETURN_OFFSET); 373*c7570492SJustin Hibbits 374*c7570492SJustin Hibbits if (!INKERNEL(callpc)) 375*c7570492SJustin Hibbits break; 376*c7570492SJustin Hibbits 377*c7570492SJustin Hibbits if (aframes > 0) { 378*c7570492SJustin Hibbits aframes--; 379*c7570492SJustin Hibbits if ((aframes == 0) && (caller != 0)) { 380*c7570492SJustin Hibbits pcstack[depth++] = caller; 381*c7570492SJustin Hibbits } 382*c7570492SJustin Hibbits } 383*c7570492SJustin Hibbits else { 384*c7570492SJustin Hibbits pcstack[depth++] = callpc; 385*c7570492SJustin Hibbits } 386*c7570492SJustin Hibbits 387*c7570492SJustin Hibbits sp = *(void **)sp; 388*c7570492SJustin Hibbits } 389*c7570492SJustin Hibbits 390*c7570492SJustin Hibbits for (; depth < pcstack_limit; depth++) { 391*c7570492SJustin Hibbits pcstack[depth] = 0; 392*c7570492SJustin Hibbits } 393*c7570492SJustin Hibbits } 394*c7570492SJustin Hibbits #endif 395*c7570492SJustin Hibbits 396*c7570492SJustin Hibbits int 397*c7570492SJustin Hibbits dtrace_getstackdepth(int aframes) 398*c7570492SJustin Hibbits { 399*c7570492SJustin Hibbits int depth = 0; 400*c7570492SJustin Hibbits register_t sp; 401*c7570492SJustin Hibbits 402*c7570492SJustin Hibbits aframes++; 403*c7570492SJustin Hibbits sp = dtrace_getfp(); 404*c7570492SJustin Hibbits depth++; 405*c7570492SJustin Hibbits for(;;) { 406*c7570492SJustin Hibbits if (!INKERNEL((long) sp)) 407*c7570492SJustin Hibbits break; 408*c7570492SJustin Hibbits if (!INKERNEL((long) *(void **)sp)) 409*c7570492SJustin Hibbits break; 410*c7570492SJustin Hibbits depth++; 411*c7570492SJustin Hibbits sp = *(uintptr_t *)sp; 412*c7570492SJustin Hibbits } 413*c7570492SJustin Hibbits if (depth < aframes) 414*c7570492SJustin Hibbits return 0; 415*c7570492SJustin Hibbits else 416*c7570492SJustin Hibbits return depth - aframes; 417*c7570492SJustin Hibbits } 418*c7570492SJustin Hibbits 419*c7570492SJustin Hibbits ulong_t 420*c7570492SJustin Hibbits dtrace_getreg(struct trapframe *rp, uint_t reg) 421*c7570492SJustin Hibbits { 422*c7570492SJustin Hibbits if (reg < 32) 423*c7570492SJustin Hibbits return (rp->fixreg[reg]); 424*c7570492SJustin Hibbits 425*c7570492SJustin Hibbits switch (reg) { 426*c7570492SJustin Hibbits case 33: 427*c7570492SJustin Hibbits return (rp->lr); 428*c7570492SJustin Hibbits case 34: 429*c7570492SJustin Hibbits return (rp->cr); 430*c7570492SJustin Hibbits case 35: 431*c7570492SJustin Hibbits return (rp->xer); 432*c7570492SJustin Hibbits case 36: 433*c7570492SJustin Hibbits return (rp->ctr); 434*c7570492SJustin Hibbits case 37: 435*c7570492SJustin Hibbits return (rp->srr0); 436*c7570492SJustin Hibbits case 38: 437*c7570492SJustin Hibbits return (rp->srr1); 438*c7570492SJustin Hibbits case 39: 439*c7570492SJustin Hibbits return (rp->exc); 440*c7570492SJustin Hibbits default: 441*c7570492SJustin Hibbits DTRACE_CPUFLAG_SET(CPU_DTRACE_ILLOP); 442*c7570492SJustin Hibbits return (0); 443*c7570492SJustin Hibbits } 444*c7570492SJustin Hibbits } 445*c7570492SJustin Hibbits 446*c7570492SJustin Hibbits static int 447*c7570492SJustin Hibbits dtrace_copycheck(uintptr_t uaddr, uintptr_t kaddr, size_t size) 448*c7570492SJustin Hibbits { 449*c7570492SJustin Hibbits ASSERT(INKERNEL(kaddr) && kaddr + size >= kaddr); 450*c7570492SJustin Hibbits 451*c7570492SJustin Hibbits if (uaddr + size > VM_MAXUSER_ADDRESS || uaddr + size < uaddr) { 452*c7570492SJustin Hibbits DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR); 453*c7570492SJustin Hibbits cpu_core[curcpu].cpuc_dtrace_illval = uaddr; 454*c7570492SJustin Hibbits return (0); 455*c7570492SJustin Hibbits } 456*c7570492SJustin Hibbits 457*c7570492SJustin Hibbits return (1); 458*c7570492SJustin Hibbits } 459*c7570492SJustin Hibbits 460*c7570492SJustin Hibbits void 461*c7570492SJustin Hibbits dtrace_copyin(uintptr_t uaddr, uintptr_t kaddr, size_t size, 462*c7570492SJustin Hibbits volatile uint16_t *flags) 463*c7570492SJustin Hibbits { 464*c7570492SJustin Hibbits if (dtrace_copycheck(uaddr, kaddr, size)) 465*c7570492SJustin Hibbits dtrace_copy(uaddr, kaddr, size); 466*c7570492SJustin Hibbits } 467*c7570492SJustin Hibbits 468*c7570492SJustin Hibbits void 469*c7570492SJustin Hibbits dtrace_copyout(uintptr_t kaddr, uintptr_t uaddr, size_t size, 470*c7570492SJustin Hibbits volatile uint16_t *flags) 471*c7570492SJustin Hibbits { 472*c7570492SJustin Hibbits if (dtrace_copycheck(uaddr, kaddr, size)) 473*c7570492SJustin Hibbits dtrace_copy(kaddr, uaddr, size); 474*c7570492SJustin Hibbits } 475*c7570492SJustin Hibbits 476*c7570492SJustin Hibbits void 477*c7570492SJustin Hibbits dtrace_copyinstr(uintptr_t uaddr, uintptr_t kaddr, size_t size, 478*c7570492SJustin Hibbits volatile uint16_t *flags) 479*c7570492SJustin Hibbits { 480*c7570492SJustin Hibbits if (dtrace_copycheck(uaddr, kaddr, size)) 481*c7570492SJustin Hibbits dtrace_copystr(uaddr, kaddr, size, flags); 482*c7570492SJustin Hibbits } 483*c7570492SJustin Hibbits 484*c7570492SJustin Hibbits void 485*c7570492SJustin Hibbits dtrace_copyoutstr(uintptr_t kaddr, uintptr_t uaddr, size_t size, 486*c7570492SJustin Hibbits volatile uint16_t *flags) 487*c7570492SJustin Hibbits { 488*c7570492SJustin Hibbits if (dtrace_copycheck(uaddr, kaddr, size)) 489*c7570492SJustin Hibbits dtrace_copystr(kaddr, uaddr, size, flags); 490*c7570492SJustin Hibbits } 491*c7570492SJustin Hibbits 492*c7570492SJustin Hibbits uint8_t 493*c7570492SJustin Hibbits dtrace_fuword8(void *uaddr) 494*c7570492SJustin Hibbits { 495*c7570492SJustin Hibbits if ((uintptr_t)uaddr > VM_MAXUSER_ADDRESS) { 496*c7570492SJustin Hibbits DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR); 497*c7570492SJustin Hibbits cpu_core[curcpu].cpuc_dtrace_illval = (uintptr_t)uaddr; 498*c7570492SJustin Hibbits return (0); 499*c7570492SJustin Hibbits } 500*c7570492SJustin Hibbits return (dtrace_fuword8_nocheck(uaddr)); 501*c7570492SJustin Hibbits } 502*c7570492SJustin Hibbits 503*c7570492SJustin Hibbits uint16_t 504*c7570492SJustin Hibbits dtrace_fuword16(void *uaddr) 505*c7570492SJustin Hibbits { 506*c7570492SJustin Hibbits if ((uintptr_t)uaddr > VM_MAXUSER_ADDRESS) { 507*c7570492SJustin Hibbits DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR); 508*c7570492SJustin Hibbits cpu_core[curcpu].cpuc_dtrace_illval = (uintptr_t)uaddr; 509*c7570492SJustin Hibbits return (0); 510*c7570492SJustin Hibbits } 511*c7570492SJustin Hibbits return (dtrace_fuword16_nocheck(uaddr)); 512*c7570492SJustin Hibbits } 513*c7570492SJustin Hibbits 514*c7570492SJustin Hibbits uint32_t 515*c7570492SJustin Hibbits dtrace_fuword32(void *uaddr) 516*c7570492SJustin Hibbits { 517*c7570492SJustin Hibbits if ((uintptr_t)uaddr > VM_MAXUSER_ADDRESS) { 518*c7570492SJustin Hibbits DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR); 519*c7570492SJustin Hibbits cpu_core[curcpu].cpuc_dtrace_illval = (uintptr_t)uaddr; 520*c7570492SJustin Hibbits return (0); 521*c7570492SJustin Hibbits } 522*c7570492SJustin Hibbits return (dtrace_fuword32_nocheck(uaddr)); 523*c7570492SJustin Hibbits } 524*c7570492SJustin Hibbits 525*c7570492SJustin Hibbits uint64_t 526*c7570492SJustin Hibbits dtrace_fuword64(void *uaddr) 527*c7570492SJustin Hibbits { 528*c7570492SJustin Hibbits if ((uintptr_t)uaddr > VM_MAXUSER_ADDRESS) { 529*c7570492SJustin Hibbits DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR); 530*c7570492SJustin Hibbits cpu_core[curcpu].cpuc_dtrace_illval = (uintptr_t)uaddr; 531*c7570492SJustin Hibbits return (0); 532*c7570492SJustin Hibbits } 533*c7570492SJustin Hibbits return (dtrace_fuword64_nocheck(uaddr)); 534*c7570492SJustin Hibbits } 535