Merge remote-tracking branch 'torvalds/master' into perf/core
[linux-2.6-microblaze.git] / arch / powerpc / perf / core-book3s.c
index 766f064..5162241 100644 (file)
@@ -17,6 +17,7 @@
 #include <asm/firmware.h>
 #include <asm/ptrace.h>
 #include <asm/code-patching.h>
+#include <asm/interrupt.h>
 
 #ifdef CONFIG_PPC64
 #include "internal.h"
@@ -168,7 +169,7 @@ static bool regs_use_siar(struct pt_regs *regs)
         * they have not been setup using perf_read_regs() and so regs->result
         * is something random.
         */
-       return ((TRAP(regs) == 0xf00) && regs->result);
+       return ((TRAP(regs) == INTERRUPT_PERFMON) && regs->result);
 }
 
 /*
@@ -347,7 +348,7 @@ static inline void perf_read_regs(struct pt_regs *regs)
         * hypervisor samples as well as samples in the kernel with
         * interrupts off hence the userspace check.
         */
-       if (TRAP(regs) != 0xf00)
+       if (TRAP(regs) != INTERRUPT_PERFMON)
                use_siar = 0;
        else if ((ppmu->flags & PPMU_NO_SIAR))
                use_siar = 0;
@@ -1963,6 +1964,17 @@ static int power_pmu_event_init(struct perf_event *event)
                return -ENOENT;
        }
 
+       /*
+        * PMU config registers have fields that are
+        * reserved and some specific values for bit fields are reserved.
+        * For ex., MMCRA[61:62] is Randome Sampling Mode (SM)
+        * and value of 0b11 to this field is reserved.
+        * Check for invalid values in attr.config.
+        */
+       if (ppmu->check_attr_config &&
+           ppmu->check_attr_config(event))
+               return -EINVAL;
+
        event->hw.config_base = ev;
        event->hw.idx = 0;
 
@@ -2206,9 +2218,9 @@ static void record_and_restart(struct perf_event *event, unsigned long val,
                                                ppmu->get_mem_data_src)
                        ppmu->get_mem_data_src(&data.data_src, ppmu->flags, regs);
 
-               if (event->attr.sample_type & PERF_SAMPLE_WEIGHT &&
+               if (event->attr.sample_type & PERF_SAMPLE_WEIGHT_TYPE &&
                                                ppmu->get_mem_weight)
-                       ppmu->get_mem_weight(&data.weight.full);
+                       ppmu->get_mem_weight(&data.weight.full, event->attr.sample_type);
 
                if (perf_event_overflow(event, &data, regs))
                        power_pmu_stop(event, 0);
@@ -2242,7 +2254,7 @@ unsigned long perf_instruction_pointer(struct pt_regs *regs)
        bool use_siar = regs_use_siar(regs);
        unsigned long siar = mfspr(SPRN_SIAR);
 
-       if (ppmu->flags & PPMU_P10_DD1) {
+       if (ppmu && (ppmu->flags & PPMU_P10_DD1)) {
                if (siar)
                        return siar;
                else