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
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]
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>
31 #include <sys/debug.h>
32 #include <sys/inline.h>
35 #include <sys/regset.h>
36 #include <sys/sysmacros.h>
37 #include <sys/systm.h>
38 #include <sys/prsystm.h>
40 #include <sys/signal.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>
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
*);
75 static int watch_fuword64(const void *, uint64_t *);
76 static int watch_suword64(void *, uint64_t);
79 struct copyops watch_copyops
= {
106 * Map the 'rw' argument to a protection flag.
109 rw_to_prot(enum seg_rw rw
)
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
128 rw_to_index(enum seg_rw rw
)
131 default: /* default case "can't happen" */
142 * Map an index back to a seg_rw.
144 static enum seg_rw S_rw
[4] = {
154 #define sum(a) (a[X] + a[W] + a[R])
157 * Common code for pr_mappage() and pr_unmappage().
160 pr_do_mappage(caddr_t addr
, size_t size
, int mapin
, enum seg_rw rw
, int kernel
)
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
);
168 struct watched_page
*pwp
;
169 struct watched_page tpw
;
177 if (avl_numnodes(&as
->a_wpage
) == 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.
206 if (kernel
|| (prot
& PROT_USER
))
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
)))
217 if (!(prot
& prot_rw
))
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.
236 mutex_enter(&p
->p_maplock
);
241 addr
= pwp
->wp_vaddr
;
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
])
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)
264 ASSERT(pwp
->wp_flags
& WP_NOWATCH
);
266 ASSERT(pwp
->wp_kmap
[xrw
] != 0);
269 ASSERT(pwp
->wp_umap
[xrw
] != 0);
272 if (sum(pwp
->wp_kmap
) + sum(pwp
->wp_umap
) == 0)
273 pwp
->wp_flags
&= ~WP_NOWATCH
;
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
])
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)
291 if (pwp
->wp_oprot
!= 0) { /* if page exists */
294 int err
, retrycnt
= 0;
296 AS_LOCK_ENTER(as
, RW_WRITER
);
298 seg
= as_segat(as
, addr
);
300 (void) segop_getprot(seg
, addr
, 0, &oprot
);
302 err
= segop_setprot(seg
, addr
, PAGESIZE
, prot
);
303 if (err
== IE_RETRY
) {
304 ASSERT(retrycnt
== 0);
313 * When all pages are mapped back to their normal state,
314 * continue the other lwps.
317 ASSERT(p
->p_mapcnt
> 0);
319 if (p
->p_mapcnt
== 0) {
320 mutex_exit(&p
->p_maplock
);
321 mutex_enter(&p
->p_lock
);
323 mutex_exit(&p
->p_lock
);
324 mutex_enter(&p
->p_maplock
);
329 mutex_exit(&p
->p_maplock
);
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.
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.
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().
367 struct as
*as
= curproc
->p_as
;
368 struct watched_page
*pwp
, *next
;
374 if (p
->p_wprot
== NULL
)
377 ASSERT(MUTEX_NOT_HELD(&curproc
->p_lock
));
379 AS_LOCK_ENTER(as
, RW_WRITER
);
382 while (pwp
!= NULL
) {
384 vaddr
= pwp
->wp_vaddr
;
387 ASSERT(pwp
->wp_flags
& WP_SETPROT
);
388 if ((seg
= as_segat(as
, vaddr
)) != NULL
&&
389 !(pwp
->wp_flags
& WP_NOWATCH
)) {
391 err
= segop_setprot(seg
, vaddr
, PAGESIZE
, prot
);
392 if (err
== IE_RETRY
) {
393 ASSERT(retrycnt
== 0);
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
));
409 pwp
->wp_flags
&= ~WP_SETPROT
;
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
;
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
);
446 ASSERT(addr
>= pwp
->wp_vaddr
&&
447 addr
< pwp
->wp_vaddr
+ PAGESIZE
);
448 if (pwp
->wp_oprot
!= 0) {
452 rv
= ((prot
& (PROT_USER
|PROT_READ
))
453 != (PROT_USER
|PROT_READ
));
456 rv
= ((prot
& (PROT_USER
|PROT_WRITE
))
457 != (PROT_USER
|PROT_WRITE
));
460 rv
= ((prot
& (PROT_USER
|PROT_EXEC
))
461 != (PROT_USER
|PROT_EXEC
));
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)
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
,
500 caddr_t addr
= *paddr
;
501 caddr_t eaddr
= addr
+ size
;
502 register struct watched_area
*pwa
;
503 struct watched_area twa
;
519 * p->p_warea is protected by p->p_lock.
521 mutex_enter(&p
->p_lock
);
525 * This loop is somewhat complicated because the fault region can span
526 * multiple watched areas. For example:
529 * +-----------------+
531 * +-------+--------+----+---+------------+
532 * | prot not right | | prot correct |
533 * +----------------+ +----------------+
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
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
)) {
552 if (pwa
->wa_flags
& WA_READ
)
556 if (pwa
->wa_flags
& WA_WRITE
)
560 if (pwa
->wa_flags
& WA_EXEC
)
569 * If protections didn't match, check the next watched
573 if (addr
< pwa
->wa_vaddr
)
574 addr
= pwa
->wa_vaddr
;
575 len
= pwa
->wa_eaddr
- addr
;
576 if (pwa
->wa_flags
& WA_TRAPAFTER
)
582 mutex_exit(&p
->p_lock
);
592 * Set up to perform a single-step at user level for the
593 * case of a trapafter watchpoint. Called from trap().
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
;
622 int mapped
= pr_mappage(vaddr
, sz
, rw
, 0);
624 lwp
->lwp_watchtrap
= 1;
627 pw
->wpcode
= watchcode
;
628 pw
->wpmapped
= mapped
;
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
);
645 if (lwp
->lwp_watchtrap
) {
646 struct lwp_watch
*pw
= lwp
->lwp_watch
;
649 for (i
= 0; i
< 4; i
++, pw
++) {
650 if (pw
->wpaddr
== NULL
)
653 pr_unmappage(pw
->wpaddr
, pw
->wpsize
, S_rw
[i
],
655 if (pw
->wpcode
!= 0) {
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
;
670 lwp
->lwp_watchtrap
= 0;
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.
683 sys_watchpoint(caddr_t addr
, int watchcode
, int ta
)
685 extern greg_t
getuserpc(void); /* XXX header file */
687 register proc_t
*p
= ttoproc(curthread
);
688 register klwp_t
*lwp
= ttolwp(curthread
);
689 register sigqueue_t
*sqp
;
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
));
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
));
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
);
750 * Wrappers for the copyin()/copyout() functions to deal
751 * with watchpoints that fire while in system calls.
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
;
765 while (count
&& error
== 0) {
771 if ((part
= PAGESIZE
-
772 (((uintptr_t)uaddr
) & PAGEOFFSET
)) > count
)
775 if (!pr_is_watchpage(watch_uaddr
, S_READ
))
779 watchcode
= pr_is_watchpoint(&vaddr
, &ta
,
781 if (watchcode
&& ta
== 0)
782 part
= vaddr
- watch_uaddr
;
786 * Copy the initial part, up to a watched address, if any.
789 mapped
= pr_mappage(watch_uaddr
, part
, S_READ
, 1);
793 copyin_noerr(watch_uaddr
, watch_kaddr
, part
);
796 pr_unmappage(watch_uaddr
, part
, S_READ
, 1);
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) {
807 if ((part
= PAGESIZE
) > count
)
811 mapped
= pr_mappage(watch_uaddr
, part
, S_READ
, 1);
815 copyin_noerr(watch_uaddr
, watch_kaddr
, part
);
818 pr_unmappage(watch_uaddr
, part
, S_READ
, 1);
825 /* if we hit a watched address, do the watchpoint logic */
827 (!sys_watchpoint(vaddr
, watchcode
, ta
) ||
828 lwp
->lwp_sysabort
)) {
829 lwp
->lwp_sysabort
= 0;
839 watch_copyin(const void *kaddr
, void *uaddr
, size_t count
)
841 return (watch_xcopyin(kaddr
, uaddr
, count
) ? -1 : 0);
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
;
854 while (count
&& error
== 0) {
862 if ((part
= PAGESIZE
-
863 (((uintptr_t)uaddr
) & PAGEOFFSET
)) > count
)
866 if (!pr_is_watchpage(watch_uaddr
, S_WRITE
))
870 watchcode
= pr_is_watchpoint(&vaddr
, &ta
,
871 part
, &len
, S_WRITE
);
874 part
= vaddr
- watch_uaddr
;
876 len
+= vaddr
- watch_uaddr
;
884 * Copy the initial part, up to a watched address, if any.
887 mapped
= pr_mappage(watch_uaddr
, part
, S_WRITE
, 1);
891 copyout_noerr(watch_kaddr
, watch_uaddr
, part
);
894 pr_unmappage(watch_uaddr
, part
, S_WRITE
, 1);
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) {
906 if ((part
= PAGESIZE
) > count
)
910 mapped
= pr_mappage(watch_uaddr
, part
, S_WRITE
, 1);
914 copyout_noerr(watch_kaddr
, watch_uaddr
, part
);
917 pr_unmappage(watch_uaddr
, part
, S_WRITE
, 1);
923 /* if we hit a watched address, do the watchpoint logic */
925 (!sys_watchpoint(vaddr
, watchcode
, ta
) ||
926 lwp
->lwp_sysabort
)) {
927 lwp
->lwp_sysabort
= 0;
937 watch_copyout(const void *kaddr
, void *uaddr
, size_t count
)
939 return (watch_xcopyout(kaddr
, uaddr
, count
) ? -1 : 0);
949 klwp_t
*lwp
= ttolwp(curthread
);
954 if ((resid
= maxlength
) == 0)
955 return (ENAMETOOLONG
);
957 while (resid
&& error
== 0) {
966 if ((part
= PAGESIZE
-
967 (((uintptr_t)uaddr
) & PAGEOFFSET
)) > resid
)
970 if (!pr_is_watchpage((caddr_t
)uaddr
, S_READ
))
973 vaddr
= (caddr_t
)uaddr
;
974 watchcode
= pr_is_watchpoint(&vaddr
, &ta
,
978 part
= vaddr
- uaddr
;
980 len
+= vaddr
- uaddr
;
988 * Copy the initial part, up to a watched address, if any.
991 mapped
= pr_mappage((caddr_t
)uaddr
, part
, S_READ
, 1);
995 error
= copyinstr_noerr(uaddr
, kaddr
, part
,
999 pr_unmappage((caddr_t
)uaddr
, part
, S_READ
, 1);
1003 if (error
== ENAMETOOLONG
&& resid
> 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') {
1017 if ((part
= PAGESIZE
) > resid
)
1021 mapped
= pr_mappage((caddr_t
)uaddr
, part
, S_READ
, 1);
1025 error
= copyinstr_noerr(uaddr
, kaddr
, part
,
1029 pr_unmappage((caddr_t
)uaddr
, part
, S_READ
, 1);
1033 if (error
== ENAMETOOLONG
&& resid
> 0)
1037 /* if we hit a watched address, do the watchpoint logic */
1039 (!sys_watchpoint(vaddr
, watchcode
, ta
) ||
1040 lwp
->lwp_sysabort
)) {
1041 lwp
->lwp_sysabort
= 0;
1046 if (error
== 0 && part
!= 0 &&
1047 (size
< part
|| kaddr
[-1] == '\0'))
1051 if (error
!= EFAULT
&& lencopied
)
1052 *lencopied
= maxlength
- resid
;
1063 klwp_t
*lwp
= ttolwp(curthread
);
1068 if ((resid
= maxlength
) == 0)
1069 return (ENAMETOOLONG
);
1071 while (resid
&& error
== 0) {
1080 if ((part
= PAGESIZE
-
1081 (((uintptr_t)uaddr
) & PAGEOFFSET
)) > resid
)
1084 if (!pr_is_watchpage(uaddr
, S_WRITE
)) {
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.
1098 mapped
= pr_mappage(uaddr
, part
, S_WRITE
, 1);
1102 error
= copyoutstr_noerr(kaddr
, uaddr
, part
,
1106 pr_unmappage(uaddr
, part
, S_WRITE
, 1);
1110 if (error
== ENAMETOOLONG
&& resid
> 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') {
1124 if ((part
= PAGESIZE
) > resid
)
1128 mapped
= pr_mappage(uaddr
, part
, S_WRITE
, 1);
1132 error
= copyoutstr_noerr(kaddr
, uaddr
, part
,
1136 pr_unmappage(uaddr
, part
, S_WRITE
, 1);
1140 if (error
== ENAMETOOLONG
&& resid
> 0)
1144 /* if we hit a watched address, do the watchpoint logic */
1146 (!sys_watchpoint(vaddr
, watchcode
, ta
) ||
1147 lwp
->lwp_sysabort
)) {
1148 lwp
->lwp_sysabort
= 0;
1153 if (error
== 0 && part
!= 0 &&
1154 (size
< part
|| kaddr
[-1] == '\0'))
1158 if (error
!= EFAULT
&& lencopied
)
1159 *lencopied
= maxlength
- resid
;
1163 typedef int (*fuword_func
)(const void *, void *);
1166 * Generic form of watch_fuword8(), watch_fuword16(), etc.
1169 watch_fuword(const void *addr
, void *dst
, fuword_func func
, size_t size
)
1171 klwp_t
*lwp
= ttolwp(curthread
);
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);
1191 pr_unmappage((caddr_t
)addr
, size
, S_READ
, 1);
1194 (!sys_watchpoint(vaddr
, watchcode
, ta
) ||
1195 lwp
->lwp_sysabort
)) {
1196 lwp
->lwp_sysabort
= 0;
1200 if (watchcode
== 0 || ta
!= 0)
1208 watch_fuword8(const void *addr
, uint8_t *dst
)
1210 return (watch_fuword(addr
, dst
, (fuword_func
)fuword8_noerr
,
1215 watch_fuword16(const void *addr
, uint16_t *dst
)
1217 return (watch_fuword(addr
, dst
, (fuword_func
)fuword16_noerr
,
1222 watch_fuword32(const void *addr
, uint32_t *dst
)
1224 return (watch_fuword(addr
, dst
, (fuword_func
)fuword32_noerr
,
1230 watch_fuword64(const void *addr
, uint64_t *dst
)
1232 return (watch_fuword(addr
, dst
, (fuword_func
)fuword64_noerr
,
1239 watch_suword8(void *addr
, uint8_t value
)
1241 klwp_t
*lwp
= ttolwp(curthread
);
1251 vaddr
= (caddr_t
)addr
;
1252 watchcode
= pr_is_watchpoint(&vaddr
, &ta
, sizeof (value
), NULL
,
1254 if (watchcode
== 0 || ta
!= 0) {
1255 mapped
= pr_mappage((caddr_t
)addr
, sizeof (value
),
1260 suword8_noerr(addr
, value
);
1263 pr_unmappage((caddr_t
)addr
, sizeof (value
),
1267 (!sys_watchpoint(vaddr
, watchcode
, ta
) ||
1268 lwp
->lwp_sysabort
)) {
1269 lwp
->lwp_sysabort
= 0;
1273 if (watchcode
== 0 || ta
!= 0)
1281 watch_suword16(void *addr
, uint16_t value
)
1283 klwp_t
*lwp
= ttolwp(curthread
);
1293 vaddr
= (caddr_t
)addr
;
1294 watchcode
= pr_is_watchpoint(&vaddr
, &ta
, sizeof (value
), NULL
,
1296 if (watchcode
== 0 || ta
!= 0) {
1297 mapped
= pr_mappage((caddr_t
)addr
, sizeof (value
),
1302 suword16_noerr(addr
, value
);
1305 pr_unmappage((caddr_t
)addr
, sizeof (value
),
1309 (!sys_watchpoint(vaddr
, watchcode
, ta
) ||
1310 lwp
->lwp_sysabort
)) {
1311 lwp
->lwp_sysabort
= 0;
1315 if (watchcode
== 0 || ta
!= 0)
1323 watch_suword32(void *addr
, uint32_t value
)
1325 klwp_t
*lwp
= ttolwp(curthread
);
1335 vaddr
= (caddr_t
)addr
;
1336 watchcode
= pr_is_watchpoint(&vaddr
, &ta
, sizeof (value
), NULL
,
1338 if (watchcode
== 0 || ta
!= 0) {
1339 mapped
= pr_mappage((caddr_t
)addr
, sizeof (value
),
1344 suword32_noerr(addr
, value
);
1347 pr_unmappage((caddr_t
)addr
, sizeof (value
),
1351 (!sys_watchpoint(vaddr
, watchcode
, ta
) ||
1352 lwp
->lwp_sysabort
)) {
1353 lwp
->lwp_sysabort
= 0;
1357 if (watchcode
== 0 || ta
!= 0)
1366 watch_suword64(void *addr
, uint64_t value
)
1368 klwp_t
*lwp
= ttolwp(curthread
);
1378 vaddr
= (caddr_t
)addr
;
1379 watchcode
= pr_is_watchpoint(&vaddr
, &ta
, sizeof (value
), NULL
,
1381 if (watchcode
== 0 || ta
!= 0) {
1382 mapped
= pr_mappage((caddr_t
)addr
, sizeof (value
),
1387 suword64_noerr(addr
, value
);
1390 pr_unmappage((caddr_t
)addr
, sizeof (value
),
1394 (!sys_watchpoint(vaddr
, watchcode
, ta
) ||
1395 lwp
->lwp_sysabort
)) {
1396 lwp
->lwp_sysabort
= 0;
1400 if (watchcode
== 0 || ta
!= 0)
1409 * Check for watched addresses in the given address space.
1410 * Return 1 if this is true, otherwise 0.
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
;
1419 for (paddr
= saddr
; paddr
< eaddr
; paddr
+= PAGESIZE
) {
1420 if (pr_is_watchpage(paddr
, rw
))
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.
1433 watch_physio(int (*strat
)(struct buf
*), struct buf
*bp
, dev_t dev
,
1434 int rw
, void (*mincnt
)(struct buf
*), struct uio
*uio
)
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.
1460 len
= MIN(iov
->iov_len
, uio
->uio_resid
);
1462 auio
.uio_iovcnt
= 1;
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
1478 error
= default_physio(strat
, bp
, dev
, rw
, mincnt
,
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
1490 if (auio
.uio_resid
|| error
)
1495 int mapped
, watchcode
, ta
;
1496 caddr_t vaddr
= base
;
1497 klwp_t
*lwp
= ttolwp(curthread
);
1499 watchcode
= pr_is_watchpoint(&vaddr
, &ta
, len
,
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
,
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.
1523 (!sys_watchpoint(vaddr
, watchcode
, ta
) ||
1524 lwp
->lwp_sysabort
)) {
1525 lwp
->lwp_sysabort
= 0;
1530 * Check for errors from default_physio().
1532 if (watchcode
== 0 || ta
!= 0) {
1533 if (auio
.uio_resid
|| 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
)
1552 else if (pa
->wa_vaddr
> pb
->wa_vaddr
)
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
)
1566 else if (pa
->wp_vaddr
> pb
->wp_vaddr
)
1573 * Given an address range, finds the first watched area which overlaps some or
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. */
1590 wap
= avl_nearest(&p
->p_warea
, real_where
, AVL_BEFORE
);
1592 (vaddr
>= wap
->wa_eaddr
|| eaddr
<= wap
->wa_vaddr
))
1596 /* Try the next area. */
1598 wap
= avl_nearest(&p
->p_warea
, real_where
, AVL_AFTER
);
1600 (vaddr
>= wap
->wa_eaddr
|| eaddr
<= wap
->wa_vaddr
))
1605 *where
= real_where
;
1611 watch_enable(kthread_id_t t
)
1613 t
->t_proc_flag
|= TP_WATCHPT
;
1614 install_copyops(t
, &watch_copyops
);
1618 watch_disable(kthread_id_t t
)
1620 t
->t_proc_flag
&= ~TP_WATCHPT
;
1625 copyin_nowatch(const void *uaddr
, void *kaddr
, size_t len
)
1629 watched
= watch_disable_addr(uaddr
, len
, S_READ
);
1630 ret
= copyin(uaddr
, kaddr
, len
);
1632 watch_enable_addr(uaddr
, len
, S_READ
);
1638 copyout_nowatch(const void *kaddr
, void *uaddr
, size_t len
)
1642 watched
= watch_disable_addr(uaddr
, len
, S_WRITE
);
1643 ret
= copyout(kaddr
, uaddr
, len
);
1645 watch_enable_addr(uaddr
, len
, S_WRITE
);
1652 fuword64_nowatch(const void *addr
, uint64_t *value
)
1656 watched
= watch_disable_addr(addr
, sizeof (*value
), S_READ
);
1657 ret
= fuword64(addr
, value
);
1659 watch_enable_addr(addr
, sizeof (*value
), S_READ
);
1666 fuword32_nowatch(const void *addr
, uint32_t *value
)
1670 watched
= watch_disable_addr(addr
, sizeof (*value
), S_READ
);
1671 ret
= fuword32(addr
, value
);
1673 watch_enable_addr(addr
, sizeof (*value
), S_READ
);
1680 suword64_nowatch(void *addr
, uint64_t value
)
1684 watched
= watch_disable_addr(addr
, sizeof (value
), S_WRITE
);
1685 ret
= suword64(addr
, value
);
1687 watch_enable_addr(addr
, sizeof (value
), S_WRITE
);
1694 suword32_nowatch(void *addr
, uint32_t value
)
1698 watched
= watch_disable_addr(addr
, sizeof (value
), S_WRITE
);
1699 ret
= suword32(addr
, value
);
1701 watch_enable_addr(addr
, sizeof (value
), S_WRITE
);
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));
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);