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