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