Merge remote-tracking branch 'lsk/v3.10/topic/gator' into linux-linaro-lsk
[firefly-linux-kernel-4.4.55.git] / arch / arm64 / kernel / perf_event.c
index 1b020200fffabee2bb4d7cb1b8b0b0994275ccea..dfcd8fadde3cc90afa4455d1a9875dd08468af73 100644 (file)
@@ -108,7 +108,12 @@ armpmu_map_cache_event(const unsigned (*cache_map)
 static int
 armpmu_map_event(const unsigned (*event_map)[PERF_COUNT_HW_MAX], u64 config)
 {
-       int mapping = (*event_map)[config];
+       int mapping;
+
+       if (config >= PERF_COUNT_HW_MAX)
+               return -EINVAL;
+
+       mapping = (*event_map)[config];
        return mapping == HW_OP_UNSUPPORTED ? -ENOENT : mapping;
 }
 
@@ -318,7 +323,13 @@ validate_event(struct pmu_hw_events *hw_events,
        struct hw_perf_event fake_event = event->hw;
        struct pmu *leader_pmu = event->group_leader->pmu;
 
-       if (event->pmu != leader_pmu || event->state <= PERF_EVENT_STATE_OFF)
+       if (is_software_event(event))
+               return 1;
+
+       if (event->pmu != leader_pmu || event->state < PERF_EVENT_STATE_OFF)
+               return 1;
+
+       if (event->state == PERF_EVENT_STATE_OFF && !event->attr.enable_on_exec)
                return 1;
 
        return armpmu->get_event_idx(hw_events, &fake_event) >= 0;
@@ -821,7 +832,7 @@ static const unsigned armv8_pmuv3_perf_cache_map[PERF_COUNT_HW_CACHE_MAX]
 /*
  * PMXEVTYPER: Event selection reg
  */
-#define        ARMV8_EVTYPE_MASK       0xc00000ff      /* Mask for writable bits */
+#define        ARMV8_EVTYPE_MASK       0xc80000ff      /* Mask for writable bits */
 #define        ARMV8_EVTYPE_EVENT      0xff            /* Mask for EVENT bits */
 
 /*
@@ -1374,6 +1385,7 @@ user_backtrace(struct frame_tail __user *tail,
        return buftail.fp;
 }
 
+#ifdef CONFIG_COMPAT
 /*
  * The registers we're interested in are at the end of the variable
  * length saved register structure. The fp points at the end of this
@@ -1418,6 +1430,7 @@ compat_user_backtrace(struct compat_frame_tail __user *tail,
 
        return (struct compat_frame_tail __user *)compat_ptr(buftail.fp) - 1;
 }
+#endif /* CONFIG_COMPAT */
 
 void perf_callchain_user(struct perf_callchain_entry *entry,
                         struct pt_regs *regs)
@@ -1439,6 +1452,7 @@ void perf_callchain_user(struct perf_callchain_entry *entry,
                       tail && !((unsigned long)tail & 0xf))
                        tail = user_backtrace(tail, entry);
        } else {
+#ifdef CONFIG_COMPAT
                /* AARCH32 compat mode */
                struct compat_frame_tail __user *tail;
 
@@ -1447,6 +1461,7 @@ void perf_callchain_user(struct perf_callchain_entry *entry,
                while ((entry->nr < PERF_MAX_STACK_DEPTH) &&
                        tail && !((unsigned long)tail & 0x3))
                        tail = compat_user_backtrace(tail, entry);
+#endif
        }
 }