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
 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
 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
 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, &as->a_lock, 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, &as->a_lock);
 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
 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
 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
 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, &as->a_lock, 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, &as->a_lock);
 417 }
 418 
 419 
 420 
 421 int
 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
 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
 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
 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
 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
 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
 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
 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
 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
 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
 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
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
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
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
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
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
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
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
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
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
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
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
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
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
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 *
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
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
1618 watch_disable(kthread_id_t t)
1619 {
1620         t->t_proc_flag &= ~TP_WATCHPT;
1621         remove_copyops(t);
1622 }
1623 
1624 int
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
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
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
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
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
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
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
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 }