include: gcc 7's cpp has problems with the line continuations in .x files
[unleashed.git] / kernel / os / watchpoint.c
blob04681532a88eef567ec81f1c0a43e1ab2f9b4f90
1 /*
2 * CDDL HEADER START
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.
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.
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]
20 * CDDL HEADER END
23 * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 #include <sys/types.h>
28 #include <sys/t_lock.h>
29 #include <sys/param.h>
30 #include <sys/cred.h>
31 #include <sys/debug.h>
32 #include <sys/inline.h>
33 #include <sys/kmem.h>
34 #include <sys/proc.h>
35 #include <sys/regset.h>
36 #include <sys/sysmacros.h>
37 #include <sys/systm.h>
38 #include <sys/prsystm.h>
39 #include <sys/buf.h>
40 #include <sys/signal.h>
41 #include <sys/user.h>
42 #include <sys/cpuvar.h>
44 #include <sys/fault.h>
45 #include <sys/syscall.h>
46 #include <sys/procfs.h>
47 #include <sys/cmn_err.h>
48 #include <sys/stack.h>
49 #include <sys/watchpoint.h>
50 #include <sys/copyops.h>
51 #include <sys/schedctl.h>
53 #include <sys/mman.h>
54 #include <vm/as.h>
55 #include <vm/seg.h>
58 * Copy ops vector for watchpoints.
60 static int watch_copyin(const void *, void *, size_t);
61 static int watch_xcopyin(const void *, void *, size_t);
62 static int watch_copyout(const void *, void *, size_t);
63 static int watch_xcopyout(const void *, void *, size_t);
64 static int watch_copyinstr(const char *, char *, size_t, size_t *);
65 static int watch_copyoutstr(const char *, char *, size_t, size_t *);
66 static int watch_fuword8(const void *, uint8_t *);
67 static int watch_fuword16(const void *, uint16_t *);
68 static int watch_fuword32(const void *, uint32_t *);
69 static int watch_suword8(void *, uint8_t);
70 static int watch_suword16(void *, uint16_t);
71 static int watch_suword32(void *, uint32_t);
72 static int watch_physio(int (*)(struct buf *), struct buf *,
73 dev_t, int, void (*)(struct buf *), struct uio *);
74 #ifdef _LP64
75 static int watch_fuword64(const void *, uint64_t *);
76 static int watch_suword64(void *, uint64_t);
77 #endif
79 struct copyops watch_copyops = {
80 watch_copyin,
81 watch_xcopyin,
82 watch_copyout,
83 watch_xcopyout,
84 watch_copyinstr,
85 watch_copyoutstr,
86 watch_fuword8,
87 watch_fuword16,
88 watch_fuword32,
89 #ifdef _LP64
90 watch_fuword64,
91 #else
92 NULL,
93 #endif
94 watch_suword8,
95 watch_suword16,
96 watch_suword32,
97 #ifdef _LP64
98 watch_suword64,
99 #else
100 NULL,
101 #endif
102 watch_physio
106 * Map the 'rw' argument to a protection flag.
108 static int
109 rw_to_prot(enum seg_rw rw)
111 switch (rw) {
112 case S_EXEC:
113 return (PROT_EXEC);
114 case S_READ:
115 return (PROT_READ);
116 case S_WRITE:
117 return (PROT_WRITE);
118 default:
119 return (PROT_NONE); /* can't happen */
124 * Map the 'rw' argument to an index into an array of exec/write/read things.
125 * The index follows the precedence order: exec .. write .. read
127 static int
128 rw_to_index(enum seg_rw rw)
130 switch (rw) {
131 default: /* default case "can't happen" */
132 case S_EXEC:
133 return (0);
134 case S_WRITE:
135 return (1);
136 case S_READ:
137 return (2);
142 * Map an index back to a seg_rw.
144 static enum seg_rw S_rw[4] = {
145 S_EXEC,
146 S_WRITE,
147 S_READ,
148 S_READ,
151 #define X 0
152 #define W 1
153 #define R 2
154 #define sum(a) (a[X] + a[W] + a[R])
157 * Common code for pr_mappage() and pr_unmappage().
159 static int
160 pr_do_mappage(caddr_t addr, size_t size, int mapin, enum seg_rw rw, int kernel)
162 proc_t *p = curproc;
163 struct as *as = p->p_as;
164 char *eaddr = addr + size;
165 int prot_rw = rw_to_prot(rw);
166 int xrw = rw_to_index(rw);
167 int rv = 0;
168 struct watched_page *pwp;
169 struct watched_page tpw;
170 avl_index_t where;
171 uint_t prot;
173 ASSERT(as != &kas);
175 startover:
176 ASSERT(rv == 0);
177 if (avl_numnodes(&as->a_wpage) == 0)
178 return (0);
181 * as->a_wpage can only be changed while the process is totally stopped.
182 * Don't grab p_lock here. Holding p_lock while grabbing the address
183 * space lock leads to deadlocks with the clock thread.
185 * p_maplock prevents simultaneous execution of this function. Under
186 * normal circumstances, holdwatch() will stop all other threads, so the
187 * lock isn't really needed. But there may be multiple threads within
188 * stop() when SWATCHOK is set, so we need to handle multiple threads
189 * at once. See holdwatch() for the details of this dance.
192 mutex_enter(&p->p_maplock);
194 tpw.wp_vaddr = (caddr_t)((uintptr_t)addr & (uintptr_t)PAGEMASK);
195 if ((pwp = avl_find(&as->a_wpage, &tpw, &where)) == NULL)
196 pwp = avl_nearest(&as->a_wpage, where, AVL_AFTER);
198 for (; pwp != NULL && pwp->wp_vaddr < eaddr;
199 pwp = AVL_NEXT(&as->a_wpage, pwp)) {
202 * If the requested protection has not been
203 * removed, we need not remap this page.
205 prot = pwp->wp_prot;
206 if (kernel || (prot & PROT_USER))
207 if (prot & prot_rw)
208 continue;
210 * If the requested access does not exist in the page's
211 * original protections, we need not remap this page.
212 * If the page does not exist yet, we can't test it.
214 if ((prot = pwp->wp_oprot) != 0) {
215 if (!(kernel || (prot & PROT_USER)))
216 continue;
217 if (!(prot & prot_rw))
218 continue;
221 if (mapin) {
223 * Before mapping the page in, ensure that
224 * all other lwps are held in the kernel.
226 if (p->p_mapcnt == 0) {
227 mutex_exit(&p->p_maplock);
228 if (holdwatch() != 0) {
230 * We stopped in holdwatch().
231 * Start all over again because the
232 * watched page list may have changed.
234 goto startover;
236 mutex_enter(&p->p_maplock);
238 p->p_mapcnt++;
241 addr = pwp->wp_vaddr;
242 rv++;
244 prot = pwp->wp_prot;
245 if (mapin) {
246 if (kernel)
247 pwp->wp_kmap[xrw]++;
248 else
249 pwp->wp_umap[xrw]++;
250 pwp->wp_flags |= WP_NOWATCH;
251 if (pwp->wp_kmap[X] + pwp->wp_umap[X])
252 /* cannot have exec-only protection */
253 prot |= PROT_READ|PROT_EXEC;
254 if (pwp->wp_kmap[R] + pwp->wp_umap[R])
255 prot |= PROT_READ;
256 if (pwp->wp_kmap[W] + pwp->wp_umap[W])
257 /* cannot have write-only protection */
258 prot |= PROT_READ|PROT_WRITE;
259 #if 0 /* damned broken mmu feature! */
260 if (sum(pwp->wp_umap) == 0)
261 prot &= ~PROT_USER;
262 #endif
263 } else {
264 ASSERT(pwp->wp_flags & WP_NOWATCH);
265 if (kernel) {
266 ASSERT(pwp->wp_kmap[xrw] != 0);
267 --pwp->wp_kmap[xrw];
268 } else {
269 ASSERT(pwp->wp_umap[xrw] != 0);
270 --pwp->wp_umap[xrw];
272 if (sum(pwp->wp_kmap) + sum(pwp->wp_umap) == 0)
273 pwp->wp_flags &= ~WP_NOWATCH;
274 else {
275 if (pwp->wp_kmap[X] + pwp->wp_umap[X])
276 /* cannot have exec-only protection */
277 prot |= PROT_READ|PROT_EXEC;
278 if (pwp->wp_kmap[R] + pwp->wp_umap[R])
279 prot |= PROT_READ;
280 if (pwp->wp_kmap[W] + pwp->wp_umap[W])
281 /* cannot have write-only protection */
282 prot |= PROT_READ|PROT_WRITE;
283 #if 0 /* damned broken mmu feature! */
284 if (sum(pwp->wp_umap) == 0)
285 prot &= ~PROT_USER;
286 #endif
291 if (pwp->wp_oprot != 0) { /* if page exists */
292 struct seg *seg;
293 uint_t oprot;
294 int err, retrycnt = 0;
296 AS_LOCK_ENTER(as, RW_WRITER);
297 retry:
298 seg = as_segat(as, addr);
299 ASSERT(seg != NULL);
300 (void) segop_getprot(seg, addr, 0, &oprot);
301 if (prot != oprot) {
302 err = segop_setprot(seg, addr, PAGESIZE, prot);
303 if (err == IE_RETRY) {
304 ASSERT(retrycnt == 0);
305 retrycnt++;
306 goto retry;
309 AS_LOCK_EXIT(as);
313 * When all pages are mapped back to their normal state,
314 * continue the other lwps.
316 if (!mapin) {
317 ASSERT(p->p_mapcnt > 0);
318 p->p_mapcnt--;
319 if (p->p_mapcnt == 0) {
320 mutex_exit(&p->p_maplock);
321 mutex_enter(&p->p_lock);
322 continuelwps(p);
323 mutex_exit(&p->p_lock);
324 mutex_enter(&p->p_maplock);
329 mutex_exit(&p->p_maplock);
331 return (rv);
335 * Restore the original page protections on an address range.
336 * If 'kernel' is non-zero, just do it for the kernel.
337 * pr_mappage() returns non-zero if it actually changed anything.
339 * pr_mappage() and pr_unmappage() must be executed in matched pairs,
340 * but pairs may be nested within other pairs. The reference counts
341 * sort it all out. See pr_do_mappage(), above.
343 static int
344 pr_mappage(const caddr_t addr, size_t size, enum seg_rw rw, int kernel)
346 return (pr_do_mappage(addr, size, 1, rw, kernel));
350 * Set the modified page protections on a watched page.
351 * Inverse of pr_mappage().
352 * Needs to be called only if pr_mappage() returned non-zero.
354 static void
355 pr_unmappage(const caddr_t addr, size_t size, enum seg_rw rw, int kernel)
357 (void) pr_do_mappage(addr, size, 0, rw, kernel);
361 * Function called by an lwp after it resumes from stop().
363 void
364 setallwatch(void)
366 proc_t *p = curproc;
367 struct as *as = curproc->p_as;
368 struct watched_page *pwp, *next;
369 struct seg *seg;
370 caddr_t vaddr;
371 uint_t prot;
372 int err, retrycnt;
374 if (p->p_wprot == NULL)
375 return;
377 ASSERT(MUTEX_NOT_HELD(&curproc->p_lock));
379 AS_LOCK_ENTER(as, RW_WRITER);
381 pwp = p->p_wprot;
382 while (pwp != NULL) {
384 vaddr = pwp->wp_vaddr;
385 retrycnt = 0;
386 retry:
387 ASSERT(pwp->wp_flags & WP_SETPROT);
388 if ((seg = as_segat(as, vaddr)) != NULL &&
389 !(pwp->wp_flags & WP_NOWATCH)) {
390 prot = pwp->wp_prot;
391 err = segop_setprot(seg, vaddr, PAGESIZE, prot);
392 if (err == IE_RETRY) {
393 ASSERT(retrycnt == 0);
394 retrycnt++;
395 goto retry;
399 next = pwp->wp_list;
401 if (pwp->wp_read + pwp->wp_write + pwp->wp_exec == 0) {
403 * No watched areas remain in this page.
404 * Free the watched_page structure.
406 avl_remove(&as->a_wpage, pwp);
407 kmem_free(pwp, sizeof (struct watched_page));
408 } else {
409 pwp->wp_flags &= ~WP_SETPROT;
412 pwp = next;
414 p->p_wprot = NULL;
416 AS_LOCK_EXIT(as);
422 pr_is_watchpage_as(caddr_t addr, enum seg_rw rw, struct as *as)
424 register struct watched_page *pwp;
425 struct watched_page tpw;
426 uint_t prot;
427 int rv = 0;
429 switch (rw) {
430 case S_READ:
431 case S_WRITE:
432 case S_EXEC:
433 break;
434 default:
435 return (0);
439 * as->a_wpage can only be modified while the process is totally
440 * stopped. We need, and should use, no locks here.
442 if (as != &kas && avl_numnodes(&as->a_wpage) != 0) {
443 tpw.wp_vaddr = (caddr_t)((uintptr_t)addr & (uintptr_t)PAGEMASK);
444 pwp = avl_find(&as->a_wpage, &tpw, NULL);
445 if (pwp != NULL) {
446 ASSERT(addr >= pwp->wp_vaddr &&
447 addr < pwp->wp_vaddr + PAGESIZE);
448 if (pwp->wp_oprot != 0) {
449 prot = pwp->wp_prot;
450 switch (rw) {
451 case S_READ:
452 rv = ((prot & (PROT_USER|PROT_READ))
453 != (PROT_USER|PROT_READ));
454 break;
455 case S_WRITE:
456 rv = ((prot & (PROT_USER|PROT_WRITE))
457 != (PROT_USER|PROT_WRITE));
458 break;
459 case S_EXEC:
460 rv = ((prot & (PROT_USER|PROT_EXEC))
461 != (PROT_USER|PROT_EXEC));
462 break;
463 default:
464 /* can't happen! */
465 break;
471 return (rv);
476 * trap() calls here to determine if a fault is in a watched page.
477 * We return nonzero if this is true and the load/store would fail.
480 pr_is_watchpage(caddr_t addr, enum seg_rw rw)
482 struct as *as = curproc->p_as;
484 if ((as == &kas) || avl_numnodes(&as->a_wpage) == 0)
485 return (0);
487 return (pr_is_watchpage_as(addr, rw, as));
493 * trap() calls here to determine if a fault is a watchpoint.
496 pr_is_watchpoint(caddr_t *paddr, int *pta, size_t size, size_t *plen,
497 enum seg_rw rw)
499 proc_t *p = curproc;
500 caddr_t addr = *paddr;
501 caddr_t eaddr = addr + size;
502 register struct watched_area *pwa;
503 struct watched_area twa;
504 int rv = 0;
505 int ta = 0;
506 size_t len = 0;
508 switch (rw) {
509 case S_READ:
510 case S_WRITE:
511 case S_EXEC:
512 break;
513 default:
514 *pta = 0;
515 return (0);
519 * p->p_warea is protected by p->p_lock.
521 mutex_enter(&p->p_lock);
523 /* BEGIN CSTYLED */
525 * This loop is somewhat complicated because the fault region can span
526 * multiple watched areas. For example:
528 * addr eaddr
529 * +-----------------+
530 * | fault region |
531 * +-------+--------+----+---+------------+
532 * | prot not right | | prot correct |
533 * +----------------+ +----------------+
534 * wa_vaddr wa_eaddr
535 * wa_vaddr wa_eaddr
537 * We start at the area greater than or equal to the starting address.
538 * As long as some portion of the fault region overlaps the current
539 * area, we continue checking permissions until we find an appropriate
540 * match.
542 /* END CSTYLED */
543 twa.wa_vaddr = addr;
544 twa.wa_eaddr = eaddr;
546 for (pwa = pr_find_watched_area(p, &twa, NULL);
547 pwa != NULL && eaddr > pwa->wa_vaddr && addr < pwa->wa_eaddr;
548 pwa = AVL_NEXT(&p->p_warea, pwa)) {
550 switch (rw) {
551 case S_READ:
552 if (pwa->wa_flags & WA_READ)
553 rv = TRAP_RWATCH;
554 break;
555 case S_WRITE:
556 if (pwa->wa_flags & WA_WRITE)
557 rv = TRAP_WWATCH;
558 break;
559 case S_EXEC:
560 if (pwa->wa_flags & WA_EXEC)
561 rv = TRAP_XWATCH;
562 break;
563 default:
564 /* can't happen */
565 break;
569 * If protections didn't match, check the next watched
570 * area
572 if (rv != 0) {
573 if (addr < pwa->wa_vaddr)
574 addr = pwa->wa_vaddr;
575 len = pwa->wa_eaddr - addr;
576 if (pwa->wa_flags & WA_TRAPAFTER)
577 ta = 1;
578 break;
582 mutex_exit(&p->p_lock);
584 *paddr = addr;
585 *pta = ta;
586 if (plen != NULL)
587 *plen = len;
588 return (rv);
592 * Set up to perform a single-step at user level for the
593 * case of a trapafter watchpoint. Called from trap().
595 void
596 do_watch_step(caddr_t vaddr, size_t sz, enum seg_rw rw,
597 int watchcode, greg_t pc)
599 register klwp_t *lwp = ttolwp(curthread);
600 struct lwp_watch *pw = &lwp->lwp_watch[rw_to_index(rw)];
603 * Check to see if we are already performing this special
604 * watchpoint single-step. We must not do pr_mappage() twice.
607 /* special check for two read traps on the same instruction */
608 if (rw == S_READ && pw->wpaddr != NULL &&
609 !(pw->wpaddr <= vaddr && vaddr < pw->wpaddr + pw->wpsize)) {
610 ASSERT(lwp->lwp_watchtrap != 0);
611 pw++; /* use the extra S_READ struct */
614 if (pw->wpaddr != NULL) {
615 ASSERT(lwp->lwp_watchtrap != 0);
616 ASSERT(pw->wpaddr <= vaddr && vaddr < pw->wpaddr + pw->wpsize);
617 if (pw->wpcode == 0) {
618 pw->wpcode = watchcode;
619 pw->wppc = pc;
621 } else {
622 int mapped = pr_mappage(vaddr, sz, rw, 0);
623 prstep(lwp, 1);
624 lwp->lwp_watchtrap = 1;
625 pw->wpaddr = vaddr;
626 pw->wpsize = sz;
627 pw->wpcode = watchcode;
628 pw->wpmapped = mapped;
629 pw->wppc = pc;
634 * Undo the effects of do_watch_step().
635 * Called from trap() after the single-step is finished.
636 * Also called from issig_forreal() and stop() with a NULL
637 * argument to avoid having these things set more than once.
640 undo_watch_step(k_siginfo_t *sip)
642 register klwp_t *lwp = ttolwp(curthread);
643 int fault = 0;
645 if (lwp->lwp_watchtrap) {
646 struct lwp_watch *pw = lwp->lwp_watch;
647 int i;
649 for (i = 0; i < 4; i++, pw++) {
650 if (pw->wpaddr == NULL)
651 continue;
652 if (pw->wpmapped)
653 pr_unmappage(pw->wpaddr, pw->wpsize, S_rw[i],
655 if (pw->wpcode != 0) {
656 if (sip != NULL) {
657 sip->si_signo = SIGTRAP;
658 sip->si_code = pw->wpcode;
659 sip->si_addr = pw->wpaddr;
660 sip->si_trapafter = 1;
661 sip->si_pc = (caddr_t)pw->wppc;
663 fault = FLTWATCH;
664 pw->wpcode = 0;
666 pw->wpaddr = NULL;
667 pw->wpsize = 0;
668 pw->wpmapped = 0;
670 lwp->lwp_watchtrap = 0;
673 return (fault);
677 * Handle a watchpoint that occurs while doing copyin()
678 * or copyout() in a system call.
679 * Return non-zero if the fault or signal is cleared
680 * by a debugger while the lwp is stopped.
682 static int
683 sys_watchpoint(caddr_t addr, int watchcode, int ta)
685 extern greg_t getuserpc(void); /* XXX header file */
686 k_sigset_t smask;
687 register proc_t *p = ttoproc(curthread);
688 register klwp_t *lwp = ttolwp(curthread);
689 register sigqueue_t *sqp;
690 int rval;
692 /* assert no locks are held */
693 /* ASSERT(curthread->t_nlocks == 0); */
695 sqp = kmem_zalloc(sizeof (sigqueue_t), KM_SLEEP);
696 sqp->sq_info.si_signo = SIGTRAP;
697 sqp->sq_info.si_code = watchcode;
698 sqp->sq_info.si_addr = addr;
699 sqp->sq_info.si_trapafter = ta;
700 sqp->sq_info.si_pc = (caddr_t)getuserpc();
702 mutex_enter(&p->p_lock);
704 /* this will be tested and cleared by the caller */
705 lwp->lwp_sysabort = 0;
707 if (prismember(&p->p_fltmask, FLTWATCH)) {
708 lwp->lwp_curflt = (uchar_t)FLTWATCH;
709 lwp->lwp_siginfo = sqp->sq_info;
710 stop(PR_FAULTED, FLTWATCH);
711 if (lwp->lwp_curflt == 0) {
712 mutex_exit(&p->p_lock);
713 kmem_free(sqp, sizeof (sigqueue_t));
714 return (1);
716 lwp->lwp_curflt = 0;
720 * post the SIGTRAP signal.
721 * Block all other signals so we only stop showing SIGTRAP.
723 if (signal_is_blocked(curthread, SIGTRAP) ||
724 sigismember(&p->p_ignore, SIGTRAP)) {
725 /* SIGTRAP is blocked or ignored, forget the rest. */
726 mutex_exit(&p->p_lock);
727 kmem_free(sqp, sizeof (sigqueue_t));
728 return (0);
730 sigdelq(p, curthread, SIGTRAP);
731 sigaddqa(p, curthread, sqp);
732 schedctl_finish_sigblock(curthread);
733 smask = curthread->t_hold;
734 sigfillset(&curthread->t_hold);
735 sigdiffset(&curthread->t_hold, &cantmask);
736 sigdelset(&curthread->t_hold, SIGTRAP);
737 mutex_exit(&p->p_lock);
739 rval = ((ISSIG_FAST(curthread, lwp, p, FORREAL))? 0 : 1);
741 /* restore the original signal mask */
742 mutex_enter(&p->p_lock);
743 curthread->t_hold = smask;
744 mutex_exit(&p->p_lock);
746 return (rval);
750 * Wrappers for the copyin()/copyout() functions to deal
751 * with watchpoints that fire while in system calls.
754 static int
755 watch_xcopyin(const void *uaddr, void *kaddr, size_t count)
757 klwp_t *lwp = ttolwp(curthread);
758 caddr_t watch_uaddr = (caddr_t)uaddr;
759 caddr_t watch_kaddr = (caddr_t)kaddr;
760 int error = 0;
761 label_t ljb;
762 size_t part;
763 int mapped;
765 while (count && error == 0) {
766 int watchcode;
767 caddr_t vaddr;
768 size_t len;
769 int ta;
771 if ((part = PAGESIZE -
772 (((uintptr_t)uaddr) & PAGEOFFSET)) > count)
773 part = count;
775 if (!pr_is_watchpage(watch_uaddr, S_READ))
776 watchcode = 0;
777 else {
778 vaddr = watch_uaddr;
779 watchcode = pr_is_watchpoint(&vaddr, &ta,
780 part, &len, S_READ);
781 if (watchcode && ta == 0)
782 part = vaddr - watch_uaddr;
786 * Copy the initial part, up to a watched address, if any.
788 if (part != 0) {
789 mapped = pr_mappage(watch_uaddr, part, S_READ, 1);
790 if (on_fault(&ljb))
791 error = EFAULT;
792 else
793 copyin_noerr(watch_uaddr, watch_kaddr, part);
794 no_fault();
795 if (mapped)
796 pr_unmappage(watch_uaddr, part, S_READ, 1);
797 watch_uaddr += part;
798 watch_kaddr += part;
799 count -= part;
802 * If trapafter was specified, then copy through the
803 * watched area before taking the watchpoint trap.
805 while (count && watchcode && ta && len > part && error == 0) {
806 len -= part;
807 if ((part = PAGESIZE) > count)
808 part = count;
809 if (part > len)
810 part = len;
811 mapped = pr_mappage(watch_uaddr, part, S_READ, 1);
812 if (on_fault(&ljb))
813 error = EFAULT;
814 else
815 copyin_noerr(watch_uaddr, watch_kaddr, part);
816 no_fault();
817 if (mapped)
818 pr_unmappage(watch_uaddr, part, S_READ, 1);
819 watch_uaddr += part;
820 watch_kaddr += part;
821 count -= part;
824 error:
825 /* if we hit a watched address, do the watchpoint logic */
826 if (watchcode &&
827 (!sys_watchpoint(vaddr, watchcode, ta) ||
828 lwp->lwp_sysabort)) {
829 lwp->lwp_sysabort = 0;
830 error = EFAULT;
831 break;
835 return (error);
838 static int
839 watch_copyin(const void *kaddr, void *uaddr, size_t count)
841 return (watch_xcopyin(kaddr, uaddr, count) ? -1 : 0);
845 static int
846 watch_xcopyout(const void *kaddr, void *uaddr, size_t count)
848 klwp_t *lwp = ttolwp(curthread);
849 caddr_t watch_uaddr = (caddr_t)uaddr;
850 caddr_t watch_kaddr = (caddr_t)kaddr;
851 int error = 0;
852 label_t ljb;
854 while (count && error == 0) {
855 int watchcode;
856 caddr_t vaddr;
857 size_t part;
858 size_t len;
859 int ta;
860 int mapped;
862 if ((part = PAGESIZE -
863 (((uintptr_t)uaddr) & PAGEOFFSET)) > count)
864 part = count;
866 if (!pr_is_watchpage(watch_uaddr, S_WRITE))
867 watchcode = 0;
868 else {
869 vaddr = watch_uaddr;
870 watchcode = pr_is_watchpoint(&vaddr, &ta,
871 part, &len, S_WRITE);
872 if (watchcode) {
873 if (ta == 0)
874 part = vaddr - watch_uaddr;
875 else {
876 len += vaddr - watch_uaddr;
877 if (part > len)
878 part = len;
884 * Copy the initial part, up to a watched address, if any.
886 if (part != 0) {
887 mapped = pr_mappage(watch_uaddr, part, S_WRITE, 1);
888 if (on_fault(&ljb))
889 error = EFAULT;
890 else
891 copyout_noerr(watch_kaddr, watch_uaddr, part);
892 no_fault();
893 if (mapped)
894 pr_unmappage(watch_uaddr, part, S_WRITE, 1);
895 watch_uaddr += part;
896 watch_kaddr += part;
897 count -= part;
901 * If trapafter was specified, then copy through the
902 * watched area before taking the watchpoint trap.
904 while (count && watchcode && ta && len > part && error == 0) {
905 len -= part;
906 if ((part = PAGESIZE) > count)
907 part = count;
908 if (part > len)
909 part = len;
910 mapped = pr_mappage(watch_uaddr, part, S_WRITE, 1);
911 if (on_fault(&ljb))
912 error = EFAULT;
913 else
914 copyout_noerr(watch_kaddr, watch_uaddr, part);
915 no_fault();
916 if (mapped)
917 pr_unmappage(watch_uaddr, part, S_WRITE, 1);
918 watch_uaddr += part;
919 watch_kaddr += part;
920 count -= part;
923 /* if we hit a watched address, do the watchpoint logic */
924 if (watchcode &&
925 (!sys_watchpoint(vaddr, watchcode, ta) ||
926 lwp->lwp_sysabort)) {
927 lwp->lwp_sysabort = 0;
928 error = EFAULT;
929 break;
933 return (error);
936 static int
937 watch_copyout(const void *kaddr, void *uaddr, size_t count)
939 return (watch_xcopyout(kaddr, uaddr, count) ? -1 : 0);
942 static int
943 watch_copyinstr(
944 const char *uaddr,
945 char *kaddr,
946 size_t maxlength,
947 size_t *lencopied)
949 klwp_t *lwp = ttolwp(curthread);
950 size_t resid;
951 int error = 0;
952 label_t ljb;
954 if ((resid = maxlength) == 0)
955 return (ENAMETOOLONG);
957 while (resid && error == 0) {
958 int watchcode;
959 caddr_t vaddr;
960 size_t part;
961 size_t len;
962 size_t size;
963 int ta;
964 int mapped;
966 if ((part = PAGESIZE -
967 (((uintptr_t)uaddr) & PAGEOFFSET)) > resid)
968 part = resid;
970 if (!pr_is_watchpage((caddr_t)uaddr, S_READ))
971 watchcode = 0;
972 else {
973 vaddr = (caddr_t)uaddr;
974 watchcode = pr_is_watchpoint(&vaddr, &ta,
975 part, &len, S_READ);
976 if (watchcode) {
977 if (ta == 0)
978 part = vaddr - uaddr;
979 else {
980 len += vaddr - uaddr;
981 if (part > len)
982 part = len;
988 * Copy the initial part, up to a watched address, if any.
990 if (part != 0) {
991 mapped = pr_mappage((caddr_t)uaddr, part, S_READ, 1);
992 if (on_fault(&ljb))
993 error = EFAULT;
994 else
995 error = copyinstr_noerr(uaddr, kaddr, part,
996 &size);
997 no_fault();
998 if (mapped)
999 pr_unmappage((caddr_t)uaddr, part, S_READ, 1);
1000 uaddr += size;
1001 kaddr += size;
1002 resid -= size;
1003 if (error == ENAMETOOLONG && resid > 0)
1004 error = 0;
1005 if (error != 0 || (watchcode &&
1006 (uaddr < vaddr || kaddr[-1] == '\0')))
1007 break; /* didn't reach the watched area */
1011 * If trapafter was specified, then copy through the
1012 * watched area before taking the watchpoint trap.
1014 while (resid && watchcode && ta && len > part && error == 0 &&
1015 size == part && kaddr[-1] != '\0') {
1016 len -= part;
1017 if ((part = PAGESIZE) > resid)
1018 part = resid;
1019 if (part > len)
1020 part = len;
1021 mapped = pr_mappage((caddr_t)uaddr, part, S_READ, 1);
1022 if (on_fault(&ljb))
1023 error = EFAULT;
1024 else
1025 error = copyinstr_noerr(uaddr, kaddr, part,
1026 &size);
1027 no_fault();
1028 if (mapped)
1029 pr_unmappage((caddr_t)uaddr, part, S_READ, 1);
1030 uaddr += size;
1031 kaddr += size;
1032 resid -= size;
1033 if (error == ENAMETOOLONG && resid > 0)
1034 error = 0;
1037 /* if we hit a watched address, do the watchpoint logic */
1038 if (watchcode &&
1039 (!sys_watchpoint(vaddr, watchcode, ta) ||
1040 lwp->lwp_sysabort)) {
1041 lwp->lwp_sysabort = 0;
1042 error = EFAULT;
1043 break;
1046 if (error == 0 && part != 0 &&
1047 (size < part || kaddr[-1] == '\0'))
1048 break;
1051 if (error != EFAULT && lencopied)
1052 *lencopied = maxlength - resid;
1053 return (error);
1056 static int
1057 watch_copyoutstr(
1058 const char *kaddr,
1059 char *uaddr,
1060 size_t maxlength,
1061 size_t *lencopied)
1063 klwp_t *lwp = ttolwp(curthread);
1064 size_t resid;
1065 int error = 0;
1066 label_t ljb;
1068 if ((resid = maxlength) == 0)
1069 return (ENAMETOOLONG);
1071 while (resid && error == 0) {
1072 int watchcode;
1073 caddr_t vaddr;
1074 size_t part;
1075 size_t len;
1076 size_t size;
1077 int ta;
1078 int mapped;
1080 if ((part = PAGESIZE -
1081 (((uintptr_t)uaddr) & PAGEOFFSET)) > resid)
1082 part = resid;
1084 if (!pr_is_watchpage(uaddr, S_WRITE)) {
1085 watchcode = 0;
1086 } else {
1087 vaddr = uaddr;
1088 watchcode = pr_is_watchpoint(&vaddr, &ta,
1089 part, &len, S_WRITE);
1090 if (watchcode && ta == 0)
1091 part = vaddr - uaddr;
1095 * Copy the initial part, up to a watched address, if any.
1097 if (part != 0) {
1098 mapped = pr_mappage(uaddr, part, S_WRITE, 1);
1099 if (on_fault(&ljb))
1100 error = EFAULT;
1101 else
1102 error = copyoutstr_noerr(kaddr, uaddr, part,
1103 &size);
1104 no_fault();
1105 if (mapped)
1106 pr_unmappage(uaddr, part, S_WRITE, 1);
1107 uaddr += size;
1108 kaddr += size;
1109 resid -= size;
1110 if (error == ENAMETOOLONG && resid > 0)
1111 error = 0;
1112 if (error != 0 || (watchcode &&
1113 (uaddr < vaddr || kaddr[-1] == '\0')))
1114 break; /* didn't reach the watched area */
1118 * If trapafter was specified, then copy through the
1119 * watched area before taking the watchpoint trap.
1121 while (resid && watchcode && ta && len > part && error == 0 &&
1122 size == part && kaddr[-1] != '\0') {
1123 len -= part;
1124 if ((part = PAGESIZE) > resid)
1125 part = resid;
1126 if (part > len)
1127 part = len;
1128 mapped = pr_mappage(uaddr, part, S_WRITE, 1);
1129 if (on_fault(&ljb))
1130 error = EFAULT;
1131 else
1132 error = copyoutstr_noerr(kaddr, uaddr, part,
1133 &size);
1134 no_fault();
1135 if (mapped)
1136 pr_unmappage(uaddr, part, S_WRITE, 1);
1137 uaddr += size;
1138 kaddr += size;
1139 resid -= size;
1140 if (error == ENAMETOOLONG && resid > 0)
1141 error = 0;
1144 /* if we hit a watched address, do the watchpoint logic */
1145 if (watchcode &&
1146 (!sys_watchpoint(vaddr, watchcode, ta) ||
1147 lwp->lwp_sysabort)) {
1148 lwp->lwp_sysabort = 0;
1149 error = EFAULT;
1150 break;
1153 if (error == 0 && part != 0 &&
1154 (size < part || kaddr[-1] == '\0'))
1155 break;
1158 if (error != EFAULT && lencopied)
1159 *lencopied = maxlength - resid;
1160 return (error);
1163 typedef int (*fuword_func)(const void *, void *);
1166 * Generic form of watch_fuword8(), watch_fuword16(), etc.
1168 static int
1169 watch_fuword(const void *addr, void *dst, fuword_func func, size_t size)
1171 klwp_t *lwp = ttolwp(curthread);
1172 int watchcode;
1173 caddr_t vaddr;
1174 int mapped;
1175 int rv = 0;
1176 int ta;
1177 label_t ljb;
1179 for (;;) {
1181 vaddr = (caddr_t)addr;
1182 watchcode = pr_is_watchpoint(&vaddr, &ta, size, NULL, S_READ);
1183 if (watchcode == 0 || ta != 0) {
1184 mapped = pr_mappage((caddr_t)addr, size, S_READ, 1);
1185 if (on_fault(&ljb))
1186 rv = -1;
1187 else
1188 (*func)(addr, dst);
1189 no_fault();
1190 if (mapped)
1191 pr_unmappage((caddr_t)addr, size, S_READ, 1);
1193 if (watchcode &&
1194 (!sys_watchpoint(vaddr, watchcode, ta) ||
1195 lwp->lwp_sysabort)) {
1196 lwp->lwp_sysabort = 0;
1197 rv = -1;
1198 break;
1200 if (watchcode == 0 || ta != 0)
1201 break;
1204 return (rv);
1207 static int
1208 watch_fuword8(const void *addr, uint8_t *dst)
1210 return (watch_fuword(addr, dst, (fuword_func)fuword8_noerr,
1211 sizeof (*dst)));
1214 static int
1215 watch_fuword16(const void *addr, uint16_t *dst)
1217 return (watch_fuword(addr, dst, (fuword_func)fuword16_noerr,
1218 sizeof (*dst)));
1221 static int
1222 watch_fuword32(const void *addr, uint32_t *dst)
1224 return (watch_fuword(addr, dst, (fuword_func)fuword32_noerr,
1225 sizeof (*dst)));
1228 #ifdef _LP64
1229 static int
1230 watch_fuword64(const void *addr, uint64_t *dst)
1232 return (watch_fuword(addr, dst, (fuword_func)fuword64_noerr,
1233 sizeof (*dst)));
1235 #endif
1238 static int
1239 watch_suword8(void *addr, uint8_t value)
1241 klwp_t *lwp = ttolwp(curthread);
1242 int watchcode;
1243 caddr_t vaddr;
1244 int mapped;
1245 int rv = 0;
1246 int ta;
1247 label_t ljb;
1249 for (;;) {
1251 vaddr = (caddr_t)addr;
1252 watchcode = pr_is_watchpoint(&vaddr, &ta, sizeof (value), NULL,
1253 S_WRITE);
1254 if (watchcode == 0 || ta != 0) {
1255 mapped = pr_mappage((caddr_t)addr, sizeof (value),
1256 S_WRITE, 1);
1257 if (on_fault(&ljb))
1258 rv = -1;
1259 else
1260 suword8_noerr(addr, value);
1261 no_fault();
1262 if (mapped)
1263 pr_unmappage((caddr_t)addr, sizeof (value),
1264 S_WRITE, 1);
1266 if (watchcode &&
1267 (!sys_watchpoint(vaddr, watchcode, ta) ||
1268 lwp->lwp_sysabort)) {
1269 lwp->lwp_sysabort = 0;
1270 rv = -1;
1271 break;
1273 if (watchcode == 0 || ta != 0)
1274 break;
1277 return (rv);
1280 static int
1281 watch_suword16(void *addr, uint16_t value)
1283 klwp_t *lwp = ttolwp(curthread);
1284 int watchcode;
1285 caddr_t vaddr;
1286 int mapped;
1287 int rv = 0;
1288 int ta;
1289 label_t ljb;
1291 for (;;) {
1293 vaddr = (caddr_t)addr;
1294 watchcode = pr_is_watchpoint(&vaddr, &ta, sizeof (value), NULL,
1295 S_WRITE);
1296 if (watchcode == 0 || ta != 0) {
1297 mapped = pr_mappage((caddr_t)addr, sizeof (value),
1298 S_WRITE, 1);
1299 if (on_fault(&ljb))
1300 rv = -1;
1301 else
1302 suword16_noerr(addr, value);
1303 no_fault();
1304 if (mapped)
1305 pr_unmappage((caddr_t)addr, sizeof (value),
1306 S_WRITE, 1);
1308 if (watchcode &&
1309 (!sys_watchpoint(vaddr, watchcode, ta) ||
1310 lwp->lwp_sysabort)) {
1311 lwp->lwp_sysabort = 0;
1312 rv = -1;
1313 break;
1315 if (watchcode == 0 || ta != 0)
1316 break;
1319 return (rv);
1322 static int
1323 watch_suword32(void *addr, uint32_t value)
1325 klwp_t *lwp = ttolwp(curthread);
1326 int watchcode;
1327 caddr_t vaddr;
1328 int mapped;
1329 int rv = 0;
1330 int ta;
1331 label_t ljb;
1333 for (;;) {
1335 vaddr = (caddr_t)addr;
1336 watchcode = pr_is_watchpoint(&vaddr, &ta, sizeof (value), NULL,
1337 S_WRITE);
1338 if (watchcode == 0 || ta != 0) {
1339 mapped = pr_mappage((caddr_t)addr, sizeof (value),
1340 S_WRITE, 1);
1341 if (on_fault(&ljb))
1342 rv = -1;
1343 else
1344 suword32_noerr(addr, value);
1345 no_fault();
1346 if (mapped)
1347 pr_unmappage((caddr_t)addr, sizeof (value),
1348 S_WRITE, 1);
1350 if (watchcode &&
1351 (!sys_watchpoint(vaddr, watchcode, ta) ||
1352 lwp->lwp_sysabort)) {
1353 lwp->lwp_sysabort = 0;
1354 rv = -1;
1355 break;
1357 if (watchcode == 0 || ta != 0)
1358 break;
1361 return (rv);
1364 #ifdef _LP64
1365 static int
1366 watch_suword64(void *addr, uint64_t value)
1368 klwp_t *lwp = ttolwp(curthread);
1369 int watchcode;
1370 caddr_t vaddr;
1371 int mapped;
1372 int rv = 0;
1373 int ta;
1374 label_t ljb;
1376 for (;;) {
1378 vaddr = (caddr_t)addr;
1379 watchcode = pr_is_watchpoint(&vaddr, &ta, sizeof (value), NULL,
1380 S_WRITE);
1381 if (watchcode == 0 || ta != 0) {
1382 mapped = pr_mappage((caddr_t)addr, sizeof (value),
1383 S_WRITE, 1);
1384 if (on_fault(&ljb))
1385 rv = -1;
1386 else
1387 suword64_noerr(addr, value);
1388 no_fault();
1389 if (mapped)
1390 pr_unmappage((caddr_t)addr, sizeof (value),
1391 S_WRITE, 1);
1393 if (watchcode &&
1394 (!sys_watchpoint(vaddr, watchcode, ta) ||
1395 lwp->lwp_sysabort)) {
1396 lwp->lwp_sysabort = 0;
1397 rv = -1;
1398 break;
1400 if (watchcode == 0 || ta != 0)
1401 break;
1404 return (rv);
1406 #endif /* _LP64 */
1409 * Check for watched addresses in the given address space.
1410 * Return 1 if this is true, otherwise 0.
1412 static int
1413 pr_is_watched(caddr_t base, size_t len, int rw)
1415 caddr_t saddr = (caddr_t)((uintptr_t)base & (uintptr_t)PAGEMASK);
1416 caddr_t eaddr = base + len;
1417 caddr_t paddr;
1419 for (paddr = saddr; paddr < eaddr; paddr += PAGESIZE) {
1420 if (pr_is_watchpage(paddr, rw))
1421 return (1);
1424 return (0);
1428 * Wrapper for the physio() function.
1429 * Splits one uio operation with multiple iovecs into uio operations with
1430 * only one iovecs to do the watchpoint handling separately for each iovecs.
1432 static int
1433 watch_physio(int (*strat)(struct buf *), struct buf *bp, dev_t dev,
1434 int rw, void (*mincnt)(struct buf *), struct uio *uio)
1436 struct uio auio;
1437 struct iovec *iov;
1438 caddr_t base;
1439 size_t len;
1440 int seg_rw;
1441 int error = 0;
1443 if (uio->uio_segflg == UIO_SYSSPACE)
1444 return (default_physio(strat, bp, dev, rw, mincnt, uio));
1446 seg_rw = (rw == B_READ) ? S_WRITE : S_READ;
1448 while (uio->uio_iovcnt > 0) {
1449 if (uio->uio_resid == 0) {
1451 * Make sure to return the uio structure with the
1452 * same values as default_physio() does.
1454 uio->uio_iov++;
1455 uio->uio_iovcnt--;
1456 continue;
1459 iov = uio->uio_iov;
1460 len = MIN(iov->iov_len, uio->uio_resid);
1462 auio.uio_iovcnt = 1;
1463 auio.uio_iov = iov;
1464 auio.uio_resid = len;
1465 auio.uio_loffset = uio->uio_loffset;
1466 auio.uio_llimit = uio->uio_llimit;
1467 auio.uio_fmode = uio->uio_fmode;
1468 auio.uio_extflg = uio->uio_extflg;
1469 auio.uio_segflg = uio->uio_segflg;
1471 base = iov->iov_base;
1473 if (!pr_is_watched(base, len, seg_rw)) {
1475 * The given memory references don't cover a
1476 * watched page.
1478 error = default_physio(strat, bp, dev, rw, mincnt,
1479 &auio);
1481 /* Update uio with values from auio. */
1482 len -= auio.uio_resid;
1483 uio->uio_resid -= len;
1484 uio->uio_loffset += len;
1487 * Return if an error occurred or not all data
1488 * was copied.
1490 if (auio.uio_resid || error)
1491 break;
1492 uio->uio_iov++;
1493 uio->uio_iovcnt--;
1494 } else {
1495 int mapped, watchcode, ta;
1496 caddr_t vaddr = base;
1497 klwp_t *lwp = ttolwp(curthread);
1499 watchcode = pr_is_watchpoint(&vaddr, &ta, len,
1500 NULL, seg_rw);
1502 if (watchcode == 0 || ta != 0) {
1504 * Do the io if the given memory references
1505 * don't cover a watched area (watchcode=0)
1506 * or if WA_TRAPAFTER was specified.
1508 mapped = pr_mappage(base, len, seg_rw, 1);
1509 error = default_physio(strat, bp, dev, rw,
1510 mincnt, &auio);
1511 if (mapped)
1512 pr_unmappage(base, len, seg_rw, 1);
1514 len -= auio.uio_resid;
1515 uio->uio_resid -= len;
1516 uio->uio_loffset += len;
1520 * If we hit a watched address, do the watchpoint logic.
1522 if (watchcode &&
1523 (!sys_watchpoint(vaddr, watchcode, ta) ||
1524 lwp->lwp_sysabort)) {
1525 lwp->lwp_sysabort = 0;
1526 return (EFAULT);
1530 * Check for errors from default_physio().
1532 if (watchcode == 0 || ta != 0) {
1533 if (auio.uio_resid || error)
1534 break;
1535 uio->uio_iov++;
1536 uio->uio_iovcnt--;
1541 return (error);
1545 wa_compare(const void *a, const void *b)
1547 const watched_area_t *pa = a;
1548 const watched_area_t *pb = b;
1550 if (pa->wa_vaddr < pb->wa_vaddr)
1551 return (-1);
1552 else if (pa->wa_vaddr > pb->wa_vaddr)
1553 return (1);
1554 else
1555 return (0);
1559 wp_compare(const void *a, const void *b)
1561 const watched_page_t *pa = a;
1562 const watched_page_t *pb = b;
1564 if (pa->wp_vaddr < pb->wp_vaddr)
1565 return (-1);
1566 else if (pa->wp_vaddr > pb->wp_vaddr)
1567 return (1);
1568 else
1569 return (0);
1573 * Given an address range, finds the first watched area which overlaps some or
1574 * all of the range.
1576 watched_area_t *
1577 pr_find_watched_area(proc_t *p, watched_area_t *pwa, avl_index_t *where)
1579 caddr_t vaddr = pwa->wa_vaddr;
1580 caddr_t eaddr = pwa->wa_eaddr;
1581 watched_area_t *wap;
1582 avl_index_t real_where;
1584 /* First, check if there is an exact match. */
1585 wap = avl_find(&p->p_warea, pwa, &real_where);
1588 /* Check to see if we overlap with the previous area. */
1589 if (wap == NULL) {
1590 wap = avl_nearest(&p->p_warea, real_where, AVL_BEFORE);
1591 if (wap != NULL &&
1592 (vaddr >= wap->wa_eaddr || eaddr <= wap->wa_vaddr))
1593 wap = NULL;
1596 /* Try the next area. */
1597 if (wap == NULL) {
1598 wap = avl_nearest(&p->p_warea, real_where, AVL_AFTER);
1599 if (wap != NULL &&
1600 (vaddr >= wap->wa_eaddr || eaddr <= wap->wa_vaddr))
1601 wap = NULL;
1604 if (where)
1605 *where = real_where;
1607 return (wap);
1610 void
1611 watch_enable(kthread_id_t t)
1613 t->t_proc_flag |= TP_WATCHPT;
1614 install_copyops(t, &watch_copyops);
1617 void
1618 watch_disable(kthread_id_t t)
1620 t->t_proc_flag &= ~TP_WATCHPT;
1621 remove_copyops(t);
1625 copyin_nowatch(const void *uaddr, void *kaddr, size_t len)
1627 int watched, ret;
1629 watched = watch_disable_addr(uaddr, len, S_READ);
1630 ret = copyin(uaddr, kaddr, len);
1631 if (watched)
1632 watch_enable_addr(uaddr, len, S_READ);
1634 return (ret);
1638 copyout_nowatch(const void *kaddr, void *uaddr, size_t len)
1640 int watched, ret;
1642 watched = watch_disable_addr(uaddr, len, S_WRITE);
1643 ret = copyout(kaddr, uaddr, len);
1644 if (watched)
1645 watch_enable_addr(uaddr, len, S_WRITE);
1647 return (ret);
1650 #ifdef _LP64
1652 fuword64_nowatch(const void *addr, uint64_t *value)
1654 int watched, ret;
1656 watched = watch_disable_addr(addr, sizeof (*value), S_READ);
1657 ret = fuword64(addr, value);
1658 if (watched)
1659 watch_enable_addr(addr, sizeof (*value), S_READ);
1661 return (ret);
1663 #endif
1666 fuword32_nowatch(const void *addr, uint32_t *value)
1668 int watched, ret;
1670 watched = watch_disable_addr(addr, sizeof (*value), S_READ);
1671 ret = fuword32(addr, value);
1672 if (watched)
1673 watch_enable_addr(addr, sizeof (*value), S_READ);
1675 return (ret);
1678 #ifdef _LP64
1680 suword64_nowatch(void *addr, uint64_t value)
1682 int watched, ret;
1684 watched = watch_disable_addr(addr, sizeof (value), S_WRITE);
1685 ret = suword64(addr, value);
1686 if (watched)
1687 watch_enable_addr(addr, sizeof (value), S_WRITE);
1689 return (ret);
1691 #endif
1694 suword32_nowatch(void *addr, uint32_t value)
1696 int watched, ret;
1698 watched = watch_disable_addr(addr, sizeof (value), S_WRITE);
1699 ret = suword32(addr, value);
1700 if (watched)
1701 watch_enable_addr(addr, sizeof (value), S_WRITE);
1703 return (ret);
1707 watch_disable_addr(const void *addr, size_t len, enum seg_rw rw)
1709 if (pr_watch_active(curproc))
1710 return (pr_mappage((caddr_t)addr, len, rw, 1));
1711 return (0);
1714 void
1715 watch_enable_addr(const void *addr, size_t len, enum seg_rw rw)
1717 if (pr_watch_active(curproc))
1718 pr_unmappage((caddr_t)addr, len, rw, 1);