Merge commit 'v2.6.34-rc1' into perf/urgent
authorIngo Molnar <mingo@elte.hu>
Tue, 9 Mar 2010 16:11:53 +0000 (17:11 +0100)
committerIngo Molnar <mingo@elte.hu>
Tue, 9 Mar 2010 16:11:53 +0000 (17:11 +0100)
Conflicts:
tools/perf/util/probe-event.c

Merge reason: Pick up -rc1 and resolve the conflict as well.

Signed-off-by: Ingo Molnar <mingo@elte.hu>
24 files changed:
MAINTAINERS
arch/x86/include/asm/hw_breakpoint.h
arch/x86/include/asm/perf_event.h
arch/x86/kernel/cpu/perf_event.c
arch/x86/kernel/cpu/perf_event_intel.c
arch/x86/kernel/cpu/perf_event_p6.c
arch/x86/kernel/cpu/perfctr-watchdog.c
arch/x86/kernel/dumpstack_64.c
arch/x86/kernel/hw_breakpoint.c
arch/x86/oprofile/op_model_amd.c
arch/x86/oprofile/op_model_ppro.c
include/linux/hw_breakpoint.h
include/linux/perf_event.h
kernel/hw_breakpoint.c
kernel/perf_event.c
lib/Kconfig.debug
samples/hw_breakpoint/data_breakpoint.c
tools/perf/Documentation/perf-lock.txt [new file with mode: 0644]
tools/perf/builtin-lock.c
tools/perf/builtin-trace.c
tools/perf/command-list.txt
tools/perf/perf-archive.sh
tools/perf/perf.h
tools/perf/util/probe-event.c

index c8a8b1f..14d5c4c 100644 (file)
@@ -4293,6 +4293,7 @@ PERFORMANCE EVENTS SUBSYSTEM
 M:     Peter Zijlstra <a.p.zijlstra@chello.nl>
 M:     Paul Mackerras <paulus@samba.org>
 M:     Ingo Molnar <mingo@elte.hu>
+M:     Arnaldo Carvalho de Melo <acme@redhat.com>
 S:     Supported
 F:     kernel/perf_event.c
 F:     include/linux/perf_event.h
index 0675a7c..2a1bd8f 100644 (file)
@@ -10,7 +10,6 @@
  * (display/resolving)
  */
 struct arch_hw_breakpoint {
-       char            *name; /* Contains name of the symbol to set bkpt */
        unsigned long   address;
        u8              len;
        u8              type;
index befd172..db6109a 100644 (file)
@@ -18,7 +18,7 @@
 #define MSR_ARCH_PERFMON_EVENTSEL0                          0x186
 #define MSR_ARCH_PERFMON_EVENTSEL1                          0x187
 
-#define ARCH_PERFMON_EVENTSEL0_ENABLE                    (1 << 22)
+#define ARCH_PERFMON_EVENTSEL_ENABLE                     (1 << 22)
 #define ARCH_PERFMON_EVENTSEL_ANY                        (1 << 21)
 #define ARCH_PERFMON_EVENTSEL_INT                        (1 << 20)
 #define ARCH_PERFMON_EVENTSEL_OS                         (1 << 17)
@@ -50,7 +50,7 @@
         INTEL_ARCH_INV_MASK| \
         INTEL_ARCH_EDGE_MASK|\
         INTEL_ARCH_UNIT_MASK|\
-        INTEL_ARCH_EVTSEL_MASK)
+        INTEL_ARCH_EVENT_MASK)
 
 #define ARCH_PERFMON_UNHALTED_CORE_CYCLES_SEL                0x3c
 #define ARCH_PERFMON_UNHALTED_CORE_CYCLES_UMASK                (0x00 << 8)
@@ -117,6 +117,18 @@ union cpuid10_edx {
  */
 #define X86_PMC_IDX_FIXED_BTS                          (X86_PMC_IDX_FIXED + 16)
 
+/* IbsFetchCtl bits/masks */
+#define IBS_FETCH_RAND_EN              (1ULL<<57)
+#define IBS_FETCH_VAL                  (1ULL<<49)
+#define IBS_FETCH_ENABLE               (1ULL<<48)
+#define IBS_FETCH_CNT                  0xFFFF0000ULL
+#define IBS_FETCH_MAX_CNT              0x0000FFFFULL
+
+/* IbsOpCtl bits */
+#define IBS_OP_CNT_CTL                 (1ULL<<19)
+#define IBS_OP_VAL                     (1ULL<<18)
+#define IBS_OP_ENABLE                  (1ULL<<17)
+#define IBS_OP_MAX_CNT                 0x0000FFFFULL
 
 #ifdef CONFIG_PERF_EVENTS
 extern void init_hw_perf_events(void);
index b1fbdee..97cddbf 100644 (file)
@@ -73,10 +73,10 @@ struct debug_store {
 struct event_constraint {
        union {
                unsigned long   idxmsk[BITS_TO_LONGS(X86_PMC_IDX_MAX)];
-               u64             idxmsk64[1];
+               u64             idxmsk64;
        };
-       int     code;
-       int     cmask;
+       u64     code;
+       u64     cmask;
        int     weight;
 };
 
@@ -103,7 +103,7 @@ struct cpu_hw_events {
 };
 
 #define __EVENT_CONSTRAINT(c, n, m, w) {\
-       { .idxmsk64[0] = (n) },         \
+       { .idxmsk64 = (n) },            \
        .code = (c),                    \
        .cmask = (m),                   \
        .weight = (w),                  \
@@ -116,7 +116,7 @@ struct cpu_hw_events {
        EVENT_CONSTRAINT(c, n, INTEL_ARCH_EVTSEL_MASK)
 
 #define FIXED_EVENT_CONSTRAINT(c, n)   \
-       EVENT_CONSTRAINT(c, n, INTEL_ARCH_FIXED_MASK)
+       EVENT_CONSTRAINT(c, (1ULL << (32+n)), INTEL_ARCH_FIXED_MASK)
 
 #define EVENT_CONSTRAINT_END           \
        EVENT_CONSTRAINT(0, 0, 0)
@@ -503,6 +503,9 @@ static int __hw_perf_event_init(struct perf_event *event)
         */
        if (attr->type == PERF_TYPE_RAW) {
                hwc->config |= x86_pmu.raw_event(attr->config);
+               if ((hwc->config & ARCH_PERFMON_EVENTSEL_ANY) &&
+                   perf_paranoid_cpu() && !capable(CAP_SYS_ADMIN))
+                       return -EACCES;
                return 0;
        }
 
@@ -553,9 +556,9 @@ static void x86_pmu_disable_all(void)
                if (!test_bit(idx, cpuc->active_mask))
                        continue;
                rdmsrl(x86_pmu.eventsel + idx, val);
-               if (!(val & ARCH_PERFMON_EVENTSEL0_ENABLE))
+               if (!(val & ARCH_PERFMON_EVENTSEL_ENABLE))
                        continue;
-               val &= ~ARCH_PERFMON_EVENTSEL0_ENABLE;
+               val &= ~ARCH_PERFMON_EVENTSEL_ENABLE;
                wrmsrl(x86_pmu.eventsel + idx, val);
        }
 }
@@ -590,7 +593,7 @@ static void x86_pmu_enable_all(void)
                        continue;
 
                val = event->hw.config;
-               val |= ARCH_PERFMON_EVENTSEL0_ENABLE;
+               val |= ARCH_PERFMON_EVENTSEL_ENABLE;
                wrmsrl(x86_pmu.eventsel + idx, val);
        }
 }
@@ -612,8 +615,8 @@ static int x86_schedule_events(struct cpu_hw_events *cpuc, int n, int *assign)
        bitmap_zero(used_mask, X86_PMC_IDX_MAX);
 
        for (i = 0; i < n; i++) {
-               constraints[i] =
-                 x86_pmu.get_event_constraints(cpuc, cpuc->event_list[i]);
+               c = x86_pmu.get_event_constraints(cpuc, cpuc->event_list[i]);
+               constraints[i] = c;
        }
 
        /*
@@ -853,7 +856,7 @@ void hw_perf_enable(void)
 static inline void __x86_pmu_enable_event(struct hw_perf_event *hwc, int idx)
 {
        (void)checking_wrmsrl(hwc->config_base + idx,
-                             hwc->config | ARCH_PERFMON_EVENTSEL0_ENABLE);
+                             hwc->config | ARCH_PERFMON_EVENTSEL_ENABLE);
 }
 
 static inline void x86_pmu_disable_event(struct hw_perf_event *hwc, int idx)
@@ -1347,6 +1350,7 @@ static void __init pmu_check_apic(void)
 
 void __init init_hw_perf_events(void)
 {
+       struct event_constraint *c;
        int err;
 
        pr_info("Performance Events: ");
@@ -1395,6 +1399,16 @@ void __init init_hw_perf_events(void)
                __EVENT_CONSTRAINT(0, (1ULL << x86_pmu.num_events) - 1,
                                   0, x86_pmu.num_events);
 
+       if (x86_pmu.event_constraints) {
+               for_each_event_constraint(c, x86_pmu.event_constraints) {
+                       if (c->cmask != INTEL_ARCH_FIXED_MASK)
+                               continue;
+
+                       c->idxmsk64 |= (1ULL << x86_pmu.num_events) - 1;
+                       c->weight += x86_pmu.num_events;
+               }
+       }
+
        pr_info("... version:                %d\n",     x86_pmu.version);
        pr_info("... bit width:              %d\n",     x86_pmu.event_bits);
        pr_info("... generic registers:      %d\n",     x86_pmu.num_events);
index 977e754..73102df 100644 (file)
@@ -1,7 +1,7 @@
 #ifdef CONFIG_CPU_SUP_INTEL
 
 /*
- * Intel PerfMon v3. Used on Core2 and later.
+ * Intel PerfMon, used on Core and later.
  */
 static const u64 intel_perfmon_event_map[] =
 {
@@ -27,8 +27,14 @@ static struct event_constraint intel_core_event_constraints[] =
 
 static struct event_constraint intel_core2_event_constraints[] =
 {
-       FIXED_EVENT_CONSTRAINT(0xc0, (0x3|(1ULL<<32))), /* INSTRUCTIONS_RETIRED */
-       FIXED_EVENT_CONSTRAINT(0x3c, (0x3|(1ULL<<33))), /* UNHALTED_CORE_CYCLES */
+       FIXED_EVENT_CONSTRAINT(0x00c0, 0), /* INST_RETIRED.ANY */
+       FIXED_EVENT_CONSTRAINT(0x003c, 1), /* CPU_CLK_UNHALTED.CORE */
+       /*
+        * Core2 has Fixed Counter 2 listed as CPU_CLK_UNHALTED.REF and event
+        * 0x013c as CPU_CLK_UNHALTED.BUS and specifies there is a fixed
+        * ratio between these counters.
+        */
+       /* FIXED_EVENT_CONSTRAINT(0x013c, 2),  CPU_CLK_UNHALTED.REF */
        INTEL_EVENT_CONSTRAINT(0x10, 0x1), /* FP_COMP_OPS_EXE */
        INTEL_EVENT_CONSTRAINT(0x11, 0x2), /* FP_ASSIST */
        INTEL_EVENT_CONSTRAINT(0x12, 0x2), /* MUL */
@@ -37,14 +43,16 @@ static struct event_constraint intel_core2_event_constraints[] =
        INTEL_EVENT_CONSTRAINT(0x18, 0x1), /* IDLE_DURING_DIV */
        INTEL_EVENT_CONSTRAINT(0x19, 0x2), /* DELAYED_BYPASS */
        INTEL_EVENT_CONSTRAINT(0xa1, 0x1), /* RS_UOPS_DISPATCH_CYCLES */
+       INTEL_EVENT_CONSTRAINT(0xc9, 0x1), /* ITLB_MISS_RETIRED (T30-9) */
        INTEL_EVENT_CONSTRAINT(0xcb, 0x1), /* MEM_LOAD_RETIRED */
        EVENT_CONSTRAINT_END
 };
 
 static struct event_constraint intel_nehalem_event_constraints[] =
 {
-       FIXED_EVENT_CONSTRAINT(0xc0, (0xf|(1ULL<<32))), /* INSTRUCTIONS_RETIRED */
-       FIXED_EVENT_CONSTRAINT(0x3c, (0xf|(1ULL<<33))), /* UNHALTED_CORE_CYCLES */
+       FIXED_EVENT_CONSTRAINT(0x00c0, 0), /* INST_RETIRED.ANY */
+       FIXED_EVENT_CONSTRAINT(0x003c, 1), /* CPU_CLK_UNHALTED.CORE */
+       /* FIXED_EVENT_CONSTRAINT(0x013c, 2), CPU_CLK_UNHALTED.REF */
        INTEL_EVENT_CONSTRAINT(0x40, 0x3), /* L1D_CACHE_LD */
        INTEL_EVENT_CONSTRAINT(0x41, 0x3), /* L1D_CACHE_ST */
        INTEL_EVENT_CONSTRAINT(0x42, 0x3), /* L1D_CACHE_LOCK */
@@ -58,8 +66,9 @@ static struct event_constraint intel_nehalem_event_constraints[] =
 
 static struct event_constraint intel_westmere_event_constraints[] =
 {
-       FIXED_EVENT_CONSTRAINT(0xc0, (0xf|(1ULL<<32))), /* INSTRUCTIONS_RETIRED */
-       FIXED_EVENT_CONSTRAINT(0x3c, (0xf|(1ULL<<33))), /* UNHALTED_CORE_CYCLES */
+       FIXED_EVENT_CONSTRAINT(0x00c0, 0), /* INST_RETIRED.ANY */
+       FIXED_EVENT_CONSTRAINT(0x003c, 1), /* CPU_CLK_UNHALTED.CORE */
+       /* FIXED_EVENT_CONSTRAINT(0x013c, 2), CPU_CLK_UNHALTED.REF */
        INTEL_EVENT_CONSTRAINT(0x51, 0x3), /* L1D */
        INTEL_EVENT_CONSTRAINT(0x60, 0x1), /* OFFCORE_REQUESTS_OUTSTANDING */
        INTEL_EVENT_CONSTRAINT(0x63, 0x3), /* CACHE_LOCK_CYCLES */
@@ -68,8 +77,9 @@ static struct event_constraint intel_westmere_event_constraints[] =
 
 static struct event_constraint intel_gen_event_constraints[] =
 {
-       FIXED_EVENT_CONSTRAINT(0xc0, (0x3|(1ULL<<32))), /* INSTRUCTIONS_RETIRED */
-       FIXED_EVENT_CONSTRAINT(0x3c, (0x3|(1ULL<<33))), /* UNHALTED_CORE_CYCLES */
+       FIXED_EVENT_CONSTRAINT(0x00c0, 0), /* INST_RETIRED.ANY */
+       FIXED_EVENT_CONSTRAINT(0x003c, 1), /* CPU_CLK_UNHALTED.CORE */
+       /* FIXED_EVENT_CONSTRAINT(0x013c, 2), CPU_CLK_UNHALTED.REF */
        EVENT_CONSTRAINT_END
 };
 
@@ -935,7 +945,7 @@ static __init int intel_pmu_init(void)
                x86_pmu.event_constraints = intel_nehalem_event_constraints;
                pr_cont("Nehalem/Corei7 events, ");
                break;
-       case 28:
+       case 28: /* Atom */
                memcpy(hw_cache_event_ids, atom_hw_cache_event_ids,
                       sizeof(hw_cache_event_ids));
 
@@ -951,6 +961,7 @@ static __init int intel_pmu_init(void)
                x86_pmu.event_constraints = intel_westmere_event_constraints;
                pr_cont("Westmere events, ");
                break;
+
        default:
                /*
                 * default constraints for v2 and up
index 1ca5ba0..a4e67b9 100644 (file)
@@ -62,7 +62,7 @@ static void p6_pmu_disable_all(void)
 
        /* p6 only has one enable register */
        rdmsrl(MSR_P6_EVNTSEL0, val);
-       val &= ~ARCH_PERFMON_EVENTSEL0_ENABLE;
+       val &= ~ARCH_PERFMON_EVENTSEL_ENABLE;
        wrmsrl(MSR_P6_EVNTSEL0, val);
 }
 
@@ -72,7 +72,7 @@ static void p6_pmu_enable_all(void)
 
        /* p6 only has one enable register */
        rdmsrl(MSR_P6_EVNTSEL0, val);
-       val |= ARCH_PERFMON_EVENTSEL0_ENABLE;
+       val |= ARCH_PERFMON_EVENTSEL_ENABLE;
        wrmsrl(MSR_P6_EVNTSEL0, val);
 }
 
@@ -83,7 +83,7 @@ p6_pmu_disable_event(struct hw_perf_event *hwc, int idx)
        u64 val = P6_NOP_EVENT;
 
        if (cpuc->enabled)
-               val |= ARCH_PERFMON_EVENTSEL0_ENABLE;
+               val |= ARCH_PERFMON_EVENTSEL_ENABLE;
 
        (void)checking_wrmsrl(hwc->config_base + idx, val);
 }
@@ -95,7 +95,7 @@ static void p6_pmu_enable_event(struct hw_perf_event *hwc, int idx)
 
        val = hwc->config;
        if (cpuc->enabled)
-               val |= ARCH_PERFMON_EVENTSEL0_ENABLE;
+               val |= ARCH_PERFMON_EVENTSEL_ENABLE;
 
        (void)checking_wrmsrl(hwc->config_base + idx, val);
 }
index 74f4e85..fb329e9 100644 (file)
@@ -680,7 +680,7 @@ static int setup_intel_arch_watchdog(unsigned nmi_hz)
        cpu_nmi_set_wd_enabled();
 
        apic_write(APIC_LVTPC, APIC_DM_NMI);
-       evntsel |= ARCH_PERFMON_EVENTSEL0_ENABLE;
+       evntsel |= ARCH_PERFMON_EVENTSEL_ENABLE;
        wrmsr(evntsel_msr, evntsel, 0);
        intel_arch_wd_ops.checkbit = 1ULL << (eax.split.bit_width - 1);
        return 1;
index dce99ab..d5e2a2e 100644 (file)
@@ -120,9 +120,15 @@ fixup_bp_irq_link(unsigned long bp, unsigned long *stack,
 {
 #ifdef CONFIG_FRAME_POINTER
        struct stack_frame *frame = (struct stack_frame *)bp;
+       unsigned long next;
 
-       if (!in_irq_stack(stack, irq_stack, irq_stack_end))
-               return (unsigned long)frame->next_frame;
+       if (!in_irq_stack(stack, irq_stack, irq_stack_end)) {
+               if (!probe_kernel_address(&frame->next_frame, next))
+                       return next;
+               else
+                       WARN_ONCE(1, "Perf: bad frame pointer = %p in "
+                                 "callchain\n", &frame->next_frame);
+       }
 #endif
        return bp;
 }
index dca2802..d6cc065 100644 (file)
@@ -344,13 +344,6 @@ int arch_validate_hwbkpt_settings(struct perf_event *bp,
        }
 
        /*
-        * For kernel-addresses, either the address or symbol name can be
-        * specified.
-        */
-       if (info->name)
-               info->address = (unsigned long)
-                               kallsyms_lookup_name(info->name);
-       /*
         * Check that the low-order bits of the address are appropriate
         * for the alignment implied by len.
         */
@@ -535,8 +528,3 @@ void hw_breakpoint_pmu_read(struct perf_event *bp)
 {
        /* TODO */
 }
-
-void hw_breakpoint_pmu_unthrottle(struct perf_event *bp)
-{
-       /* TODO */
-}
index 6a58256..090cbbe 100644 (file)
 
 static unsigned long reset_value[NUM_VIRT_COUNTERS];
 
-/* IbsFetchCtl bits/masks */
-#define IBS_FETCH_RAND_EN              (1ULL<<57)
-#define IBS_FETCH_VAL                  (1ULL<<49)
-#define IBS_FETCH_ENABLE               (1ULL<<48)
-#define IBS_FETCH_CNT_MASK             0xFFFF0000ULL
-
-/* IbsOpCtl bits */
-#define IBS_OP_CNT_CTL                 (1ULL<<19)
-#define IBS_OP_VAL                     (1ULL<<18)
-#define IBS_OP_ENABLE                  (1ULL<<17)
-
 #define IBS_FETCH_SIZE                 6
 #define IBS_OP_SIZE                    12
 
@@ -182,7 +171,7 @@ static void op_amd_setup_ctrs(struct op_x86_model_spec const *model,
                        continue;
                }
                rdmsrl(msrs->controls[i].addr, val);
-               if (val & ARCH_PERFMON_EVENTSEL0_ENABLE)
+               if (val & ARCH_PERFMON_EVENTSEL_ENABLE)
                        op_x86_warn_in_use(i);
                val &= model->reserved;
                wrmsrl(msrs->controls[i].addr, val);
@@ -290,7 +279,7 @@ op_amd_handle_ibs(struct pt_regs * const regs,
                        oprofile_write_commit(&entry);
 
                        /* reenable the IRQ */
-                       ctl &= ~(IBS_FETCH_VAL | IBS_FETCH_CNT_MASK);
+                       ctl &= ~(IBS_FETCH_VAL | IBS_FETCH_CNT);
                        ctl |= IBS_FETCH_ENABLE;
                        wrmsrl(MSR_AMD64_IBSFETCHCTL, ctl);
                }
@@ -330,7 +319,7 @@ static inline void op_amd_start_ibs(void)
                return;
 
        if (ibs_config.fetch_enabled) {
-               val = (ibs_config.max_cnt_fetch >> 4) & 0xFFFF;
+               val = (ibs_config.max_cnt_fetch >> 4) & IBS_FETCH_MAX_CNT;
                val |= ibs_config.rand_en ? IBS_FETCH_RAND_EN : 0;
                val |= IBS_FETCH_ENABLE;
                wrmsrl(MSR_AMD64_IBSFETCHCTL, val);
@@ -352,7 +341,7 @@ static inline void op_amd_start_ibs(void)
                         * avoid underflows.
                         */
                        ibs_op_ctl = min(ibs_op_ctl + IBS_RANDOM_MAXCNT_OFFSET,
-                                        0xFFFFULL);
+                                        IBS_OP_MAX_CNT);
                }
                if (ibs_caps & IBS_CAPS_OPCNT && ibs_config.dispatched_ops)
                        ibs_op_ctl |= IBS_OP_CNT_CTL;
@@ -409,7 +398,7 @@ static void op_amd_start(struct op_msrs const * const msrs)
                if (!reset_value[op_x86_phys_to_virt(i)])
                        continue;
                rdmsrl(msrs->controls[i].addr, val);
-               val |= ARCH_PERFMON_EVENTSEL0_ENABLE;
+               val |= ARCH_PERFMON_EVENTSEL_ENABLE;
                wrmsrl(msrs->controls[i].addr, val);
        }
 
@@ -429,7 +418,7 @@ static void op_amd_stop(struct op_msrs const * const msrs)
                if (!reset_value[op_x86_phys_to_virt(i)])
                        continue;
                rdmsrl(msrs->controls[i].addr, val);
-               val &= ~ARCH_PERFMON_EVENTSEL0_ENABLE;
+               val &= ~ARCH_PERFMON_EVENTSEL_ENABLE;
                wrmsrl(msrs->controls[i].addr, val);
        }
 
index 5d1727b..2bf90fa 100644 (file)
@@ -88,7 +88,7 @@ static void ppro_setup_ctrs(struct op_x86_model_spec const *model,
                        continue;
                }
                rdmsrl(msrs->controls[i].addr, val);
-               if (val & ARCH_PERFMON_EVENTSEL0_ENABLE)
+               if (val & ARCH_PERFMON_EVENTSEL_ENABLE)
                        op_x86_warn_in_use(i);
                val &= model->reserved;
                wrmsrl(msrs->controls[i].addr, val);
@@ -166,7 +166,7 @@ static void ppro_start(struct op_msrs const * const msrs)
        for (i = 0; i < num_counters; ++i) {
                if (reset_value[i]) {
                        rdmsrl(msrs->controls[i].addr, val);
-                       val |= ARCH_PERFMON_EVENTSEL0_ENABLE;
+                       val |= ARCH_PERFMON_EVENTSEL_ENABLE;
                        wrmsrl(msrs->controls[i].addr, val);
                }
        }
@@ -184,7 +184,7 @@ static void ppro_stop(struct op_msrs const * const msrs)
                if (!reset_value[i])
                        continue;
                rdmsrl(msrs->controls[i].addr, val);
-               val &= ~ARCH_PERFMON_EVENTSEL0_ENABLE;
+               val &= ~ARCH_PERFMON_EVENTSEL_ENABLE;
                wrmsrl(msrs->controls[i].addr, val);
        }
 }
index 5977b72..c70d27a 100644 (file)
@@ -66,14 +66,14 @@ register_wide_hw_breakpoint_cpu(struct perf_event_attr *attr,
                                perf_overflow_handler_t triggered,
                                int cpu);
 
-extern struct perf_event **
+extern struct perf_event * __percpu *
 register_wide_hw_breakpoint(struct perf_event_attr *attr,
                            perf_overflow_handler_t triggered);
 
 extern int register_perf_hw_breakpoint(struct perf_event *bp);
 extern int __register_perf_hw_breakpoint(struct perf_event *bp);
 extern void unregister_hw_breakpoint(struct perf_event *bp);
-extern void unregister_wide_hw_breakpoint(struct perf_event **cpu_events);
+extern void unregister_wide_hw_breakpoint(struct perf_event * __percpu *cpu_events);
 
 extern int dbg_reserve_bp_slot(struct perf_event *bp);
 extern int dbg_release_bp_slot(struct perf_event *bp);
@@ -100,7 +100,7 @@ static inline struct perf_event *
 register_wide_hw_breakpoint_cpu(struct perf_event_attr *attr,
                                perf_overflow_handler_t  triggered,
                                int cpu)                { return NULL; }
-static inline struct perf_event **
+static inline struct perf_event * __percpu *
 register_wide_hw_breakpoint(struct perf_event_attr *attr,
                            perf_overflow_handler_t triggered)  { return NULL; }
 static inline int
@@ -109,7 +109,7 @@ static inline int
 __register_perf_hw_breakpoint(struct perf_event *bp)   { return -ENOSYS; }
 static inline void unregister_hw_breakpoint(struct perf_event *bp)     { }
 static inline void
-unregister_wide_hw_breakpoint(struct perf_event **cpu_events)          { }
+unregister_wide_hw_breakpoint(struct perf_event * __percpu *cpu_events)        { }
 static inline int
 reserve_bp_slot(struct perf_event *bp)                 {return -ENOSYS; }
 static inline void release_bp_slot(struct perf_event *bp)              { }
index 7b18b4f..90e0521 100644 (file)
@@ -487,9 +487,8 @@ struct hw_perf_event {
                        struct hrtimer  hrtimer;
                };
 #ifdef CONFIG_HAVE_HW_BREAKPOINT
-               union { /* breakpoint */
-                       struct arch_hw_breakpoint       info;
-               };
+               /* breakpoint */
+               struct arch_hw_breakpoint       info;
 #endif
        };
        atomic64_t                      prev_count;
@@ -858,6 +857,21 @@ extern int sysctl_perf_event_paranoid;
 extern int sysctl_perf_event_mlock;
 extern int sysctl_perf_event_sample_rate;
 
+static inline bool perf_paranoid_tracepoint_raw(void)
+{
+       return sysctl_perf_event_paranoid > -1;
+}
+
+static inline bool perf_paranoid_cpu(void)
+{
+       return sysctl_perf_event_paranoid > 0;
+}
+
+static inline bool perf_paranoid_kernel(void)
+{
+       return sysctl_perf_event_paranoid > 1;
+}
+
 extern void perf_event_init(void);
 extern void perf_tp_event(int event_id, u64 addr, u64 count, void *record, int entry_size);
 extern void perf_bp_event(struct perf_event *event, void *data);
index 967e661..03808ed 100644 (file)
@@ -413,17 +413,17 @@ EXPORT_SYMBOL_GPL(unregister_hw_breakpoint);
  *
  * @return a set of per_cpu pointers to perf events
  */
-struct perf_event **
+struct perf_event * __percpu *
 register_wide_hw_breakpoint(struct perf_event_attr *attr,
                            perf_overflow_handler_t triggered)
 {
-       struct perf_event **cpu_events, **pevent, *bp;
+       struct perf_event * __percpu *cpu_events, **pevent, *bp;
        long err;
        int cpu;
 
        cpu_events = alloc_percpu(typeof(*cpu_events));
        if (!cpu_events)
-               return ERR_PTR(-ENOMEM);
+               return (void __percpu __force *)ERR_PTR(-ENOMEM);
 
        get_online_cpus();
        for_each_online_cpu(cpu) {
@@ -451,7 +451,7 @@ fail:
        put_online_cpus();
 
        free_percpu(cpu_events);
-       return ERR_PTR(err);
+       return (void __percpu __force *)ERR_PTR(err);
 }
 EXPORT_SYMBOL_GPL(register_wide_hw_breakpoint);
 
@@ -459,7 +459,7 @@ EXPORT_SYMBOL_GPL(register_wide_hw_breakpoint);
  * unregister_wide_hw_breakpoint - unregister a wide breakpoint in the kernel
  * @cpu_events: the per cpu set of events to unregister
  */
-void unregister_wide_hw_breakpoint(struct perf_event **cpu_events)
+void unregister_wide_hw_breakpoint(struct perf_event * __percpu *cpu_events)
 {
        int cpu;
        struct perf_event **pevent;
@@ -489,5 +489,4 @@ struct pmu perf_ops_bp = {
        .enable         = arch_install_hw_breakpoint,
        .disable        = arch_uninstall_hw_breakpoint,
        .read           = hw_breakpoint_pmu_read,
-       .unthrottle     = hw_breakpoint_pmu_unthrottle
 };
index f40560b..e687450 100644 (file)
@@ -56,21 +56,6 @@ static atomic_t nr_task_events __read_mostly;
  */
 int sysctl_perf_event_paranoid __read_mostly = 1;
 
-static inline bool perf_paranoid_tracepoint_raw(void)
-{
-       return sysctl_perf_event_paranoid > -1;
-}
-
-static inline bool perf_paranoid_cpu(void)
-{
-       return sysctl_perf_event_paranoid > 0;
-}
-
-static inline bool perf_paranoid_kernel(void)
-{
-       return sysctl_perf_event_paranoid > 1;
-}
-
 int sysctl_perf_event_mlock __read_mostly = 512; /* 'free' kb per user */
 
 /*
index b520ec1..8e5ec5e 100644 (file)
@@ -532,6 +532,14 @@ config LOCK_STAT
 
         For more details, see Documentation/lockstat.txt
 
+        This also enables lock events required by "perf lock",
+        subcommand of perf.
+        If you want to use "perf lock", you also need to turn on
+        CONFIG_EVENT_TRACING.
+
+        CONFIG_LOCK_STAT defines "contended" and "acquired" lock events.
+        (CONFIG_LOCKDEP defines "acquire" and "release" events.)
+
 config DEBUG_LOCKDEP
        bool "Lock dependency engine debugging"
        depends on DEBUG_KERNEL && LOCKDEP
index c69cbe9..bd0f337 100644 (file)
@@ -34,7 +34,7 @@
 #include <linux/perf_event.h>
 #include <linux/hw_breakpoint.h>
 
-struct perf_event **sample_hbp;
+struct perf_event * __percpu *sample_hbp;
 
 static char ksym_name[KSYM_NAME_LEN] = "pid_max";
 module_param_string(ksym, ksym_name, KSYM_NAME_LEN, S_IRUGO);
@@ -61,8 +61,8 @@ static int __init hw_break_module_init(void)
        attr.bp_type = HW_BREAKPOINT_W | HW_BREAKPOINT_R;
 
        sample_hbp = register_wide_hw_breakpoint(&attr, sample_hbp_handler);
-       if (IS_ERR(sample_hbp)) {
-               ret = PTR_ERR(sample_hbp);
+       if (IS_ERR((void __force *)sample_hbp)) {
+               ret = PTR_ERR((void __force *)sample_hbp);
                goto fail;
        }
 
diff --git a/tools/perf/Documentation/perf-lock.txt b/tools/perf/Documentation/perf-lock.txt
new file mode 100644 (file)
index 0000000..b317102
--- /dev/null
@@ -0,0 +1,29 @@
+perf-lock(1)
+============
+
+NAME
+----
+perf-lock - Analyze lock events
+
+SYNOPSIS
+--------
+[verse]
+'perf lock' {record|report|trace}
+
+DESCRIPTION
+-----------
+You can analyze various lock behaviours
+and statistics with this 'perf lock' command.
+
+  'perf lock record <command>' records lock events
+  between start and end <command>. And this command
+  produces the file "perf.data" which contains tracing
+  results of lock events.
+
+  'perf lock trace' shows raw lock events.
+
+  'perf lock report' reports statistical data.
+
+SEE ALSO
+--------
+linkperf:perf[1]
index fb9ab2a..e12c844 100644 (file)
@@ -460,6 +460,150 @@ process_raw_event(void *data, int cpu,
                process_lock_release_event(data, event, cpu, timestamp, thread);
 }
 
+struct raw_event_queue {
+       u64                     timestamp;
+       int                     cpu;
+       void                    *data;
+       struct thread           *thread;
+       struct list_head        list;
+};
+
+static LIST_HEAD(raw_event_head);
+
+#define FLUSH_PERIOD   (5 * NSEC_PER_SEC)
+
+static u64 flush_limit = ULLONG_MAX;
+static u64 last_flush = 0;
+struct raw_event_queue *last_inserted;
+
+static void flush_raw_event_queue(u64 limit)
+{
+       struct raw_event_queue *tmp, *iter;
+
+       list_for_each_entry_safe(iter, tmp, &raw_event_head, list) {
+               if (iter->timestamp > limit)
+                       return;
+
+               if (iter == last_inserted)
+                       last_inserted = NULL;
+
+               process_raw_event(iter->data, iter->cpu, iter->timestamp,
+                                 iter->thread);
+
+               last_flush = iter->timestamp;
+               list_del(&iter->list);
+               free(iter->data);
+               free(iter);
+       }
+}
+
+static void __queue_raw_event_end(struct raw_event_queue *new)
+{
+       struct raw_event_queue *iter;
+
+       list_for_each_entry_reverse(iter, &raw_event_head, list) {
+               if (iter->timestamp < new->timestamp) {
+                       list_add(&new->list, &iter->list);
+                       return;
+               }
+       }
+
+       list_add(&new->list, &raw_event_head);
+}
+
+static void __queue_raw_event_before(struct raw_event_queue *new,
+                                    struct raw_event_queue *iter)
+{
+       list_for_each_entry_continue_reverse(iter, &raw_event_head, list) {
+               if (iter->timestamp < new->timestamp) {
+                       list_add(&new->list, &iter->list);
+                       return;
+               }
+       }
+
+       list_add(&new->list, &raw_event_head);
+}
+
+static void __queue_raw_event_after(struct raw_event_queue *new,
+                                    struct raw_event_queue *iter)
+{
+       list_for_each_entry_continue(iter, &raw_event_head, list) {
+               if (iter->timestamp > new->timestamp) {
+                       list_add_tail(&new->list, &iter->list);
+                       return;
+               }
+       }
+       list_add_tail(&new->list, &raw_event_head);
+}
+
+/* The queue is ordered by time */
+static void __queue_raw_event(struct raw_event_queue *new)
+{
+       if (!last_inserted) {
+               __queue_raw_event_end(new);
+               return;
+       }
+
+       /*
+        * Most of the time the current event has a timestamp
+        * very close to the last event inserted, unless we just switched
+        * to another event buffer. Having a sorting based on a list and
+        * on the last inserted event that is close to the current one is
+        * probably more efficient than an rbtree based sorting.
+        */
+       if (last_inserted->timestamp >= new->timestamp)
+               __queue_raw_event_before(new, last_inserted);
+       else
+               __queue_raw_event_after(new, last_inserted);
+}
+
+static void queue_raw_event(void *data, int raw_size, int cpu,
+                           u64 timestamp, struct thread *thread)
+{
+       struct raw_event_queue *new;
+
+       if (flush_limit == ULLONG_MAX)
+               flush_limit = timestamp + FLUSH_PERIOD;
+
+       if (timestamp < last_flush) {
+               printf("Warning: Timestamp below last timeslice flush\n");
+               return;
+       }
+
+       new = malloc(sizeof(*new));
+       if (!new)
+               die("Not enough memory\n");
+
+       new->timestamp = timestamp;
+       new->cpu = cpu;
+       new->thread = thread;
+
+       new->data = malloc(raw_size);
+       if (!new->data)
+               die("Not enough memory\n");
+
+       memcpy(new->data, data, raw_size);
+
+       __queue_raw_event(new);
+       last_inserted = new;
+
+       /*
+        * We want to have a slice of events covering 2 * FLUSH_PERIOD
+        * If FLUSH_PERIOD is big enough, it ensures every events that occured
+        * in the first half of the timeslice have all been buffered and there
+        * are none remaining (we need that because of the weakly ordered
+        * event recording we have). Then once we reach the 2 * FLUSH_PERIOD
+        * timeslice, we flush the first half to be gentle with the memory
+        * (the second half can still get new events in the middle, so wait
+        * another period to flush it)
+        */
+       if (new->timestamp > flush_limit &&
+               new->timestamp - flush_limit > FLUSH_PERIOD) {
+               flush_limit += FLUSH_PERIOD;
+               flush_raw_event_queue(flush_limit);
+       }
+}
+
 static int process_sample_event(event_t *event, struct perf_session *session)
 {
        struct thread *thread;
@@ -480,7 +624,7 @@ static int process_sample_event(event_t *event, struct perf_session *session)
        if (profile_cpu != -1 && profile_cpu != (int) data.cpu)
                return 0;
 
-       process_raw_event(data.raw_data, data.cpu, data.time, thread);
+       queue_raw_event(data.raw_data, data.raw_size, data.cpu, data.time, thread);
 
        return 0;
 }
@@ -576,6 +720,7 @@ static void __cmd_report(void)
        setup_pager();
        select_key();
        read_events();
+       flush_raw_event_queue(ULLONG_MAX);
        sort_result();
        print_result();
 }
@@ -608,7 +753,6 @@ static const char *record_args[] = {
        "record",
        "-a",
        "-R",
-       "-M",
        "-f",
        "-m", "1024",
        "-c", "1",
index 5db687f..407041d 100644 (file)
@@ -573,7 +573,8 @@ int cmd_trace(int argc, const char **argv, const char *prefix __used)
 
        if (symbol__init() < 0)
                return -1;
-       setup_pager();
+       if (!script_name)
+               setup_pager();
 
        session = perf_session__new(input_name, O_RDONLY, 0);
        if (session == NULL)
@@ -608,7 +609,6 @@ int cmd_trace(int argc, const char **argv, const char *prefix __used)
                        return -1;
                }
 
-               perf_header__read(&session->header, input);
                err = scripting_ops->generate_script("perf-trace");
                goto out;
        }
index 9afcff2..db6ee94 100644 (file)
@@ -18,3 +18,4 @@ perf-top                      mainporcelain common
 perf-trace                     mainporcelain common
 perf-probe                     mainporcelain common
 perf-kmem                      mainporcelain common
+perf-lock                      mainporcelain common
index 45fbe2f..910468e 100644 (file)
@@ -9,8 +9,9 @@ fi
 
 DEBUGDIR=~/.debug/
 BUILDIDS=$(mktemp /tmp/perf-archive-buildids.XXXXXX)
+NOBUILDID=0000000000000000000000000000000000000000
 
-perf buildid-list -i $PERF_DATA --with-hits > $BUILDIDS
+perf buildid-list -i $PERF_DATA --with-hits | grep -v "^$NOBUILDID " > $BUILDIDS
 if [ ! -s $BUILDIDS ] ; then
        echo "perf archive: no build-ids found"
        rm -f $BUILDIDS
index 75f941b..6fb379b 100644 (file)
@@ -65,9 +65,7 @@
  * Use the __kuser_memory_barrier helper in the CPU helper page. See
  * arch/arm/kernel/entry-armv.S in the kernel source for details.
  */
-#define rmb()          asm volatile("mov r0, #0xffff0fff; mov lr, pc;" \
-                                    "sub pc, r0, #95" ::: "r0", "lr", "cc", \
-                                    "memory")
+#define rmb()          ((void(*)(void))0xffff0fa0)()
 #define cpu_relax()    asm volatile("":::"memory")
 #endif
 
index c971e81..53181db 100644 (file)
@@ -508,8 +508,8 @@ void show_perf_probe_events(void)
        struct str_node *ent;
 
        setup_pager();
-
        memset(&pp, 0, sizeof(pp));
+
        fd = open_kprobe_events(O_RDONLY, 0);
        rawlist = get_trace_kprobe_event_rawlist(fd);
        close(fd);