Deleted Added
full compact
hwpmc_mod.c (199972) hwpmc_mod.c (201021)
1/*-
2 * Copyright (c) 2003-2008 Joseph Koshy
3 * Copyright (c) 2007 The FreeBSD Foundation
4 * All rights reserved.
5 *
6 * Portions of this software were developed by A. Joseph Koshy under
7 * sponsorship from the FreeBSD Foundation and Google, Inc.
8 *

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

25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 * SUCH DAMAGE.
29 *
30 */
31
32#include <sys/cdefs.h>
1/*-
2 * Copyright (c) 2003-2008 Joseph Koshy
3 * Copyright (c) 2007 The FreeBSD Foundation
4 * All rights reserved.
5 *
6 * Portions of this software were developed by A. Joseph Koshy under
7 * sponsorship from the FreeBSD Foundation and Google, Inc.
8 *

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

25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 * SUCH DAMAGE.
29 *
30 */
31
32#include <sys/cdefs.h>
33__FBSDID("$FreeBSD: head/sys/dev/hwpmc/hwpmc_mod.c 199972 2009-11-30 20:41:30Z emaste $");
33__FBSDID("$FreeBSD: head/sys/dev/hwpmc/hwpmc_mod.c 201021 2009-12-26 13:58:52Z jkoshy $");
34
35#include <sys/param.h>
36#include <sys/eventhandler.h>
37#include <sys/jail.h>
38#include <sys/kernel.h>
39#include <sys/kthread.h>
40#include <sys/limits.h>
41#include <sys/lock.h>

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

58#include <sys/systm.h>
59#include <sys/vnode.h>
60
61#include <sys/linker.h> /* needs to be after <sys/malloc.h> */
62
63#include <machine/atomic.h>
64#include <machine/md_var.h>
65
34
35#include <sys/param.h>
36#include <sys/eventhandler.h>
37#include <sys/jail.h>
38#include <sys/kernel.h>
39#include <sys/kthread.h>
40#include <sys/limits.h>
41#include <sys/lock.h>

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

58#include <sys/systm.h>
59#include <sys/vnode.h>
60
61#include <sys/linker.h> /* needs to be after <sys/malloc.h> */
62
63#include <machine/atomic.h>
64#include <machine/md_var.h>
65
66#include <vm/vm.h>
67#include <vm/vm_extern.h>
68#include <vm/pmap.h>
69#include <vm/vm_map.h>
70#include <vm/vm_object.h>
71
66/*
67 * Types
68 */
69
70enum pmc_flags {
71 PMC_FLAG_NONE = 0x00, /* do nothing */
72 PMC_FLAG_REMOVE = 0x01, /* atomically remove entry from hash */
73 PMC_FLAG_ALLOCATE = 0x02, /* add entry to hash if not found */

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

1614
1615/*
1616 * Log the mappings for a single process.
1617 */
1618
1619static void
1620pmc_log_process_mappings(struct pmc_owner *po, struct proc *p)
1621{
72/*
73 * Types
74 */
75
76enum pmc_flags {
77 PMC_FLAG_NONE = 0x00, /* do nothing */
78 PMC_FLAG_REMOVE = 0x01, /* atomically remove entry from hash */
79 PMC_FLAG_ALLOCATE = 0x02, /* add entry to hash if not found */

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

1620
1621/*
1622 * Log the mappings for a single process.
1623 */
1624
1625static void
1626pmc_log_process_mappings(struct pmc_owner *po, struct proc *p)
1627{
1628 vm_map_t map;
1629 struct vnode *vp;
1630 struct vmspace *vm;
1631 vm_map_entry_t entry;
1632 vm_offset_t last_end;
1633 u_int last_timestamp;
1634 struct vnode *last_vp;
1635 vm_offset_t start_addr;
1636 vm_object_t obj, lobj, tobj;
1637 char *fullpath, *freepath;
1638
1639 last_vp = NULL;
1640 last_end = (vm_offset_t) 0;
1641 fullpath = freepath = NULL;
1642
1643 if ((vm = vmspace_acquire_ref(p)) == NULL)
1644 return;
1645
1646 map = &vm->vm_map;
1647 vm_map_lock_read(map);
1648
1649 for (entry = map->header.next; entry != &map->header; entry = entry->next) {
1650
1651 if (entry == NULL) {
1652 PMCDBG(LOG,OPS,2, "hwpmc: vm_map entry unexpectedly "
1653 "NULL! pid=%d vm_map=%p\n", p->p_pid, map);
1654 break;
1655 }
1656
1657 /*
1658 * We only care about executable map entries.
1659 */
1660 if ((entry->eflags & MAP_ENTRY_IS_SUB_MAP) ||
1661 !(entry->protection & VM_PROT_EXECUTE) ||
1662 (entry->object.vm_object == NULL)) {
1663 continue;
1664 }
1665
1666 obj = entry->object.vm_object;
1667 VM_OBJECT_LOCK(obj);
1668
1669 /*
1670 * Walk the backing_object list to find the base
1671 * (non-shadowed) vm_object.
1672 */
1673 for (lobj = tobj = obj; tobj != NULL; tobj = tobj->backing_object) {
1674 if (tobj != obj)
1675 VM_OBJECT_LOCK(tobj);
1676 if (lobj != obj)
1677 VM_OBJECT_UNLOCK(lobj);
1678 lobj = tobj;
1679 }
1680
1681 /*
1682 * At this point lobj is the base vm_object and it is locked.
1683 */
1684 if (lobj == NULL) {
1685 PMCDBG(LOG,OPS,2, "hwpmc: lobj unexpectedly NULL! pid=%d "
1686 "vm_map=%p vm_obj=%p\n", p->p_pid, map, obj);
1687 VM_OBJECT_UNLOCK(obj);
1688 continue;
1689 }
1690
1691 if (lobj->type != OBJT_VNODE || lobj->handle == NULL) {
1692 if (lobj != obj)
1693 VM_OBJECT_UNLOCK(lobj);
1694 VM_OBJECT_UNLOCK(obj);
1695 continue;
1696 }
1697
1698 /*
1699 * Skip contiguous regions that point to the same
1700 * vnode, so we don't emit redundant MAP-IN
1701 * directives.
1702 */
1703 if (entry->start == last_end && lobj->handle == last_vp) {
1704 last_end = entry->end;
1705 if (lobj != obj)
1706 VM_OBJECT_UNLOCK(lobj);
1707 VM_OBJECT_UNLOCK(obj);
1708 continue;
1709 }
1710
1711 /*
1712 * We don't want to keep the proc's vm_map or this
1713 * vm_object locked while we walk the pathname, since
1714 * vn_fullpath() can sleep. However, if we drop the
1715 * lock, it's possible for concurrent activity to
1716 * modify the vm_map list. To protect against this,
1717 * we save the vm_map timestamp before we release the
1718 * lock, and check it after we reacquire the lock
1719 * below.
1720 */
1721 start_addr = entry->start;
1722 last_end = entry->end;
1723 last_timestamp = map->timestamp;
1724 vm_map_unlock_read(map);
1725
1726 vp = lobj->handle;
1727 vref(vp);
1728 if (lobj != obj)
1729 VM_OBJECT_UNLOCK(lobj);
1730
1731 VM_OBJECT_UNLOCK(obj);
1732
1733 freepath = NULL;
1734 pmc_getfilename(vp, &fullpath, &freepath);
1735 last_vp = vp;
1736 vrele(vp);
1737 vp = NULL;
1738 pmclog_process_map_in(po, p->p_pid, start_addr, fullpath);
1739 if (freepath)
1740 free(freepath, M_TEMP);
1741
1742 vm_map_lock_read(map);
1743
1744 /*
1745 * If our saved timestamp doesn't match, this means
1746 * that the vm_map was modified out from under us and
1747 * we can't trust our current "entry" pointer. Do a
1748 * new lookup for this entry. If there is no entry
1749 * for this address range, vm_map_lookup_entry() will
1750 * return the previous one, so we always want to go to
1751 * entry->next on the next loop iteration.
1752 *
1753 * There is an edge condition here that can occur if
1754 * there is no entry at or before this address. In
1755 * this situation, vm_map_lookup_entry returns
1756 * &map->header, which would cause our loop to abort
1757 * without processing the rest of the map. However,
1758 * in practice this will never happen for process
1759 * vm_map. This is because the executable's text
1760 * segment is the first mapping in the proc's address
1761 * space, and this mapping is never removed until the
1762 * process exits, so there will always be a non-header
1763 * entry at or before the requested address for
1764 * vm_map_lookup_entry to return.
1765 */
1766 if (map->timestamp != last_timestamp)
1767 vm_map_lookup_entry(map, last_end - 1, &entry);
1768 }
1769
1770 vm_map_unlock_read(map);
1771 vmspace_free(vm);
1772 return;
1622}
1623
1624/*
1625 * Log mappings for all processes in the system.
1626 */
1627
1628static void
1629pmc_log_all_process_mappings(struct pmc_owner *po)

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

1892 struct pmc_owner *po;
1893 struct pmc_ownerhash *poh;
1894
1895 hindex = PMC_HASH_PTR(p, pmc_ownerhashmask);
1896 poh = &pmc_ownerhash[hindex];
1897
1898 /* allocate space for N pointers and one descriptor struct */
1899 po = malloc(sizeof(struct pmc_owner), M_PMC, M_WAITOK|M_ZERO);
1773}
1774
1775/*
1776 * Log mappings for all processes in the system.
1777 */
1778
1779static void
1780pmc_log_all_process_mappings(struct pmc_owner *po)

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

2043 struct pmc_owner *po;
2044 struct pmc_ownerhash *poh;
2045
2046 hindex = PMC_HASH_PTR(p, pmc_ownerhashmask);
2047 poh = &pmc_ownerhash[hindex];
2048
2049 /* allocate space for N pointers and one descriptor struct */
2050 po = malloc(sizeof(struct pmc_owner), M_PMC, M_WAITOK|M_ZERO);
1900 po->po_sscount = po->po_error = po->po_flags = 0;
2051 po->po_sscount = po->po_error = po->po_flags = po->po_logprocmaps = 0;
1901 po->po_file = NULL;
1902 po->po_owner = p;
1903 po->po_kthread = NULL;
1904 LIST_INIT(&po->po_pmcs);
1905 LIST_INSERT_HEAD(poh, po, po_next); /* insert into hash table */
1906
1907 TAILQ_INIT(&po->po_logbuffers);
1908 mtx_init(&po->po_mtx, "pmc-owner-mtx", "pmc-per-proc", MTX_SPIN);

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

2515 if (po->po_sscount == 0) {
2516 LIST_INSERT_HEAD(&pmc_ss_owners, po, po_ssnext);
2517 atomic_add_rel_int(&pmc_ss_count, 1);
2518 PMCDBG(PMC,OPS,1, "po=%p in global list", po);
2519 }
2520 po->po_sscount++;
2521 }
2522
2052 po->po_file = NULL;
2053 po->po_owner = p;
2054 po->po_kthread = NULL;
2055 LIST_INIT(&po->po_pmcs);
2056 LIST_INSERT_HEAD(poh, po, po_next); /* insert into hash table */
2057
2058 TAILQ_INIT(&po->po_logbuffers);
2059 mtx_init(&po->po_mtx, "pmc-owner-mtx", "pmc-per-proc", MTX_SPIN);

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

2666 if (po->po_sscount == 0) {
2667 LIST_INSERT_HEAD(&pmc_ss_owners, po, po_ssnext);
2668 atomic_add_rel_int(&pmc_ss_count, 1);
2669 PMCDBG(PMC,OPS,1, "po=%p in global list", po);
2670 }
2671 po->po_sscount++;
2672 }
2673
2523 /* Log mapping information for all processes in the system. */
2524 pmc_log_all_process_mappings(po);
2674 /*
2675 * Log mapping information for all existing processes in the
2676 * system. Subsequent mappings are logged as they happen;
2677 * see pmc_process_mmap().
2678 */
2679 if (po->po_logprocmaps == 0) {
2680 pmc_log_all_process_mappings(po);
2681 po->po_logprocmaps = 1;
2682 }
2525
2526 /*
2527 * Move to the CPU associated with this
2528 * PMC, and start the hardware.
2529 */
2530
2531 pmc_save_cpu_binding(&pb);
2532

--- 2254 unchanged lines hidden ---
2683
2684 /*
2685 * Move to the CPU associated with this
2686 * PMC, and start the hardware.
2687 */
2688
2689 pmc_save_cpu_binding(&pb);
2690

--- 2254 unchanged lines hidden ---