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 /*
23 * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 */
26
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>
43
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>
52
53 #include <sys/mman.h>
54 #include <vm/as.h>
55 #include <vm/seg.h>
56
57 /*
58 * Copy ops vector for watchpoints.
59 */
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
78
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
103 };
104
105 /*
106 * Map the 'rw' argument to a protection flag.
107 */
108 static int
rw_to_prot(enum seg_rw rw)109 rw_to_prot(enum seg_rw rw)
110 {
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 */
120 }
121 }
122
123 /*
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
126 */
127 static int
rw_to_index(enum seg_rw rw)128 rw_to_index(enum seg_rw rw)
129 {
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);
138 }
139 }
140
141 /*
142 * Map an index back to a seg_rw.
143 */
144 static enum seg_rw S_rw[4] = {
145 S_EXEC,
146 S_WRITE,
147 S_READ,
148 S_READ,
149 };
150
151 #define X 0
152 #define W 1
153 #define R 2
154 #define sum(a) (a[X] + a[W] + a[R])
155
156 /*
157 * Common code for pr_mappage() and pr_unmappage().
158 */
159 static int
pr_do_mappage(caddr_t addr,size_t size,int mapin,enum seg_rw rw,int kernel)160 pr_do_mappage(caddr_t addr, size_t size, int mapin, enum seg_rw rw, int kernel)
161 {
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;
172
173 ASSERT(as != &kas);
174
175 startover:
176 ASSERT(rv == 0);
177 if (avl_numnodes(&as->a_wpage) == 0)
178 return (0);
179
180 /*
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.
184 *
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.
190 */
191
192 mutex_enter(&p->p_maplock);
193
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);
197
198 for (; pwp != NULL && pwp->wp_vaddr < eaddr;
199 pwp = AVL_NEXT(&as->a_wpage, pwp)) {
200
201 /*
202 * If the requested protection has not been
203 * removed, we need not remap this page.
204 */
205 prot = pwp->wp_prot;
206 if (kernel || (prot & PROT_USER))
207 if (prot & prot_rw)
208 continue;
209 /*
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.
213 */
214 if ((prot = pwp->wp_oprot) != 0) {
215 if (!(kernel || (prot & PROT_USER)))
216 continue;
217 if (!(prot & prot_rw))
218 continue;
219 }
220
221 if (mapin) {
222 /*
223 * Before mapping the page in, ensure that
224 * all other lwps are held in the kernel.
225 */
226 if (p->p_mapcnt == 0) {
227 mutex_exit(&p->p_maplock);
228 if (holdwatch() != 0) {
229 /*
230 * We stopped in holdwatch().
231 * Start all over again because the
232 * watched page list may have changed.
233 */
234 goto startover;
235 }
236 mutex_enter(&p->p_maplock);
237 }
238 p->p_mapcnt++;
239 }
240
241 addr = pwp->wp_vaddr;
242 rv++;
243
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];
271 }
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
287 }
288 }
289
290
291 if (pwp->wp_oprot != 0) { /* if page exists */
292 struct seg *seg;
293 uint_t oprot;
294 int err, retrycnt = 0;
295
296 AS_LOCK_ENTER(as, RW_WRITER);
297 retry:
298 seg = as_segat(as, addr);
299 ASSERT(seg != NULL);
300 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;
307 }
308 }
309 AS_LOCK_EXIT(as);
310 }
311
312 /*
313 * When all pages are mapped back to their normal state,
314 * continue the other lwps.
315 */
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);
325 }
326 }
327 }
328
329 mutex_exit(&p->p_maplock);
330
331 return (rv);
332 }
333
334 /*
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.
338 *
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.
342 */
343 static int
pr_mappage(const caddr_t addr,size_t size,enum seg_rw rw,int kernel)344 pr_mappage(const caddr_t addr, size_t size, enum seg_rw rw, int kernel)
345 {
346 return (pr_do_mappage(addr, size, 1, rw, kernel));
347 }
348
349 /*
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.
353 */
354 static void
pr_unmappage(const caddr_t addr,size_t size,enum seg_rw rw,int kernel)355 pr_unmappage(const caddr_t addr, size_t size, enum seg_rw rw, int kernel)
356 {
357 (void) pr_do_mappage(addr, size, 0, rw, kernel);
358 }
359
360 /*
361 * Function called by an lwp after it resumes from stop().
362 */
363 void
setallwatch(void)364 setallwatch(void)
365 {
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;
373
374 if (p->p_wprot == NULL)
375 return;
376
377 ASSERT(MUTEX_NOT_HELD(&curproc->p_lock));
378
379 AS_LOCK_ENTER(as, RW_WRITER);
380
381 pwp = p->p_wprot;
382 while (pwp != NULL) {
383
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;
396 }
397 }
398
399 next = pwp->wp_list;
400
401 if (pwp->wp_read + pwp->wp_write + pwp->wp_exec == 0) {
402 /*
403 * No watched areas remain in this page.
404 * Free the watched_page structure.
405 */
406 avl_remove(&as->a_wpage, pwp);
407 kmem_free(pwp, sizeof (struct watched_page));
408 } else {
409 pwp->wp_flags &= ~WP_SETPROT;
410 }
411
412 pwp = next;
413 }
414 p->p_wprot = NULL;
415
416 AS_LOCK_EXIT(as);
417 }
418
419
420
421 int
pr_is_watchpage_as(caddr_t addr,enum seg_rw rw,struct as * as)422 pr_is_watchpage_as(caddr_t addr, enum seg_rw rw, struct as *as)
423 {
424 register struct watched_page *pwp;
425 struct watched_page tpw;
426 uint_t prot;
427 int rv = 0;
428
429 switch (rw) {
430 case S_READ:
431 case S_WRITE:
432 case S_EXEC:
433 break;
434 default:
435 return (0);
436 }
437
438 /*
439 * as->a_wpage can only be modified while the process is totally
440 * stopped. We need, and should use, no locks here.
441 */
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;
466 }
467 }
468 }
469 }
470
471 return (rv);
472 }
473
474
475 /*
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.
478 */
479 int
pr_is_watchpage(caddr_t addr,enum seg_rw rw)480 pr_is_watchpage(caddr_t addr, enum seg_rw rw)
481 {
482 struct as *as = curproc->p_as;
483
484 if ((as == &kas) || avl_numnodes(&as->a_wpage) == 0)
485 return (0);
486
487 return (pr_is_watchpage_as(addr, rw, as));
488 }
489
490
491
492 /*
493 * trap() calls here to determine if a fault is a watchpoint.
494 */
495 int
pr_is_watchpoint(caddr_t * paddr,int * pta,size_t size,size_t * plen,enum seg_rw rw)496 pr_is_watchpoint(caddr_t *paddr, int *pta, size_t size, size_t *plen,
497 enum seg_rw rw)
498 {
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;
507
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);
516 }
517
518 /*
519 * p->p_warea is protected by p->p_lock.
520 */
521 mutex_enter(&p->p_lock);
522
523 /* BEGIN CSTYLED */
524 /*
525 * This loop is somewhat complicated because the fault region can span
526 * multiple watched areas. For example:
527 *
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
536 *
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.
541 */
542 /* END CSTYLED */
543 twa.wa_vaddr = addr;
544 twa.wa_eaddr = eaddr;
545
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)) {
549
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;
566 }
567
568 /*
569 * If protections didn't match, check the next watched
570 * area
571 */
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;
579 }
580 }
581
582 mutex_exit(&p->p_lock);
583
584 *paddr = addr;
585 *pta = ta;
586 if (plen != NULL)
587 *plen = len;
588 return (rv);
589 }
590
591 /*
592 * Set up to perform a single-step at user level for the
593 * case of a trapafter watchpoint. Called from trap().
594 */
595 void
do_watch_step(caddr_t vaddr,size_t sz,enum seg_rw rw,int watchcode,greg_t pc)596 do_watch_step(caddr_t vaddr, size_t sz, enum seg_rw rw,
597 int watchcode, greg_t pc)
598 {
599 register klwp_t *lwp = ttolwp(curthread);
600 struct lwp_watch *pw = &lwp->lwp_watch[rw_to_index(rw)];
601
602 /*
603 * Check to see if we are already performing this special
604 * watchpoint single-step. We must not do pr_mappage() twice.
605 */
606
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 */
612 }
613
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;
620 }
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;
630 }
631 }
632
633 /*
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.
638 */
639 int
undo_watch_step(k_siginfo_t * sip)640 undo_watch_step(k_siginfo_t *sip)
641 {
642 register klwp_t *lwp = ttolwp(curthread);
643 int fault = 0;
644
645 if (lwp->lwp_watchtrap) {
646 struct lwp_watch *pw = lwp->lwp_watch;
647 int i;
648
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],
654 0);
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;
662 }
663 fault = FLTWATCH;
664 pw->wpcode = 0;
665 }
666 pw->wpaddr = NULL;
667 pw->wpsize = 0;
668 pw->wpmapped = 0;
669 }
670 lwp->lwp_watchtrap = 0;
671 }
672
673 return (fault);
674 }
675
676 /*
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.
681 */
682 static int
sys_watchpoint(caddr_t addr,int watchcode,int ta)683 sys_watchpoint(caddr_t addr, int watchcode, int ta)
684 {
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;
691
692 /* assert no locks are held */
693 /* ASSERT(curthread->t_nlocks == 0); */
694
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();
701
702 mutex_enter(&p->p_lock);
703
704 /* this will be tested and cleared by the caller */
705 lwp->lwp_sysabort = 0;
706
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);
715 }
716 lwp->lwp_curflt = 0;
717 }
718
719 /*
720 * post the SIGTRAP signal.
721 * Block all other signals so we only stop showing SIGTRAP.
722 */
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);
729 }
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);
738
739 rval = ((ISSIG_FAST(curthread, lwp, p, FORREAL))? 0 : 1);
740
741 /* restore the original signal mask */
742 mutex_enter(&p->p_lock);
743 curthread->t_hold = smask;
744 mutex_exit(&p->p_lock);
745
746 return (rval);
747 }
748
749 /*
750 * Wrappers for the copyin()/copyout() functions to deal
751 * with watchpoints that fire while in system calls.
752 */
753
754 static int
watch_xcopyin(const void * uaddr,void * kaddr,size_t count)755 watch_xcopyin(const void *uaddr, void *kaddr, size_t count)
756 {
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;
764
765 while (count && error == 0) {
766 int watchcode;
767 caddr_t vaddr;
768 size_t len;
769 int ta;
770
771 if ((part = PAGESIZE -
772 (((uintptr_t)uaddr) & PAGEOFFSET)) > count)
773 part = count;
774
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;
783 }
784
785 /*
786 * Copy the initial part, up to a watched address, if any.
787 */
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;
800 }
801 /*
802 * If trapafter was specified, then copy through the
803 * watched area before taking the watchpoint trap.
804 */
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;
822 }
823
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;
832 }
833 }
834
835 return (error);
836 }
837
838 static int
watch_copyin(const void * kaddr,void * uaddr,size_t count)839 watch_copyin(const void *kaddr, void *uaddr, size_t count)
840 {
841 return (watch_xcopyin(kaddr, uaddr, count) ? -1 : 0);
842 }
843
844
845 static int
watch_xcopyout(const void * kaddr,void * uaddr,size_t count)846 watch_xcopyout(const void *kaddr, void *uaddr, size_t count)
847 {
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;
853
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;
861
862 if ((part = PAGESIZE -
863 (((uintptr_t)uaddr) & PAGEOFFSET)) > count)
864 part = count;
865
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;
879 }
880 }
881 }
882
883 /*
884 * Copy the initial part, up to a watched address, if any.
885 */
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;
898 }
899
900 /*
901 * If trapafter was specified, then copy through the
902 * watched area before taking the watchpoint trap.
903 */
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;
921 }
922
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;
930 }
931 }
932
933 return (error);
934 }
935
936 static int
watch_copyout(const void * kaddr,void * uaddr,size_t count)937 watch_copyout(const void *kaddr, void *uaddr, size_t count)
938 {
939 return (watch_xcopyout(kaddr, uaddr, count) ? -1 : 0);
940 }
941
942 static int
watch_copyinstr(const char * uaddr,char * kaddr,size_t maxlength,size_t * lencopied)943 watch_copyinstr(
944 const char *uaddr,
945 char *kaddr,
946 size_t maxlength,
947 size_t *lencopied)
948 {
949 klwp_t *lwp = ttolwp(curthread);
950 size_t resid;
951 int error = 0;
952 label_t ljb;
953
954 if ((resid = maxlength) == 0)
955 return (ENAMETOOLONG);
956
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;
965
966 if ((part = PAGESIZE -
967 (((uintptr_t)uaddr) & PAGEOFFSET)) > resid)
968 part = resid;
969
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;
983 }
984 }
985 }
986
987 /*
988 * Copy the initial part, up to a watched address, if any.
989 */
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 */
1008 }
1009
1010 /*
1011 * If trapafter was specified, then copy through the
1012 * watched area before taking the watchpoint trap.
1013 */
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;
1035 }
1036
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;
1044 }
1045
1046 if (error == 0 && part != 0 &&
1047 (size < part || kaddr[-1] == '\0'))
1048 break;
1049 }
1050
1051 if (error != EFAULT && lencopied)
1052 *lencopied = maxlength - resid;
1053 return (error);
1054 }
1055
1056 static int
watch_copyoutstr(const char * kaddr,char * uaddr,size_t maxlength,size_t * lencopied)1057 watch_copyoutstr(
1058 const char *kaddr,
1059 char *uaddr,
1060 size_t maxlength,
1061 size_t *lencopied)
1062 {
1063 klwp_t *lwp = ttolwp(curthread);
1064 size_t resid;
1065 int error = 0;
1066 label_t ljb;
1067
1068 if ((resid = maxlength) == 0)
1069 return (ENAMETOOLONG);
1070
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;
1079
1080 if ((part = PAGESIZE -
1081 (((uintptr_t)uaddr) & PAGEOFFSET)) > resid)
1082 part = resid;
1083
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;
1092 }
1093
1094 /*
1095 * Copy the initial part, up to a watched address, if any.
1096 */
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 */
1115 }
1116
1117 /*
1118 * If trapafter was specified, then copy through the
1119 * watched area before taking the watchpoint trap.
1120 */
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;
1142 }
1143
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;
1151 }
1152
1153 if (error == 0 && part != 0 &&
1154 (size < part || kaddr[-1] == '\0'))
1155 break;
1156 }
1157
1158 if (error != EFAULT && lencopied)
1159 *lencopied = maxlength - resid;
1160 return (error);
1161 }
1162
1163 typedef int (*fuword_func)(const void *, void *);
1164
1165 /*
1166 * Generic form of watch_fuword8(), watch_fuword16(), etc.
1167 */
1168 static int
watch_fuword(const void * addr,void * dst,fuword_func func,size_t size)1169 watch_fuword(const void *addr, void *dst, fuword_func func, size_t size)
1170 {
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;
1178
1179 for (;;) {
1180
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);
1192 }
1193 if (watchcode &&
1194 (!sys_watchpoint(vaddr, watchcode, ta) ||
1195 lwp->lwp_sysabort)) {
1196 lwp->lwp_sysabort = 0;
1197 rv = -1;
1198 break;
1199 }
1200 if (watchcode == 0 || ta != 0)
1201 break;
1202 }
1203
1204 return (rv);
1205 }
1206
1207 static int
watch_fuword8(const void * addr,uint8_t * dst)1208 watch_fuword8(const void *addr, uint8_t *dst)
1209 {
1210 return (watch_fuword(addr, dst, (fuword_func)fuword8_noerr,
1211 sizeof (*dst)));
1212 }
1213
1214 static int
watch_fuword16(const void * addr,uint16_t * dst)1215 watch_fuword16(const void *addr, uint16_t *dst)
1216 {
1217 return (watch_fuword(addr, dst, (fuword_func)fuword16_noerr,
1218 sizeof (*dst)));
1219 }
1220
1221 static int
watch_fuword32(const void * addr,uint32_t * dst)1222 watch_fuword32(const void *addr, uint32_t *dst)
1223 {
1224 return (watch_fuword(addr, dst, (fuword_func)fuword32_noerr,
1225 sizeof (*dst)));
1226 }
1227
1228 #ifdef _LP64
1229 static int
watch_fuword64(const void * addr,uint64_t * dst)1230 watch_fuword64(const void *addr, uint64_t *dst)
1231 {
1232 return (watch_fuword(addr, dst, (fuword_func)fuword64_noerr,
1233 sizeof (*dst)));
1234 }
1235 #endif
1236
1237
1238 static int
watch_suword8(void * addr,uint8_t value)1239 watch_suword8(void *addr, uint8_t value)
1240 {
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;
1248
1249 for (;;) {
1250
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);
1265 }
1266 if (watchcode &&
1267 (!sys_watchpoint(vaddr, watchcode, ta) ||
1268 lwp->lwp_sysabort)) {
1269 lwp->lwp_sysabort = 0;
1270 rv = -1;
1271 break;
1272 }
1273 if (watchcode == 0 || ta != 0)
1274 break;
1275 }
1276
1277 return (rv);
1278 }
1279
1280 static int
watch_suword16(void * addr,uint16_t value)1281 watch_suword16(void *addr, uint16_t value)
1282 {
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;
1290
1291 for (;;) {
1292
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);
1307 }
1308 if (watchcode &&
1309 (!sys_watchpoint(vaddr, watchcode, ta) ||
1310 lwp->lwp_sysabort)) {
1311 lwp->lwp_sysabort = 0;
1312 rv = -1;
1313 break;
1314 }
1315 if (watchcode == 0 || ta != 0)
1316 break;
1317 }
1318
1319 return (rv);
1320 }
1321
1322 static int
watch_suword32(void * addr,uint32_t value)1323 watch_suword32(void *addr, uint32_t value)
1324 {
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;
1332
1333 for (;;) {
1334
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);
1349 }
1350 if (watchcode &&
1351 (!sys_watchpoint(vaddr, watchcode, ta) ||
1352 lwp->lwp_sysabort)) {
1353 lwp->lwp_sysabort = 0;
1354 rv = -1;
1355 break;
1356 }
1357 if (watchcode == 0 || ta != 0)
1358 break;
1359 }
1360
1361 return (rv);
1362 }
1363
1364 #ifdef _LP64
1365 static int
watch_suword64(void * addr,uint64_t value)1366 watch_suword64(void *addr, uint64_t value)
1367 {
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;
1375
1376 for (;;) {
1377
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);
1392 }
1393 if (watchcode &&
1394 (!sys_watchpoint(vaddr, watchcode, ta) ||
1395 lwp->lwp_sysabort)) {
1396 lwp->lwp_sysabort = 0;
1397 rv = -1;
1398 break;
1399 }
1400 if (watchcode == 0 || ta != 0)
1401 break;
1402 }
1403
1404 return (rv);
1405 }
1406 #endif /* _LP64 */
1407
1408 /*
1409 * Check for watched addresses in the given address space.
1410 * Return 1 if this is true, otherwise 0.
1411 */
1412 static int
pr_is_watched(caddr_t base,size_t len,int rw)1413 pr_is_watched(caddr_t base, size_t len, int rw)
1414 {
1415 caddr_t saddr = (caddr_t)((uintptr_t)base & (uintptr_t)PAGEMASK);
1416 caddr_t eaddr = base + len;
1417 caddr_t paddr;
1418
1419 for (paddr = saddr; paddr < eaddr; paddr += PAGESIZE) {
1420 if (pr_is_watchpage(paddr, rw))
1421 return (1);
1422 }
1423
1424 return (0);
1425 }
1426
1427 /*
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.
1431 */
1432 static int
watch_physio(int (* strat)(struct buf *),struct buf * bp,dev_t dev,int rw,void (* mincnt)(struct buf *),struct uio * uio)1433 watch_physio(int (*strat)(struct buf *), struct buf *bp, dev_t dev,
1434 int rw, void (*mincnt)(struct buf *), struct uio *uio)
1435 {
1436 struct uio auio;
1437 struct iovec *iov;
1438 caddr_t base;
1439 size_t len;
1440 int seg_rw;
1441 int error = 0;
1442
1443 if (uio->uio_segflg == UIO_SYSSPACE)
1444 return (default_physio(strat, bp, dev, rw, mincnt, uio));
1445
1446 seg_rw = (rw == B_READ) ? S_WRITE : S_READ;
1447
1448 while (uio->uio_iovcnt > 0) {
1449 if (uio->uio_resid == 0) {
1450 /*
1451 * Make sure to return the uio structure with the
1452 * same values as default_physio() does.
1453 */
1454 uio->uio_iov++;
1455 uio->uio_iovcnt--;
1456 continue;
1457 }
1458
1459 iov = uio->uio_iov;
1460 len = MIN(iov->iov_len, uio->uio_resid);
1461
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;
1470
1471 base = iov->iov_base;
1472
1473 if (!pr_is_watched(base, len, seg_rw)) {
1474 /*
1475 * The given memory references don't cover a
1476 * watched page.
1477 */
1478 error = default_physio(strat, bp, dev, rw, mincnt,
1479 &auio);
1480
1481 /* Update uio with values from auio. */
1482 len -= auio.uio_resid;
1483 uio->uio_resid -= len;
1484 uio->uio_loffset += len;
1485
1486 /*
1487 * Return if an error occurred or not all data
1488 * was copied.
1489 */
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);
1498
1499 watchcode = pr_is_watchpoint(&vaddr, &ta, len,
1500 NULL, seg_rw);
1501
1502 if (watchcode == 0 || ta != 0) {
1503 /*
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.
1507 */
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);
1513
1514 len -= auio.uio_resid;
1515 uio->uio_resid -= len;
1516 uio->uio_loffset += len;
1517 }
1518
1519 /*
1520 * If we hit a watched address, do the watchpoint logic.
1521 */
1522 if (watchcode &&
1523 (!sys_watchpoint(vaddr, watchcode, ta) ||
1524 lwp->lwp_sysabort)) {
1525 lwp->lwp_sysabort = 0;
1526 return (EFAULT);
1527 }
1528
1529 /*
1530 * Check for errors from default_physio().
1531 */
1532 if (watchcode == 0 || ta != 0) {
1533 if (auio.uio_resid || error)
1534 break;
1535 uio->uio_iov++;
1536 uio->uio_iovcnt--;
1537 }
1538 }
1539 }
1540
1541 return (error);
1542 }
1543
1544 int
wa_compare(const void * a,const void * b)1545 wa_compare(const void *a, const void *b)
1546 {
1547 const watched_area_t *pa = a;
1548 const watched_area_t *pb = b;
1549
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);
1556 }
1557
1558 int
wp_compare(const void * a,const void * b)1559 wp_compare(const void *a, const void *b)
1560 {
1561 const watched_page_t *pa = a;
1562 const watched_page_t *pb = b;
1563
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);
1570 }
1571
1572 /*
1573 * Given an address range, finds the first watched area which overlaps some or
1574 * all of the range.
1575 */
1576 watched_area_t *
pr_find_watched_area(proc_t * p,watched_area_t * pwa,avl_index_t * where)1577 pr_find_watched_area(proc_t *p, watched_area_t *pwa, avl_index_t *where)
1578 {
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;
1583
1584 /* First, check if there is an exact match. */
1585 wap = avl_find(&p->p_warea, pwa, &real_where);
1586
1587
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;
1594 }
1595
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;
1602 }
1603
1604 if (where)
1605 *where = real_where;
1606
1607 return (wap);
1608 }
1609
1610 void
watch_enable(kthread_id_t t)1611 watch_enable(kthread_id_t t)
1612 {
1613 t->t_proc_flag |= TP_WATCHPT;
1614 install_copyops(t, &watch_copyops);
1615 }
1616
1617 void
watch_disable(kthread_id_t t)1618 watch_disable(kthread_id_t t)
1619 {
1620 t->t_proc_flag &= ~TP_WATCHPT;
1621 remove_copyops(t);
1622 }
1623
1624 int
copyin_nowatch(const void * uaddr,void * kaddr,size_t len)1625 copyin_nowatch(const void *uaddr, void *kaddr, size_t len)
1626 {
1627 int watched, ret;
1628
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);
1633
1634 return (ret);
1635 }
1636
1637 int
copyout_nowatch(const void * kaddr,void * uaddr,size_t len)1638 copyout_nowatch(const void *kaddr, void *uaddr, size_t len)
1639 {
1640 int watched, ret;
1641
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);
1646
1647 return (ret);
1648 }
1649
1650 #ifdef _LP64
1651 int
fuword64_nowatch(const void * addr,uint64_t * value)1652 fuword64_nowatch(const void *addr, uint64_t *value)
1653 {
1654 int watched, ret;
1655
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);
1660
1661 return (ret);
1662 }
1663 #endif
1664
1665 int
fuword32_nowatch(const void * addr,uint32_t * value)1666 fuword32_nowatch(const void *addr, uint32_t *value)
1667 {
1668 int watched, ret;
1669
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);
1674
1675 return (ret);
1676 }
1677
1678 #ifdef _LP64
1679 int
suword64_nowatch(void * addr,uint64_t value)1680 suword64_nowatch(void *addr, uint64_t value)
1681 {
1682 int watched, ret;
1683
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);
1688
1689 return (ret);
1690 }
1691 #endif
1692
1693 int
suword32_nowatch(void * addr,uint32_t value)1694 suword32_nowatch(void *addr, uint32_t value)
1695 {
1696 int watched, ret;
1697
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);
1702
1703 return (ret);
1704 }
1705
1706 int
watch_disable_addr(const void * addr,size_t len,enum seg_rw rw)1707 watch_disable_addr(const void *addr, size_t len, enum seg_rw rw)
1708 {
1709 if (pr_watch_active(curproc))
1710 return (pr_mappage((caddr_t)addr, len, rw, 1));
1711 return (0);
1712 }
1713
1714 void
watch_enable_addr(const void * addr,size_t len,enum seg_rw rw)1715 watch_enable_addr(const void *addr, size_t len, enum seg_rw rw)
1716 {
1717 if (pr_watch_active(curproc))
1718 pr_unmappage((caddr_t)addr, len, rw, 1);
1719 }
1720