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