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 }
|