aboutsummaryrefslogtreecommitdiffstats
path: root/common/recipes-kernel/linux/linux-yocto-4.9.21/0001-kaiser-fix-intel_bts-perf-crashes.patch
diff options
context:
space:
mode:
Diffstat (limited to 'common/recipes-kernel/linux/linux-yocto-4.9.21/0001-kaiser-fix-intel_bts-perf-crashes.patch')
-rw-r--r--common/recipes-kernel/linux/linux-yocto-4.9.21/0001-kaiser-fix-intel_bts-perf-crashes.patch135
1 files changed, 135 insertions, 0 deletions
diff --git a/common/recipes-kernel/linux/linux-yocto-4.9.21/0001-kaiser-fix-intel_bts-perf-crashes.patch b/common/recipes-kernel/linux/linux-yocto-4.9.21/0001-kaiser-fix-intel_bts-perf-crashes.patch
new file mode 100644
index 00000000..3e53e978
--- /dev/null
+++ b/common/recipes-kernel/linux/linux-yocto-4.9.21/0001-kaiser-fix-intel_bts-perf-crashes.patch
@@ -0,0 +1,135 @@
+From f07b0b948b09b02e7386560ad509d1afdbd6ef0b Mon Sep 17 00:00:00 2001
+From: Hugh Dickins <hughd@google.com>
+Date: Mon, 29 Jan 2018 18:16:55 -0800
+Subject: [PATCH 01/42] kaiser: fix intel_bts perf crashes
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Vince reported perf_fuzzer quickly locks up on 4.15-rc7 with PTI;
+Robert reported Bad RIP with KPTI and Intel BTS also on 4.15-rc7:
+honggfuzz -f /tmp/somedirectorywithatleastonefile \
+ --linux_perf_bts_edge -s -- /bin/true
+(honggfuzz from https://github.com/google/honggfuzz) crashed with
+BUG: unable to handle kernel paging request at ffff9d3215100000
+(then narrowed it down to
+perf record --per-thread -e intel_bts//u -- /bin/ls).
+
+The intel_bts driver does not use the 'normal' BTS buffer which is
+exposed through kaiser_add_mapping(), but instead uses the memory
+allocated for the perf AUX buffer.
+
+This obviously comes apart when using PTI, because then the kernel
+mapping, which includes that AUX buffer memory, disappears while
+switched to user page tables.
+
+Easily fixed in old-Kaiser backports, by applying kaiser_add_mapping()
+to those pages; perhaps not so easy for upstream, where 4.15-rc8 commit
+99a9dc98ba52 ("x86,perf: Disable intel_bts when PTI") disables for now.
+
+Slightly reorganized surrounding code in bts_buffer_setup_aux(),
+so it can better match bts_buffer_free_aux(): free_aux with an #ifdef
+to avoid the loop when PTI is off, but setup_aux needs to loop anyway
+(and kaiser_add_mapping() is cheap when PTI config is off or "pti=off").
+
+Reported-by: Vince Weaver <vincent.weaver@maine.edu>
+Reported-by: Robert Święcki <robert@swiecki.net>
+Analyzed-by: Peter Zijlstra <peterz@infradead.org>
+Analyzed-by: Stephane Eranian <eranian@google.com>
+Cc: Thomas Gleixner <tglx@linutronix.de>
+Cc: Ingo Molnar <mingo@kernel.org>
+Cc: Andy Lutomirski <luto@amacapital.net>
+Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
+Cc: Linus Torvalds <torvalds@linux-foundation.org>
+Cc: Vince Weaver <vince@deater.net>
+Cc: Jiri Kosina <jkosina@suse.cz>
+Signed-off-by: Hugh Dickins <hughd@google.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/x86/events/intel/bts.c | 44 +++++++++++++++++++++++++++++++++-----------
+ 1 file changed, 33 insertions(+), 11 deletions(-)
+
+diff --git a/arch/x86/events/intel/bts.c b/arch/x86/events/intel/bts.c
+index 982c9e3..21298c1 100644
+--- a/arch/x86/events/intel/bts.c
++++ b/arch/x86/events/intel/bts.c
+@@ -22,6 +22,7 @@
+ #include <linux/debugfs.h>
+ #include <linux/device.h>
+ #include <linux/coredump.h>
++#include <linux/kaiser.h>
+
+ #include <asm-generic/sizes.h>
+ #include <asm/perf_event.h>
+@@ -77,6 +78,23 @@ static size_t buf_size(struct page *page)
+ return 1 << (PAGE_SHIFT + page_private(page));
+ }
+
++static void bts_buffer_free_aux(void *data)
++{
++#ifdef CONFIG_PAGE_TABLE_ISOLATION
++ struct bts_buffer *buf = data;
++ int nbuf;
++
++ for (nbuf = 0; nbuf < buf->nr_bufs; nbuf++) {
++ struct page *page = buf->buf[nbuf].page;
++ void *kaddr = page_address(page);
++ size_t page_size = buf_size(page);
++
++ kaiser_remove_mapping((unsigned long)kaddr, page_size);
++ }
++#endif
++ kfree(data);
++}
++
+ static void *
+ bts_buffer_setup_aux(int cpu, void **pages, int nr_pages, bool overwrite)
+ {
+@@ -113,29 +131,33 @@ bts_buffer_setup_aux(int cpu, void **pages, int nr_pages, bool overwrite)
+ buf->real_size = size - size % BTS_RECORD_SIZE;
+
+ for (pg = 0, nbuf = 0, offset = 0, pad = 0; nbuf < buf->nr_bufs; nbuf++) {
+- unsigned int __nr_pages;
++ void *kaddr = pages[pg];
++ size_t page_size;
++
++ page = virt_to_page(kaddr);
++ page_size = buf_size(page);
++
++ if (kaiser_add_mapping((unsigned long)kaddr,
++ page_size, __PAGE_KERNEL) < 0) {
++ buf->nr_bufs = nbuf;
++ bts_buffer_free_aux(buf);
++ return NULL;
++ }
+
+- page = virt_to_page(pages[pg]);
+- __nr_pages = PagePrivate(page) ? 1 << page_private(page) : 1;
+ buf->buf[nbuf].page = page;
+ buf->buf[nbuf].offset = offset;
+ buf->buf[nbuf].displacement = (pad ? BTS_RECORD_SIZE - pad : 0);
+- buf->buf[nbuf].size = buf_size(page) - buf->buf[nbuf].displacement;
++ buf->buf[nbuf].size = page_size - buf->buf[nbuf].displacement;
+ pad = buf->buf[nbuf].size % BTS_RECORD_SIZE;
+ buf->buf[nbuf].size -= pad;
+
+- pg += __nr_pages;
+- offset += __nr_pages << PAGE_SHIFT;
++ pg += page_size >> PAGE_SHIFT;
++ offset += page_size;
+ }
+
+ return buf;
+ }
+
+-static void bts_buffer_free_aux(void *data)
+-{
+- kfree(data);
+-}
+-
+ static unsigned long bts_buffer_offset(struct bts_buffer *buf, unsigned int idx)
+ {
+ return buf->buf[idx].offset + buf->buf[idx].displacement;
+--
+2.7.4
+