Linus,

Please pull the latest perf-urgent-for-linus git tree from:

   git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git 
perf-urgent-for-linus

   # HEAD: 7f635ff187ab6be0b350b3ec06791e376af238ab perf/core: Fix crash when 
using HW tracing kernel filters

Misc fixes:

 - AMD IBS data corruptor fix (uncovered by UBSAN)
 - an Intel PEBS entry unwind error fix
 - a HW-tracing crash fix
 - a MAINTAINERS update

 Thanks,

        Ingo

------------------>
Ananth N Mavinakayanahalli (1):
      MAINTAINERS: Add Naveen N. Rao as kprobes co-maintainer

Mathieu Poirier (1):
      perf/core: Fix crash when using HW tracing kernel filters

Peter Zijlstra (1):
      perf/x86/intel: Fix unwind errors from PEBS entries (mk-II)

Thomas Gleixner (1):
      perf/x86/amd/ibs: Don't access non-started event


 MAINTAINERS                     |  2 +-
 arch/x86/events/amd/ibs.c       |  6 +++++-
 arch/x86/events/intel/core.c    |  3 +++
 arch/x86/events/intel/ds.c      | 25 +++++++++++--------------
 include/linux/perf_event.h      |  1 +
 include/uapi/linux/perf_event.h |  2 ++
 kernel/events/core.c            | 10 ++++++++--
 7 files changed, 31 insertions(+), 18 deletions(-)

diff --git a/MAINTAINERS b/MAINTAINERS
index 0fe4228f78cb..42a884c1b0f7 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -7984,7 +7984,7 @@ F:        lib/test_kmod.c
 F:     tools/testing/selftests/kmod/
 
 KPROBES
-M:     Ananth N Mavinakayanahalli <ana...@linux.vnet.ibm.com>
+M:     Naveen N. Rao <naveen.n....@linux.vnet.ibm.com>
 M:     Anil S Keshavamurthy <anil.s.keshavamur...@intel.com>
 M:     "David S. Miller" <da...@davemloft.net>
 M:     Masami Hiramatsu <mhira...@kernel.org>
diff --git a/arch/x86/events/amd/ibs.c b/arch/x86/events/amd/ibs.c
index 4b98101209a1..d50bb4dc0650 100644
--- a/arch/x86/events/amd/ibs.c
+++ b/arch/x86/events/amd/ibs.c
@@ -579,7 +579,7 @@ static int perf_ibs_handle_irq(struct perf_ibs *perf_ibs, 
struct pt_regs *iregs)
 {
        struct cpu_perf_ibs *pcpu = this_cpu_ptr(perf_ibs->pcpu);
        struct perf_event *event = pcpu->event;
-       struct hw_perf_event *hwc = &event->hw;
+       struct hw_perf_event *hwc;
        struct perf_sample_data data;
        struct perf_raw_record raw;
        struct pt_regs regs;
@@ -602,6 +602,10 @@ static int perf_ibs_handle_irq(struct perf_ibs *perf_ibs, 
struct pt_regs *iregs)
                return 0;
        }
 
+       if (WARN_ON_ONCE(!event))
+               goto fail;
+
+       hwc = &event->hw;
        msr = hwc->config_base;
        buf = ibs_data.regs;
        rdmsrl(msr, *buf);
diff --git a/arch/x86/events/intel/core.c b/arch/x86/events/intel/core.c
index 707b2a96e516..86f0c15dcc2d 100644
--- a/arch/x86/events/intel/core.c
+++ b/arch/x86/events/intel/core.c
@@ -2997,6 +2997,9 @@ static int intel_pmu_hw_config(struct perf_event *event)
                }
                if (x86_pmu.pebs_aliases)
                        x86_pmu.pebs_aliases(event);
+
+               if (event->attr.sample_type & PERF_SAMPLE_CALLCHAIN)
+                       event->attr.sample_type |= 
__PERF_SAMPLE_CALLCHAIN_EARLY;
        }
 
        if (needs_branch_stack(event)) {
diff --git a/arch/x86/events/intel/ds.c b/arch/x86/events/intel/ds.c
index 8cf03f101938..8dbba77e0518 100644
--- a/arch/x86/events/intel/ds.c
+++ b/arch/x86/events/intel/ds.c
@@ -1185,17 +1185,21 @@ static void setup_pebs_sample_data(struct perf_event 
*event,
                data->data_src.val = val;
        }
 
+       /*
+        * We must however always use iregs for the unwinder to stay sane; the
+        * record BP,SP,IP can point into thin air when the record is from a
+        * previous PMI context or an (I)RET happend between the record and
+        * PMI.
+        */
+       if (sample_type & PERF_SAMPLE_CALLCHAIN)
+               data->callchain = perf_callchain(event, iregs);
+
        /*
         * We use the interrupt regs as a base because the PEBS record does not
         * contain a full regs set, specifically it seems to lack segment
         * descriptors, which get used by things like user_mode().
         *
         * In the simple case fix up only the IP for PERF_SAMPLE_IP.
-        *
-        * We must however always use BP,SP from iregs for the unwinder to stay
-        * sane; the record BP,SP can point into thin air when the record is
-        * from a previous PMI context or an (I)RET happend between the record
-        * and PMI.
         */
        *regs = *iregs;
 
@@ -1214,15 +1218,8 @@ static void setup_pebs_sample_data(struct perf_event 
*event,
                regs->si = pebs->si;
                regs->di = pebs->di;
 
-               /*
-                * Per the above; only set BP,SP if we don't need callchains.
-                *
-                * XXX: does this make sense?
-                */
-               if (!(sample_type & PERF_SAMPLE_CALLCHAIN)) {
-                       regs->bp = pebs->bp;
-                       regs->sp = pebs->sp;
-               }
+               regs->bp = pebs->bp;
+               regs->sp = pebs->sp;
 
 #ifndef CONFIG_X86_32
                regs->r8 = pebs->r8;
diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h
index 1fa12887ec02..87f6db437e4a 100644
--- a/include/linux/perf_event.h
+++ b/include/linux/perf_event.h
@@ -1130,6 +1130,7 @@ extern void perf_callchain_kernel(struct 
perf_callchain_entry_ctx *entry, struct
 extern struct perf_callchain_entry *
 get_perf_callchain(struct pt_regs *regs, u32 init_nr, bool kernel, bool user,
                   u32 max_stack, bool crosstask, bool add_mark);
+extern struct perf_callchain_entry *perf_callchain(struct perf_event *event, 
struct pt_regs *regs);
 extern int get_callchain_buffers(int max_stack);
 extern void put_callchain_buffers(void);
 
diff --git a/include/uapi/linux/perf_event.h b/include/uapi/linux/perf_event.h
index b8e288a1f740..eeb787b1c53c 100644
--- a/include/uapi/linux/perf_event.h
+++ b/include/uapi/linux/perf_event.h
@@ -143,6 +143,8 @@ enum perf_event_sample_format {
        PERF_SAMPLE_PHYS_ADDR                   = 1U << 19,
 
        PERF_SAMPLE_MAX = 1U << 20,             /* non-ABI */
+
+       __PERF_SAMPLE_CALLCHAIN_EARLY           = 1ULL << 63,
 };
 
 /*
diff --git a/kernel/events/core.c b/kernel/events/core.c
index 8f0434a9951a..eec2d5fb676b 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -6343,7 +6343,7 @@ static u64 perf_virt_to_phys(u64 virt)
 
 static struct perf_callchain_entry __empty_callchain = { .nr = 0, };
 
-static struct perf_callchain_entry *
+struct perf_callchain_entry *
 perf_callchain(struct perf_event *event, struct pt_regs *regs)
 {
        bool kernel = !event->attr.exclude_callchain_kernel;
@@ -6382,7 +6382,9 @@ void perf_prepare_sample(struct perf_event_header *header,
        if (sample_type & PERF_SAMPLE_CALLCHAIN) {
                int size = 1;
 
-               data->callchain = perf_callchain(event, regs);
+               if (!(sample_type & __PERF_SAMPLE_CALLCHAIN_EARLY))
+                       data->callchain = perf_callchain(event, regs);
+
                size += data->callchain->nr;
 
                header->size += size * sizeof(u64);
@@ -7335,6 +7337,10 @@ static bool perf_addr_filter_match(struct 
perf_addr_filter *filter,
                                     struct file *file, unsigned long offset,
                                     unsigned long size)
 {
+       /* d_inode(NULL) won't be equal to any mapped user-space file */
+       if (!filter->path.dentry)
+               return false;
+
        if (d_inode(filter->path.dentry) != file_inode(file))
                return false;
 

Reply via email to