xref: /freebsd/sys/cddl/dev/dtrace/powerpc/dtrace_isa.c (revision 5e91185b)
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  * Portions Copyright 2012,2013 Justin Hibbits <jhibbits@freebsd.org>
23  *
24  * $FreeBSD$
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 #include <sys/stack.h>
36 #include <sys/sysent.h>
37 #include <sys/pcpu.h>
38 
39 #include <machine/frame.h>
40 #include <machine/md_var.h>
41 #include <machine/psl.h>
42 #include <machine/reg.h>
43 #include <machine/stack.h>
44 
45 #include <vm/vm.h>
46 #include <vm/vm_param.h>
47 #include <vm/pmap.h>
48 
49 #include "regset.h"
50 
51 /* Offset to the LR Save word (ppc32) */
52 #define RETURN_OFFSET	4
53 /* Offset to LR Save word (ppc64).  CR Save area sits between back chain and LR */
54 #define RETURN_OFFSET64	16
55 
56 #ifdef __powerpc64__
57 #define OFFSET 4 /* Account for the TOC reload slot */
58 #define	FRAME_OFFSET	48
59 #else
60 #define OFFSET 0
61 #define	FRAME_OFFSET	8
62 #endif
63 
64 #define INKERNEL(x)	((x) <= VM_MAX_KERNEL_ADDRESS && \
65 		(x) >= VM_MIN_KERNEL_ADDRESS)
66 
67 static __inline int
68 dtrace_sp_inkernel(uintptr_t sp)
69 {
70 	struct trapframe *frame;
71 	vm_offset_t callpc;
72 
73 #ifdef __powerpc64__
74 	callpc = *(vm_offset_t *)(sp + RETURN_OFFSET64);
75 #else
76 	callpc = *(vm_offset_t *)(sp + RETURN_OFFSET);
77 #endif
78 	if ((callpc & 3) || (callpc < 0x100))
79 		return (0);
80 
81 	/*
82 	 * trapexit() and asttrapexit() are sentinels
83 	 * for kernel stack tracing.
84 	 */
85 	if (callpc + OFFSET == (vm_offset_t) &trapexit ||
86 	    callpc + OFFSET == (vm_offset_t) &asttrapexit) {
87 		if (sp == 0)
88 			return (0);
89 		frame = (struct trapframe *)(sp + FRAME_OFFSET);
90 
91 		return ((frame->srr1 & PSL_PR) == 0);
92 	}
93 
94 	return (1);
95 }
96 
97 static __inline uintptr_t
98 dtrace_next_sp(uintptr_t sp)
99 {
100 	vm_offset_t callpc;
101 	uintptr_t *r1;
102 	struct trapframe *frame;
103 
104 #ifdef __powerpc64__
105 	callpc = *(vm_offset_t *)(sp + RETURN_OFFSET64);
106 #else
107 	callpc = *(vm_offset_t *)(sp + RETURN_OFFSET);
108 #endif
109 
110 	/*
111 	 * trapexit() and asttrapexit() are sentinels
112 	 * for kernel stack tracing.
113 	 */
114 	if ((callpc + OFFSET == (vm_offset_t) &trapexit ||
115 	    callpc + OFFSET == (vm_offset_t) &asttrapexit)) {
116 		/* Access the trap frame */
117 		frame = (struct trapframe *)(sp + FRAME_OFFSET);
118 		r1 = (uintptr_t *)frame->fixreg[1];
119 		if (r1 == NULL)
120 			return (0);
121 		return (*r1);
122 	}
123 
124 	return (*(uintptr_t*)sp);
125 }
126 
127 static __inline uintptr_t
128 dtrace_get_pc(uintptr_t sp)
129 {
130 	struct trapframe *frame;
131 	vm_offset_t callpc;
132 
133 #ifdef __powerpc64__
134 	callpc = *(vm_offset_t *)(sp + RETURN_OFFSET64);
135 #else
136 	callpc = *(vm_offset_t *)(sp + RETURN_OFFSET);
137 #endif
138 
139 	/*
140 	 * trapexit() and asttrapexit() are sentinels
141 	 * for kernel stack tracing.
142 	 */
143 	if ((callpc + OFFSET == (vm_offset_t) &trapexit ||
144 	    callpc + OFFSET == (vm_offset_t) &asttrapexit)) {
145 		/* Access the trap frame */
146 		frame = (struct trapframe *)(sp + FRAME_OFFSET);
147 		return (frame->srr0);
148 	}
149 
150 	return (callpc);
151 }
152 
153 greg_t
154 dtrace_getfp(void)
155 {
156 	return (greg_t)__builtin_frame_address(0);
157 }
158 
159 void
160 dtrace_getpcstack(pc_t *pcstack, int pcstack_limit, int aframes,
161     uint32_t *intrpc)
162 {
163 	int depth = 0;
164 	uintptr_t osp, sp;
165 	vm_offset_t callpc;
166 	pc_t caller = (pc_t) solaris_cpu[curcpu].cpu_dtrace_caller;
167 
168 	osp = PAGE_SIZE;
169 	if (intrpc != 0)
170 		pcstack[depth++] = (pc_t) intrpc;
171 
172 	aframes++;
173 
174 	sp = dtrace_getfp();
175 
176 	while (depth < pcstack_limit) {
177 		if (sp <= osp)
178 			break;
179 
180 		if (!dtrace_sp_inkernel(sp))
181 			break;
182 		callpc = dtrace_get_pc(sp);
183 
184 		if (aframes > 0) {
185 			aframes--;
186 			if ((aframes == 0) && (caller != 0)) {
187 				pcstack[depth++] = caller;
188 			}
189 		}
190 		else {
191 			pcstack[depth++] = callpc;
192 		}
193 
194 		osp = sp;
195 		sp = dtrace_next_sp(sp);
196 	}
197 
198 	for (; depth < pcstack_limit; depth++) {
199 		pcstack[depth] = 0;
200 	}
201 }
202 
203 static int
204 dtrace_getustack_common(uint64_t *pcstack, int pcstack_limit, uintptr_t pc,
205     uintptr_t sp)
206 {
207 	proc_t *p = curproc;
208 	int ret = 0;
209 
210 	ASSERT(pcstack == NULL || pcstack_limit > 0);
211 
212 	while (pc != 0) {
213 		ret++;
214 		if (pcstack != NULL) {
215 			*pcstack++ = (uint64_t)pc;
216 			pcstack_limit--;
217 			if (pcstack_limit <= 0)
218 				break;
219 		}
220 
221 		if (sp == 0)
222 			break;
223 
224 		if (SV_PROC_FLAG(p, SV_ILP32)) {
225 			pc = dtrace_fuword32((void *)(sp + RETURN_OFFSET));
226 			sp = dtrace_fuword32((void *)sp);
227 		}
228 		else {
229 			pc = dtrace_fuword64((void *)(sp + RETURN_OFFSET64));
230 			sp = dtrace_fuword64((void *)sp);
231 		}
232 	}
233 
234 	return (ret);
235 }
236 
237 void
238 dtrace_getupcstack(uint64_t *pcstack, int pcstack_limit)
239 {
240 	proc_t *p = curproc;
241 	struct trapframe *tf;
242 	uintptr_t pc, sp;
243 	volatile uint16_t *flags =
244 	    (volatile uint16_t *)&cpu_core[curcpu].cpuc_dtrace_flags;
245 	int n;
246 
247 	if (*flags & CPU_DTRACE_FAULT)
248 		return;
249 
250 	if (pcstack_limit <= 0)
251 		return;
252 
253 	/*
254 	 * If there's no user context we still need to zero the stack.
255 	 */
256 	if (p == NULL || (tf = curthread->td_frame) == NULL)
257 		goto zero;
258 
259 	*pcstack++ = (uint64_t)p->p_pid;
260 	pcstack_limit--;
261 
262 	if (pcstack_limit <= 0)
263 		return;
264 
265 	pc = tf->srr0;
266 	sp = tf->fixreg[1];
267 
268 	if (DTRACE_CPUFLAG_ISSET(CPU_DTRACE_ENTRY)) {
269 		/*
270 		 * In an entry probe.  The frame pointer has not yet been
271 		 * pushed (that happens in the function prologue).  The
272 		 * best approach is to add the current pc as a missing top
273 		 * of stack and back the pc up to the caller, which is stored
274 		 * at the current stack pointer address since the call
275 		 * instruction puts it there right before the branch.
276 		 */
277 
278 		*pcstack++ = (uint64_t)pc;
279 		pcstack_limit--;
280 		if (pcstack_limit <= 0)
281 			return;
282 
283 		pc = tf->lr;
284 	}
285 
286 	n = dtrace_getustack_common(pcstack, pcstack_limit, pc, sp);
287 	ASSERT(n >= 0);
288 	ASSERT(n <= pcstack_limit);
289 
290 	pcstack += n;
291 	pcstack_limit -= n;
292 
293 zero:
294 	while (pcstack_limit-- > 0)
295 		*pcstack++ = 0;
296 }
297 
298 int
299 dtrace_getustackdepth(void)
300 {
301 	proc_t *p = curproc;
302 	struct trapframe *tf;
303 	uintptr_t pc, sp;
304 	int n = 0;
305 
306 	if (p == NULL || (tf = curthread->td_frame) == NULL)
307 		return (0);
308 
309 	if (DTRACE_CPUFLAG_ISSET(CPU_DTRACE_FAULT))
310 		return (-1);
311 
312 	pc = tf->srr0;
313 	sp = tf->fixreg[1];
314 
315 	if (DTRACE_CPUFLAG_ISSET(CPU_DTRACE_ENTRY)) {
316 		/*
317 		 * In an entry probe.  The frame pointer has not yet been
318 		 * pushed (that happens in the function prologue).  The
319 		 * best approach is to add the current pc as a missing top
320 		 * of stack and back the pc up to the caller, which is stored
321 		 * at the current stack pointer address since the call
322 		 * instruction puts it there right before the branch.
323 		 */
324 
325 		if (SV_PROC_FLAG(p, SV_ILP32)) {
326 			pc = dtrace_fuword32((void *) sp);
327 		}
328 		else
329 			pc = dtrace_fuword64((void *) sp);
330 		n++;
331 	}
332 
333 	n += dtrace_getustack_common(NULL, 0, pc, sp);
334 
335 	return (n);
336 }
337 
338 void
339 dtrace_getufpstack(uint64_t *pcstack, uint64_t *fpstack, int pcstack_limit)
340 {
341 	proc_t *p = curproc;
342 	struct trapframe *tf;
343 	uintptr_t pc, sp;
344 	volatile uint16_t *flags =
345 	    (volatile uint16_t *)&cpu_core[curcpu].cpuc_dtrace_flags;
346 #ifdef notyet	/* XXX signal stack */
347 	uintptr_t oldcontext;
348 	size_t s1, s2;
349 #endif
350 
351 	if (*flags & CPU_DTRACE_FAULT)
352 		return;
353 
354 	if (pcstack_limit <= 0)
355 		return;
356 
357 	/*
358 	 * If there's no user context we still need to zero the stack.
359 	 */
360 	if (p == NULL || (tf = curthread->td_frame) == NULL)
361 		goto zero;
362 
363 	*pcstack++ = (uint64_t)p->p_pid;
364 	pcstack_limit--;
365 
366 	if (pcstack_limit <= 0)
367 		return;
368 
369 	pc = tf->srr0;
370 	sp = tf->fixreg[1];
371 
372 #ifdef notyet /* XXX signal stack */
373 	oldcontext = lwp->lwp_oldcontext;
374 	s1 = sizeof (struct xframe) + 2 * sizeof (long);
375 	s2 = s1 + sizeof (siginfo_t);
376 #endif
377 
378 	if (DTRACE_CPUFLAG_ISSET(CPU_DTRACE_ENTRY)) {
379 		*pcstack++ = (uint64_t)pc;
380 		*fpstack++ = 0;
381 		pcstack_limit--;
382 		if (pcstack_limit <= 0)
383 			return;
384 
385 		if (SV_PROC_FLAG(p, SV_ILP32)) {
386 			pc = dtrace_fuword32((void *)sp);
387 		}
388 		else {
389 			pc = dtrace_fuword64((void *)sp);
390 		}
391 	}
392 
393 	while (pc != 0) {
394 		*pcstack++ = (uint64_t)pc;
395 		*fpstack++ = sp;
396 		pcstack_limit--;
397 		if (pcstack_limit <= 0)
398 			break;
399 
400 		if (sp == 0)
401 			break;
402 
403 #ifdef notyet /* XXX signal stack */
404 		if (oldcontext == sp + s1 || oldcontext == sp + s2) {
405 			ucontext_t *ucp = (ucontext_t *)oldcontext;
406 			greg_t *gregs = ucp->uc_mcontext.gregs;
407 
408 			sp = dtrace_fulword(&gregs[REG_FP]);
409 			pc = dtrace_fulword(&gregs[REG_PC]);
410 
411 			oldcontext = dtrace_fulword(&ucp->uc_link);
412 		} else
413 #endif /* XXX */
414 		{
415 			if (SV_PROC_FLAG(p, SV_ILP32)) {
416 				pc = dtrace_fuword32((void *)(sp + RETURN_OFFSET));
417 				sp = dtrace_fuword32((void *)sp);
418 			}
419 			else {
420 				pc = dtrace_fuword64((void *)(sp + RETURN_OFFSET64));
421 				sp = dtrace_fuword64((void *)sp);
422 			}
423 		}
424 
425 		/*
426 		 * This is totally bogus:  if we faulted, we're going to clear
427 		 * the fault and break.  This is to deal with the apparently
428 		 * broken Java stacks on x86.
429 		 */
430 		if (*flags & CPU_DTRACE_FAULT) {
431 			*flags &= ~CPU_DTRACE_FAULT;
432 			break;
433 		}
434 	}
435 
436 zero:
437 	while (pcstack_limit-- > 0)
438 		*pcstack++ = 0;
439 }
440 
441 /*ARGSUSED*/
442 uint64_t
443 dtrace_getarg(int arg, int aframes)
444 {
445 	uintptr_t val;
446 	uintptr_t *fp = (uintptr_t *)dtrace_getfp();
447 	uintptr_t *stack;
448 	int i;
449 
450 	/*
451 	 * A total of 8 arguments are passed via registers; any argument with
452 	 * index of 7 or lower is therefore in a register.
453 	 */
454 	int inreg = 7;
455 
456 	for (i = 1; i <= aframes; i++) {
457 		fp = (uintptr_t *)*fp;
458 
459 		/*
460 		 * On ppc32 AIM, and booke, trapexit() is the immediately following
461 		 * label.  On ppc64 AIM trapexit() follows a nop.
462 		 */
463 #ifdef __powerpc64__
464 		if ((long)(fp[2]) + 4 == (long)trapexit) {
465 #else
466 		if ((long)(fp[1]) == (long)trapexit) {
467 #endif
468 			/*
469 			 * In the case of powerpc, we will use the pointer to the regs
470 			 * structure that was pushed when we took the trap.  To get this
471 			 * structure, we must increment beyond the frame structure.  If the
472 			 * argument that we're seeking is passed on the stack, we'll pull
473 			 * the true stack pointer out of the saved registers and decrement
474 			 * our argument by the number of arguments passed in registers; if
475 			 * the argument we're seeking is passed in regsiters, we can just
476 			 * load it directly.
477 			 */
478 #ifdef __powerpc64__
479 			struct reg *rp = (struct reg *)((uintptr_t)fp[0] + 48);
480 #else
481 			struct reg *rp = (struct reg *)((uintptr_t)fp[0] + 8);
482 #endif
483 
484 			if (arg <= inreg) {
485 				stack = &rp->fixreg[3];
486 			} else {
487 				stack = (uintptr_t *)(rp->fixreg[1]);
488 				arg -= inreg;
489 			}
490 			goto load;
491 		}
492 
493 	}
494 
495 	/*
496 	 * We know that we did not come through a trap to get into
497 	 * dtrace_probe() -- the provider simply called dtrace_probe()
498 	 * directly.  As this is the case, we need to shift the argument
499 	 * that we're looking for:  the probe ID is the first argument to
500 	 * dtrace_probe(), so the argument n will actually be found where
501 	 * one would expect to find argument (n + 1).
502 	 */
503 	arg++;
504 
505 	if (arg <= inreg) {
506 		/*
507 		 * This shouldn't happen.  If the argument is passed in a
508 		 * register then it should have been, well, passed in a
509 		 * register...
510 		 */
511 		DTRACE_CPUFLAG_SET(CPU_DTRACE_ILLOP);
512 		return (0);
513 	}
514 
515 	arg -= (inreg + 1);
516 	stack = fp + 2;
517 
518 load:
519 	DTRACE_CPUFLAG_SET(CPU_DTRACE_NOFAULT);
520 	val = stack[arg];
521 	DTRACE_CPUFLAG_CLEAR(CPU_DTRACE_NOFAULT);
522 
523 	return (val);
524 }
525 
526 int
527 dtrace_getstackdepth(int aframes)
528 {
529 	int depth = 0;
530 	uintptr_t osp, sp;
531 	vm_offset_t callpc;
532 
533 	osp = PAGE_SIZE;
534 	aframes++;
535 	sp = dtrace_getfp();
536 	depth++;
537 	for(;;) {
538 		if (sp <= osp)
539 			break;
540 
541 		if (!dtrace_sp_inkernel(sp))
542 			break;
543 
544 		if (aframes == 0)
545 			depth++;
546 		else
547 			aframes--;
548 		osp = sp;
549 		sp = dtrace_next_sp(sp);
550 	}
551 	if (depth < aframes)
552 		return (0);
553 
554 	return (depth);
555 }
556 
557 ulong_t
558 dtrace_getreg(struct trapframe *rp, uint_t reg)
559 {
560 	if (reg < 32)
561 		return (rp->fixreg[reg]);
562 
563 	switch (reg) {
564 	case 33:
565 		return (rp->lr);
566 	case 34:
567 		return (rp->cr);
568 	case 35:
569 		return (rp->xer);
570 	case 36:
571 		return (rp->ctr);
572 	case 37:
573 		return (rp->srr0);
574 	case 38:
575 		return (rp->srr1);
576 	case 39:
577 		return (rp->exc);
578 	default:
579 		DTRACE_CPUFLAG_SET(CPU_DTRACE_ILLOP);
580 		return (0);
581 	}
582 }
583 
584 static int
585 dtrace_copycheck(uintptr_t uaddr, uintptr_t kaddr, size_t size)
586 {
587 	ASSERT(INKERNEL(kaddr) && kaddr + size >= kaddr);
588 
589 	if (uaddr + size > VM_MAXUSER_ADDRESS || uaddr + size < uaddr) {
590 		DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR);
591 		cpu_core[curcpu].cpuc_dtrace_illval = uaddr;
592 		return (0);
593 	}
594 
595 	return (1);
596 }
597 
598 void
599 dtrace_copyin(uintptr_t uaddr, uintptr_t kaddr, size_t size,
600     volatile uint16_t *flags)
601 {
602 	if (dtrace_copycheck(uaddr, kaddr, size))
603 		if (copyin((const void *)uaddr, (void *)kaddr, size)) {
604 			DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR);
605 			cpu_core[curcpu].cpuc_dtrace_illval = (uintptr_t)uaddr;
606 		}
607 }
608 
609 void
610 dtrace_copyout(uintptr_t kaddr, uintptr_t uaddr, size_t size,
611     volatile uint16_t *flags)
612 {
613 	if (dtrace_copycheck(uaddr, kaddr, size)) {
614 		if (copyout((const void *)kaddr, (void *)uaddr, size)) {
615 			DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR);
616 			cpu_core[curcpu].cpuc_dtrace_illval = (uintptr_t)uaddr;
617 		}
618 	}
619 }
620 
621 void
622 dtrace_copyinstr(uintptr_t uaddr, uintptr_t kaddr, size_t size,
623     volatile uint16_t *flags)
624 {
625 	size_t actual;
626 	int    error;
627 
628 	if (dtrace_copycheck(uaddr, kaddr, size)) {
629 		error = copyinstr((const void *)uaddr, (void *)kaddr,
630 		    size, &actual);
631 
632 		/* ENAMETOOLONG is not a fault condition. */
633 		if (error && error != ENAMETOOLONG) {
634 			DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR);
635 			cpu_core[curcpu].cpuc_dtrace_illval = (uintptr_t)uaddr;
636 		}
637 	}
638 }
639 
640 /*
641  * The bulk of this function could be replaced to match dtrace_copyinstr()
642  * if we ever implement a copyoutstr().
643  */
644 void
645 dtrace_copyoutstr(uintptr_t kaddr, uintptr_t uaddr, size_t size,
646     volatile uint16_t *flags)
647 {
648 	size_t len;
649 
650 	if (dtrace_copycheck(uaddr, kaddr, size)) {
651 		len = strlen((const char *)kaddr);
652 		if (len > size)
653 			len = size;
654 
655 		if (copyout((const void *)kaddr, (void *)uaddr, len)) {
656 			DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR);
657 			cpu_core[curcpu].cpuc_dtrace_illval = (uintptr_t)uaddr;
658 		}
659 	}
660 }
661 
662 uint8_t
663 dtrace_fuword8(void *uaddr)
664 {
665 	if ((uintptr_t)uaddr > VM_MAXUSER_ADDRESS) {
666 		DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR);
667 		cpu_core[curcpu].cpuc_dtrace_illval = (uintptr_t)uaddr;
668 		return (0);
669 	}
670 	return (fubyte(uaddr));
671 }
672 
673 uint16_t
674 dtrace_fuword16(void *uaddr)
675 {
676 	uint16_t ret = 0;
677 
678 	if (dtrace_copycheck((uintptr_t)uaddr, (uintptr_t)&ret, sizeof(ret))) {
679 		if (copyin((const void *)uaddr, (void *)&ret, sizeof(ret))) {
680 			DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR);
681 			cpu_core[curcpu].cpuc_dtrace_illval = (uintptr_t)uaddr;
682 		}
683 	}
684 	return ret;
685 }
686 
687 uint32_t
688 dtrace_fuword32(void *uaddr)
689 {
690 	if ((uintptr_t)uaddr > VM_MAXUSER_ADDRESS) {
691 		DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR);
692 		cpu_core[curcpu].cpuc_dtrace_illval = (uintptr_t)uaddr;
693 		return (0);
694 	}
695 	return (fuword32(uaddr));
696 }
697 
698 uint64_t
699 dtrace_fuword64(void *uaddr)
700 {
701 	uint64_t ret = 0;
702 
703 	if (dtrace_copycheck((uintptr_t)uaddr, (uintptr_t)&ret, sizeof(ret))) {
704 		if (copyin((const void *)uaddr, (void *)&ret, sizeof(ret))) {
705 			DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR);
706 			cpu_core[curcpu].cpuc_dtrace_illval = (uintptr_t)uaddr;
707 		}
708 	}
709 	return ret;
710 }
711 
712 uintptr_t
713 dtrace_fulword(void *uaddr)
714 {
715 	uintptr_t ret = 0;
716 
717 	if (dtrace_copycheck((uintptr_t)uaddr, (uintptr_t)&ret, sizeof(ret))) {
718 		if (copyin((const void *)uaddr, (void *)&ret, sizeof(ret))) {
719 			DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR);
720 			cpu_core[curcpu].cpuc_dtrace_illval = (uintptr_t)uaddr;
721 		}
722 	}
723 	return ret;
724 }
725