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.  Note that if an
 184          * as_fault() is servicing a fault to a watched page on behalf of an
 185          * XHAT provider, watchpoint will be temporarily cleared (and wp_prot
 186          * will be set to wp_oprot).  Since this is done while holding as writer
 187          * lock, we need to grab as lock (reader lock is good enough).
 188          *
 189          * p_maplock prevents simultaneous execution of this function.  Under
 190          * normal circumstances, holdwatch() will stop all other threads, so the
 191          * lock isn't really needed.  But there may be multiple threads within
 192          * stop() when SWATCHOK is set, so we need to handle multiple threads
 193          * at once.  See holdwatch() for the details of this dance.
 194          */
 195 
 196         mutex_enter(&p->p_maplock);
 197         AS_LOCK_ENTER(as, &as->a_lock, RW_READER);
 198 
 199         tpw.wp_vaddr = (caddr_t)((uintptr_t)addr & (uintptr_t)PAGEMASK);
 200         if ((pwp = avl_find(&as->a_wpage, &tpw, &where)) == NULL)
 201                 pwp = avl_nearest(&as->a_wpage, where, AVL_AFTER);
 202 
 203         for (; pwp != NULL && pwp->wp_vaddr < eaddr;
 204                 pwp = AVL_NEXT(&as->a_wpage, pwp)) {
 205 
 206                 /*
 207                  * If the requested protection has not been
 208                  * removed, we need not remap this page.
 209                  */
 210                 prot = pwp->wp_prot;
 211                 if (kernel || (prot & PROT_USER))
 212                         if (prot & prot_rw)
 213                                 continue;
 214                 /*
 215                  * If the requested access does not exist in the page's
 216                  * original protections, we need not remap this page.
 217                  * If the page does not exist yet, we can't test it.
 218                  */
 219                 if ((prot = pwp->wp_oprot) != 0) {
 220                         if (!(kernel || (prot & PROT_USER)))
 221                                 continue;
 222                         if (!(prot & prot_rw))
 223                                 continue;
 224                 }
 225 
 226                 if (mapin) {
 227                         /*
 228                          * Before mapping the page in, ensure that
 229                          * all other lwps are held in the kernel.
 230                          */
 231                         if (p->p_mapcnt == 0) {
 232                                 /*
 233                                  * Release as lock while in holdwatch()
 234                                  * in case other threads need to grab it.
 235                                  */
 236                                 AS_LOCK_EXIT(as, &as->a_lock);
 237                                 mutex_exit(&p->p_maplock);
 238                                 if (holdwatch() != 0) {
 239                                         /*
 240                                          * We stopped in holdwatch().
 241                                          * Start all over again because the
 242                                          * watched page list may have changed.
 243                                          */
 244                                         goto startover;
 245                                 }
 246                                 mutex_enter(&p->p_maplock);
 247                                 AS_LOCK_ENTER(as, &as->a_lock, RW_READER);
 248                         }
 249                         p->p_mapcnt++;
 250                 }
 251 
 252                 addr = pwp->wp_vaddr;
 253                 rv++;
 254 
 255                 prot = pwp->wp_prot;
 256                 if (mapin) {
 257                         if (kernel)
 258                                 pwp->wp_kmap[xrw]++;
 259                         else
 260                                 pwp->wp_umap[xrw]++;
 261                         pwp->wp_flags |= WP_NOWATCH;
 262                         if (pwp->wp_kmap[X] + pwp->wp_umap[X])
 263                                 /* cannot have exec-only protection */
 264                                 prot |= PROT_READ|PROT_EXEC;
 265                         if (pwp->wp_kmap[R] + pwp->wp_umap[R])
 266                                 prot |= PROT_READ;
 267                         if (pwp->wp_kmap[W] + pwp->wp_umap[W])
 268                                 /* cannot have write-only protection */
 269                                 prot |= PROT_READ|PROT_WRITE;
 270 #if 0   /* damned broken mmu feature! */
 271                         if (sum(pwp->wp_umap) == 0)
 272                                 prot &= ~PROT_USER;
 273 #endif
 274                 } else {
 275                         ASSERT(pwp->wp_flags & WP_NOWATCH);
 276                         if (kernel) {
 277                                 ASSERT(pwp->wp_kmap[xrw] != 0);
 278                                 --pwp->wp_kmap[xrw];
 279                         } else {
 280                                 ASSERT(pwp->wp_umap[xrw] != 0);
 281                                 --pwp->wp_umap[xrw];
 282                         }
 283                         if (sum(pwp->wp_kmap) + sum(pwp->wp_umap) == 0)
 284                                 pwp->wp_flags &= ~WP_NOWATCH;
 285                         else {
 286                                 if (pwp->wp_kmap[X] + pwp->wp_umap[X])
 287                                         /* cannot have exec-only protection */
 288                                         prot |= PROT_READ|PROT_EXEC;
 289                                 if (pwp->wp_kmap[R] + pwp->wp_umap[R])
 290                                         prot |= PROT_READ;
 291                                 if (pwp->wp_kmap[W] + pwp->wp_umap[W])
 292                                         /* cannot have write-only protection */
 293                                         prot |= PROT_READ|PROT_WRITE;
 294 #if 0   /* damned broken mmu feature! */
 295                                 if (sum(pwp->wp_umap) == 0)
 296                                         prot &= ~PROT_USER;
 297 #endif
 298                         }
 299                 }
 300 
 301 
 302                 if (pwp->wp_oprot != 0) {    /* if page exists */
 303                         struct seg *seg;
 304                         uint_t oprot;
 305                         int err, retrycnt = 0;
 306 
 307                         AS_LOCK_EXIT(as, &as->a_lock);
 308                         AS_LOCK_ENTER(as, &as->a_lock, RW_WRITER);
 309                 retry:
 310                         seg = as_segat(as, addr);
 311                         ASSERT(seg != NULL);
 312                         (void) segop_getprot(seg, addr, 0, &oprot);
 313                         if (prot != oprot) {
 314                                 err = segop_setprot(seg, addr, PAGESIZE, prot);
 315                                 if (err == IE_RETRY) {
 316                                         ASSERT(retrycnt == 0);
 317                                         retrycnt++;
 318                                         goto retry;
 319                                 }
 320                         }
 321                         AS_LOCK_EXIT(as, &as->a_lock);
 322                 } else
 323                         AS_LOCK_EXIT(as, &as->a_lock);
 324 
 325                 /*
 326                  * When all pages are mapped back to their normal state,
 327                  * continue the other lwps.
 328                  */
 329                 if (!mapin) {
 330                         ASSERT(p->p_mapcnt > 0);
 331                         p->p_mapcnt--;
 332                         if (p->p_mapcnt == 0) {
 333                                 mutex_exit(&p->p_maplock);
 334                                 mutex_enter(&p->p_lock);
 335                                 continuelwps(p);
 336                                 mutex_exit(&p->p_lock);
 337                                 mutex_enter(&p->p_maplock);
 338                         }
 339                 }
 340 
 341                 AS_LOCK_ENTER(as, &as->a_lock, RW_READER);
 342         }
 343 
 344         AS_LOCK_EXIT(as, &as->a_lock);
 345         mutex_exit(&p->p_maplock);
 346 
 347         return (rv);
 348 }
 349 
 350 /*
 351  * Restore the original page protections on an address range.
 352  * If 'kernel' is non-zero, just do it for the kernel.
 353  * pr_mappage() returns non-zero if it actually changed anything.
 354  *
 355  * pr_mappage() and pr_unmappage() must be executed in matched pairs,
 356  * but pairs may be nested within other pairs.  The reference counts
 357  * sort it all out.  See pr_do_mappage(), above.
 358  */
 359 static int
 360 pr_mappage(const caddr_t addr, size_t size, enum seg_rw rw, int kernel)
 361 {
 362         return (pr_do_mappage(addr, size, 1, rw, kernel));
 363 }
 364 
 365 /*
 366  * Set the modified page protections on a watched page.
 367  * Inverse of pr_mappage().
 368  * Needs to be called only if pr_mappage() returned non-zero.
 369  */
 370 static void
 371 pr_unmappage(const caddr_t addr, size_t size, enum seg_rw rw, int kernel)
 372 {
 373         (void) pr_do_mappage(addr, size, 0, rw, kernel);
 374 }
 375 
 376 /*
 377  * Function called by an lwp after it resumes from stop().
 378  */
 379 void
 380 setallwatch(void)
 381 {
 382         proc_t *p = curproc;
 383         struct as *as = curproc->p_as;
 384         struct watched_page *pwp, *next;
 385         struct seg *seg;
 386         caddr_t vaddr;
 387         uint_t prot;
 388         int err, retrycnt;
 389 
 390         if (p->p_wprot == NULL)
 391                 return;
 392 
 393         ASSERT(MUTEX_NOT_HELD(&curproc->p_lock));
 394 
 395         AS_LOCK_ENTER(as, &as->a_lock, RW_WRITER);
 396 
 397         pwp = p->p_wprot;
 398         while (pwp != NULL) {
 399 
 400                 vaddr = pwp->wp_vaddr;
 401                 retrycnt = 0;
 402         retry:
 403                 ASSERT(pwp->wp_flags & WP_SETPROT);
 404                 if ((seg = as_segat(as, vaddr)) != NULL &&
 405                     !(pwp->wp_flags & WP_NOWATCH)) {
 406                         prot = pwp->wp_prot;
 407                         err = segop_setprot(seg, vaddr, PAGESIZE, prot);
 408                         if (err == IE_RETRY) {
 409                                 ASSERT(retrycnt == 0);
 410                                 retrycnt++;
 411                                 goto retry;
 412                         }
 413                 }
 414 
 415                 next = pwp->wp_list;
 416 
 417                 if (pwp->wp_read + pwp->wp_write + pwp->wp_exec == 0) {
 418                         /*
 419                          * No watched areas remain in this page.
 420                          * Free the watched_page structure.
 421                          */
 422                         avl_remove(&as->a_wpage, pwp);
 423                         kmem_free(pwp, sizeof (struct watched_page));
 424                 } else {
 425                         pwp->wp_flags &= ~WP_SETPROT;
 426                 }
 427 
 428                 pwp = next;
 429         }
 430         p->p_wprot = NULL;
 431 
 432         AS_LOCK_EXIT(as, &as->a_lock);
 433 }
 434 
 435 
 436 
 437 /* Must be called with as lock held */
 438 int
 439 pr_is_watchpage_as(caddr_t addr, enum seg_rw rw, struct as *as)
 440 {
 441         register struct watched_page *pwp;
 442         struct watched_page tpw;
 443         uint_t prot;
 444         int rv = 0;
 445 
 446         switch (rw) {
 447         case S_READ:
 448         case S_WRITE:
 449         case S_EXEC:
 450                 break;
 451         default:
 452                 return (0);
 453         }
 454 
 455         /*
 456          * as->a_wpage can only be modified while the process is totally
 457          * stopped.  We need, and should use, no locks here.
 458          */
 459         if (as != &kas && avl_numnodes(&as->a_wpage) != 0) {
 460                 tpw.wp_vaddr = (caddr_t)((uintptr_t)addr & (uintptr_t)PAGEMASK);
 461                 pwp = avl_find(&as->a_wpage, &tpw, NULL);
 462                 if (pwp != NULL) {
 463                         ASSERT(addr >= pwp->wp_vaddr &&
 464                             addr < pwp->wp_vaddr + PAGESIZE);
 465                         if (pwp->wp_oprot != 0) {
 466                                 prot = pwp->wp_prot;
 467                                 switch (rw) {
 468                                 case S_READ:
 469                                         rv = ((prot & (PROT_USER|PROT_READ))
 470                                                 != (PROT_USER|PROT_READ));
 471                                         break;
 472                                 case S_WRITE:
 473                                         rv = ((prot & (PROT_USER|PROT_WRITE))
 474                                                 != (PROT_USER|PROT_WRITE));
 475                                         break;
 476                                 case S_EXEC:
 477                                         rv = ((prot & (PROT_USER|PROT_EXEC))
 478                                                 != (PROT_USER|PROT_EXEC));
 479                                         break;
 480                                 default:
 481                                         /* can't happen! */
 482                                         break;
 483                                 }
 484                         }
 485                 }
 486         }
 487 
 488         return (rv);
 489 }
 490 
 491 
 492 /*
 493  * trap() calls here to determine if a fault is in a watched page.
 494  * We return nonzero if this is true and the load/store would fail.
 495  */
 496 int
 497 pr_is_watchpage(caddr_t addr, enum seg_rw rw)
 498 {
 499         struct as *as = curproc->p_as;
 500         int rv;
 501 
 502         if ((as == &kas) || avl_numnodes(&as->a_wpage) == 0)
 503                 return (0);
 504 
 505         /* Grab the lock because of XHAT (see comment in pr_mappage()) */
 506         AS_LOCK_ENTER(as, &as->a_lock, RW_READER);
 507         rv = pr_is_watchpage_as(addr, rw, as);
 508         AS_LOCK_EXIT(as, &as->a_lock);
 509 
 510         return (rv);
 511 }
 512 
 513 
 514 
 515 /*
 516  * trap() calls here to determine if a fault is a watchpoint.
 517  */
 518 int
 519 pr_is_watchpoint(caddr_t *paddr, int *pta, size_t size, size_t *plen,
 520         enum seg_rw rw)
 521 {
 522         proc_t *p = curproc;
 523         caddr_t addr = *paddr;
 524         caddr_t eaddr = addr + size;
 525         register struct watched_area *pwa;
 526         struct watched_area twa;
 527         int rv = 0;
 528         int ta = 0;
 529         size_t len = 0;
 530 
 531         switch (rw) {
 532         case S_READ:
 533         case S_WRITE:
 534         case S_EXEC:
 535                 break;
 536         default:
 537                 *pta = 0;
 538                 return (0);
 539         }
 540 
 541         /*
 542          * p->p_warea is protected by p->p_lock.
 543          */
 544         mutex_enter(&p->p_lock);
 545 
 546         /* BEGIN CSTYLED */
 547         /*
 548          * This loop is somewhat complicated because the fault region can span
 549          * multiple watched areas.  For example:
 550          *
 551          *            addr              eaddr
 552          *              +-----------------+
 553          *              | fault region    |
 554          *      +-------+--------+----+---+------------+
 555          *      | prot not right |    | prot correct   |
 556          *      +----------------+    +----------------+
 557          *    wa_vaddr        wa_eaddr
 558          *                    wa_vaddr          wa_eaddr
 559          *
 560          * We start at the area greater than or equal to the starting address.
 561          * As long as some portion of the fault region overlaps the current
 562          * area, we continue checking permissions until we find an appropriate
 563          * match.
 564          */
 565         /* END CSTYLED */
 566         twa.wa_vaddr = addr;
 567         twa.wa_eaddr = eaddr;
 568 
 569         for (pwa = pr_find_watched_area(p, &twa, NULL);
 570             pwa != NULL && eaddr > pwa->wa_vaddr && addr < pwa->wa_eaddr;
 571             pwa = AVL_NEXT(&p->p_warea, pwa)) {
 572 
 573                 switch (rw) {
 574                 case S_READ:
 575                         if (pwa->wa_flags & WA_READ)
 576                                 rv = TRAP_RWATCH;
 577                         break;
 578                 case S_WRITE:
 579                         if (pwa->wa_flags & WA_WRITE)
 580                                 rv = TRAP_WWATCH;
 581                         break;
 582                 case S_EXEC:
 583                         if (pwa->wa_flags & WA_EXEC)
 584                                 rv = TRAP_XWATCH;
 585                         break;
 586                 default:
 587                         /* can't happen */
 588                         break;
 589                 }
 590 
 591                 /*
 592                  * If protections didn't match, check the next watched
 593                  * area
 594                  */
 595                 if (rv != 0) {
 596                         if (addr < pwa->wa_vaddr)
 597                                 addr = pwa->wa_vaddr;
 598                         len = pwa->wa_eaddr - addr;
 599                         if (pwa->wa_flags & WA_TRAPAFTER)
 600                                 ta = 1;
 601                         break;
 602                 }
 603         }
 604 
 605         mutex_exit(&p->p_lock);
 606 
 607         *paddr = addr;
 608         *pta = ta;
 609         if (plen != NULL)
 610                 *plen = len;
 611         return (rv);
 612 }
 613 
 614 /*
 615  * Set up to perform a single-step at user level for the
 616  * case of a trapafter watchpoint.  Called from trap().
 617  */
 618 void
 619 do_watch_step(caddr_t vaddr, size_t sz, enum seg_rw rw,
 620         int watchcode, greg_t pc)
 621 {
 622         register klwp_t *lwp = ttolwp(curthread);
 623         struct lwp_watch *pw = &lwp->lwp_watch[rw_to_index(rw)];
 624 
 625         /*
 626          * Check to see if we are already performing this special
 627          * watchpoint single-step.  We must not do pr_mappage() twice.
 628          */
 629 
 630         /* special check for two read traps on the same instruction */
 631         if (rw == S_READ && pw->wpaddr != NULL &&
 632             !(pw->wpaddr <= vaddr && vaddr < pw->wpaddr + pw->wpsize)) {
 633                 ASSERT(lwp->lwp_watchtrap != 0);
 634                 pw++;   /* use the extra S_READ struct */
 635         }
 636 
 637         if (pw->wpaddr != NULL) {
 638                 ASSERT(lwp->lwp_watchtrap != 0);
 639                 ASSERT(pw->wpaddr <= vaddr && vaddr < pw->wpaddr + pw->wpsize);
 640                 if (pw->wpcode == 0) {
 641                         pw->wpcode = watchcode;
 642                         pw->wppc = pc;
 643                 }
 644         } else {
 645                 int mapped = pr_mappage(vaddr, sz, rw, 0);
 646                 prstep(lwp, 1);
 647                 lwp->lwp_watchtrap = 1;
 648                 pw->wpaddr = vaddr;
 649                 pw->wpsize = sz;
 650                 pw->wpcode = watchcode;
 651                 pw->wpmapped = mapped;
 652                 pw->wppc = pc;
 653         }
 654 }
 655 
 656 /*
 657  * Undo the effects of do_watch_step().
 658  * Called from trap() after the single-step is finished.
 659  * Also called from issig_forreal() and stop() with a NULL
 660  * argument to avoid having these things set more than once.
 661  */
 662 int
 663 undo_watch_step(k_siginfo_t *sip)
 664 {
 665         register klwp_t *lwp = ttolwp(curthread);
 666         int fault = 0;
 667 
 668         if (lwp->lwp_watchtrap) {
 669                 struct lwp_watch *pw = lwp->lwp_watch;
 670                 int i;
 671 
 672                 for (i = 0; i < 4; i++, pw++) {
 673                         if (pw->wpaddr == NULL)
 674                                 continue;
 675                         if (pw->wpmapped)
 676                                 pr_unmappage(pw->wpaddr, pw->wpsize, S_rw[i],
 677                                     0);
 678                         if (pw->wpcode != 0) {
 679                                 if (sip != NULL) {
 680                                         sip->si_signo = SIGTRAP;
 681                                         sip->si_code = pw->wpcode;
 682                                         sip->si_addr = pw->wpaddr;
 683                                         sip->si_trapafter = 1;
 684                                         sip->si_pc = (caddr_t)pw->wppc;
 685                                 }
 686                                 fault = FLTWATCH;
 687                                 pw->wpcode = 0;
 688                         }
 689                         pw->wpaddr = NULL;
 690                         pw->wpsize = 0;
 691                         pw->wpmapped = 0;
 692                 }
 693                 lwp->lwp_watchtrap = 0;
 694         }
 695 
 696         return (fault);
 697 }
 698 
 699 /*
 700  * Handle a watchpoint that occurs while doing copyin()
 701  * or copyout() in a system call.
 702  * Return non-zero if the fault or signal is cleared
 703  * by a debugger while the lwp is stopped.
 704  */
 705 static int
 706 sys_watchpoint(caddr_t addr, int watchcode, int ta)
 707 {
 708         extern greg_t getuserpc(void);  /* XXX header file */
 709         k_sigset_t smask;
 710         register proc_t *p = ttoproc(curthread);
 711         register klwp_t *lwp = ttolwp(curthread);
 712         register sigqueue_t *sqp;
 713         int rval;
 714 
 715         /* assert no locks are held */
 716         /* ASSERT(curthread->t_nlocks == 0); */
 717 
 718         sqp = kmem_zalloc(sizeof (sigqueue_t), KM_SLEEP);
 719         sqp->sq_info.si_signo = SIGTRAP;
 720         sqp->sq_info.si_code = watchcode;
 721         sqp->sq_info.si_addr = addr;
 722         sqp->sq_info.si_trapafter = ta;
 723         sqp->sq_info.si_pc = (caddr_t)getuserpc();
 724 
 725         mutex_enter(&p->p_lock);
 726 
 727         /* this will be tested and cleared by the caller */
 728         lwp->lwp_sysabort = 0;
 729 
 730         if (prismember(&p->p_fltmask, FLTWATCH)) {
 731                 lwp->lwp_curflt = (uchar_t)FLTWATCH;
 732                 lwp->lwp_siginfo = sqp->sq_info;
 733                 stop(PR_FAULTED, FLTWATCH);
 734                 if (lwp->lwp_curflt == 0) {
 735                         mutex_exit(&p->p_lock);
 736                         kmem_free(sqp, sizeof (sigqueue_t));
 737                         return (1);
 738                 }
 739                 lwp->lwp_curflt = 0;
 740         }
 741 
 742         /*
 743          * post the SIGTRAP signal.
 744          * Block all other signals so we only stop showing SIGTRAP.
 745          */
 746         if (signal_is_blocked(curthread, SIGTRAP) ||
 747             sigismember(&p->p_ignore, SIGTRAP)) {
 748                 /* SIGTRAP is blocked or ignored, forget the rest. */
 749                 mutex_exit(&p->p_lock);
 750                 kmem_free(sqp, sizeof (sigqueue_t));
 751                 return (0);
 752         }
 753         sigdelq(p, curthread, SIGTRAP);
 754         sigaddqa(p, curthread, sqp);
 755         schedctl_finish_sigblock(curthread);
 756         smask = curthread->t_hold;
 757         sigfillset(&curthread->t_hold);
 758         sigdiffset(&curthread->t_hold, &cantmask);
 759         sigdelset(&curthread->t_hold, SIGTRAP);
 760         mutex_exit(&p->p_lock);
 761 
 762         rval = ((ISSIG_FAST(curthread, lwp, p, FORREAL))? 0 : 1);
 763 
 764         /* restore the original signal mask */
 765         mutex_enter(&p->p_lock);
 766         curthread->t_hold = smask;
 767         mutex_exit(&p->p_lock);
 768 
 769         return (rval);
 770 }
 771 
 772 /*
 773  * Wrappers for the copyin()/copyout() functions to deal
 774  * with watchpoints that fire while in system calls.
 775  */
 776 
 777 static int
 778 watch_xcopyin(const void *uaddr, void *kaddr, size_t count)
 779 {
 780         klwp_t *lwp = ttolwp(curthread);
 781         caddr_t watch_uaddr = (caddr_t)uaddr;
 782         caddr_t watch_kaddr = (caddr_t)kaddr;
 783         int error = 0;
 784         label_t ljb;
 785         size_t part;
 786         int mapped;
 787 
 788         while (count && error == 0) {
 789                 int watchcode;
 790                 caddr_t vaddr;
 791                 size_t len;
 792                 int ta;
 793 
 794                 if ((part = PAGESIZE -
 795                     (((uintptr_t)uaddr) & PAGEOFFSET)) > count)
 796                         part = count;
 797 
 798                 if (!pr_is_watchpage(watch_uaddr, S_READ))
 799                         watchcode = 0;
 800                 else {
 801                         vaddr = watch_uaddr;
 802                         watchcode = pr_is_watchpoint(&vaddr, &ta,
 803                             part, &len, S_READ);
 804                         if (watchcode && ta == 0)
 805                                 part = vaddr - watch_uaddr;
 806                 }
 807 
 808                 /*
 809                  * Copy the initial part, up to a watched address, if any.
 810                  */
 811                 if (part != 0) {
 812                         mapped = pr_mappage(watch_uaddr, part, S_READ, 1);
 813                         if (on_fault(&ljb))
 814                                 error = EFAULT;
 815                         else
 816                                 copyin_noerr(watch_uaddr, watch_kaddr, part);
 817                         no_fault();
 818                         if (mapped)
 819                                 pr_unmappage(watch_uaddr, part, S_READ, 1);
 820                         watch_uaddr += part;
 821                         watch_kaddr += part;
 822                         count -= part;
 823                 }
 824                 /*
 825                  * If trapafter was specified, then copy through the
 826                  * watched area before taking the watchpoint trap.
 827                  */
 828                 while (count && watchcode && ta && len > part && error == 0) {
 829                         len -= part;
 830                         if ((part = PAGESIZE) > count)
 831                                 part = count;
 832                         if (part > len)
 833                                 part = len;
 834                         mapped = pr_mappage(watch_uaddr, part, S_READ, 1);
 835                         if (on_fault(&ljb))
 836                                 error = EFAULT;
 837                         else
 838                                 copyin_noerr(watch_uaddr, watch_kaddr, part);
 839                         no_fault();
 840                         if (mapped)
 841                                 pr_unmappage(watch_uaddr, part, S_READ, 1);
 842                         watch_uaddr += part;
 843                         watch_kaddr += part;
 844                         count -= part;
 845                 }
 846 
 847 error:
 848                 /* if we hit a watched address, do the watchpoint logic */
 849                 if (watchcode &&
 850                     (!sys_watchpoint(vaddr, watchcode, ta) ||
 851                     lwp->lwp_sysabort)) {
 852                         lwp->lwp_sysabort = 0;
 853                         error = EFAULT;
 854                         break;
 855                 }
 856         }
 857 
 858         return (error);
 859 }
 860 
 861 static int
 862 watch_copyin(const void *kaddr, void *uaddr, size_t count)
 863 {
 864         return (watch_xcopyin(kaddr, uaddr, count) ? -1 : 0);
 865 }
 866 
 867 
 868 static int
 869 watch_xcopyout(const void *kaddr, void *uaddr, size_t count)
 870 {
 871         klwp_t *lwp = ttolwp(curthread);
 872         caddr_t watch_uaddr = (caddr_t)uaddr;
 873         caddr_t watch_kaddr = (caddr_t)kaddr;
 874         int error = 0;
 875         label_t ljb;
 876 
 877         while (count && error == 0) {
 878                 int watchcode;
 879                 caddr_t vaddr;
 880                 size_t part;
 881                 size_t len;
 882                 int ta;
 883                 int mapped;
 884 
 885                 if ((part = PAGESIZE -
 886                     (((uintptr_t)uaddr) & PAGEOFFSET)) > count)
 887                         part = count;
 888 
 889                 if (!pr_is_watchpage(watch_uaddr, S_WRITE))
 890                         watchcode = 0;
 891                 else {
 892                         vaddr = watch_uaddr;
 893                         watchcode = pr_is_watchpoint(&vaddr, &ta,
 894                             part, &len, S_WRITE);
 895                         if (watchcode) {
 896                                 if (ta == 0)
 897                                         part = vaddr - watch_uaddr;
 898                                 else {
 899                                         len += vaddr - watch_uaddr;
 900                                         if (part > len)
 901                                                 part = len;
 902                                 }
 903                         }
 904                 }
 905 
 906                 /*
 907                  * Copy the initial part, up to a watched address, if any.
 908                  */
 909                 if (part != 0) {
 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                 /*
 924                  * If trapafter was specified, then copy through the
 925                  * watched area before taking the watchpoint trap.
 926                  */
 927                 while (count && watchcode && ta && len > part && error == 0) {
 928                         len -= part;
 929                         if ((part = PAGESIZE) > count)
 930                                 part = count;
 931                         if (part > len)
 932                                 part = len;
 933                         mapped = pr_mappage(watch_uaddr, part, S_WRITE, 1);
 934                         if (on_fault(&ljb))
 935                                 error = EFAULT;
 936                         else
 937                                 copyout_noerr(watch_kaddr, watch_uaddr, part);
 938                         no_fault();
 939                         if (mapped)
 940                                 pr_unmappage(watch_uaddr, part, S_WRITE, 1);
 941                         watch_uaddr += part;
 942                         watch_kaddr += part;
 943                         count -= part;
 944                 }
 945 
 946                 /* if we hit a watched address, do the watchpoint logic */
 947                 if (watchcode &&
 948                     (!sys_watchpoint(vaddr, watchcode, ta) ||
 949                     lwp->lwp_sysabort)) {
 950                         lwp->lwp_sysabort = 0;
 951                         error = EFAULT;
 952                         break;
 953                 }
 954         }
 955 
 956         return (error);
 957 }
 958 
 959 static int
 960 watch_copyout(const void *kaddr, void *uaddr, size_t count)
 961 {
 962         return (watch_xcopyout(kaddr, uaddr, count) ? -1 : 0);
 963 }
 964 
 965 static int
 966 watch_copyinstr(
 967         const char *uaddr,
 968         char *kaddr,
 969         size_t maxlength,
 970         size_t *lencopied)
 971 {
 972         klwp_t *lwp = ttolwp(curthread);
 973         size_t resid;
 974         int error = 0;
 975         label_t ljb;
 976 
 977         if ((resid = maxlength) == 0)
 978                 return (ENAMETOOLONG);
 979 
 980         while (resid && error == 0) {
 981                 int watchcode;
 982                 caddr_t vaddr;
 983                 size_t part;
 984                 size_t len;
 985                 size_t size;
 986                 int ta;
 987                 int mapped;
 988 
 989                 if ((part = PAGESIZE -
 990                     (((uintptr_t)uaddr) & PAGEOFFSET)) > resid)
 991                         part = resid;
 992 
 993                 if (!pr_is_watchpage((caddr_t)uaddr, S_READ))
 994                         watchcode = 0;
 995                 else {
 996                         vaddr = (caddr_t)uaddr;
 997                         watchcode = pr_is_watchpoint(&vaddr, &ta,
 998                             part, &len, S_READ);
 999                         if (watchcode) {
1000                                 if (ta == 0)
1001                                         part = vaddr - uaddr;
1002                                 else {
1003                                         len += vaddr - uaddr;
1004                                         if (part > len)
1005                                                 part = len;
1006                                 }
1007                         }
1008                 }
1009 
1010                 /*
1011                  * Copy the initial part, up to a watched address, if any.
1012                  */
1013                 if (part != 0) {
1014                         mapped = pr_mappage((caddr_t)uaddr, part, S_READ, 1);
1015                         if (on_fault(&ljb))
1016                                 error = EFAULT;
1017                         else
1018                                 error = copyinstr_noerr(uaddr, kaddr, part,
1019                                     &size);
1020                         no_fault();
1021                         if (mapped)
1022                                 pr_unmappage((caddr_t)uaddr, part, S_READ, 1);
1023                         uaddr += size;
1024                         kaddr += size;
1025                         resid -= size;
1026                         if (error == ENAMETOOLONG && resid > 0)
1027                             error = 0;
1028                         if (error != 0 || (watchcode &&
1029                             (uaddr < vaddr || kaddr[-1] == '\0')))
1030                                 break;  /* didn't reach the watched area */
1031                 }
1032 
1033                 /*
1034                  * If trapafter was specified, then copy through the
1035                  * watched area before taking the watchpoint trap.
1036                  */
1037                 while (resid && watchcode && ta && len > part && error == 0 &&
1038                     size == part && kaddr[-1] != '\0') {
1039                         len -= part;
1040                         if ((part = PAGESIZE) > resid)
1041                                 part = resid;
1042                         if (part > len)
1043                                 part = len;
1044                         mapped = pr_mappage((caddr_t)uaddr, part, S_READ, 1);
1045                         if (on_fault(&ljb))
1046                                 error = EFAULT;
1047                         else
1048                                 error = copyinstr_noerr(uaddr, kaddr, part,
1049                                     &size);
1050                         no_fault();
1051                         if (mapped)
1052                                 pr_unmappage((caddr_t)uaddr, part, S_READ, 1);
1053                         uaddr += size;
1054                         kaddr += size;
1055                         resid -= size;
1056                         if (error == ENAMETOOLONG && resid > 0)
1057                             error = 0;
1058                 }
1059 
1060                 /* if we hit a watched address, do the watchpoint logic */
1061                 if (watchcode &&
1062                     (!sys_watchpoint(vaddr, watchcode, ta) ||
1063                     lwp->lwp_sysabort)) {
1064                         lwp->lwp_sysabort = 0;
1065                         error = EFAULT;
1066                         break;
1067                 }
1068 
1069                 if (error == 0 && part != 0 &&
1070                     (size < part || kaddr[-1] == '\0'))
1071                         break;
1072         }
1073 
1074         if (error != EFAULT && lencopied)
1075                 *lencopied = maxlength - resid;
1076         return (error);
1077 }
1078 
1079 static int
1080 watch_copyoutstr(
1081         const char *kaddr,
1082         char *uaddr,
1083         size_t maxlength,
1084         size_t *lencopied)
1085 {
1086         klwp_t *lwp = ttolwp(curthread);
1087         size_t resid;
1088         int error = 0;
1089         label_t ljb;
1090 
1091         if ((resid = maxlength) == 0)
1092                 return (ENAMETOOLONG);
1093 
1094         while (resid && error == 0) {
1095                 int watchcode;
1096                 caddr_t vaddr;
1097                 size_t part;
1098                 size_t len;
1099                 size_t size;
1100                 int ta;
1101                 int mapped;
1102 
1103                 if ((part = PAGESIZE -
1104                     (((uintptr_t)uaddr) & PAGEOFFSET)) > resid)
1105                         part = resid;
1106 
1107                 if (!pr_is_watchpage(uaddr, S_WRITE)) {
1108                         watchcode = 0;
1109                 } else {
1110                         vaddr = uaddr;
1111                         watchcode = pr_is_watchpoint(&vaddr, &ta,
1112                             part, &len, S_WRITE);
1113                         if (watchcode && ta == 0)
1114                                 part = vaddr - uaddr;
1115                 }
1116 
1117                 /*
1118                  * Copy the initial part, up to a watched address, if any.
1119                  */
1120                 if (part != 0) {
1121                         mapped = pr_mappage(uaddr, part, S_WRITE, 1);
1122                         if (on_fault(&ljb))
1123                                 error = EFAULT;
1124                         else
1125                                 error = copyoutstr_noerr(kaddr, uaddr, part,
1126                                     &size);
1127                         no_fault();
1128                         if (mapped)
1129                                 pr_unmappage(uaddr, part, S_WRITE, 1);
1130                         uaddr += size;
1131                         kaddr += size;
1132                         resid -= size;
1133                         if (error == ENAMETOOLONG && resid > 0)
1134                             error = 0;
1135                         if (error != 0 || (watchcode &&
1136                             (uaddr < vaddr || kaddr[-1] == '\0')))
1137                                 break;  /* didn't reach the watched area */
1138                 }
1139 
1140                 /*
1141                  * If trapafter was specified, then copy through the
1142                  * watched area before taking the watchpoint trap.
1143                  */
1144                 while (resid && watchcode && ta && len > part && error == 0 &&
1145                     size == part && kaddr[-1] != '\0') {
1146                         len -= part;
1147                         if ((part = PAGESIZE) > resid)
1148                                 part = resid;
1149                         if (part > len)
1150                                 part = len;
1151                         mapped = pr_mappage(uaddr, part, S_WRITE, 1);
1152                         if (on_fault(&ljb))
1153                                 error = EFAULT;
1154                         else
1155                                 error = copyoutstr_noerr(kaddr, uaddr, part,
1156                                     &size);
1157                         no_fault();
1158                         if (mapped)
1159                                 pr_unmappage(uaddr, part, S_WRITE, 1);
1160                         uaddr += size;
1161                         kaddr += size;
1162                         resid -= size;
1163                         if (error == ENAMETOOLONG && resid > 0)
1164                             error = 0;
1165                 }
1166 
1167                 /* if we hit a watched address, do the watchpoint logic */
1168                 if (watchcode &&
1169                     (!sys_watchpoint(vaddr, watchcode, ta) ||
1170                     lwp->lwp_sysabort)) {
1171                         lwp->lwp_sysabort = 0;
1172                         error = EFAULT;
1173                         break;
1174                 }
1175 
1176                 if (error == 0 && part != 0 &&
1177                     (size < part || kaddr[-1] == '\0'))
1178                         break;
1179         }
1180 
1181         if (error != EFAULT && lencopied)
1182                 *lencopied = maxlength - resid;
1183         return (error);
1184 }
1185 
1186 typedef int (*fuword_func)(const void *, void *);
1187 
1188 /*
1189  * Generic form of watch_fuword8(), watch_fuword16(), etc.
1190  */
1191 static int
1192 watch_fuword(const void *addr, void *dst, fuword_func func, size_t size)
1193 {
1194         klwp_t *lwp = ttolwp(curthread);
1195         int watchcode;
1196         caddr_t vaddr;
1197         int mapped;
1198         int rv = 0;
1199         int ta;
1200         label_t ljb;
1201 
1202         for (;;) {
1203 
1204                 vaddr = (caddr_t)addr;
1205                 watchcode = pr_is_watchpoint(&vaddr, &ta, size, NULL, S_READ);
1206                 if (watchcode == 0 || ta != 0) {
1207                         mapped = pr_mappage((caddr_t)addr, size, S_READ, 1);
1208                         if (on_fault(&ljb))
1209                                 rv = -1;
1210                         else
1211                                 (*func)(addr, dst);
1212                         no_fault();
1213                         if (mapped)
1214                                 pr_unmappage((caddr_t)addr, size, S_READ, 1);
1215                 }
1216                 if (watchcode &&
1217                     (!sys_watchpoint(vaddr, watchcode, ta) ||
1218                     lwp->lwp_sysabort)) {
1219                         lwp->lwp_sysabort = 0;
1220                         rv = -1;
1221                         break;
1222                 }
1223                 if (watchcode == 0 || ta != 0)
1224                         break;
1225         }
1226 
1227         return (rv);
1228 }
1229 
1230 static int
1231 watch_fuword8(const void *addr, uint8_t *dst)
1232 {
1233         return (watch_fuword(addr, dst, (fuword_func)fuword8_noerr,
1234             sizeof (*dst)));
1235 }
1236 
1237 static int
1238 watch_fuword16(const void *addr, uint16_t *dst)
1239 {
1240         return (watch_fuword(addr, dst, (fuword_func)fuword16_noerr,
1241             sizeof (*dst)));
1242 }
1243 
1244 static int
1245 watch_fuword32(const void *addr, uint32_t *dst)
1246 {
1247         return (watch_fuword(addr, dst, (fuword_func)fuword32_noerr,
1248             sizeof (*dst)));
1249 }
1250 
1251 #ifdef _LP64
1252 static int
1253 watch_fuword64(const void *addr, uint64_t *dst)
1254 {
1255         return (watch_fuword(addr, dst, (fuword_func)fuword64_noerr,
1256             sizeof (*dst)));
1257 }
1258 #endif
1259 
1260 
1261 static int
1262 watch_suword8(void *addr, uint8_t value)
1263 {
1264         klwp_t *lwp = ttolwp(curthread);
1265         int watchcode;
1266         caddr_t vaddr;
1267         int mapped;
1268         int rv = 0;
1269         int ta;
1270         label_t ljb;
1271 
1272         for (;;) {
1273 
1274                 vaddr = (caddr_t)addr;
1275                 watchcode = pr_is_watchpoint(&vaddr, &ta, sizeof (value), NULL,
1276                     S_WRITE);
1277                 if (watchcode == 0 || ta != 0) {
1278                         mapped = pr_mappage((caddr_t)addr, sizeof (value),
1279                             S_WRITE, 1);
1280                         if (on_fault(&ljb))
1281                                 rv = -1;
1282                         else
1283                                 suword8_noerr(addr, value);
1284                         no_fault();
1285                         if (mapped)
1286                                 pr_unmappage((caddr_t)addr, sizeof (value),
1287                                     S_WRITE, 1);
1288                 }
1289                 if (watchcode &&
1290                     (!sys_watchpoint(vaddr, watchcode, ta) ||
1291                     lwp->lwp_sysabort)) {
1292                         lwp->lwp_sysabort = 0;
1293                         rv = -1;
1294                         break;
1295                 }
1296                 if (watchcode == 0 || ta != 0)
1297                         break;
1298         }
1299 
1300         return (rv);
1301 }
1302 
1303 static int
1304 watch_suword16(void *addr, uint16_t value)
1305 {
1306         klwp_t *lwp = ttolwp(curthread);
1307         int watchcode;
1308         caddr_t vaddr;
1309         int mapped;
1310         int rv = 0;
1311         int ta;
1312         label_t ljb;
1313 
1314         for (;;) {
1315 
1316                 vaddr = (caddr_t)addr;
1317                 watchcode = pr_is_watchpoint(&vaddr, &ta, sizeof (value), NULL,
1318                     S_WRITE);
1319                 if (watchcode == 0 || ta != 0) {
1320                         mapped = pr_mappage((caddr_t)addr, sizeof (value),
1321                             S_WRITE, 1);
1322                         if (on_fault(&ljb))
1323                                 rv = -1;
1324                         else
1325                                 suword16_noerr(addr, value);
1326                         no_fault();
1327                         if (mapped)
1328                                 pr_unmappage((caddr_t)addr, sizeof (value),
1329                                     S_WRITE, 1);
1330                 }
1331                 if (watchcode &&
1332                     (!sys_watchpoint(vaddr, watchcode, ta) ||
1333                     lwp->lwp_sysabort)) {
1334                         lwp->lwp_sysabort = 0;
1335                         rv = -1;
1336                         break;
1337                 }
1338                 if (watchcode == 0 || ta != 0)
1339                         break;
1340         }
1341 
1342         return (rv);
1343 }
1344 
1345 static int
1346 watch_suword32(void *addr, uint32_t value)
1347 {
1348         klwp_t *lwp = ttolwp(curthread);
1349         int watchcode;
1350         caddr_t vaddr;
1351         int mapped;
1352         int rv = 0;
1353         int ta;
1354         label_t ljb;
1355 
1356         for (;;) {
1357 
1358                 vaddr = (caddr_t)addr;
1359                 watchcode = pr_is_watchpoint(&vaddr, &ta, sizeof (value), NULL,
1360                     S_WRITE);
1361                 if (watchcode == 0 || ta != 0) {
1362                         mapped = pr_mappage((caddr_t)addr, sizeof (value),
1363                             S_WRITE, 1);
1364                         if (on_fault(&ljb))
1365                                 rv = -1;
1366                         else
1367                                 suword32_noerr(addr, value);
1368                         no_fault();
1369                         if (mapped)
1370                                 pr_unmappage((caddr_t)addr, sizeof (value),
1371                                     S_WRITE, 1);
1372                 }
1373                 if (watchcode &&
1374                     (!sys_watchpoint(vaddr, watchcode, ta) ||
1375                     lwp->lwp_sysabort)) {
1376                         lwp->lwp_sysabort = 0;
1377                         rv = -1;
1378                         break;
1379                 }
1380                 if (watchcode == 0 || ta != 0)
1381                         break;
1382         }
1383 
1384         return (rv);
1385 }
1386 
1387 #ifdef _LP64
1388 static int
1389 watch_suword64(void *addr, uint64_t value)
1390 {
1391         klwp_t *lwp = ttolwp(curthread);
1392         int watchcode;
1393         caddr_t vaddr;
1394         int mapped;
1395         int rv = 0;
1396         int ta;
1397         label_t ljb;
1398 
1399         for (;;) {
1400 
1401                 vaddr = (caddr_t)addr;
1402                 watchcode = pr_is_watchpoint(&vaddr, &ta, sizeof (value), NULL,
1403                     S_WRITE);
1404                 if (watchcode == 0 || ta != 0) {
1405                         mapped = pr_mappage((caddr_t)addr, sizeof (value),
1406                             S_WRITE, 1);
1407                         if (on_fault(&ljb))
1408                                 rv = -1;
1409                         else
1410                                 suword64_noerr(addr, value);
1411                         no_fault();
1412                         if (mapped)
1413                                 pr_unmappage((caddr_t)addr, sizeof (value),
1414                                     S_WRITE, 1);
1415                 }
1416                 if (watchcode &&
1417                     (!sys_watchpoint(vaddr, watchcode, ta) ||
1418                     lwp->lwp_sysabort)) {
1419                         lwp->lwp_sysabort = 0;
1420                         rv = -1;
1421                         break;
1422                 }
1423                 if (watchcode == 0 || ta != 0)
1424                         break;
1425         }
1426 
1427         return (rv);
1428 }
1429 #endif /* _LP64 */
1430 
1431 /*
1432  * Check for watched addresses in the given address space.
1433  * Return 1 if this is true, otherwise 0.
1434  */
1435 static int
1436 pr_is_watched(caddr_t base, size_t len, int rw)
1437 {
1438         caddr_t saddr = (caddr_t)((uintptr_t)base & (uintptr_t)PAGEMASK);
1439         caddr_t eaddr = base + len;
1440         caddr_t paddr;
1441 
1442         for (paddr = saddr; paddr < eaddr; paddr += PAGESIZE) {
1443                 if (pr_is_watchpage(paddr, rw))
1444                         return (1);
1445         }
1446 
1447         return (0);
1448 }
1449 
1450 /*
1451  * Wrapper for the physio() function.
1452  * Splits one uio operation with multiple iovecs into uio operations with
1453  * only one iovecs to do the watchpoint handling separately for each iovecs.
1454  */
1455 static int
1456 watch_physio(int (*strat)(struct buf *), struct buf *bp, dev_t dev,
1457     int rw, void (*mincnt)(struct buf *), struct uio *uio)
1458 {
1459         struct uio auio;
1460         struct iovec *iov;
1461         caddr_t  base;
1462         size_t len;
1463         int seg_rw;
1464         int error = 0;
1465 
1466         if (uio->uio_segflg == UIO_SYSSPACE)
1467                 return (default_physio(strat, bp, dev, rw, mincnt, uio));
1468 
1469         seg_rw = (rw == B_READ) ? S_WRITE : S_READ;
1470 
1471         while (uio->uio_iovcnt > 0) {
1472                 if (uio->uio_resid == 0) {
1473                         /*
1474                          * Make sure to return the uio structure with the
1475                          * same values as default_physio() does.
1476                          */
1477                         uio->uio_iov++;
1478                         uio->uio_iovcnt--;
1479                         continue;
1480                 }
1481 
1482                 iov = uio->uio_iov;
1483                 len = MIN(iov->iov_len, uio->uio_resid);
1484 
1485                 auio.uio_iovcnt = 1;
1486                 auio.uio_iov = iov;
1487                 auio.uio_resid = len;
1488                 auio.uio_loffset = uio->uio_loffset;
1489                 auio.uio_llimit = uio->uio_llimit;
1490                 auio.uio_fmode = uio->uio_fmode;
1491                 auio.uio_extflg = uio->uio_extflg;
1492                 auio.uio_segflg = uio->uio_segflg;
1493 
1494                 base = iov->iov_base;
1495 
1496                 if (!pr_is_watched(base, len, seg_rw)) {
1497                         /*
1498                          * The given memory references don't cover a
1499                          * watched page.
1500                          */
1501                         error = default_physio(strat, bp, dev, rw, mincnt,
1502                             &auio);
1503 
1504                         /* Update uio with values from auio. */
1505                         len -= auio.uio_resid;
1506                         uio->uio_resid -= len;
1507                         uio->uio_loffset += len;
1508 
1509                         /*
1510                          * Return if an error occurred or not all data
1511                          * was copied.
1512                          */
1513                         if (auio.uio_resid || error)
1514                                 break;
1515                         uio->uio_iov++;
1516                         uio->uio_iovcnt--;
1517                 } else {
1518                         int mapped, watchcode, ta;
1519                         caddr_t vaddr = base;
1520                         klwp_t *lwp = ttolwp(curthread);
1521 
1522                         watchcode = pr_is_watchpoint(&vaddr, &ta, len,
1523                             NULL, seg_rw);
1524 
1525                         if (watchcode == 0 || ta != 0) {
1526                                 /*
1527                                  * Do the io if the given memory references
1528                                  * don't cover a watched area (watchcode=0)
1529                                  * or if WA_TRAPAFTER was specified.
1530                                  */
1531                                 mapped = pr_mappage(base, len, seg_rw, 1);
1532                                 error = default_physio(strat, bp, dev, rw,
1533                                     mincnt, &auio);
1534                                 if (mapped)
1535                                         pr_unmappage(base, len, seg_rw, 1);
1536 
1537                                 len -= auio.uio_resid;
1538                                 uio->uio_resid -= len;
1539                                 uio->uio_loffset += len;
1540                         }
1541 
1542                         /*
1543                          * If we hit a watched address, do the watchpoint logic.
1544                          */
1545                         if (watchcode &&
1546                             (!sys_watchpoint(vaddr, watchcode, ta) ||
1547                             lwp->lwp_sysabort)) {
1548                                 lwp->lwp_sysabort = 0;
1549                                 return (EFAULT);
1550                         }
1551 
1552                         /*
1553                          * Check for errors from default_physio().
1554                          */
1555                         if (watchcode == 0 || ta != 0) {
1556                                 if (auio.uio_resid || error)
1557                                         break;
1558                                 uio->uio_iov++;
1559                                 uio->uio_iovcnt--;
1560                         }
1561                 }
1562         }
1563 
1564         return (error);
1565 }
1566 
1567 int
1568 wa_compare(const void *a, const void *b)
1569 {
1570         const watched_area_t *pa = a;
1571         const watched_area_t *pb = b;
1572 
1573         if (pa->wa_vaddr < pb->wa_vaddr)
1574                 return (-1);
1575         else if (pa->wa_vaddr > pb->wa_vaddr)
1576                 return (1);
1577         else
1578                 return (0);
1579 }
1580 
1581 int
1582 wp_compare(const void *a, const void *b)
1583 {
1584         const watched_page_t *pa = a;
1585         const watched_page_t *pb = b;
1586 
1587         if (pa->wp_vaddr < pb->wp_vaddr)
1588                 return (-1);
1589         else if (pa->wp_vaddr > pb->wp_vaddr)
1590                 return (1);
1591         else
1592                 return (0);
1593 }
1594 
1595 /*
1596  * Given an address range, finds the first watched area which overlaps some or
1597  * all of the range.
1598  */
1599 watched_area_t *
1600 pr_find_watched_area(proc_t *p, watched_area_t *pwa, avl_index_t *where)
1601 {
1602         caddr_t vaddr = pwa->wa_vaddr;
1603         caddr_t eaddr = pwa->wa_eaddr;
1604         watched_area_t *wap;
1605         avl_index_t real_where;
1606 
1607         /* First, check if there is an exact match.  */
1608         wap = avl_find(&p->p_warea, pwa, &real_where);
1609 
1610 
1611         /* Check to see if we overlap with the previous area.  */
1612         if (wap == NULL) {
1613                 wap = avl_nearest(&p->p_warea, real_where, AVL_BEFORE);
1614                 if (wap != NULL &&
1615                     (vaddr >= wap->wa_eaddr || eaddr <= wap->wa_vaddr))
1616                         wap = NULL;
1617         }
1618 
1619         /* Try the next area.  */
1620         if (wap == NULL) {
1621                 wap = avl_nearest(&p->p_warea, real_where, AVL_AFTER);
1622                 if (wap != NULL &&
1623                     (vaddr >= wap->wa_eaddr || eaddr <= wap->wa_vaddr))
1624                         wap = NULL;
1625         }
1626 
1627         if (where)
1628                 *where = real_where;
1629 
1630         return (wap);
1631 }
1632 
1633 void
1634 watch_enable(kthread_id_t t)
1635 {
1636         t->t_proc_flag |= TP_WATCHPT;
1637         install_copyops(t, &watch_copyops);
1638 }
1639 
1640 void
1641 watch_disable(kthread_id_t t)
1642 {
1643         t->t_proc_flag &= ~TP_WATCHPT;
1644         remove_copyops(t);
1645 }
1646 
1647 int
1648 copyin_nowatch(const void *uaddr, void *kaddr, size_t len)
1649 {
1650         int watched, ret;
1651 
1652         watched = watch_disable_addr(uaddr, len, S_READ);
1653         ret = copyin(uaddr, kaddr, len);
1654         if (watched)
1655                 watch_enable_addr(uaddr, len, S_READ);
1656 
1657         return (ret);
1658 }
1659 
1660 int
1661 copyout_nowatch(const void *kaddr, void *uaddr, size_t len)
1662 {
1663         int watched, ret;
1664 
1665         watched = watch_disable_addr(uaddr, len, S_WRITE);
1666         ret = copyout(kaddr, uaddr, len);
1667         if (watched)
1668                 watch_enable_addr(uaddr, len, S_WRITE);
1669 
1670         return (ret);
1671 }
1672 
1673 #ifdef _LP64
1674 int
1675 fuword64_nowatch(const void *addr, uint64_t *value)
1676 {
1677         int watched, ret;
1678 
1679         watched = watch_disable_addr(addr, sizeof (*value), S_READ);
1680         ret = fuword64(addr, value);
1681         if (watched)
1682                 watch_enable_addr(addr, sizeof (*value), S_READ);
1683 
1684         return (ret);
1685 }
1686 #endif
1687 
1688 int
1689 fuword32_nowatch(const void *addr, uint32_t *value)
1690 {
1691         int watched, ret;
1692 
1693         watched = watch_disable_addr(addr, sizeof (*value), S_READ);
1694         ret = fuword32(addr, value);
1695         if (watched)
1696                 watch_enable_addr(addr, sizeof (*value), S_READ);
1697 
1698         return (ret);
1699 }
1700 
1701 #ifdef _LP64
1702 int
1703 suword64_nowatch(void *addr, uint64_t value)
1704 {
1705         int watched, ret;
1706 
1707         watched = watch_disable_addr(addr, sizeof (value), S_WRITE);
1708         ret = suword64(addr, value);
1709         if (watched)
1710                 watch_enable_addr(addr, sizeof (value), S_WRITE);
1711 
1712         return (ret);
1713 }
1714 #endif
1715 
1716 int
1717 suword32_nowatch(void *addr, uint32_t value)
1718 {
1719         int watched, ret;
1720 
1721         watched = watch_disable_addr(addr, sizeof (value), S_WRITE);
1722         ret = suword32(addr, value);
1723         if (watched)
1724                 watch_enable_addr(addr, sizeof (value), S_WRITE);
1725 
1726         return (ret);
1727 }
1728 
1729 int
1730 watch_disable_addr(const void *addr, size_t len, enum seg_rw rw)
1731 {
1732         if (pr_watch_active(curproc))
1733                 return (pr_mappage((caddr_t)addr, len, rw, 1));
1734         return (0);
1735 }
1736 
1737 void
1738 watch_enable_addr(const void *addr, size_t len, enum seg_rw rw)
1739 {
1740         if (pr_watch_active(curproc))
1741                 pr_unmappage((caddr_t)addr, len, rw, 1);
1742 }