Print this page
5045 use atomic_{inc,dec}_* instead of atomic_add_*


   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 
  22 /*
  23  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
  24  * Use is subject to license terms.
  25  */
  26 
  27 #pragma ident   "%Z%%M% %I%     %E% SMI"
  28 
  29 #include <sys/fasttrap_isa.h>
  30 #include <sys/fasttrap_impl.h>
  31 #include <sys/dtrace.h>
  32 #include <sys/dtrace_impl.h>
  33 #include <sys/cmn_err.h>
  34 #include <sys/frame.h>
  35 #include <sys/stack.h>
  36 #include <sys/sysmacros.h>
  37 #include <sys/trap.h>
  38 
  39 #include <v9/sys/machpcb.h>
  40 #include <v9/sys/privregs.h>
  41 
  42 /*
  43  * Lossless User-Land Tracing on SPARC
  44  * -----------------------------------
  45  *
  46  * The Basic Idea
  47  *
  48  * The most important design constraint is, of course, correct execution of


1393         /*
1394          * We have the %os and %gs in our struct regs, but if we need to
1395          * snag a %l or %i we need to go scrounging around in the process's
1396          * address space.
1397          */
1398         if (reg == 0)
1399                 return (0);
1400 
1401         if (reg < 16)
1402                 return ((&rp->r_g1)[reg - 1]);
1403 
1404         /*
1405          * Before we look at the user's stack, we'll check the register
1406          * windows to see if the information we want is in there.
1407          */
1408         cookie = dtrace_interrupt_disable();
1409         if (dtrace_getotherwin() > 0) {
1410                 value = dtrace_getreg_win(reg, 1);
1411                 dtrace_interrupt_enable(cookie);
1412 
1413                 atomic_add_64(&fasttrap_getreg_fast_cnt, 1);
1414 
1415                 return (value);
1416         }
1417         dtrace_interrupt_enable(cookie);
1418 
1419         /*
1420          * First check the machpcb structure to see if we've already read
1421          * in the register window we're looking for; if we haven't, (and
1422          * we probably haven't) try to copy in the value of the register.
1423          */
1424         /* LINTED - alignment */
1425         mpcb = (struct machpcb *)((caddr_t)rp - REGOFF);
1426 
1427         if (get_udatamodel() == DATAMODEL_NATIVE) {
1428                 struct frame *fr = (struct frame *)(rp->r_sp + STACK_BIAS);
1429 
1430                 if (mpcb->mpcb_wbcnt > 0) {
1431                         struct rwindow *rwin = (void *)mpcb->mpcb_wbuf;
1432                         int i = mpcb->mpcb_wbcnt;
1433                         do {
1434                                 i--;
1435                                 if ((long)mpcb->mpcb_spbuf[i] != rp->r_sp)
1436                                         continue;
1437 
1438                                 atomic_add_64(&fasttrap_getreg_mpcb_cnt, 1);
1439                                 return (rwin[i].rw_local[reg - 16]);
1440                         } while (i > 0);
1441                 }
1442 
1443                 if (fasttrap_fulword(&fr->fr_local[reg - 16], &value) != 0)
1444                         goto err;
1445         } else {
1446                 struct frame32 *fr =
1447                     (struct frame32 *)(uintptr_t)(caddr32_t)rp->r_sp;
1448                 uint32_t *v32 = (uint32_t *)&value;
1449 
1450                 if (mpcb->mpcb_wbcnt > 0) {
1451                         struct rwindow32 *rwin = (void *)mpcb->mpcb_wbuf;
1452                         int i = mpcb->mpcb_wbcnt;
1453                         do {
1454                                 i--;
1455                                 if ((long)mpcb->mpcb_spbuf[i] != rp->r_sp)
1456                                         continue;
1457 
1458                                 atomic_add_64(&fasttrap_getreg_mpcb_cnt, 1);
1459                                 return (rwin[i].rw_local[reg - 16]);
1460                         } while (i > 0);
1461                 }
1462 
1463                 if (fasttrap_fuword32(&fr->fr_local[reg - 16], &v32[1]) != 0)
1464                         goto err;
1465 
1466                 v32[0] = 0;
1467         }
1468 
1469         atomic_add_64(&fasttrap_getreg_slow_cnt, 1);
1470         return (value);
1471 
1472 err:
1473         /*
1474          * If the copy in failed, the process will be in a irrecoverable
1475          * state, and we have no choice but to kill it.
1476          */
1477         psignal(ttoproc(curthread), SIGILL);
1478         return (0);
1479 }
1480 
1481 static uint64_t fasttrap_putreg_fast_cnt;
1482 static uint64_t fasttrap_putreg_mpcb_cnt;
1483 static uint64_t fasttrap_putreg_slow_cnt;
1484 
1485 static void
1486 fasttrap_putreg(struct regs *rp, uint_t reg, ulong_t value)
1487 {
1488         dtrace_icookie_t cookie;
1489         struct machpcb *mpcb;
1490         extern void dtrace_putreg_win(uint_t, ulong_t);
1491 
1492         if (reg == 0)
1493                 return;
1494 
1495         if (reg < 16) {
1496                 (&rp->r_g1)[reg - 1] = value;
1497                 return;
1498         }
1499 
1500         /*
1501          * If the user process is still using some register windows, we
1502          * can just place the value in the correct window.
1503          */
1504         cookie = dtrace_interrupt_disable();
1505         if (dtrace_getotherwin() > 0) {
1506                 dtrace_putreg_win(reg, value);
1507                 dtrace_interrupt_enable(cookie);
1508                 atomic_add_64(&fasttrap_putreg_fast_cnt, 1);
1509                 return;
1510         }
1511         dtrace_interrupt_enable(cookie);
1512 
1513         /*
1514          * First see if there's a copy of the register window in the
1515          * machpcb structure that we can modify; if there isn't try to
1516          * copy out the value. If that fails, we try to create a new
1517          * register window in the machpcb structure. While this isn't
1518          * _precisely_ the intended use of the machpcb structure, it
1519          * can't cause any problems since we know at this point in the
1520          * code that all of the user's data have been flushed out of the
1521          * register file (since %otherwin is 0).
1522          */
1523         /* LINTED - alignment */
1524         mpcb = (struct machpcb *)((caddr_t)rp - REGOFF);
1525 
1526         if (get_udatamodel() == DATAMODEL_NATIVE) {
1527                 struct frame *fr = (struct frame *)(rp->r_sp + STACK_BIAS);
1528                 /* LINTED - alignment */
1529                 struct rwindow *rwin = (struct rwindow *)mpcb->mpcb_wbuf;
1530 
1531                 if (mpcb->mpcb_wbcnt > 0) {
1532                         int i = mpcb->mpcb_wbcnt;
1533                         do {
1534                                 i--;
1535                                 if ((long)mpcb->mpcb_spbuf[i] != rp->r_sp)
1536                                         continue;
1537 
1538                                 rwin[i].rw_local[reg - 16] = value;
1539                                 atomic_add_64(&fasttrap_putreg_mpcb_cnt, 1);
1540                                 return;
1541                         } while (i > 0);
1542                 }
1543 
1544                 if (fasttrap_sulword(&fr->fr_local[reg - 16], value) != 0) {
1545                         if (mpcb->mpcb_wbcnt >= MAXWIN || copyin(fr,
1546                             &rwin[mpcb->mpcb_wbcnt], sizeof (*rwin)) != 0)
1547                                 goto err;
1548 
1549                         rwin[mpcb->mpcb_wbcnt].rw_local[reg - 16] = value;
1550                         mpcb->mpcb_spbuf[mpcb->mpcb_wbcnt] = (caddr_t)rp->r_sp;
1551                         mpcb->mpcb_wbcnt++;
1552                         atomic_add_64(&fasttrap_putreg_mpcb_cnt, 1);
1553                         return;
1554                 }
1555         } else {
1556                 struct frame32 *fr =
1557                     (struct frame32 *)(uintptr_t)(caddr32_t)rp->r_sp;
1558                 /* LINTED - alignment */
1559                 struct rwindow32 *rwin = (struct rwindow32 *)mpcb->mpcb_wbuf;
1560                 uint32_t v32 = (uint32_t)value;
1561 
1562                 if (mpcb->mpcb_wbcnt > 0) {
1563                         int i = mpcb->mpcb_wbcnt;
1564                         do {
1565                                 i--;
1566                                 if ((long)mpcb->mpcb_spbuf[i] != rp->r_sp)
1567                                         continue;
1568 
1569                                 rwin[i].rw_local[reg - 16] = v32;
1570                                 atomic_add_64(&fasttrap_putreg_mpcb_cnt, 1);
1571                                 return;
1572                         } while (i > 0);
1573                 }
1574 
1575                 if (fasttrap_suword32(&fr->fr_local[reg - 16], v32) != 0) {
1576                         if (mpcb->mpcb_wbcnt >= MAXWIN || copyin(fr,
1577                             &rwin[mpcb->mpcb_wbcnt], sizeof (*rwin)) != 0)
1578                                 goto err;
1579 
1580                         rwin[mpcb->mpcb_wbcnt].rw_local[reg - 16] = v32;
1581                         mpcb->mpcb_spbuf[mpcb->mpcb_wbcnt] = (caddr_t)rp->r_sp;
1582                         mpcb->mpcb_wbcnt++;
1583                         atomic_add_64(&fasttrap_putreg_mpcb_cnt, 1);
1584                         return;
1585                 }
1586         }
1587 
1588         atomic_add_64(&fasttrap_putreg_slow_cnt, 1);
1589         return;
1590 
1591 err:
1592         /*
1593          * If we couldn't record this register's value, the process is in an
1594          * irrecoverable state and we have no choice but to euthanize it.
1595          */
1596         psignal(ttoproc(curthread), SIGILL);
1597 }


   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 
  22 /*
  23  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
  24  * Use is subject to license terms.
  25  */
  26 


  27 #include <sys/fasttrap_isa.h>
  28 #include <sys/fasttrap_impl.h>
  29 #include <sys/dtrace.h>
  30 #include <sys/dtrace_impl.h>
  31 #include <sys/cmn_err.h>
  32 #include <sys/frame.h>
  33 #include <sys/stack.h>
  34 #include <sys/sysmacros.h>
  35 #include <sys/trap.h>
  36 
  37 #include <v9/sys/machpcb.h>
  38 #include <v9/sys/privregs.h>
  39 
  40 /*
  41  * Lossless User-Land Tracing on SPARC
  42  * -----------------------------------
  43  *
  44  * The Basic Idea
  45  *
  46  * The most important design constraint is, of course, correct execution of


1391         /*
1392          * We have the %os and %gs in our struct regs, but if we need to
1393          * snag a %l or %i we need to go scrounging around in the process's
1394          * address space.
1395          */
1396         if (reg == 0)
1397                 return (0);
1398 
1399         if (reg < 16)
1400                 return ((&rp->r_g1)[reg - 1]);
1401 
1402         /*
1403          * Before we look at the user's stack, we'll check the register
1404          * windows to see if the information we want is in there.
1405          */
1406         cookie = dtrace_interrupt_disable();
1407         if (dtrace_getotherwin() > 0) {
1408                 value = dtrace_getreg_win(reg, 1);
1409                 dtrace_interrupt_enable(cookie);
1410 
1411                 atomic_inc_64(&fasttrap_getreg_fast_cnt);
1412 
1413                 return (value);
1414         }
1415         dtrace_interrupt_enable(cookie);
1416 
1417         /*
1418          * First check the machpcb structure to see if we've already read
1419          * in the register window we're looking for; if we haven't, (and
1420          * we probably haven't) try to copy in the value of the register.
1421          */
1422         /* LINTED - alignment */
1423         mpcb = (struct machpcb *)((caddr_t)rp - REGOFF);
1424 
1425         if (get_udatamodel() == DATAMODEL_NATIVE) {
1426                 struct frame *fr = (struct frame *)(rp->r_sp + STACK_BIAS);
1427 
1428                 if (mpcb->mpcb_wbcnt > 0) {
1429                         struct rwindow *rwin = (void *)mpcb->mpcb_wbuf;
1430                         int i = mpcb->mpcb_wbcnt;
1431                         do {
1432                                 i--;
1433                                 if ((long)mpcb->mpcb_spbuf[i] != rp->r_sp)
1434                                         continue;
1435 
1436                                 atomic_inc_64(&fasttrap_getreg_mpcb_cnt);
1437                                 return (rwin[i].rw_local[reg - 16]);
1438                         } while (i > 0);
1439                 }
1440 
1441                 if (fasttrap_fulword(&fr->fr_local[reg - 16], &value) != 0)
1442                         goto err;
1443         } else {
1444                 struct frame32 *fr =
1445                     (struct frame32 *)(uintptr_t)(caddr32_t)rp->r_sp;
1446                 uint32_t *v32 = (uint32_t *)&value;
1447 
1448                 if (mpcb->mpcb_wbcnt > 0) {
1449                         struct rwindow32 *rwin = (void *)mpcb->mpcb_wbuf;
1450                         int i = mpcb->mpcb_wbcnt;
1451                         do {
1452                                 i--;
1453                                 if ((long)mpcb->mpcb_spbuf[i] != rp->r_sp)
1454                                         continue;
1455 
1456                                 atomic_inc_64(&fasttrap_getreg_mpcb_cnt);
1457                                 return (rwin[i].rw_local[reg - 16]);
1458                         } while (i > 0);
1459                 }
1460 
1461                 if (fasttrap_fuword32(&fr->fr_local[reg - 16], &v32[1]) != 0)
1462                         goto err;
1463 
1464                 v32[0] = 0;
1465         }
1466 
1467         atomic_inc_64(&fasttrap_getreg_slow_cnt);
1468         return (value);
1469 
1470 err:
1471         /*
1472          * If the copy in failed, the process will be in a irrecoverable
1473          * state, and we have no choice but to kill it.
1474          */
1475         psignal(ttoproc(curthread), SIGILL);
1476         return (0);
1477 }
1478 
1479 static uint64_t fasttrap_putreg_fast_cnt;
1480 static uint64_t fasttrap_putreg_mpcb_cnt;
1481 static uint64_t fasttrap_putreg_slow_cnt;
1482 
1483 static void
1484 fasttrap_putreg(struct regs *rp, uint_t reg, ulong_t value)
1485 {
1486         dtrace_icookie_t cookie;
1487         struct machpcb *mpcb;
1488         extern void dtrace_putreg_win(uint_t, ulong_t);
1489 
1490         if (reg == 0)
1491                 return;
1492 
1493         if (reg < 16) {
1494                 (&rp->r_g1)[reg - 1] = value;
1495                 return;
1496         }
1497 
1498         /*
1499          * If the user process is still using some register windows, we
1500          * can just place the value in the correct window.
1501          */
1502         cookie = dtrace_interrupt_disable();
1503         if (dtrace_getotherwin() > 0) {
1504                 dtrace_putreg_win(reg, value);
1505                 dtrace_interrupt_enable(cookie);
1506                 atomic_inc_64(&fasttrap_putreg_fast_cnt);
1507                 return;
1508         }
1509         dtrace_interrupt_enable(cookie);
1510 
1511         /*
1512          * First see if there's a copy of the register window in the
1513          * machpcb structure that we can modify; if there isn't try to
1514          * copy out the value. If that fails, we try to create a new
1515          * register window in the machpcb structure. While this isn't
1516          * _precisely_ the intended use of the machpcb structure, it
1517          * can't cause any problems since we know at this point in the
1518          * code that all of the user's data have been flushed out of the
1519          * register file (since %otherwin is 0).
1520          */
1521         /* LINTED - alignment */
1522         mpcb = (struct machpcb *)((caddr_t)rp - REGOFF);
1523 
1524         if (get_udatamodel() == DATAMODEL_NATIVE) {
1525                 struct frame *fr = (struct frame *)(rp->r_sp + STACK_BIAS);
1526                 /* LINTED - alignment */
1527                 struct rwindow *rwin = (struct rwindow *)mpcb->mpcb_wbuf;
1528 
1529                 if (mpcb->mpcb_wbcnt > 0) {
1530                         int i = mpcb->mpcb_wbcnt;
1531                         do {
1532                                 i--;
1533                                 if ((long)mpcb->mpcb_spbuf[i] != rp->r_sp)
1534                                         continue;
1535 
1536                                 rwin[i].rw_local[reg - 16] = value;
1537                                 atomic_inc_64(&fasttrap_putreg_mpcb_cnt);
1538                                 return;
1539                         } while (i > 0);
1540                 }
1541 
1542                 if (fasttrap_sulword(&fr->fr_local[reg - 16], value) != 0) {
1543                         if (mpcb->mpcb_wbcnt >= MAXWIN || copyin(fr,
1544                             &rwin[mpcb->mpcb_wbcnt], sizeof (*rwin)) != 0)
1545                                 goto err;
1546 
1547                         rwin[mpcb->mpcb_wbcnt].rw_local[reg - 16] = value;
1548                         mpcb->mpcb_spbuf[mpcb->mpcb_wbcnt] = (caddr_t)rp->r_sp;
1549                         mpcb->mpcb_wbcnt++;
1550                         atomic_inc_64(&fasttrap_putreg_mpcb_cnt);
1551                         return;
1552                 }
1553         } else {
1554                 struct frame32 *fr =
1555                     (struct frame32 *)(uintptr_t)(caddr32_t)rp->r_sp;
1556                 /* LINTED - alignment */
1557                 struct rwindow32 *rwin = (struct rwindow32 *)mpcb->mpcb_wbuf;
1558                 uint32_t v32 = (uint32_t)value;
1559 
1560                 if (mpcb->mpcb_wbcnt > 0) {
1561                         int i = mpcb->mpcb_wbcnt;
1562                         do {
1563                                 i--;
1564                                 if ((long)mpcb->mpcb_spbuf[i] != rp->r_sp)
1565                                         continue;
1566 
1567                                 rwin[i].rw_local[reg - 16] = v32;
1568                                 atomic_inc_64(&fasttrap_putreg_mpcb_cnt);
1569                                 return;
1570                         } while (i > 0);
1571                 }
1572 
1573                 if (fasttrap_suword32(&fr->fr_local[reg - 16], v32) != 0) {
1574                         if (mpcb->mpcb_wbcnt >= MAXWIN || copyin(fr,
1575                             &rwin[mpcb->mpcb_wbcnt], sizeof (*rwin)) != 0)
1576                                 goto err;
1577 
1578                         rwin[mpcb->mpcb_wbcnt].rw_local[reg - 16] = v32;
1579                         mpcb->mpcb_spbuf[mpcb->mpcb_wbcnt] = (caddr_t)rp->r_sp;
1580                         mpcb->mpcb_wbcnt++;
1581                         atomic_inc_64(&fasttrap_putreg_mpcb_cnt);
1582                         return;
1583                 }
1584         }
1585 
1586         atomic_inc_64(&fasttrap_putreg_slow_cnt);
1587         return;
1588 
1589 err:
1590         /*
1591          * If we couldn't record this register's value, the process is in an
1592          * irrecoverable state and we have no choice but to euthanize it.
1593          */
1594         psignal(ttoproc(curthread), SIGILL);
1595 }