Deleted Added
full compact
hwpmc_mod.c (156834) hwpmc_mod.c (157144)
1/*-
1/*-
2 * Copyright (c) 2003-2005 Joseph Koshy
2 * Copyright (c) 2003-2006 Joseph Koshy
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright

--- 10 unchanged lines hidden (view full) ---

21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 *
26 */
27
28#include <sys/cdefs.h>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright

--- 10 unchanged lines hidden (view full) ---

21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 *
26 */
27
28#include <sys/cdefs.h>
29__FBSDID("$FreeBSD: head/sys/dev/hwpmc/hwpmc_mod.c 156834 2006-03-18 03:54:07Z jkoshy $");
29__FBSDID("$FreeBSD: head/sys/dev/hwpmc/hwpmc_mod.c 157144 2006-03-26 12:20:54Z jkoshy $");
30
31#include <sys/param.h>
32#include <sys/eventhandler.h>
33#include <sys/jail.h>
34#include <sys/kernel.h>
35#include <sys/kthread.h>
36#include <sys/limits.h>
37#include <sys/lock.h>

--- 10 unchanged lines hidden (view full) ---

48#include <sys/signalvar.h>
49#include <sys/smp.h>
50#include <sys/sx.h>
51#include <sys/sysctl.h>
52#include <sys/sysent.h>
53#include <sys/systm.h>
54#include <sys/vnode.h>
55
30
31#include <sys/param.h>
32#include <sys/eventhandler.h>
33#include <sys/jail.h>
34#include <sys/kernel.h>
35#include <sys/kthread.h>
36#include <sys/limits.h>
37#include <sys/lock.h>

--- 10 unchanged lines hidden (view full) ---

48#include <sys/signalvar.h>
49#include <sys/smp.h>
50#include <sys/sx.h>
51#include <sys/sysctl.h>
52#include <sys/sysent.h>
53#include <sys/systm.h>
54#include <sys/vnode.h>
55
56#include <sys/linker.h> /* needs to be after <sys/malloc.h> */
57
56#include <machine/atomic.h>
57#include <machine/md_var.h>
58
59/*
60 * Types
61 */
62
63enum pmc_flags {

--- 1342 unchanged lines hidden (view full) ---

1406 */
1407
1408 (void) (*md->pmd_switch_out)(pc, pp);
1409
1410 critical_exit();
1411}
1412
1413/*
58#include <machine/atomic.h>
59#include <machine/md_var.h>
60
61/*
62 * Types
63 */
64
65enum pmc_flags {

--- 1342 unchanged lines hidden (view full) ---

1408 */
1409
1410 (void) (*md->pmd_switch_out)(pc, pp);
1411
1412 critical_exit();
1413}
1414
1415/*
1416 * Log a KLD operation.
1417 */
1418
1419static void
1420pmc_process_kld_load(struct pmckern_map_in *pkm)
1421{
1422 struct pmc_owner *po;
1423
1424 sx_assert(&pmc_sx, SX_LOCKED);
1425
1426 /*
1427 * Notify owners of system sampling PMCs about KLD operations.
1428 */
1429
1430 LIST_FOREACH(po, &pmc_ss_owners, po_ssnext)
1431 if (po->po_flags & PMC_PO_OWNS_LOGFILE)
1432 pmclog_process_map_in(po, (pid_t) -1, pkm->pm_address,
1433 (char *) pkm->pm_file);
1434
1435 /*
1436 * TODO: Notify owners of (all) process-sampling PMCs too.
1437 */
1438
1439 return;
1440}
1441
1442static void
1443pmc_process_kld_unload(struct pmckern_map_out *pkm)
1444{
1445 struct pmc_owner *po;
1446
1447 sx_assert(&pmc_sx, SX_LOCKED);
1448
1449 LIST_FOREACH(po, &pmc_ss_owners, po_ssnext)
1450 if (po->po_flags & PMC_PO_OWNS_LOGFILE)
1451 pmclog_process_map_out(po, (pid_t) -1,
1452 pkm->pm_address, pkm->pm_address + pkm->pm_size);
1453
1454 /*
1455 * TODO: Notify owners of process-sampling PMCs.
1456 */
1457}
1458
1459/*
1460 * A mapping change for a process.
1461 */
1462
1463static void
1464pmc_process_mmap(struct thread *td, struct pmckern_map_in *pkm)
1465{
1466 int ri;
1467 pid_t pid;
1468 char *fullpath, *freepath;
1469 const struct pmc *pm;
1470 struct pmc_owner *po;
1471 const struct pmc_process *pp;
1472
1473 freepath = fullpath = NULL;
1474 pmc_getfilename((struct vnode *) pkm->pm_file, &fullpath, &freepath);
1475
1476 pid = td->td_proc->p_pid;
1477
1478 /* Inform owners of all system-wide sampling PMCs. */
1479 LIST_FOREACH(po, &pmc_ss_owners, po_ssnext)
1480 if (po->po_flags & PMC_PO_OWNS_LOGFILE)
1481 pmclog_process_map_in(po, pid, pkm->pm_address, fullpath);
1482
1483 if ((pp = pmc_find_process_descriptor(td->td_proc, 0)) == NULL)
1484 goto done;
1485
1486 /*
1487 * Inform sampling PMC owners tracking this process.
1488 */
1489 for (ri = 0; ri < md->pmd_npmc; ri++)
1490 if ((pm = pp->pp_pmcs[ri].pp_pmc) != NULL &&
1491 PMC_IS_SAMPLING_MODE(PMC_TO_MODE(pm)))
1492 pmclog_process_map_in(pm->pm_owner,
1493 pid, pkm->pm_address, fullpath);
1494
1495 done:
1496 if (freepath)
1497 FREE(freepath, M_TEMP);
1498}
1499
1500
1501/*
1502 * Log an munmap request.
1503 */
1504
1505static void
1506pmc_process_munmap(struct thread *td, struct pmckern_map_out *pkm)
1507{
1508 int ri;
1509 pid_t pid;
1510 struct pmc_owner *po;
1511 const struct pmc *pm;
1512 const struct pmc_process *pp;
1513
1514 pid = td->td_proc->p_pid;
1515
1516 LIST_FOREACH(po, &pmc_ss_owners, po_ssnext)
1517 if (po->po_flags & PMC_PO_OWNS_LOGFILE)
1518 pmclog_process_map_out(po, pid, pkm->pm_address,
1519 pkm->pm_address + pkm->pm_size);
1520
1521 if ((pp = pmc_find_process_descriptor(td->td_proc, 0)) == NULL)
1522 return;
1523
1524 for (ri = 0; ri < md->pmd_npmc; ri++)
1525 if ((pm = pp->pp_pmcs[ri].pp_pmc) != NULL &&
1526 PMC_IS_SAMPLING_MODE(PMC_TO_MODE(pm)))
1527 pmclog_process_map_out(po, pid, pkm->pm_address,
1528 pkm->pm_address + pkm->pm_size);
1529}
1530
1531/*
1414 * The 'hook' invoked from the kernel proper
1415 */
1416
1417
1418#ifdef DEBUG
1419const char *pmc_hooknames[] = {
1532 * The 'hook' invoked from the kernel proper
1533 */
1534
1535
1536#ifdef DEBUG
1537const char *pmc_hooknames[] = {
1538 /* these strings correspond to PMC_FN_* in <sys/pmckern.h> */
1420 "",
1539 "",
1421 "EXIT",
1422 "EXEC",
1540 "EXEC",
1423 "FORK",
1424 "CSW-IN",
1425 "CSW-OUT",
1541 "CSW-IN",
1542 "CSW-OUT",
1426 "SAMPLE"
1543 "SAMPLE",
1544 "KLDLOAD",
1545 "KLDUNLOAD",
1546 "MMAP",
1547 "MUNMAP"
1427};
1428#endif
1429
1430static int
1431pmc_hook_handler(struct thread *td, int function, void *arg)
1432{
1433
1434 PMCDBG(MOD,PMH,1, "hook td=%p func=%d \"%s\" arg=%p", td, function,

--- 145 unchanged lines hidden (view full) ---

1580 * may find nothing to do if "pmc_process_samples()"
1581 * had already processed the interrupt). We don't
1582 * lose the interrupt sample.
1583 */
1584 atomic_clear_int(&pmc_cpumask, (1 << PCPU_GET(cpuid)));
1585 pmc_process_samples(PCPU_GET(cpuid));
1586 break;
1587
1548};
1549#endif
1550
1551static int
1552pmc_hook_handler(struct thread *td, int function, void *arg)
1553{
1554
1555 PMCDBG(MOD,PMH,1, "hook td=%p func=%d \"%s\" arg=%p", td, function,

--- 145 unchanged lines hidden (view full) ---

1701 * may find nothing to do if "pmc_process_samples()"
1702 * had already processed the interrupt). We don't
1703 * lose the interrupt sample.
1704 */
1705 atomic_clear_int(&pmc_cpumask, (1 << PCPU_GET(cpuid)));
1706 pmc_process_samples(PCPU_GET(cpuid));
1707 break;
1708
1709
1710 case PMC_FN_KLD_LOAD:
1711 sx_assert(&pmc_sx, SX_LOCKED);
1712 pmc_process_kld_load((struct pmckern_map_in *) arg);
1713 break;
1714
1715 case PMC_FN_KLD_UNLOAD:
1716 sx_assert(&pmc_sx, SX_LOCKED);
1717 pmc_process_kld_unload((struct pmckern_map_out *) arg);
1718 break;
1719
1720 case PMC_FN_MMAP:
1721 sx_assert(&pmc_sx, SX_LOCKED);
1722 pmc_process_mmap(td, (struct pmckern_map_in *) arg);
1723 break;
1724
1725 case PMC_FN_MUNMAP:
1726 sx_assert(&pmc_sx, SX_LOCKED);
1727 pmc_process_munmap(td, (struct pmckern_map_out *) arg);
1728 break;
1729
1588 default:
1589#ifdef DEBUG
1590 KASSERT(0, ("[pmc,%d] unknown hook %d\n", __LINE__, function));
1591#endif
1592 break;
1593
1594 }
1595

--- 636 unchanged lines hidden (view full) ---

2232 if (po->po_sscount == 0) {
2233 LIST_INSERT_HEAD(&pmc_ss_owners, po, po_ssnext);
2234 atomic_add_rel_int(&pmc_ss_count, 1);
2235 PMCDBG(PMC,OPS,1, "po=%p in global list", po);
2236 }
2237 po->po_sscount++;
2238 }
2239
1730 default:
1731#ifdef DEBUG
1732 KASSERT(0, ("[pmc,%d] unknown hook %d\n", __LINE__, function));
1733#endif
1734 break;
1735
1736 }
1737

--- 636 unchanged lines hidden (view full) ---

2374 if (po->po_sscount == 0) {
2375 LIST_INSERT_HEAD(&pmc_ss_owners, po, po_ssnext);
2376 atomic_add_rel_int(&pmc_ss_count, 1);
2377 PMCDBG(PMC,OPS,1, "po=%p in global list", po);
2378 }
2379 po->po_sscount++;
2380 }
2381
2382 /* TODO: dump system wide process mappings to the log? */
2383
2240 /*
2241 * Move to the CPU associated with this
2242 * PMC, and start the hardware.
2243 */
2244
2245 pmc_save_cpu_binding(&pb);
2246
2247 cpu = PMC_TO_CPU(pm);

--- 155 unchanged lines hidden (view full) ---

2403 /*
2404 * Configure a log file.
2405 *
2406 * XXX This OP will be reworked.
2407 */
2408
2409 case PMC_OP_CONFIGURELOG:
2410 {
2384 /*
2385 * Move to the CPU associated with this
2386 * PMC, and start the hardware.
2387 */
2388
2389 pmc_save_cpu_binding(&pb);
2390
2391 cpu = PMC_TO_CPU(pm);

--- 155 unchanged lines hidden (view full) ---

2547 /*
2548 * Configure a log file.
2549 *
2550 * XXX This OP will be reworked.
2551 */
2552
2553 case PMC_OP_CONFIGURELOG:
2554 {
2555 struct proc *p;
2411 struct pmc *pm;
2412 struct pmc_owner *po;
2556 struct pmc *pm;
2557 struct pmc_owner *po;
2558 struct pmckern_map_in *km, *kmbase;
2413 struct pmc_op_configurelog cl;
2559 struct pmc_op_configurelog cl;
2414 struct proc *p;
2415
2416 sx_assert(&pmc_sx, SX_XLOCKED);
2417
2418 if ((error = copyin(arg, &cl, sizeof(cl))) != 0)
2419 break;
2420
2421 /* mark this process as owning a log file */
2422 p = td->td_proc;

--- 18 unchanged lines hidden (view full) ---

2441 LIST_FOREACH(pm, &po->po_pmcs, pm_next)
2442 if (pm->pm_flags & PMC_F_NEEDS_LOGFILE &&
2443 pm->pm_state == PMC_STATE_RUNNING)
2444 pmc_stop(pm);
2445 error = pmclog_deconfigure_log(po);
2446 }
2447 } else
2448 error = EINVAL;
2560
2561 sx_assert(&pmc_sx, SX_XLOCKED);
2562
2563 if ((error = copyin(arg, &cl, sizeof(cl))) != 0)
2564 break;
2565
2566 /* mark this process as owning a log file */
2567 p = td->td_proc;

--- 18 unchanged lines hidden (view full) ---

2586 LIST_FOREACH(pm, &po->po_pmcs, pm_next)
2587 if (pm->pm_flags & PMC_F_NEEDS_LOGFILE &&
2588 pm->pm_state == PMC_STATE_RUNNING)
2589 pmc_stop(pm);
2590 error = pmclog_deconfigure_log(po);
2591 }
2592 } else
2593 error = EINVAL;
2594
2595 if (error)
2596 break;
2597
2598 /*
2599 * Log the current set of kernel modules.
2600 */
2601 kmbase = linker_hwpmc_list_objects();
2602 for (km = kmbase; km->pm_file != NULL; km++) {
2603 PMCDBG(LOG,REG,1,"%s %p", (char *) km->pm_file,
2604 (void *) km->pm_address);
2605 pmclog_process_map_in(po, (pid_t) -1, km->pm_address,
2606 km->pm_file);
2607 }
2608 FREE(kmbase, M_LINKER);
2449 }
2450 break;
2451
2452
2453 /*
2454 * Flush a log file.
2455 */
2456

--- 1785 unchanged lines hidden ---
2609 }
2610 break;
2611
2612
2613 /*
2614 * Flush a log file.
2615 */
2616

--- 1785 unchanged lines hidden ---