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