From: Alexander Shishkin alexander.shishkin@linux.intel.com
[ Upstream commit ff61541cc6c1962957758ba433c574b76f588d23 ]
Commit
8062382c8dbe2 ("perf/x86/intel/bts: Add BTS PMU driver")
brought in a warning with the BTS buffer initialization that is easily tripped with (assuming KPTI is disabled):
instantly throwing:
------------[ cut here ]------------ WARNING: CPU: 2 PID: 326 at arch/x86/events/intel/bts.c:86 bts_buffer_setup_aux+0x117/0x3d0 Modules linked in: CPU: 2 PID: 326 Comm: perf Not tainted 5.4.0-rc8-00291-gceb9e77324fa #904 RIP: 0010:bts_buffer_setup_aux+0x117/0x3d0 Call Trace: rb_alloc_aux+0x339/0x550 perf_mmap+0x607/0xc70 mmap_region+0x76b/0xbd0
...
It appears to assume (for lost raisins) that PagePrivate() is set, while later it actually tests for PagePrivate() before using page_private().
Make it consistent and always check PagePrivate() before using page_private().
Fixes: 8062382c8dbe2 ("perf/x86/intel/bts: Add BTS PMU driver") Signed-off-by: Alexander Shishkin alexander.shishkin@linux.intel.com Signed-off-by: Peter Zijlstra (Intel) peterz@infradead.org Cc: Jiri Olsa jolsa@kernel.org Cc: Vince Weaver vincent.weaver@maine.edu Cc: Ingo Molnar mingo@redhat.com Cc: Arnaldo Carvalho de Melo acme@redhat.com Link: https://lkml.kernel.org/r/20191205142853.28894-2-alexander.shishkin@linux.in... Signed-off-by: Sasha Levin sashal@kernel.org Signed-off-by: Yang Yingliang yangyingliang@huawei.com --- arch/x86/events/intel/bts.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-)
diff --git a/arch/x86/events/intel/bts.c b/arch/x86/events/intel/bts.c index 7139f6b..510f946 100644 --- a/arch/x86/events/intel/bts.c +++ b/arch/x86/events/intel/bts.c @@ -71,9 +71,17 @@ struct bts_buffer {
static struct pmu bts_pmu;
+static int buf_nr_pages(struct page *page) +{ + if (!PagePrivate(page)) + return 1; + + return 1 << page_private(page); +} + static size_t buf_size(struct page *page) { - return 1 << (PAGE_SHIFT + page_private(page)); + return buf_nr_pages(page) * PAGE_SIZE; }
static void * @@ -91,9 +99,7 @@ static size_t buf_size(struct page *page) /* count all the high order buffers */ for (pg = 0, nbuf = 0; pg < nr_pages;) { page = virt_to_page(pages[pg]); - if (WARN_ON_ONCE(!PagePrivate(page) && nr_pages > 1)) - return NULL; - pg += 1 << page_private(page); + pg += buf_nr_pages(page); nbuf++; }
@@ -117,7 +123,7 @@ static size_t buf_size(struct page *page) unsigned int __nr_pages;
page = virt_to_page(pages[pg]); - __nr_pages = PagePrivate(page) ? 1 << page_private(page) : 1; + __nr_pages = buf_nr_pages(page); buf->buf[nbuf].page = page; buf->buf[nbuf].offset = offset; buf->buf[nbuf].displacement = (pad ? BTS_RECORD_SIZE - pad : 0);