1 /*	$NetBSD: dtrace_isa.c,v 1.4 2016/05/14 21:19:05 chs Exp $	*/
2 
3 /*
4  * CDDL HEADER START
5  *
6  * The contents of this file are subject to the terms of the
7  * Common Development and Distribution License, Version 1.0 only
8  * (the "License").  You may not use this file except in compliance
9  * with the License.
10  *
11  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
12  * or http://www.opensolaris.org/os/licensing.
13  * See the License for the specific language governing permissions
14  * and limitations under the License.
15  *
16  * When distributing Covered Code, include this CDDL HEADER in each
17  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
18  * If applicable, add the following below this CDDL HEADER, with the
19  * fields enclosed by brackets "[]" replaced with your own identifying
20  * information: Portions Copyright [yyyy] [name of copyright owner]
21  *
22  * CDDL HEADER END
23  *
24  * $FreeBSD: src/sys/cddl/dev/dtrace/i386/dtrace_isa.c,v 1.1.4.1 2009/08/03 08:13:06 kensmith Exp $
25  */
26 /*
27  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
28  * Use is subject to license terms.
29  */
30 #include <sys/cdefs.h>
31 
32 #include <sys/param.h>
33 #include <sys/systm.h>
34 #include <sys/kernel.h>
35 
36 #include <machine/vmparam.h>
37 #include <machine/pmap.h>
38 
39 uintptr_t kernelbase = (uintptr_t)KERNBASE;
40 
41 #define INKERNEL(va) \
42 	(((vm_offset_t)(va)) >= VM_MIN_KERNEL_ADDRESS && \
43 	 ((vm_offset_t)(va)) < VM_MAX_KERNEL_ADDRESS)
44 
45 struct i386_frame {
46 	struct i386_frame	*f_frame;
47 	int			 f_retaddr;
48 	int			 f_arg0;
49 };
50 
51 typedef	unsigned long	vm_offset_t;
52 
53 uint8_t dtrace_fuword8_nocheck(void *);
54 uint16_t dtrace_fuword16_nocheck(void *);
55 uint32_t dtrace_fuword32_nocheck(void *);
56 uint64_t dtrace_fuword64_nocheck(void *);
57 
58 void
dtrace_getpcstack(pc_t * pcstack,int pcstack_limit,int aframes,uint32_t * intrpc)59 dtrace_getpcstack(pc_t *pcstack, int pcstack_limit, int aframes,
60     uint32_t *intrpc)
61 {
62 	int depth = 0;
63 	register_t ebp;
64 	struct i386_frame *frame;
65 	vm_offset_t callpc;
66 	pc_t caller = (pc_t) solaris_cpu[cpu_number()].cpu_dtrace_caller;
67 
68 	if (intrpc != 0)
69 		pcstack[depth++] = (pc_t) intrpc;
70 
71 	aframes++;
72 
73 	__asm __volatile("movl %%ebp,%0" : "=r" (ebp));
74 
75 	frame = (struct i386_frame *)ebp;
76 	while (depth < pcstack_limit) {
77 		if (!INKERNEL(frame))
78 			break;
79 
80 		callpc = frame->f_retaddr;
81 
82 		if (!INKERNEL(callpc))
83 			break;
84 
85 		if (aframes > 0) {
86 			aframes--;
87 			if ((aframes == 0) && (caller != 0)) {
88 				pcstack[depth++] = caller;
89 			}
90 		}
91 		else {
92 			pcstack[depth++] = callpc;
93 		}
94 
95 		if (frame->f_frame <= frame ||
96 		    (vm_offset_t)frame->f_frame >=
97 		    (vm_offset_t)ebp + KSTACK_SIZE)
98 			break;
99 		frame = frame->f_frame;
100 	}
101 
102 	for (; depth < pcstack_limit; depth++) {
103 		pcstack[depth] = 0;
104 	}
105 }
106 
107 static int
dtrace_getustack_common(uint64_t * pcstack,int pcstack_limit,uintptr_t pc,uintptr_t sp)108 dtrace_getustack_common(uint64_t *pcstack, int pcstack_limit, uintptr_t pc,
109     uintptr_t sp)
110 {
111 #ifdef notyet
112 	proc_t *p = curproc;
113 	uintptr_t oldcontext = lwp->lwp_oldcontext; /* XXX signal stack. */
114 	size_t s1, s2;
115 #endif
116 	volatile uint16_t *flags =
117 	    (volatile uint16_t *)&cpu_core[cpu_number()].cpuc_dtrace_flags;
118 	int ret = 0;
119 
120 	ASSERT(pcstack == NULL || pcstack_limit > 0);
121 
122 #ifdef notyet /* XXX signal stack. */
123 	if (p->p_model == DATAMODEL_NATIVE) {
124 		s1 = sizeof (struct frame) + 2 * sizeof (long);
125 		s2 = s1 + sizeof (siginfo_t);
126 	} else {
127 		s1 = sizeof (struct frame32) + 3 * sizeof (int);
128 		s2 = s1 + sizeof (siginfo32_t);
129 	}
130 #endif
131 
132 	while (pc != 0) {
133 		ret++;
134 		if (pcstack != NULL) {
135 			*pcstack++ = (uint64_t)pc;
136 			pcstack_limit--;
137 			if (pcstack_limit <= 0)
138 				break;
139 		}
140 
141 		if (sp == 0)
142 			break;
143 
144 #ifdef notyet /* XXX signal stack. */
145 		if (oldcontext == sp + s1 || oldcontext == sp + s2) {
146 			if (p->p_model == DATAMODEL_NATIVE) {
147 				ucontext_t *ucp = (ucontext_t *)oldcontext;
148 				greg_t *gregs = ucp->uc_mcontext.gregs;
149 
150 				sp = dtrace_fulword(&gregs[REG_FP]);
151 				pc = dtrace_fulword(&gregs[REG_PC]);
152 
153 				oldcontext = dtrace_fulword(&ucp->uc_link);
154 			} else {
155 				ucontext32_t *ucp = (ucontext32_t *)oldcontext;
156 				greg32_t *gregs = ucp->uc_mcontext.gregs;
157 
158 				sp = dtrace_fuword32(&gregs[EBP]);
159 				pc = dtrace_fuword32(&gregs[EIP]);
160 
161 				oldcontext = dtrace_fuword32(&ucp->uc_link);
162 			}
163 		} else {
164 			if (p->p_model == DATAMODEL_NATIVE) {
165 				struct frame *fr = (struct frame *)sp;
166 
167 				pc = dtrace_fulword(&fr->fr_savpc);
168 				sp = dtrace_fulword(&fr->fr_savfp);
169 			} else {
170 				struct frame32 *fr = (struct frame32 *)sp;
171 
172 				pc = dtrace_fuword32(&fr->fr_savpc);
173 				sp = dtrace_fuword32(&fr->fr_savfp);
174 			}
175 		}
176 #else
177 		pc = dtrace_fuword32((void *)(sp +
178 			offsetof(struct i386_frame, f_retaddr)));
179 		sp = dtrace_fuword32((void *)sp);
180 #endif /* ! notyet */
181 
182 		/*
183 		 * This is totally bogus:  if we faulted, we're going to clear
184 		 * the fault and break.  This is to deal with the apparently
185 		 * broken Java stacks on x86.
186 		 */
187 		if (*flags & CPU_DTRACE_FAULT) {
188 			*flags &= ~CPU_DTRACE_FAULT;
189 			break;
190 		}
191 	}
192 
193 	return (ret);
194 }
195 
196 void
dtrace_getupcstack(uint64_t * pcstack,int pcstack_limit)197 dtrace_getupcstack(uint64_t *pcstack, int pcstack_limit)
198 {
199 	proc_t *p = curproc;
200 	struct trapframe *tf;
201 	uintptr_t pc, sp, fp;
202 	volatile uint16_t *flags =
203 	    (volatile uint16_t *)&cpu_core[cpu_number()].cpuc_dtrace_flags;
204 	int n;
205 
206 	if (*flags & CPU_DTRACE_FAULT)
207 		return;
208 
209 	if (pcstack_limit <= 0)
210 		return;
211 
212 	/*
213 	 * If there's no user context we still need to zero the stack.
214 	 */
215 	if (p == NULL || (tf = curlwp->l_md.md_regs) == NULL)
216 		goto zero;
217 
218 	*pcstack++ = (uint64_t)p->p_pid;
219 	pcstack_limit--;
220 
221 	if (pcstack_limit <= 0)
222 		return;
223 
224 	pc = tf->tf_eip;
225 	fp = tf->tf_ebp;
226 	sp = tf->tf_esp;
227 
228 	if (DTRACE_CPUFLAG_ISSET(CPU_DTRACE_ENTRY)) {
229 		/*
230 		 * In an entry probe.  The frame pointer has not yet been
231 		 * pushed (that happens in the function prologue).  The
232 		 * best approach is to add the current pc as a missing top
233 		 * of stack and back the pc up to the caller, which is stored
234 		 * at the current stack pointer address since the call
235 		 * instruction puts it there right before the branch.
236 		 */
237 
238 		*pcstack++ = (uint64_t)pc;
239 		pcstack_limit--;
240 		if (pcstack_limit <= 0)
241 			return;
242 
243 		pc = dtrace_fuword32((void *) sp);
244 	}
245 
246 	n = dtrace_getustack_common(pcstack, pcstack_limit, pc, fp);
247 	ASSERT(n >= 0);
248 	ASSERT(n <= pcstack_limit);
249 
250 	pcstack += n;
251 	pcstack_limit -= n;
252 
253 zero:
254 	while (pcstack_limit-- > 0)
255 		*pcstack++ = 0;
256 }
257 
258 int
dtrace_getustackdepth(void)259 dtrace_getustackdepth(void)
260 {
261 	proc_t *p = curproc;
262 	struct trapframe *tf;
263 	uintptr_t pc, fp, sp;
264 	int n = 0;
265 
266 	if (p == NULL || (tf = curlwp->l_md.md_regs) == NULL)
267 		return (0);
268 
269 	if (DTRACE_CPUFLAG_ISSET(CPU_DTRACE_FAULT))
270 		return (-1);
271 
272 	pc = tf->tf_eip;
273 	fp = tf->tf_ebp;
274 	sp = tf->tf_esp;
275 
276 	if (DTRACE_CPUFLAG_ISSET(CPU_DTRACE_ENTRY)) {
277 		/*
278 		 * In an entry probe.  The frame pointer has not yet been
279 		 * pushed (that happens in the function prologue).  The
280 		 * best approach is to add the current pc as a missing top
281 		 * of stack and back the pc up to the caller, which is stored
282 		 * at the current stack pointer address since the call
283 		 * instruction puts it there right before the branch.
284 		 */
285 
286 		pc = dtrace_fuword32((void *) sp);
287 		n++;
288 	}
289 
290 	n += dtrace_getustack_common(NULL, 0, pc, fp);
291 
292 	return (n);
293 }
294 
295 void
dtrace_getufpstack(uint64_t * pcstack,uint64_t * fpstack,int pcstack_limit)296 dtrace_getufpstack(uint64_t *pcstack, uint64_t *fpstack, int pcstack_limit)
297 {
298 	proc_t *p = curproc;
299 	struct trapframe *tf;
300 	uintptr_t pc, sp, fp;
301 	volatile uint16_t *flags =
302 	    (volatile uint16_t *)&cpu_core[cpu_number()].cpuc_dtrace_flags;
303 #ifdef notyet /* XXX signal stack */
304 	uintptr_t oldcontext;
305 	size_t s1, s2;
306 #endif
307 
308 	if (*flags & CPU_DTRACE_FAULT)
309 		return;
310 
311 	if (pcstack_limit <= 0)
312 		return;
313 
314 	/*
315 	 * If there's no user context we still need to zero the stack.
316 	 */
317 	if (p == NULL || (tf = curlwp->l_md.md_regs) == NULL)
318 		goto zero;
319 
320 	*pcstack++ = (uint64_t)p->p_pid;
321 	pcstack_limit--;
322 
323 	if (pcstack_limit <= 0)
324 		return;
325 
326 	pc = tf->tf_eip;
327 	fp = tf->tf_ebp;
328 	sp = tf->tf_esp;
329 
330 #ifdef notyet /* XXX signal stack */
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 #endif
341 
342 	if (DTRACE_CPUFLAG_ISSET(CPU_DTRACE_ENTRY)) {
343 		*pcstack++ = (uint64_t)pc;
344 		*fpstack++ = 0;
345 		pcstack_limit--;
346 		if (pcstack_limit <= 0)
347 			return;
348 
349 		pc = dtrace_fuword32((void *)sp);
350 	}
351 
352 	while (pc != 0) {
353 		*pcstack++ = (uint64_t)pc;
354 		*fpstack++ = fp;
355 		pcstack_limit--;
356 		if (pcstack_limit <= 0)
357 			break;
358 
359 		if (fp == 0)
360 			break;
361 
362 #ifdef notyet /* XXX signal stack */
363 		if (oldcontext == sp + s1 || oldcontext == sp + s2) {
364 			if (p->p_model == DATAMODEL_NATIVE) {
365 				ucontext_t *ucp = (ucontext_t *)oldcontext;
366 				greg_t *gregs = ucp->uc_mcontext.gregs;
367 
368 				sp = dtrace_fulword(&gregs[REG_FP]);
369 				pc = dtrace_fulword(&gregs[REG_PC]);
370 
371 				oldcontext = dtrace_fulword(&ucp->uc_link);
372 			} else {
373 				ucontext_t *ucp = (ucontext_t *)oldcontext;
374 				greg_t *gregs = ucp->uc_mcontext.gregs;
375 
376 				sp = dtrace_fuword32(&gregs[EBP]);
377 				pc = dtrace_fuword32(&gregs[EIP]);
378 
379 				oldcontext = dtrace_fuword32(&ucp->uc_link);
380 			}
381 		} else
382 #endif /* XXX */
383 		{
384 			pc = dtrace_fuword32((void *)(fp +
385 				offsetof(struct i386_frame, f_retaddr)));
386 			fp = dtrace_fuword32((void *)fp);
387 		}
388 
389 		/*
390 		 * This is totally bogus:  if we faulted, we're going to clear
391 		 * the fault and break.  This is to deal with the apparently
392 		 * broken Java stacks on x86.
393 		 */
394 		if (*flags & CPU_DTRACE_FAULT) {
395 			*flags &= ~CPU_DTRACE_FAULT;
396 			break;
397 		}
398 	}
399 
400 zero:
401 	while (pcstack_limit-- > 0)
402 		*pcstack++ = 0;
403 }
404 
405 uint64_t
dtrace_getarg(int arg,int aframes)406 dtrace_getarg(int arg, int aframes)
407 {
408 	uintptr_t val;
409 	struct i386_frame *fp = (struct i386_frame *)dtrace_getfp();
410 	uintptr_t *stack;
411 	int i;
412 
413 	for (i = 1; i <= aframes; i++) {
414 		fp = fp->f_frame;
415 
416 		if (fp->f_retaddr == (long)dtrace_invop_callsite) {
417 			/*
418 			 * If we pass through the invalid op handler, we will
419 			 * use the pointer that it passed to the stack as the
420 			 * second argument to dtrace_invop() as the pointer to
421 			 * the stack.  When using this stack, we must step
422 			 * beyond the EIP/RIP that was pushed when the trap was
423 			 * taken -- hence the "+ 1" below.
424 			 */
425 			stack = ((uintptr_t **)&fp[1])[1] + 1;
426 			goto load;
427 		}
428 	}
429 
430 	/*
431 	 * We know that we did not come through a trap to get into
432 	 * dtrace_probe() -- the provider simply called dtrace_probe()
433 	 * directly.  As this is the case, we need to shift the argument
434 	 * that we're looking for:  the probe ID is the first argument to
435 	 * dtrace_probe(), so the argument n will actually be found where
436 	 * one would expect to find argument (n + 1).
437 	 */
438 	arg++;
439 
440 	stack = (uintptr_t *)fp + 2;
441 
442 load:
443 	DTRACE_CPUFLAG_SET(CPU_DTRACE_NOFAULT);
444 	val = stack[arg];
445 	DTRACE_CPUFLAG_CLEAR(CPU_DTRACE_NOFAULT);
446 
447 	return (val);
448 }
449 
450 int
dtrace_getstackdepth(int aframes)451 dtrace_getstackdepth(int aframes)
452 {
453 	int depth = 0;
454 	struct i386_frame *frame;
455 	vm_offset_t ebp;
456 
457 	aframes++;
458 	ebp = dtrace_getfp();
459 	frame = (struct i386_frame *)ebp;
460 	depth++;
461 	for(;;) {
462 		if (!INKERNEL((long) frame))
463 			break;
464 		if (!INKERNEL((long) frame->f_frame))
465 			break;
466 		depth++;
467 		if (frame->f_frame <= frame ||
468 		    (vm_offset_t)frame->f_frame >=
469 		    (vm_offset_t)ebp + KSTACK_SIZE)
470 			break;
471 		frame = frame->f_frame;
472 	}
473 	if (depth < aframes)
474 		return 0;
475 	else
476 		return depth - aframes;
477 }
478 
479 #ifdef notyet
480 ulong_t
dtrace_getreg(struct regs * rp,uint_t reg)481 dtrace_getreg(struct regs *rp, uint_t reg)
482 {
483 #if defined(__amd64)
484 	int regmap[] = {
485 		REG_GS,		/* GS */
486 		REG_FS,		/* FS */
487 		REG_ES,		/* ES */
488 		REG_DS,		/* DS */
489 		REG_RDI,	/* EDI */
490 		REG_RSI,	/* ESI */
491 		REG_RBP,	/* EBP */
492 		REG_RSP,	/* ESP */
493 		REG_RBX,	/* EBX */
494 		REG_RDX,	/* EDX */
495 		REG_RCX,	/* ECX */
496 		REG_RAX,	/* EAX */
497 		REG_TRAPNO,	/* TRAPNO */
498 		REG_ERR,	/* ERR */
499 		REG_RIP,	/* EIP */
500 		REG_CS,		/* CS */
501 		REG_RFL,	/* EFL */
502 		REG_RSP,	/* UESP */
503 		REG_SS		/* SS */
504 	};
505 
506 	if (reg <= SS) {
507 		if (reg >= sizeof (regmap) / sizeof (int)) {
508 			DTRACE_CPUFLAG_SET(CPU_DTRACE_ILLOP);
509 			return (0);
510 		}
511 
512 		reg = regmap[reg];
513 	} else {
514 		reg -= SS + 1;
515 	}
516 
517 	switch (reg) {
518 	case REG_RDI:
519 		return (rp->r_rdi);
520 	case REG_RSI:
521 		return (rp->r_rsi);
522 	case REG_RDX:
523 		return (rp->r_rdx);
524 	case REG_RCX:
525 		return (rp->r_rcx);
526 	case REG_R8:
527 		return (rp->r_r8);
528 	case REG_R9:
529 		return (rp->r_r9);
530 	case REG_RAX:
531 		return (rp->r_rax);
532 	case REG_RBX:
533 		return (rp->r_rbx);
534 	case REG_RBP:
535 		return (rp->r_rbp);
536 	case REG_R10:
537 		return (rp->r_r10);
538 	case REG_R11:
539 		return (rp->r_r11);
540 	case REG_R12:
541 		return (rp->r_r12);
542 	case REG_R13:
543 		return (rp->r_r13);
544 	case REG_R14:
545 		return (rp->r_r14);
546 	case REG_R15:
547 		return (rp->r_r15);
548 	case REG_DS:
549 		return (rp->r_ds);
550 	case REG_ES:
551 		return (rp->r_es);
552 	case REG_FS:
553 		return (rp->r_fs);
554 	case REG_GS:
555 		return (rp->r_gs);
556 	case REG_TRAPNO:
557 		return (rp->r_trapno);
558 	case REG_ERR:
559 		return (rp->r_err);
560 	case REG_RIP:
561 		return (rp->r_rip);
562 	case REG_CS:
563 		return (rp->r_cs);
564 	case REG_SS:
565 		return (rp->r_ss);
566 	case REG_RFL:
567 		return (rp->r_rfl);
568 	case REG_RSP:
569 		return (rp->r_rsp);
570 	default:
571 		DTRACE_CPUFLAG_SET(CPU_DTRACE_ILLOP);
572 		return (0);
573 	}
574 
575 #else
576 	if (reg > SS) {
577 		DTRACE_CPUFLAG_SET(CPU_DTRACE_ILLOP);
578 		return (0);
579 	}
580 
581 	return ((&rp->r_gs)[reg]);
582 #endif
583 }
584 #endif
585 
586 static int
dtrace_copycheck(uintptr_t uaddr,uintptr_t kaddr,size_t size)587 dtrace_copycheck(uintptr_t uaddr, uintptr_t kaddr, size_t size)
588 {
589 	ASSERT(kaddr >= kernelbase && kaddr + size >= kaddr);
590 
591 	if (uaddr + size >= kernelbase || uaddr + size < uaddr) {
592 		DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR);
593 		cpu_core[cpu_number()].cpuc_dtrace_illval = uaddr;
594 		return (0);
595 	}
596 
597 	return (1);
598 }
599 
600 void
dtrace_copyin(uintptr_t uaddr,uintptr_t kaddr,size_t size,volatile uint16_t * flags)601 dtrace_copyin(uintptr_t uaddr, uintptr_t kaddr, size_t size,
602     volatile uint16_t *flags)
603 {
604 	if (dtrace_copycheck(uaddr, kaddr, size))
605 		dtrace_copy(uaddr, kaddr, size);
606 }
607 
608 void
dtrace_copyout(uintptr_t kaddr,uintptr_t uaddr,size_t size,volatile uint16_t * flags)609 dtrace_copyout(uintptr_t kaddr, uintptr_t uaddr, size_t size,
610     volatile uint16_t *flags)
611 {
612 	if (dtrace_copycheck(uaddr, kaddr, size))
613 		dtrace_copy(kaddr, uaddr, size);
614 }
615 
616 void
dtrace_copyinstr(uintptr_t uaddr,uintptr_t kaddr,size_t size,volatile uint16_t * flags)617 dtrace_copyinstr(uintptr_t uaddr, uintptr_t kaddr, size_t size,
618     volatile uint16_t *flags)
619 {
620 	if (dtrace_copycheck(uaddr, kaddr, size))
621 		dtrace_copystr(uaddr, kaddr, size, flags);
622 }
623 
624 void
dtrace_copyoutstr(uintptr_t kaddr,uintptr_t uaddr,size_t size,volatile uint16_t * flags)625 dtrace_copyoutstr(uintptr_t kaddr, uintptr_t uaddr, size_t size,
626     volatile uint16_t *flags)
627 {
628 	if (dtrace_copycheck(uaddr, kaddr, size))
629 		dtrace_copystr(kaddr, uaddr, size, flags);
630 }
631 
632 uint8_t
dtrace_fuword8(void * uaddr)633 dtrace_fuword8(void *uaddr)
634 {
635 	if ((uintptr_t)uaddr >= kernelbase) {
636 		DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR);
637 		cpu_core[cpu_number()].cpuc_dtrace_illval = (uintptr_t)uaddr;
638 		return (0);
639 	}
640 	return (dtrace_fuword8_nocheck(uaddr));
641 }
642 
643 uint16_t
dtrace_fuword16(void * uaddr)644 dtrace_fuword16(void *uaddr)
645 {
646 	if ((uintptr_t)uaddr >= kernelbase) {
647 		DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR);
648 		cpu_core[cpu_number()].cpuc_dtrace_illval = (uintptr_t)uaddr;
649 		return (0);
650 	}
651 	return (dtrace_fuword16_nocheck(uaddr));
652 }
653 
654 uint32_t
dtrace_fuword32(void * uaddr)655 dtrace_fuword32(void *uaddr)
656 {
657 	if ((uintptr_t)uaddr >= kernelbase) {
658 		DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR);
659 		cpu_core[cpu_number()].cpuc_dtrace_illval = (uintptr_t)uaddr;
660 		return (0);
661 	}
662 	return (dtrace_fuword32_nocheck(uaddr));
663 }
664 
665 uint64_t
dtrace_fuword64(void * uaddr)666 dtrace_fuword64(void *uaddr)
667 {
668 	if ((uintptr_t)uaddr >= kernelbase) {
669 		DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR);
670 		cpu_core[cpu_number()].cpuc_dtrace_illval = (uintptr_t)uaddr;
671 		return (0);
672 	}
673 	return (dtrace_fuword64_nocheck(uaddr));
674 }
675