xref: /illumos-gate/usr/src/uts/intel/dtrace/dtrace_isa.c (revision 0dee7919e2f2a6479d16b370af93747b9416b242)
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 
27 #pragma ident	"%Z%%M%	%I%	%E% SMI"
28 
29 #include <sys/dtrace_impl.h>
30 #include <sys/stack.h>
31 #include <sys/frame.h>
32 #include <sys/cmn_err.h>
33 #include <sys/privregs.h>
34 #include <sys/sysmacros.h>
35 
36 /*
37  * This is gross knowledge to have to encode here...
38  */
39 extern void _interrupt();
40 extern void _cmntrap();
41 extern void _allsyscalls();
42 
43 extern size_t _interrupt_size;
44 extern size_t _cmntrap_size;
45 extern size_t _allsyscalls_size;
46 
47 extern uintptr_t kernelbase;
48 
49 void
50 dtrace_getpcstack(pc_t *pcstack, int pcstack_limit, int aframes,
51     uint32_t *intrpc)
52 {
53 	struct frame *fp = (struct frame *)dtrace_getfp();
54 	struct frame *nextfp, *minfp, *stacktop;
55 	int depth = 0;
56 	int on_intr, last = 0;
57 	uintptr_t pc;
58 	uintptr_t caller = CPU->cpu_dtrace_caller;
59 
60 	if ((on_intr = CPU_ON_INTR(CPU)) != 0)
61 		stacktop = (struct frame *)(CPU->cpu_intr_stack + SA(MINFRAME));
62 	else
63 		stacktop = (struct frame *)curthread->t_stk;
64 	minfp = fp;
65 
66 	aframes++;
67 
68 	if (intrpc != NULL && depth < pcstack_limit)
69 		pcstack[depth++] = (pc_t)intrpc;
70 
71 	while (depth < pcstack_limit) {
72 		nextfp = (struct frame *)fp->fr_savfp;
73 		pc = fp->fr_savpc;
74 
75 		if (nextfp <= minfp || nextfp >= stacktop) {
76 			if (on_intr) {
77 				/*
78 				 * Hop from interrupt stack to thread stack.
79 				 */
80 				stacktop = (struct frame *)curthread->t_stk;
81 				minfp = (struct frame *)curthread->t_stkbase;
82 				on_intr = 0;
83 				continue;
84 			}
85 
86 			/*
87 			 * This is the last frame we can process; indicate
88 			 * that we should return after processing this frame.
89 			 */
90 			last = 1;
91 		}
92 
93 		if (aframes > 0) {
94 			if (--aframes == 0 && caller != NULL) {
95 				/*
96 				 * We've just run out of artificial frames,
97 				 * and we have a valid caller -- fill it in
98 				 * now.
99 				 */
100 				ASSERT(depth < pcstack_limit);
101 				pcstack[depth++] = (pc_t)caller;
102 				caller = NULL;
103 			}
104 		} else {
105 			if (depth < pcstack_limit)
106 				pcstack[depth++] = (pc_t)pc;
107 		}
108 
109 		if (last) {
110 			while (depth < pcstack_limit)
111 				pcstack[depth++] = NULL;
112 			return;
113 		}
114 
115 		fp = nextfp;
116 		minfp = fp;
117 	}
118 }
119 
120 static int
121 dtrace_getustack_common(uint64_t *pcstack, int pcstack_limit, uintptr_t pc,
122     uintptr_t sp)
123 {
124 	klwp_t *lwp = ttolwp(curthread);
125 	proc_t *p = curproc;
126 	uintptr_t oldcontext = lwp->lwp_oldcontext;
127 	volatile uint16_t *flags =
128 	    (volatile uint16_t *)&cpu_core[CPU->cpu_id].cpuc_dtrace_flags;
129 	size_t s1, s2;
130 	int ret = 0;
131 
132 	ASSERT(pcstack == NULL || pcstack_limit > 0);
133 
134 	if (p->p_model == DATAMODEL_NATIVE) {
135 		s1 = sizeof (struct frame) + 2 * sizeof (long);
136 		s2 = s1 + sizeof (siginfo_t);
137 	} else {
138 		s1 = sizeof (struct frame32) + 3 * sizeof (int);
139 		s2 = s1 + sizeof (siginfo32_t);
140 	}
141 
142 	while (pc != 0 && sp != 0) {
143 		ret++;
144 		if (pcstack != NULL) {
145 			*pcstack++ = (uint64_t)pc;
146 			pcstack_limit--;
147 			if (pcstack_limit <= 0)
148 				break;
149 		}
150 
151 		if (oldcontext == sp + s1 || oldcontext == sp + s2) {
152 			if (p->p_model == DATAMODEL_NATIVE) {
153 				ucontext_t *ucp = (ucontext_t *)oldcontext;
154 				greg_t *gregs = ucp->uc_mcontext.gregs;
155 
156 				sp = dtrace_fulword(&gregs[REG_FP]);
157 				pc = dtrace_fulword(&gregs[REG_PC]);
158 
159 				oldcontext = dtrace_fulword(&ucp->uc_link);
160 			} else {
161 				ucontext32_t *ucp = (ucontext32_t *)oldcontext;
162 				greg32_t *gregs = ucp->uc_mcontext.gregs;
163 
164 				sp = dtrace_fuword32(&gregs[EBP]);
165 				pc = dtrace_fuword32(&gregs[EIP]);
166 
167 				oldcontext = dtrace_fuword32(&ucp->uc_link);
168 			}
169 		} else {
170 			if (p->p_model == DATAMODEL_NATIVE) {
171 				struct frame *fr = (struct frame *)sp;
172 
173 				pc = dtrace_fulword(&fr->fr_savpc);
174 				sp = dtrace_fulword(&fr->fr_savfp);
175 			} else {
176 				struct frame32 *fr = (struct frame32 *)sp;
177 
178 				pc = dtrace_fuword32(&fr->fr_savpc);
179 				sp = dtrace_fuword32(&fr->fr_savfp);
180 			}
181 		}
182 
183 		/*
184 		 * This is totally bogus:  if we faulted, we're going to clear
185 		 * the fault and break.  This is to deal with the apparently
186 		 * broken Java stacks on x86.
187 		 */
188 		if (*flags & CPU_DTRACE_FAULT) {
189 			*flags &= ~CPU_DTRACE_FAULT;
190 			break;
191 		}
192 	}
193 
194 	return (ret);
195 }
196 
197 void
198 dtrace_getupcstack(uint64_t *pcstack, int pcstack_limit)
199 {
200 	klwp_t *lwp = ttolwp(curthread);
201 	proc_t *p = curproc;
202 	struct regs *rp;
203 	uintptr_t pc, sp;
204 	volatile uint16_t *flags =
205 	    (volatile uint16_t *)&cpu_core[CPU->cpu_id].cpuc_dtrace_flags;
206 	int n;
207 
208 	if (lwp == NULL || p == NULL || (rp = lwp->lwp_regs) == NULL)
209 		return;
210 
211 	if (*flags & CPU_DTRACE_FAULT)
212 		return;
213 
214 	if (pcstack_limit <= 0)
215 		return;
216 
217 	*pcstack++ = (uint64_t)p->p_pid;
218 	pcstack_limit--;
219 
220 	if (pcstack_limit <= 0)
221 		return;
222 
223 	pc = rp->r_pc;
224 	sp = rp->r_fp;
225 
226 	if (DTRACE_CPUFLAG_ISSET(CPU_DTRACE_ENTRY)) {
227 		*pcstack++ = (uint64_t)pc;
228 		pcstack_limit--;
229 		if (pcstack_limit <= 0)
230 			return;
231 
232 		if (p->p_model == DATAMODEL_NATIVE)
233 			pc = dtrace_fulword((void *)rp->r_sp);
234 		else
235 			pc = dtrace_fuword32((void *)rp->r_sp);
236 	}
237 
238 	n = dtrace_getustack_common(pcstack, pcstack_limit, pc, sp);
239 	ASSERT(n >= 0);
240 	ASSERT(n <= pcstack_limit);
241 
242 	pcstack += n;
243 	pcstack_limit -= n;
244 
245 	while (pcstack_limit-- > 0)
246 		*pcstack++ = NULL;
247 }
248 
249 int
250 dtrace_getustackdepth(void)
251 {
252 	klwp_t *lwp = ttolwp(curthread);
253 	proc_t *p = curproc;
254 	struct regs *rp;
255 	uintptr_t pc, sp;
256 	int n = 0;
257 
258 	if (lwp == NULL || p == NULL || (rp = lwp->lwp_regs) == NULL)
259 		return (0);
260 
261 	if (DTRACE_CPUFLAG_ISSET(CPU_DTRACE_FAULT))
262 		return (-1);
263 
264 	pc = rp->r_pc;
265 	sp = rp->r_fp;
266 
267 	if (DTRACE_CPUFLAG_ISSET(CPU_DTRACE_ENTRY)) {
268 		n++;
269 
270 		if (p->p_model == DATAMODEL_NATIVE)
271 			pc = dtrace_fulword((void *)rp->r_sp);
272 		else
273 			pc = dtrace_fuword32((void *)rp->r_sp);
274 	}
275 
276 	n += dtrace_getustack_common(NULL, 0, pc, sp);
277 
278 	return (n);
279 }
280 
281 /*ARGSUSED*/
282 void
283 dtrace_getufpstack(uint64_t *pcstack, uint64_t *fpstack, int pcstack_limit)
284 {
285 	klwp_t *lwp = ttolwp(curthread);
286 	proc_t *p = curproc;
287 	struct regs *rp;
288 	uintptr_t pc, sp, oldcontext;
289 	volatile uint16_t *flags =
290 	    (volatile uint16_t *)&cpu_core[CPU->cpu_id].cpuc_dtrace_flags;
291 	size_t s1, s2;
292 
293 	if (lwp == NULL || p == NULL || (rp = lwp->lwp_regs) == NULL)
294 		return;
295 
296 	if (*flags & CPU_DTRACE_FAULT)
297 		return;
298 
299 	if (pcstack_limit <= 0)
300 		return;
301 
302 	*pcstack++ = (uint64_t)p->p_pid;
303 	pcstack_limit--;
304 
305 	if (pcstack_limit <= 0)
306 		return;
307 
308 	pc = rp->r_pc;
309 	sp = rp->r_fp;
310 	oldcontext = lwp->lwp_oldcontext;
311 
312 	if (p->p_model == DATAMODEL_NATIVE) {
313 		s1 = sizeof (struct frame) + 2 * sizeof (long);
314 		s2 = s1 + sizeof (siginfo_t);
315 	} else {
316 		s1 = sizeof (struct frame32) + 3 * sizeof (int);
317 		s2 = s1 + sizeof (siginfo32_t);
318 	}
319 
320 	if (DTRACE_CPUFLAG_ISSET(CPU_DTRACE_ENTRY)) {
321 		*pcstack++ = (uint64_t)pc;
322 		*fpstack++ = 0;
323 		pcstack_limit--;
324 		if (pcstack_limit <= 0)
325 			return;
326 
327 		if (p->p_model == DATAMODEL_NATIVE)
328 			pc = dtrace_fulword((void *)rp->r_sp);
329 		else
330 			pc = dtrace_fuword32((void *)rp->r_sp);
331 	}
332 
333 	while (pc != 0 && sp != 0) {
334 		*pcstack++ = (uint64_t)pc;
335 		*fpstack++ = sp;
336 		pcstack_limit--;
337 		if (pcstack_limit <= 0)
338 			break;
339 
340 		if (oldcontext == sp + s1 || oldcontext == sp + s2) {
341 			if (p->p_model == DATAMODEL_NATIVE) {
342 				ucontext_t *ucp = (ucontext_t *)oldcontext;
343 				greg_t *gregs = ucp->uc_mcontext.gregs;
344 
345 				sp = dtrace_fulword(&gregs[REG_FP]);
346 				pc = dtrace_fulword(&gregs[REG_PC]);
347 
348 				oldcontext = dtrace_fulword(&ucp->uc_link);
349 			} else {
350 				ucontext_t *ucp = (ucontext_t *)oldcontext;
351 				greg_t *gregs = ucp->uc_mcontext.gregs;
352 
353 				sp = dtrace_fuword32(&gregs[EBP]);
354 				pc = dtrace_fuword32(&gregs[EIP]);
355 
356 				oldcontext = dtrace_fuword32(&ucp->uc_link);
357 			}
358 		} else {
359 			if (p->p_model == DATAMODEL_NATIVE) {
360 				struct frame *fr = (struct frame *)sp;
361 
362 				pc = dtrace_fulword(&fr->fr_savpc);
363 				sp = dtrace_fulword(&fr->fr_savfp);
364 			} else {
365 				struct frame32 *fr = (struct frame32 *)sp;
366 
367 				pc = dtrace_fuword32(&fr->fr_savpc);
368 				sp = dtrace_fuword32(&fr->fr_savfp);
369 			}
370 		}
371 
372 		/*
373 		 * This is totally bogus:  if we faulted, we're going to clear
374 		 * the fault and break.  This is to deal with the apparently
375 		 * broken Java stacks on x86.
376 		 */
377 		if (*flags & CPU_DTRACE_FAULT) {
378 			*flags &= ~CPU_DTRACE_FAULT;
379 			break;
380 		}
381 	}
382 
383 	while (pcstack_limit-- > 0)
384 		*pcstack++ = NULL;
385 }
386 
387 /*ARGSUSED*/
388 uint64_t
389 dtrace_getarg(int arg, int aframes)
390 {
391 	uintptr_t val;
392 	struct frame *fp = (struct frame *)dtrace_getfp();
393 	uintptr_t *stack;
394 	int i;
395 #if defined(__amd64)
396 	/*
397 	 * A total of 6 arguments are passed via registers; any argument with
398 	 * index of 5 or lower is therefore in a register.
399 	 */
400 	int inreg = 5;
401 #endif
402 
403 	for (i = 1; i <= aframes; i++) {
404 		fp = (struct frame *)(fp->fr_savfp);
405 
406 		if (fp->fr_savpc == (pc_t)dtrace_invop_callsite) {
407 #if !defined(__amd64)
408 			/*
409 			 * If we pass through the invalid op handler, we will
410 			 * use the pointer that it passed to the stack as the
411 			 * second argument to dtrace_invop() as the pointer to
412 			 * the stack.  When using this stack, we must step
413 			 * beyond the EIP/RIP that was pushed when the trap was
414 			 * taken -- hence the "+ 1" below.
415 			 */
416 			stack = ((uintptr_t **)&fp[1])[1] + 1;
417 #else
418 			/*
419 			 * In the case of amd64, we will use the pointer to the
420 			 * regs structure that was pushed when we took the
421 			 * trap.  To get this structure, we must increment
422 			 * beyond the frame structure, and then again beyond
423 			 * the calling RIP stored in dtrace_invop().  If the
424 			 * argument that we're seeking is passed on the stack,
425 			 * we'll pull the true stack pointer out of the saved
426 			 * registers and decrement our argument by the number
427 			 * of arguments passed in registers; if the argument
428 			 * we're seeking is passed in regsiters, we can just
429 			 * load it directly.
430 			 */
431 			struct regs *rp = (struct regs *)((uintptr_t)&fp[1] +
432 			    sizeof (uintptr_t));
433 
434 			if (arg <= inreg) {
435 				stack = (uintptr_t *)&rp->r_rdi;
436 			} else {
437 				stack = (uintptr_t *)(rp->r_rsp);
438 				arg -= inreg;
439 			}
440 #endif
441 			goto load;
442 		}
443 
444 	}
445 
446 	/*
447 	 * We know that we did not come through a trap to get into
448 	 * dtrace_probe() -- the provider simply called dtrace_probe()
449 	 * directly.  As this is the case, we need to shift the argument
450 	 * that we're looking for:  the probe ID is the first argument to
451 	 * dtrace_probe(), so the argument n will actually be found where
452 	 * one would expect to find argument (n + 1).
453 	 */
454 	arg++;
455 
456 #if defined(__amd64)
457 	if (arg <= inreg) {
458 		/*
459 		 * This shouldn't happen.  If the argument is passed in a
460 		 * register then it should have been, well, passed in a
461 		 * register...
462 		 */
463 		DTRACE_CPUFLAG_SET(CPU_DTRACE_ILLOP);
464 		return (0);
465 	}
466 
467 	arg -= (inreg + 1);
468 #endif
469 	stack = (uintptr_t *)&fp[1];
470 
471 load:
472 	DTRACE_CPUFLAG_SET(CPU_DTRACE_NOFAULT);
473 	val = stack[arg];
474 	DTRACE_CPUFLAG_CLEAR(CPU_DTRACE_NOFAULT);
475 
476 	return (val);
477 }
478 
479 /*ARGSUSED*/
480 int
481 dtrace_getstackdepth(int aframes)
482 {
483 	struct frame *fp = (struct frame *)dtrace_getfp();
484 	struct frame *nextfp, *minfp, *stacktop;
485 	int depth = 0;
486 	int on_intr;
487 
488 	if ((on_intr = CPU_ON_INTR(CPU)) != 0)
489 		stacktop = (struct frame *)(CPU->cpu_intr_stack + SA(MINFRAME));
490 	else
491 		stacktop = (struct frame *)curthread->t_stk;
492 	minfp = fp;
493 
494 	aframes++;
495 
496 	for (;;) {
497 		depth++;
498 
499 		nextfp = (struct frame *)fp->fr_savfp;
500 
501 		if (nextfp <= minfp || nextfp >= stacktop) {
502 			if (on_intr) {
503 				/*
504 				 * Hop from interrupt stack to thread stack.
505 				 */
506 				stacktop = (struct frame *)curthread->t_stk;
507 				minfp = (struct frame *)curthread->t_stkbase;
508 				on_intr = 0;
509 				continue;
510 			}
511 			break;
512 		}
513 
514 		fp = nextfp;
515 		minfp = fp;
516 	}
517 
518 	if (depth <= aframes)
519 		return (0);
520 
521 	return (depth - aframes);
522 }
523 
524 ulong_t
525 dtrace_getreg(struct regs *rp, uint_t reg)
526 {
527 #if defined(__amd64)
528 	int regmap[] = {
529 		REG_GS,		/* GS */
530 		REG_FS,		/* FS */
531 		REG_ES,		/* ES */
532 		REG_DS,		/* DS */
533 		REG_RDI,	/* EDI */
534 		REG_RSI,	/* ESI */
535 		REG_RBP,	/* EBP */
536 		REG_RSP,	/* ESP */
537 		REG_RBX,	/* EBX */
538 		REG_RDX,	/* EDX */
539 		REG_RCX,	/* ECX */
540 		REG_RAX,	/* EAX */
541 		REG_TRAPNO,	/* TRAPNO */
542 		REG_ERR,	/* ERR */
543 		REG_RIP,	/* EIP */
544 		REG_CS,		/* CS */
545 		REG_RFL,	/* EFL */
546 		REG_RSP,	/* UESP */
547 		REG_SS		/* SS */
548 	};
549 
550 	if (reg <= SS) {
551 		if (reg >= sizeof (regmap) / sizeof (int)) {
552 			DTRACE_CPUFLAG_SET(CPU_DTRACE_ILLOP);
553 			return (0);
554 		}
555 
556 		reg = regmap[reg];
557 	} else {
558 		reg -= SS + 1;
559 	}
560 
561 	switch (reg) {
562 	case REG_RDI:
563 		return (rp->r_rdi);
564 	case REG_RSI:
565 		return (rp->r_rsi);
566 	case REG_RDX:
567 		return (rp->r_rdx);
568 	case REG_RCX:
569 		return (rp->r_rcx);
570 	case REG_R8:
571 		return (rp->r_r8);
572 	case REG_R9:
573 		return (rp->r_r9);
574 	case REG_RAX:
575 		return (rp->r_rax);
576 	case REG_RBX:
577 		return (rp->r_rbx);
578 	case REG_RBP:
579 		return (rp->r_rbp);
580 	case REG_R10:
581 		return (rp->r_r10);
582 	case REG_R11:
583 		return (rp->r_r11);
584 	case REG_R12:
585 		return (rp->r_r12);
586 	case REG_R13:
587 		return (rp->r_r13);
588 	case REG_R14:
589 		return (rp->r_r14);
590 	case REG_R15:
591 		return (rp->r_r15);
592 	case REG_DS:
593 		return (rp->r_ds);
594 	case REG_ES:
595 		return (rp->r_es);
596 	case REG_FS:
597 		return (rp->r_fs);
598 	case REG_GS:
599 		return (rp->r_gs);
600 	case REG_TRAPNO:
601 		return (rp->r_trapno);
602 	case REG_ERR:
603 		return (rp->r_err);
604 	case REG_RIP:
605 		return (rp->r_rip);
606 	case REG_CS:
607 		return (rp->r_cs);
608 	case REG_SS:
609 		return (rp->r_ss);
610 	case REG_RFL:
611 		return (rp->r_rfl);
612 	case REG_RSP:
613 		return (rp->r_rsp);
614 	default:
615 		DTRACE_CPUFLAG_SET(CPU_DTRACE_ILLOP);
616 		return (0);
617 	}
618 
619 #else
620 	if (reg > SS) {
621 		DTRACE_CPUFLAG_SET(CPU_DTRACE_ILLOP);
622 		return (0);
623 	}
624 
625 	return ((&rp->r_gs)[reg]);
626 #endif
627 }
628 
629 static int
630 dtrace_copycheck(uintptr_t uaddr, uintptr_t kaddr, size_t size)
631 {
632 	ASSERT(kaddr >= kernelbase && kaddr + size >= kaddr);
633 
634 	if (uaddr + size >= kernelbase || uaddr + size < uaddr) {
635 		DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR);
636 		cpu_core[CPU->cpu_id].cpuc_dtrace_illval = uaddr;
637 		return (0);
638 	}
639 
640 	return (1);
641 }
642 
643 void
644 dtrace_copyin(uintptr_t uaddr, uintptr_t kaddr, size_t size)
645 {
646 	if (dtrace_copycheck(uaddr, kaddr, size))
647 		dtrace_copy(uaddr, kaddr, size);
648 }
649 
650 void
651 dtrace_copyout(uintptr_t kaddr, uintptr_t uaddr, size_t size)
652 {
653 	if (dtrace_copycheck(uaddr, kaddr, size))
654 		dtrace_copy(kaddr, uaddr, size);
655 }
656 
657 void
658 dtrace_copyinstr(uintptr_t uaddr, uintptr_t kaddr, size_t size)
659 {
660 	if (dtrace_copycheck(uaddr, kaddr, size))
661 		dtrace_copystr(uaddr, kaddr, size);
662 }
663 
664 void
665 dtrace_copyoutstr(uintptr_t kaddr, uintptr_t uaddr, size_t size)
666 {
667 	if (dtrace_copycheck(uaddr, kaddr, size))
668 		dtrace_copystr(kaddr, uaddr, size);
669 }
670 
671 uint8_t
672 dtrace_fuword8(void *uaddr)
673 {
674 	extern uint8_t dtrace_fuword8_nocheck(void *);
675 	if ((uintptr_t)uaddr >= _userlimit) {
676 		DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR);
677 		cpu_core[CPU->cpu_id].cpuc_dtrace_illval = (uintptr_t)uaddr;
678 		return (0);
679 	}
680 	return (dtrace_fuword8_nocheck(uaddr));
681 }
682 
683 uint16_t
684 dtrace_fuword16(void *uaddr)
685 {
686 	extern uint16_t dtrace_fuword16_nocheck(void *);
687 	if ((uintptr_t)uaddr >= _userlimit) {
688 		DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR);
689 		cpu_core[CPU->cpu_id].cpuc_dtrace_illval = (uintptr_t)uaddr;
690 		return (0);
691 	}
692 	return (dtrace_fuword16_nocheck(uaddr));
693 }
694 
695 uint32_t
696 dtrace_fuword32(void *uaddr)
697 {
698 	extern uint32_t dtrace_fuword32_nocheck(void *);
699 	if ((uintptr_t)uaddr >= _userlimit) {
700 		DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR);
701 		cpu_core[CPU->cpu_id].cpuc_dtrace_illval = (uintptr_t)uaddr;
702 		return (0);
703 	}
704 	return (dtrace_fuword32_nocheck(uaddr));
705 }
706 
707 uint64_t
708 dtrace_fuword64(void *uaddr)
709 {
710 	extern uint64_t dtrace_fuword64_nocheck(void *);
711 	if ((uintptr_t)uaddr >= _userlimit) {
712 		DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR);
713 		cpu_core[CPU->cpu_id].cpuc_dtrace_illval = (uintptr_t)uaddr;
714 		return (0);
715 	}
716 	return (dtrace_fuword64_nocheck(uaddr));
717 }
718