Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge branch 'perf-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip

Pull perf fixes from Ingo Molnar:
"Misc fixes: a BTS fix, a PT NMI handling fix, a PMU sysfs fix and an
SRCU annotation"

* 'perf-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
perf/core: Add SRCU annotation for pmus list walk
perf/x86/intel: Fix PT PMI handling
perf/x86/intel/bts: Fix the use of page_private()
perf/x86: Fix potential out-of-bounds access

+27 -10
+15 -4
arch/x86/events/core.c
··· 376 376 * LBR and BTS are still mutually exclusive. 377 377 */ 378 378 if (x86_pmu.lbr_pt_coexist && what == x86_lbr_exclusive_pt) 379 - return 0; 379 + goto out; 380 380 381 381 if (!atomic_inc_not_zero(&x86_pmu.lbr_exclusive[what])) { 382 382 mutex_lock(&pmc_reserve_mutex); ··· 388 388 mutex_unlock(&pmc_reserve_mutex); 389 389 } 390 390 391 + out: 391 392 atomic_inc(&active_events); 392 393 return 0; 393 394 ··· 399 398 400 399 void x86_del_exclusive(unsigned int what) 401 400 { 401 + atomic_dec(&active_events); 402 + 403 + /* 404 + * See the comment in x86_add_exclusive(). 405 + */ 402 406 if (x86_pmu.lbr_pt_coexist && what == x86_lbr_exclusive_pt) 403 407 return; 404 408 405 409 atomic_dec(&x86_pmu.lbr_exclusive[what]); 406 - atomic_dec(&active_events); 407 410 } 408 411 409 412 int x86_setup_perfctr(struct perf_event *event) ··· 1647 1642 1648 1643 ssize_t events_sysfs_show(struct device *dev, struct device_attribute *attr, char *page) 1649 1644 { 1650 - struct perf_pmu_events_attr *pmu_attr = \ 1645 + struct perf_pmu_events_attr *pmu_attr = 1651 1646 container_of(attr, struct perf_pmu_events_attr, attr); 1652 - u64 config = x86_pmu.event_map(pmu_attr->id); 1647 + u64 config = 0; 1648 + 1649 + if (pmu_attr->id < x86_pmu.max_events) 1650 + config = x86_pmu.event_map(pmu_attr->id); 1653 1651 1654 1652 /* string trumps id */ 1655 1653 if (pmu_attr->event_str) ··· 1720 1712 is_visible(struct kobject *kobj, struct attribute *attr, int idx) 1721 1713 { 1722 1714 struct perf_pmu_events_attr *pmu_attr; 1715 + 1716 + if (idx >= x86_pmu.max_events) 1717 + return 0; 1723 1718 1724 1719 pmu_attr = container_of(attr, struct perf_pmu_events_attr, attr.attr); 1725 1720 /* str trumps id */
+11 -5
arch/x86/events/intel/bts.c
··· 63 63 64 64 static struct pmu bts_pmu; 65 65 66 + static int buf_nr_pages(struct page *page) 67 + { 68 + if (!PagePrivate(page)) 69 + return 1; 70 + 71 + return 1 << page_private(page); 72 + } 73 + 66 74 static size_t buf_size(struct page *page) 67 75 { 68 - return 1 << (PAGE_SHIFT + page_private(page)); 76 + return buf_nr_pages(page) * PAGE_SIZE; 69 77 } 70 78 71 79 static void * ··· 91 83 /* count all the high order buffers */ 92 84 for (pg = 0, nbuf = 0; pg < nr_pages;) { 93 85 page = virt_to_page(pages[pg]); 94 - if (WARN_ON_ONCE(!PagePrivate(page) && nr_pages > 1)) 95 - return NULL; 96 - pg += 1 << page_private(page); 86 + pg += buf_nr_pages(page); 97 87 nbuf++; 98 88 } 99 89 ··· 115 109 unsigned int __nr_pages; 116 110 117 111 page = virt_to_page(pages[pg]); 118 - __nr_pages = PagePrivate(page) ? 1 << page_private(page) : 1; 112 + __nr_pages = buf_nr_pages(page); 119 113 buf->buf[nbuf].page = page; 120 114 buf->buf[nbuf].offset = offset; 121 115 buf->buf[nbuf].displacement = (pad ? BTS_RECORD_SIZE - pad : 0);
+1 -1
kernel/events/core.c
··· 10523 10523 goto unlock; 10524 10524 } 10525 10525 10526 - list_for_each_entry_rcu(pmu, &pmus, entry) { 10526 + list_for_each_entry_rcu(pmu, &pmus, entry, lockdep_is_held(&pmus_srcu)) { 10527 10527 ret = perf_try_init_event(pmu, event); 10528 10528 if (!ret) 10529 10529 goto unlock;