1fed1ca4bSRuslan Bukin /* 2fed1ca4bSRuslan Bukin * CDDL HEADER START 3fed1ca4bSRuslan Bukin * 4fed1ca4bSRuslan Bukin * The contents of this file are subject to the terms of the 5fed1ca4bSRuslan Bukin * Common Development and Distribution License, Version 1.0 only 6fed1ca4bSRuslan Bukin * (the "License"). You may not use this file except in compliance 7fed1ca4bSRuslan Bukin * with the License. 8fed1ca4bSRuslan Bukin * 9fed1ca4bSRuslan Bukin * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10fed1ca4bSRuslan Bukin * or http://www.opensolaris.org/os/licensing. 11fed1ca4bSRuslan Bukin * See the License for the specific language governing permissions 12fed1ca4bSRuslan Bukin * and limitations under the License. 13fed1ca4bSRuslan Bukin * 14fed1ca4bSRuslan Bukin * When distributing Covered Code, include this CDDL HEADER in each 15fed1ca4bSRuslan Bukin * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16fed1ca4bSRuslan Bukin * If applicable, add the following below this CDDL HEADER, with the 17fed1ca4bSRuslan Bukin * fields enclosed by brackets "[]" replaced with your own identifying 18fed1ca4bSRuslan Bukin * information: Portions Copyright [yyyy] [name of copyright owner] 19fed1ca4bSRuslan Bukin * 20fed1ca4bSRuslan Bukin * CDDL HEADER END 21fed1ca4bSRuslan Bukin * 22fed1ca4bSRuslan Bukin * Portions Copyright 2016 Ruslan Bukin <br@bsdpad.com> 23fed1ca4bSRuslan Bukin * 24fed1ca4bSRuslan Bukin * $FreeBSD$ 25fed1ca4bSRuslan Bukin */ 26fed1ca4bSRuslan Bukin /* 27fed1ca4bSRuslan Bukin * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 28fed1ca4bSRuslan Bukin * Use is subject to license terms. 29fed1ca4bSRuslan Bukin */ 30fed1ca4bSRuslan Bukin #include <sys/cdefs.h> 31fed1ca4bSRuslan Bukin 32fed1ca4bSRuslan Bukin #include <sys/param.h> 33fed1ca4bSRuslan Bukin #include <sys/systm.h> 34fed1ca4bSRuslan Bukin #include <sys/kernel.h> 35fed1ca4bSRuslan Bukin #include <sys/stack.h> 36fed1ca4bSRuslan Bukin #include <sys/pcpu.h> 37fed1ca4bSRuslan Bukin 38fed1ca4bSRuslan Bukin #include <machine/frame.h> 39fed1ca4bSRuslan Bukin #include <machine/md_var.h> 40fed1ca4bSRuslan Bukin 41fed1ca4bSRuslan Bukin #include <vm/vm.h> 42fed1ca4bSRuslan Bukin #include <vm/vm_param.h> 43fed1ca4bSRuslan Bukin #include <vm/pmap.h> 44fed1ca4bSRuslan Bukin 45fed1ca4bSRuslan Bukin #include <machine/atomic.h> 46fed1ca4bSRuslan Bukin #include <machine/db_machdep.h> 47fed1ca4bSRuslan Bukin #include <machine/md_var.h> 48fed1ca4bSRuslan Bukin #include <machine/stack.h> 49fed1ca4bSRuslan Bukin #include <ddb/db_sym.h> 50fed1ca4bSRuslan Bukin #include <ddb/ddb.h> 51fed1ca4bSRuslan Bukin #include <sys/kdb.h> 52fed1ca4bSRuslan Bukin 53fed1ca4bSRuslan Bukin #include "regset.h" 54fed1ca4bSRuslan Bukin 55fed1ca4bSRuslan Bukin #define MAX_USTACK_DEPTH 2048 56fed1ca4bSRuslan Bukin 57fed1ca4bSRuslan Bukin uint8_t dtrace_fuword8_nocheck(void *); 58fed1ca4bSRuslan Bukin uint16_t dtrace_fuword16_nocheck(void *); 59fed1ca4bSRuslan Bukin uint32_t dtrace_fuword32_nocheck(void *); 60fed1ca4bSRuslan Bukin uint64_t dtrace_fuword64_nocheck(void *); 61fed1ca4bSRuslan Bukin 62fed1ca4bSRuslan Bukin void 63fed1ca4bSRuslan Bukin dtrace_getpcstack(pc_t *pcstack, int pcstack_limit, int aframes, 64fed1ca4bSRuslan Bukin uint32_t *intrpc) 65fed1ca4bSRuslan Bukin { 66fed1ca4bSRuslan Bukin struct unwind_state state; 67cdfa49f2SMitchell Horne uintptr_t caller; 68fed1ca4bSRuslan Bukin register_t sp; 69cdfa49f2SMitchell Horne int scp_offset; 70fed1ca4bSRuslan Bukin int depth; 71fed1ca4bSRuslan Bukin 72fed1ca4bSRuslan Bukin depth = 0; 73cdfa49f2SMitchell Horne caller = solaris_cpu[curcpu].cpu_dtrace_caller; 74fed1ca4bSRuslan Bukin 75fed1ca4bSRuslan Bukin if (intrpc != 0) { 76fed1ca4bSRuslan Bukin pcstack[depth++] = (pc_t)intrpc; 77fed1ca4bSRuslan Bukin } 78fed1ca4bSRuslan Bukin 79cdfa49f2SMitchell Horne /* 80cdfa49f2SMitchell Horne * Construct the unwind state, starting from this function. This frame, 81cdfa49f2SMitchell Horne * and 'aframes' others will be skipped. 82cdfa49f2SMitchell Horne */ 83fed1ca4bSRuslan Bukin __asm __volatile("mv %0, sp" : "=&r" (sp)); 84fed1ca4bSRuslan Bukin 85fdd947e4SJohn Baldwin state.fp = (uintptr_t)__builtin_frame_address(0); 86cdfa49f2SMitchell Horne state.sp = (uintptr_t)sp; 87fdd947e4SJohn Baldwin state.pc = (uintptr_t)dtrace_getpcstack; 88fed1ca4bSRuslan Bukin 89fed1ca4bSRuslan Bukin while (depth < pcstack_limit) { 909b9e7f4cSJohn Baldwin if (!unwind_frame(curthread, &state)) 91fed1ca4bSRuslan Bukin break; 92fed1ca4bSRuslan Bukin 93cdfa49f2SMitchell Horne if (!INKERNEL(state.pc) || !kstack_contains(curthread, 94cdfa49f2SMitchell Horne (vm_offset_t)state.fp, sizeof(uintptr_t))) 95fed1ca4bSRuslan Bukin break; 96fed1ca4bSRuslan Bukin 97fed1ca4bSRuslan Bukin if (aframes > 0) { 98fed1ca4bSRuslan Bukin aframes--; 99cdfa49f2SMitchell Horne 100cdfa49f2SMitchell Horne /* 101cdfa49f2SMitchell Horne * fbt_invop() records the return address at the time 102cdfa49f2SMitchell Horne * the FBT probe fires. We need to insert this into the 103cdfa49f2SMitchell Horne * backtrace manually, since the stack frame state at 104cdfa49f2SMitchell Horne * the time of the probe does not capture it. 105cdfa49f2SMitchell Horne */ 106cdfa49f2SMitchell Horne if (aframes == 0 && caller != 0) 107cdfa49f2SMitchell Horne pcstack[depth++] = caller; 108fed1ca4bSRuslan Bukin } else { 109fed1ca4bSRuslan Bukin pcstack[depth++] = state.pc; 110fed1ca4bSRuslan Bukin } 111fed1ca4bSRuslan Bukin } 112fed1ca4bSRuslan Bukin 113fed1ca4bSRuslan Bukin for (; depth < pcstack_limit; depth++) { 114fed1ca4bSRuslan Bukin pcstack[depth] = 0; 115fed1ca4bSRuslan Bukin } 116fed1ca4bSRuslan Bukin } 117fed1ca4bSRuslan Bukin 118fed1ca4bSRuslan Bukin static int 119fed1ca4bSRuslan Bukin dtrace_getustack_common(uint64_t *pcstack, int pcstack_limit, uintptr_t pc, 120fed1ca4bSRuslan Bukin uintptr_t fp) 121fed1ca4bSRuslan Bukin { 122fed1ca4bSRuslan Bukin volatile uint16_t *flags; 123fed1ca4bSRuslan Bukin uintptr_t oldfp; 124fed1ca4bSRuslan Bukin int ret; 125fed1ca4bSRuslan Bukin 1260b92d1ddSMitchell Horne oldfp = fp; 127fed1ca4bSRuslan Bukin ret = 0; 128fed1ca4bSRuslan Bukin flags = (volatile uint16_t *)&cpu_core[curcpu].cpuc_dtrace_flags; 129fed1ca4bSRuslan Bukin 130fed1ca4bSRuslan Bukin ASSERT(pcstack == NULL || pcstack_limit > 0); 131fed1ca4bSRuslan Bukin 132fed1ca4bSRuslan Bukin while (pc != 0) { 133fed1ca4bSRuslan Bukin /* 134fed1ca4bSRuslan Bukin * We limit the number of times we can go around this 135fed1ca4bSRuslan Bukin * loop to account for a circular stack. 136fed1ca4bSRuslan Bukin */ 137fed1ca4bSRuslan Bukin if (ret++ >= MAX_USTACK_DEPTH) { 138fed1ca4bSRuslan Bukin *flags |= CPU_DTRACE_BADSTACK; 139fed1ca4bSRuslan Bukin cpu_core[curcpu].cpuc_dtrace_illval = fp; 140fed1ca4bSRuslan Bukin break; 141fed1ca4bSRuslan Bukin } 142fed1ca4bSRuslan Bukin 143fed1ca4bSRuslan Bukin if (pcstack != NULL) { 144fed1ca4bSRuslan Bukin *pcstack++ = (uint64_t)pc; 145fed1ca4bSRuslan Bukin pcstack_limit--; 146fed1ca4bSRuslan Bukin if (pcstack_limit <= 0) 147fed1ca4bSRuslan Bukin break; 148fed1ca4bSRuslan Bukin } 149fed1ca4bSRuslan Bukin 150fed1ca4bSRuslan Bukin if (fp == 0) 151fed1ca4bSRuslan Bukin break; 152fed1ca4bSRuslan Bukin 15338720107SJessica Clarke pc = dtrace_fuword64((void *)(fp - 1 * sizeof(uint64_t))); 15438720107SJessica Clarke fp = dtrace_fuword64((void *)(fp - 2 * sizeof(uint64_t))); 155fed1ca4bSRuslan Bukin 156fed1ca4bSRuslan Bukin if (fp == oldfp) { 157fed1ca4bSRuslan Bukin *flags |= CPU_DTRACE_BADSTACK; 158fed1ca4bSRuslan Bukin cpu_core[curcpu].cpuc_dtrace_illval = fp; 159fed1ca4bSRuslan Bukin break; 160fed1ca4bSRuslan Bukin } 1610b92d1ddSMitchell Horne oldfp = fp; 162fed1ca4bSRuslan Bukin } 163fed1ca4bSRuslan Bukin 164fed1ca4bSRuslan Bukin return (ret); 165fed1ca4bSRuslan Bukin } 166fed1ca4bSRuslan Bukin 167fed1ca4bSRuslan Bukin void 168fed1ca4bSRuslan Bukin dtrace_getupcstack(uint64_t *pcstack, int pcstack_limit) 169fed1ca4bSRuslan Bukin { 170fed1ca4bSRuslan Bukin volatile uint16_t *flags; 171fed1ca4bSRuslan Bukin struct trapframe *tf; 172c6943b44SMitchell Horne uintptr_t pc, fp; 173fed1ca4bSRuslan Bukin proc_t *p; 174fed1ca4bSRuslan Bukin int n; 175fed1ca4bSRuslan Bukin 176fed1ca4bSRuslan Bukin p = curproc; 177fed1ca4bSRuslan Bukin flags = (volatile uint16_t *)&cpu_core[curcpu].cpuc_dtrace_flags; 178fed1ca4bSRuslan Bukin 179fed1ca4bSRuslan Bukin if (*flags & CPU_DTRACE_FAULT) 180fed1ca4bSRuslan Bukin return; 181fed1ca4bSRuslan Bukin 182fed1ca4bSRuslan Bukin if (pcstack_limit <= 0) 183fed1ca4bSRuslan Bukin return; 184fed1ca4bSRuslan Bukin 185fed1ca4bSRuslan Bukin /* 186fed1ca4bSRuslan Bukin * If there's no user context we still need to zero the stack. 187fed1ca4bSRuslan Bukin */ 188fed1ca4bSRuslan Bukin if (p == NULL || (tf = curthread->td_frame) == NULL) 189fed1ca4bSRuslan Bukin goto zero; 190fed1ca4bSRuslan Bukin 191fed1ca4bSRuslan Bukin *pcstack++ = (uint64_t)p->p_pid; 192fed1ca4bSRuslan Bukin pcstack_limit--; 193fed1ca4bSRuslan Bukin 194fed1ca4bSRuslan Bukin if (pcstack_limit <= 0) 195fed1ca4bSRuslan Bukin return; 196fed1ca4bSRuslan Bukin 197fed1ca4bSRuslan Bukin pc = tf->tf_sepc; 198fed1ca4bSRuslan Bukin fp = tf->tf_s[0]; 199fed1ca4bSRuslan Bukin 200fed1ca4bSRuslan Bukin if (DTRACE_CPUFLAG_ISSET(CPU_DTRACE_ENTRY)) { 201fed1ca4bSRuslan Bukin /* 202fed1ca4bSRuslan Bukin * In an entry probe. The frame pointer has not yet been 203fed1ca4bSRuslan Bukin * pushed (that happens in the function prologue). The 204fed1ca4bSRuslan Bukin * best approach is to add the current pc as a missing top 205fed1ca4bSRuslan Bukin * of stack and back the pc up to the caller, which is stored 206fed1ca4bSRuslan Bukin * at the current stack pointer address since the call 207fed1ca4bSRuslan Bukin * instruction puts it there right before the branch. 208fed1ca4bSRuslan Bukin */ 209fed1ca4bSRuslan Bukin *pcstack++ = (uint64_t)pc; 210fed1ca4bSRuslan Bukin pcstack_limit--; 211fed1ca4bSRuslan Bukin if (pcstack_limit <= 0) 212fed1ca4bSRuslan Bukin return; 213fed1ca4bSRuslan Bukin 214fed1ca4bSRuslan Bukin pc = tf->tf_ra; 215fed1ca4bSRuslan Bukin } 216fed1ca4bSRuslan Bukin 217fed1ca4bSRuslan Bukin n = dtrace_getustack_common(pcstack, pcstack_limit, pc, fp); 218fed1ca4bSRuslan Bukin ASSERT(n >= 0); 219fed1ca4bSRuslan Bukin ASSERT(n <= pcstack_limit); 220fed1ca4bSRuslan Bukin 221fed1ca4bSRuslan Bukin pcstack += n; 222fed1ca4bSRuslan Bukin pcstack_limit -= n; 223fed1ca4bSRuslan Bukin 224fed1ca4bSRuslan Bukin zero: 225fed1ca4bSRuslan Bukin while (pcstack_limit-- > 0) 226fed1ca4bSRuslan Bukin *pcstack++ = 0; 227fed1ca4bSRuslan Bukin } 228fed1ca4bSRuslan Bukin 229fed1ca4bSRuslan Bukin int 230fed1ca4bSRuslan Bukin dtrace_getustackdepth(void) 231fed1ca4bSRuslan Bukin { 232c6943b44SMitchell Horne struct trapframe *tf; 233c6943b44SMitchell Horne uintptr_t pc, fp; 234c6943b44SMitchell Horne int n = 0; 235fed1ca4bSRuslan Bukin 236c6943b44SMitchell Horne if (curproc == NULL || (tf = curthread->td_frame) == NULL) 237c6943b44SMitchell Horne return (0); 238c6943b44SMitchell Horne 239c6943b44SMitchell Horne if (DTRACE_CPUFLAG_ISSET(CPU_DTRACE_FAULT)) 240c6943b44SMitchell Horne return (-1); 241c6943b44SMitchell Horne 242c6943b44SMitchell Horne pc = tf->tf_sepc; 243c6943b44SMitchell Horne fp = tf->tf_s[0]; 244c6943b44SMitchell Horne 245c6943b44SMitchell Horne if (DTRACE_CPUFLAG_ISSET(CPU_DTRACE_ENTRY)) { 246c6943b44SMitchell Horne /* 247c6943b44SMitchell Horne * In an entry probe. The frame pointer has not yet been 248c6943b44SMitchell Horne * pushed (that happens in the function prologue). The 249c6943b44SMitchell Horne * best approach is to add the current pc as a missing top 250c6943b44SMitchell Horne * of stack and back the pc up to the caller, which is stored 251c6943b44SMitchell Horne * at the current stack pointer address since the call 252c6943b44SMitchell Horne * instruction puts it there right before the branch. 253c6943b44SMitchell Horne */ 254c6943b44SMitchell Horne pc = tf->tf_ra; 255c6943b44SMitchell Horne n++; 256c6943b44SMitchell Horne } 257c6943b44SMitchell Horne 258c6943b44SMitchell Horne n += dtrace_getustack_common(NULL, 0, pc, fp); 259fed1ca4bSRuslan Bukin 260fed1ca4bSRuslan Bukin return (0); 261fed1ca4bSRuslan Bukin } 262fed1ca4bSRuslan Bukin 263fed1ca4bSRuslan Bukin void 264fed1ca4bSRuslan Bukin dtrace_getufpstack(uint64_t *pcstack, uint64_t *fpstack, int pcstack_limit) 265fed1ca4bSRuslan Bukin { 266fed1ca4bSRuslan Bukin 267fed1ca4bSRuslan Bukin printf("IMPLEMENT ME: %s\n", __func__); 268fed1ca4bSRuslan Bukin } 269fed1ca4bSRuslan Bukin 270fed1ca4bSRuslan Bukin /*ARGSUSED*/ 271fed1ca4bSRuslan Bukin uint64_t 272fed1ca4bSRuslan Bukin dtrace_getarg(int arg, int aframes) 273fed1ca4bSRuslan Bukin { 274fed1ca4bSRuslan Bukin 275fed1ca4bSRuslan Bukin printf("IMPLEMENT ME: %s\n", __func__); 276fed1ca4bSRuslan Bukin 277fed1ca4bSRuslan Bukin return (0); 278fed1ca4bSRuslan Bukin } 279fed1ca4bSRuslan Bukin 280fed1ca4bSRuslan Bukin int 281fed1ca4bSRuslan Bukin dtrace_getstackdepth(int aframes) 282fed1ca4bSRuslan Bukin { 283fed1ca4bSRuslan Bukin struct unwind_state state; 284fed1ca4bSRuslan Bukin int scp_offset; 285fed1ca4bSRuslan Bukin register_t sp; 286fed1ca4bSRuslan Bukin int depth; 2879b9e7f4cSJohn Baldwin bool done; 288fed1ca4bSRuslan Bukin 289fed1ca4bSRuslan Bukin depth = 1; 2909b9e7f4cSJohn Baldwin done = false; 291fed1ca4bSRuslan Bukin 292fed1ca4bSRuslan Bukin __asm __volatile("mv %0, sp" : "=&r" (sp)); 293fed1ca4bSRuslan Bukin 294fdd947e4SJohn Baldwin state.fp = (uintptr_t)__builtin_frame_address(0); 295fed1ca4bSRuslan Bukin state.sp = sp; 296fdd947e4SJohn Baldwin state.pc = (uintptr_t)dtrace_getstackdepth; 297fed1ca4bSRuslan Bukin 298fed1ca4bSRuslan Bukin do { 2999b9e7f4cSJohn Baldwin done = !unwind_frame(curthread, &state); 300fed1ca4bSRuslan Bukin if (!INKERNEL(state.pc) || !INKERNEL(state.fp)) 301fed1ca4bSRuslan Bukin break; 302fed1ca4bSRuslan Bukin depth++; 303fed1ca4bSRuslan Bukin } while (!done); 304fed1ca4bSRuslan Bukin 305fed1ca4bSRuslan Bukin if (depth < aframes) 306fed1ca4bSRuslan Bukin return (0); 307fed1ca4bSRuslan Bukin else 308fed1ca4bSRuslan Bukin return (depth - aframes); 309fed1ca4bSRuslan Bukin } 310fed1ca4bSRuslan Bukin 311fed1ca4bSRuslan Bukin ulong_t 312fed1ca4bSRuslan Bukin dtrace_getreg(struct trapframe *rp, uint_t reg) 313fed1ca4bSRuslan Bukin { 314*1fef7abdSChristos Margiolis switch (reg) { 315*1fef7abdSChristos Margiolis case REG_ZERO: 316fed1ca4bSRuslan Bukin return (0); 317*1fef7abdSChristos Margiolis case REG_RA: 318*1fef7abdSChristos Margiolis return (rp->tf_ra); 319*1fef7abdSChristos Margiolis case REG_SP: 320*1fef7abdSChristos Margiolis return (rp->tf_sp); 321*1fef7abdSChristos Margiolis case REG_GP: 322*1fef7abdSChristos Margiolis return (rp->tf_gp); 323*1fef7abdSChristos Margiolis case REG_TP: 324*1fef7abdSChristos Margiolis return (rp->tf_tp); 325*1fef7abdSChristos Margiolis case REG_T0 ... REG_T2: 326*1fef7abdSChristos Margiolis return (rp->tf_t[reg - REG_T0]); 327*1fef7abdSChristos Margiolis case REG_S0 ... REG_S1: 328*1fef7abdSChristos Margiolis return (rp->tf_s[reg - REG_S0]); 329*1fef7abdSChristos Margiolis case REG_A0 ... REG_A7: 330*1fef7abdSChristos Margiolis return (rp->tf_a[reg - REG_A0]); 331*1fef7abdSChristos Margiolis case REG_S2 ... REG_S11: 332*1fef7abdSChristos Margiolis return (rp->tf_s[reg - REG_S2 + 2]); 333*1fef7abdSChristos Margiolis case REG_T3 ... REG_T6: 334*1fef7abdSChristos Margiolis return (rp->tf_t[reg - REG_T3 + 3]); 335*1fef7abdSChristos Margiolis case REG_PC: 336*1fef7abdSChristos Margiolis return (rp->tf_sepc); 337*1fef7abdSChristos Margiolis default: 338*1fef7abdSChristos Margiolis DTRACE_CPUFLAG_SET(CPU_DTRACE_ILLOP); 339*1fef7abdSChristos Margiolis return (0); 340*1fef7abdSChristos Margiolis } 341*1fef7abdSChristos Margiolis /* NOTREACHED */ 342fed1ca4bSRuslan Bukin } 343fed1ca4bSRuslan Bukin 344fed1ca4bSRuslan Bukin static int 345fed1ca4bSRuslan Bukin dtrace_copycheck(uintptr_t uaddr, uintptr_t kaddr, size_t size) 346fed1ca4bSRuslan Bukin { 347fed1ca4bSRuslan Bukin 348fed1ca4bSRuslan Bukin if (uaddr + size > VM_MAXUSER_ADDRESS || uaddr + size < uaddr) { 349fed1ca4bSRuslan Bukin DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR); 350fed1ca4bSRuslan Bukin cpu_core[curcpu].cpuc_dtrace_illval = uaddr; 351fed1ca4bSRuslan Bukin return (0); 352fed1ca4bSRuslan Bukin } 353fed1ca4bSRuslan Bukin 354fed1ca4bSRuslan Bukin return (1); 355fed1ca4bSRuslan Bukin } 356fed1ca4bSRuslan Bukin 357fed1ca4bSRuslan Bukin void 358fed1ca4bSRuslan Bukin dtrace_copyin(uintptr_t uaddr, uintptr_t kaddr, size_t size, 359fed1ca4bSRuslan Bukin volatile uint16_t *flags) 360fed1ca4bSRuslan Bukin { 361fed1ca4bSRuslan Bukin 362fed1ca4bSRuslan Bukin if (dtrace_copycheck(uaddr, kaddr, size)) 363fed1ca4bSRuslan Bukin dtrace_copy(uaddr, kaddr, size); 364fed1ca4bSRuslan Bukin } 365fed1ca4bSRuslan Bukin 366fed1ca4bSRuslan Bukin void 367fed1ca4bSRuslan Bukin dtrace_copyout(uintptr_t kaddr, uintptr_t uaddr, size_t size, 368fed1ca4bSRuslan Bukin volatile uint16_t *flags) 369fed1ca4bSRuslan Bukin { 370fed1ca4bSRuslan Bukin 371fed1ca4bSRuslan Bukin if (dtrace_copycheck(uaddr, kaddr, size)) 372fed1ca4bSRuslan Bukin dtrace_copy(kaddr, uaddr, size); 373fed1ca4bSRuslan Bukin } 374fed1ca4bSRuslan Bukin 375fed1ca4bSRuslan Bukin void 376fed1ca4bSRuslan Bukin dtrace_copyinstr(uintptr_t uaddr, uintptr_t kaddr, size_t size, 377fed1ca4bSRuslan Bukin volatile uint16_t *flags) 378fed1ca4bSRuslan Bukin { 379fed1ca4bSRuslan Bukin 380fed1ca4bSRuslan Bukin if (dtrace_copycheck(uaddr, kaddr, size)) 381fed1ca4bSRuslan Bukin dtrace_copystr(uaddr, kaddr, size, flags); 382fed1ca4bSRuslan Bukin } 383fed1ca4bSRuslan Bukin 384fed1ca4bSRuslan Bukin void 385fed1ca4bSRuslan Bukin dtrace_copyoutstr(uintptr_t kaddr, uintptr_t uaddr, size_t size, 386fed1ca4bSRuslan Bukin volatile uint16_t *flags) 387fed1ca4bSRuslan Bukin { 388fed1ca4bSRuslan Bukin 389fed1ca4bSRuslan Bukin if (dtrace_copycheck(uaddr, kaddr, size)) 390fed1ca4bSRuslan Bukin dtrace_copystr(kaddr, uaddr, size, flags); 391fed1ca4bSRuslan Bukin } 392fed1ca4bSRuslan Bukin 393fed1ca4bSRuslan Bukin uint8_t 394fed1ca4bSRuslan Bukin dtrace_fuword8(void *uaddr) 395fed1ca4bSRuslan Bukin { 396fed1ca4bSRuslan Bukin 397fed1ca4bSRuslan Bukin if ((uintptr_t)uaddr > VM_MAXUSER_ADDRESS) { 398fed1ca4bSRuslan Bukin DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR); 399fed1ca4bSRuslan Bukin cpu_core[curcpu].cpuc_dtrace_illval = (uintptr_t)uaddr; 400fed1ca4bSRuslan Bukin return (0); 401fed1ca4bSRuslan Bukin } 402fed1ca4bSRuslan Bukin 403fed1ca4bSRuslan Bukin return (dtrace_fuword8_nocheck(uaddr)); 404fed1ca4bSRuslan Bukin } 405fed1ca4bSRuslan Bukin 406fed1ca4bSRuslan Bukin uint16_t 407fed1ca4bSRuslan Bukin dtrace_fuword16(void *uaddr) 408fed1ca4bSRuslan Bukin { 409fed1ca4bSRuslan Bukin 410fed1ca4bSRuslan Bukin if ((uintptr_t)uaddr > VM_MAXUSER_ADDRESS) { 411fed1ca4bSRuslan Bukin DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR); 412fed1ca4bSRuslan Bukin cpu_core[curcpu].cpuc_dtrace_illval = (uintptr_t)uaddr; 413fed1ca4bSRuslan Bukin return (0); 414fed1ca4bSRuslan Bukin } 415fed1ca4bSRuslan Bukin 416fed1ca4bSRuslan Bukin return (dtrace_fuword16_nocheck(uaddr)); 417fed1ca4bSRuslan Bukin } 418fed1ca4bSRuslan Bukin 419fed1ca4bSRuslan Bukin uint32_t 420fed1ca4bSRuslan Bukin dtrace_fuword32(void *uaddr) 421fed1ca4bSRuslan Bukin { 422fed1ca4bSRuslan Bukin 423fed1ca4bSRuslan Bukin if ((uintptr_t)uaddr > VM_MAXUSER_ADDRESS) { 424fed1ca4bSRuslan Bukin DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR); 425fed1ca4bSRuslan Bukin cpu_core[curcpu].cpuc_dtrace_illval = (uintptr_t)uaddr; 426fed1ca4bSRuslan Bukin return (0); 427fed1ca4bSRuslan Bukin } 428fed1ca4bSRuslan Bukin 429fed1ca4bSRuslan Bukin return (dtrace_fuword32_nocheck(uaddr)); 430fed1ca4bSRuslan Bukin } 431fed1ca4bSRuslan Bukin 432fed1ca4bSRuslan Bukin uint64_t 433fed1ca4bSRuslan Bukin dtrace_fuword64(void *uaddr) 434fed1ca4bSRuslan Bukin { 435fed1ca4bSRuslan Bukin 436fed1ca4bSRuslan Bukin if ((uintptr_t)uaddr > VM_MAXUSER_ADDRESS) { 437fed1ca4bSRuslan Bukin DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR); 438fed1ca4bSRuslan Bukin cpu_core[curcpu].cpuc_dtrace_illval = (uintptr_t)uaddr; 439fed1ca4bSRuslan Bukin return (0); 440fed1ca4bSRuslan Bukin } 441fed1ca4bSRuslan Bukin 442fed1ca4bSRuslan Bukin return (dtrace_fuword64_nocheck(uaddr)); 443fed1ca4bSRuslan Bukin } 444