Commit 9fdfbc2b authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'perf-fixes-for-linus' of...

Merge branch 'perf-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip

* 'perf-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip:
  perf: Provide generic perf_sample_data initialization
  MAINTAINERS: Add Arnaldo as tools/perf/ co-maintainer
  perf trace: Don't use pager if scripting
  perf trace/scripting: Remove extraneous header read
  perf, ARM: Modify kuser rmb() call to compile for Thumb-2
  x86/stacktrace: Don't dereference bad frame pointers
  perf archive: Don't try to collect files without a build-id
  perf_events, x86: Fixup fixed counter constraints
  perf, x86: Restrict the ANY flag
  perf, x86: rename macro in ARCH_PERFMON_EVENTSEL_ENABLE
  perf, x86: add some IBS macros to perf_event.h
  perf, x86: make IBS macros available in perf_event.h
  hw-breakpoints: Remove stub unthrottle callback
  x86/hw-breakpoints: Remove the name field
  perf: Remove pointless breakpoint union
  perf lock: Drop the buffers multiplexing dependency
  perf lock: Fix and add misc documentally things
  percpu: Add __percpu sparse annotations to hw_breakpoint
parents 8cea4eb6 dc1d628a
...@@ -4316,6 +4316,7 @@ PERFORMANCE EVENTS SUBSYSTEM ...@@ -4316,6 +4316,7 @@ PERFORMANCE EVENTS SUBSYSTEM
M: Peter Zijlstra <a.p.zijlstra@chello.nl> M: Peter Zijlstra <a.p.zijlstra@chello.nl>
M: Paul Mackerras <paulus@samba.org> M: Paul Mackerras <paulus@samba.org>
M: Ingo Molnar <mingo@elte.hu> M: Ingo Molnar <mingo@elte.hu>
M: Arnaldo Carvalho de Melo <acme@redhat.com>
S: Supported S: Supported
F: kernel/perf_event.c F: kernel/perf_event.c
F: include/linux/perf_event.h F: include/linux/perf_event.h
......
...@@ -965,7 +965,7 @@ armv6pmu_handle_irq(int irq_num, ...@@ -965,7 +965,7 @@ armv6pmu_handle_irq(int irq_num,
*/ */
armv6_pmcr_write(pmcr); armv6_pmcr_write(pmcr);
data.addr = 0; perf_sample_data_init(&data, 0);
cpuc = &__get_cpu_var(cpu_hw_events); cpuc = &__get_cpu_var(cpu_hw_events);
for (idx = 0; idx <= armpmu->num_events; ++idx) { for (idx = 0; idx <= armpmu->num_events; ++idx) {
...@@ -1945,7 +1945,7 @@ static irqreturn_t armv7pmu_handle_irq(int irq_num, void *dev) ...@@ -1945,7 +1945,7 @@ static irqreturn_t armv7pmu_handle_irq(int irq_num, void *dev)
*/ */
regs = get_irq_regs(); regs = get_irq_regs();
data.addr = 0; perf_sample_data_init(&data, 0);
cpuc = &__get_cpu_var(cpu_hw_events); cpuc = &__get_cpu_var(cpu_hw_events);
for (idx = 0; idx <= armpmu->num_events; ++idx) { for (idx = 0; idx <= armpmu->num_events; ++idx) {
......
...@@ -1164,10 +1164,10 @@ static void record_and_restart(struct perf_event *event, unsigned long val, ...@@ -1164,10 +1164,10 @@ static void record_and_restart(struct perf_event *event, unsigned long val,
* Finally record data if requested. * Finally record data if requested.
*/ */
if (record) { if (record) {
struct perf_sample_data data = { struct perf_sample_data data;
.addr = ~0ULL,
.period = event->hw.last_period, perf_sample_data_init(&data, ~0ULL);
}; data.period = event->hw.last_period;
if (event->attr.sample_type & PERF_SAMPLE_ADDR) if (event->attr.sample_type & PERF_SAMPLE_ADDR)
perf_get_data_addr(regs, &data.addr); perf_get_data_addr(regs, &data.addr);
......
...@@ -1189,7 +1189,7 @@ static int __kprobes perf_event_nmi_handler(struct notifier_block *self, ...@@ -1189,7 +1189,7 @@ static int __kprobes perf_event_nmi_handler(struct notifier_block *self,
regs = args->regs; regs = args->regs;
data.addr = 0; perf_sample_data_init(&data, 0);
cpuc = &__get_cpu_var(cpu_hw_events); cpuc = &__get_cpu_var(cpu_hw_events);
......
...@@ -10,7 +10,6 @@ ...@@ -10,7 +10,6 @@
* (display/resolving) * (display/resolving)
*/ */
struct arch_hw_breakpoint { struct arch_hw_breakpoint {
char *name; /* Contains name of the symbol to set bkpt */
unsigned long address; unsigned long address;
u8 len; u8 len;
u8 type; u8 type;
......
...@@ -18,7 +18,7 @@ ...@@ -18,7 +18,7 @@
#define MSR_ARCH_PERFMON_EVENTSEL0 0x186 #define MSR_ARCH_PERFMON_EVENTSEL0 0x186
#define MSR_ARCH_PERFMON_EVENTSEL1 0x187 #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_ANY (1 << 21)
#define ARCH_PERFMON_EVENTSEL_INT (1 << 20) #define ARCH_PERFMON_EVENTSEL_INT (1 << 20)
#define ARCH_PERFMON_EVENTSEL_OS (1 << 17) #define ARCH_PERFMON_EVENTSEL_OS (1 << 17)
...@@ -50,7 +50,7 @@ ...@@ -50,7 +50,7 @@
INTEL_ARCH_INV_MASK| \ INTEL_ARCH_INV_MASK| \
INTEL_ARCH_EDGE_MASK|\ INTEL_ARCH_EDGE_MASK|\
INTEL_ARCH_UNIT_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_SEL 0x3c
#define ARCH_PERFMON_UNHALTED_CORE_CYCLES_UMASK (0x00 << 8) #define ARCH_PERFMON_UNHALTED_CORE_CYCLES_UMASK (0x00 << 8)
...@@ -117,6 +117,18 @@ union cpuid10_edx { ...@@ -117,6 +117,18 @@ union cpuid10_edx {
*/ */
#define X86_PMC_IDX_FIXED_BTS (X86_PMC_IDX_FIXED + 16) #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 #ifdef CONFIG_PERF_EVENTS
extern void init_hw_perf_events(void); extern void init_hw_perf_events(void);
......
...@@ -73,10 +73,10 @@ struct debug_store { ...@@ -73,10 +73,10 @@ struct debug_store {
struct event_constraint { struct event_constraint {
union { union {
unsigned long idxmsk[BITS_TO_LONGS(X86_PMC_IDX_MAX)]; unsigned long idxmsk[BITS_TO_LONGS(X86_PMC_IDX_MAX)];
u64 idxmsk64[1]; u64 idxmsk64;
}; };
int code; u64 code;
int cmask; u64 cmask;
int weight; int weight;
}; };
...@@ -103,7 +103,7 @@ struct cpu_hw_events { ...@@ -103,7 +103,7 @@ struct cpu_hw_events {
}; };
#define __EVENT_CONSTRAINT(c, n, m, w) {\ #define __EVENT_CONSTRAINT(c, n, m, w) {\
{ .idxmsk64[0] = (n) }, \ { .idxmsk64 = (n) }, \
.code = (c), \ .code = (c), \
.cmask = (m), \ .cmask = (m), \
.weight = (w), \ .weight = (w), \
...@@ -116,7 +116,7 @@ struct cpu_hw_events { ...@@ -116,7 +116,7 @@ struct cpu_hw_events {
EVENT_CONSTRAINT(c, n, INTEL_ARCH_EVTSEL_MASK) EVENT_CONSTRAINT(c, n, INTEL_ARCH_EVTSEL_MASK)
#define FIXED_EVENT_CONSTRAINT(c, n) \ #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 \ #define EVENT_CONSTRAINT_END \
EVENT_CONSTRAINT(0, 0, 0) EVENT_CONSTRAINT(0, 0, 0)
...@@ -503,6 +503,9 @@ static int __hw_perf_event_init(struct perf_event *event) ...@@ -503,6 +503,9 @@ static int __hw_perf_event_init(struct perf_event *event)
*/ */
if (attr->type == PERF_TYPE_RAW) { if (attr->type == PERF_TYPE_RAW) {
hwc->config |= x86_pmu.raw_event(attr->config); 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; return 0;
} }
...@@ -553,9 +556,9 @@ static void x86_pmu_disable_all(void) ...@@ -553,9 +556,9 @@ static void x86_pmu_disable_all(void)
if (!test_bit(idx, cpuc->active_mask)) if (!test_bit(idx, cpuc->active_mask))
continue; continue;
rdmsrl(x86_pmu.eventsel + idx, val); rdmsrl(x86_pmu.eventsel + idx, val);
if (!(val & ARCH_PERFMON_EVENTSEL0_ENABLE)) if (!(val & ARCH_PERFMON_EVENTSEL_ENABLE))
continue; continue;
val &= ~ARCH_PERFMON_EVENTSEL0_ENABLE; val &= ~ARCH_PERFMON_EVENTSEL_ENABLE;
wrmsrl(x86_pmu.eventsel + idx, val); wrmsrl(x86_pmu.eventsel + idx, val);
} }
} }
...@@ -590,7 +593,7 @@ static void x86_pmu_enable_all(void) ...@@ -590,7 +593,7 @@ static void x86_pmu_enable_all(void)
continue; continue;
val = event->hw.config; val = event->hw.config;
val |= ARCH_PERFMON_EVENTSEL0_ENABLE; val |= ARCH_PERFMON_EVENTSEL_ENABLE;
wrmsrl(x86_pmu.eventsel + idx, val); wrmsrl(x86_pmu.eventsel + idx, val);
} }
} }
...@@ -612,8 +615,8 @@ static int x86_schedule_events(struct cpu_hw_events *cpuc, int n, int *assign) ...@@ -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); bitmap_zero(used_mask, X86_PMC_IDX_MAX);
for (i = 0; i < n; i++) { for (i = 0; i < n; i++) {
constraints[i] = c = x86_pmu.get_event_constraints(cpuc, cpuc->event_list[i]);
x86_pmu.get_event_constraints(cpuc, cpuc->event_list[i]); constraints[i] = c;
} }
/* /*
...@@ -853,7 +856,7 @@ void hw_perf_enable(void) ...@@ -853,7 +856,7 @@ void hw_perf_enable(void)
static inline void __x86_pmu_enable_event(struct hw_perf_event *hwc, int idx) static inline void __x86_pmu_enable_event(struct hw_perf_event *hwc, int idx)
{ {
(void)checking_wrmsrl(hwc->config_base + 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) static inline void x86_pmu_disable_event(struct hw_perf_event *hwc, int idx)
...@@ -1094,8 +1097,7 @@ static int x86_pmu_handle_irq(struct pt_regs *regs) ...@@ -1094,8 +1097,7 @@ static int x86_pmu_handle_irq(struct pt_regs *regs)
int idx, handled = 0; int idx, handled = 0;
u64 val; u64 val;
data.addr = 0; perf_sample_data_init(&data, 0);
data.raw = NULL;
cpuc = &__get_cpu_var(cpu_hw_events); cpuc = &__get_cpu_var(cpu_hw_events);
...@@ -1347,6 +1349,7 @@ static void __init pmu_check_apic(void) ...@@ -1347,6 +1349,7 @@ static void __init pmu_check_apic(void)
void __init init_hw_perf_events(void) void __init init_hw_perf_events(void)
{ {
struct event_constraint *c;
int err; int err;
pr_info("Performance Events: "); pr_info("Performance Events: ");
...@@ -1395,6 +1398,16 @@ void __init init_hw_perf_events(void) ...@@ -1395,6 +1398,16 @@ void __init init_hw_perf_events(void)
__EVENT_CONSTRAINT(0, (1ULL << x86_pmu.num_events) - 1, __EVENT_CONSTRAINT(0, (1ULL << x86_pmu.num_events) - 1,
0, x86_pmu.num_events); 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("... version: %d\n", x86_pmu.version);
pr_info("... bit width: %d\n", x86_pmu.event_bits); pr_info("... bit width: %d\n", x86_pmu.event_bits);
pr_info("... generic registers: %d\n", x86_pmu.num_events); pr_info("... generic registers: %d\n", x86_pmu.num_events);
......
#ifdef CONFIG_CPU_SUP_INTEL #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[] = static const u64 intel_perfmon_event_map[] =
{ {
...@@ -27,8 +27,14 @@ static struct event_constraint intel_core_event_constraints[] = ...@@ -27,8 +27,14 @@ static struct event_constraint intel_core_event_constraints[] =
static struct event_constraint intel_core2_event_constraints[] = static struct event_constraint intel_core2_event_constraints[] =
{ {
FIXED_EVENT_CONSTRAINT(0xc0, (0x3|(1ULL<<32))), /* INSTRUCTIONS_RETIRED */ FIXED_EVENT_CONSTRAINT(0x00c0, 0), /* INST_RETIRED.ANY */
FIXED_EVENT_CONSTRAINT(0x3c, (0x3|(1ULL<<33))), /* UNHALTED_CORE_CYCLES */ 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(0x10, 0x1), /* FP_COMP_OPS_EXE */
INTEL_EVENT_CONSTRAINT(0x11, 0x2), /* FP_ASSIST */ INTEL_EVENT_CONSTRAINT(0x11, 0x2), /* FP_ASSIST */
INTEL_EVENT_CONSTRAINT(0x12, 0x2), /* MUL */ INTEL_EVENT_CONSTRAINT(0x12, 0x2), /* MUL */
...@@ -37,14 +43,16 @@ static struct event_constraint intel_core2_event_constraints[] = ...@@ -37,14 +43,16 @@ static struct event_constraint intel_core2_event_constraints[] =
INTEL_EVENT_CONSTRAINT(0x18, 0x1), /* IDLE_DURING_DIV */ INTEL_EVENT_CONSTRAINT(0x18, 0x1), /* IDLE_DURING_DIV */
INTEL_EVENT_CONSTRAINT(0x19, 0x2), /* DELAYED_BYPASS */ INTEL_EVENT_CONSTRAINT(0x19, 0x2), /* DELAYED_BYPASS */
INTEL_EVENT_CONSTRAINT(0xa1, 0x1), /* RS_UOPS_DISPATCH_CYCLES */ 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 */ INTEL_EVENT_CONSTRAINT(0xcb, 0x1), /* MEM_LOAD_RETIRED */
EVENT_CONSTRAINT_END EVENT_CONSTRAINT_END
}; };
static struct event_constraint intel_nehalem_event_constraints[] = static struct event_constraint intel_nehalem_event_constraints[] =
{ {
FIXED_EVENT_CONSTRAINT(0xc0, (0xf|(1ULL<<32))), /* INSTRUCTIONS_RETIRED */ FIXED_EVENT_CONSTRAINT(0x00c0, 0), /* INST_RETIRED.ANY */
FIXED_EVENT_CONSTRAINT(0x3c, (0xf|(1ULL<<33))), /* UNHALTED_CORE_CYCLES */ 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(0x40, 0x3), /* L1D_CACHE_LD */
INTEL_EVENT_CONSTRAINT(0x41, 0x3), /* L1D_CACHE_ST */ INTEL_EVENT_CONSTRAINT(0x41, 0x3), /* L1D_CACHE_ST */
INTEL_EVENT_CONSTRAINT(0x42, 0x3), /* L1D_CACHE_LOCK */ INTEL_EVENT_CONSTRAINT(0x42, 0x3), /* L1D_CACHE_LOCK */
...@@ -58,8 +66,9 @@ static struct event_constraint intel_nehalem_event_constraints[] = ...@@ -58,8 +66,9 @@ static struct event_constraint intel_nehalem_event_constraints[] =
static struct event_constraint intel_westmere_event_constraints[] = static struct event_constraint intel_westmere_event_constraints[] =
{ {
FIXED_EVENT_CONSTRAINT(0xc0, (0xf|(1ULL<<32))), /* INSTRUCTIONS_RETIRED */ FIXED_EVENT_CONSTRAINT(0x00c0, 0), /* INST_RETIRED.ANY */
FIXED_EVENT_CONSTRAINT(0x3c, (0xf|(1ULL<<33))), /* UNHALTED_CORE_CYCLES */ 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(0x51, 0x3), /* L1D */
INTEL_EVENT_CONSTRAINT(0x60, 0x1), /* OFFCORE_REQUESTS_OUTSTANDING */ INTEL_EVENT_CONSTRAINT(0x60, 0x1), /* OFFCORE_REQUESTS_OUTSTANDING */
INTEL_EVENT_CONSTRAINT(0x63, 0x3), /* CACHE_LOCK_CYCLES */ INTEL_EVENT_CONSTRAINT(0x63, 0x3), /* CACHE_LOCK_CYCLES */
...@@ -68,8 +77,9 @@ static struct event_constraint intel_westmere_event_constraints[] = ...@@ -68,8 +77,9 @@ static struct event_constraint intel_westmere_event_constraints[] =
static struct event_constraint intel_gen_event_constraints[] = static struct event_constraint intel_gen_event_constraints[] =
{ {
FIXED_EVENT_CONSTRAINT(0xc0, (0x3|(1ULL<<32))), /* INSTRUCTIONS_RETIRED */ FIXED_EVENT_CONSTRAINT(0x00c0, 0), /* INST_RETIRED.ANY */
FIXED_EVENT_CONSTRAINT(0x3c, (0x3|(1ULL<<33))), /* UNHALTED_CORE_CYCLES */ FIXED_EVENT_CONSTRAINT(0x003c, 1), /* CPU_CLK_UNHALTED.CORE */
/* FIXED_EVENT_CONSTRAINT(0x013c, 2), CPU_CLK_UNHALTED.REF */
EVENT_CONSTRAINT_END EVENT_CONSTRAINT_END
}; };
...@@ -580,10 +590,9 @@ static void intel_pmu_drain_bts_buffer(void) ...@@ -580,10 +590,9 @@ static void intel_pmu_drain_bts_buffer(void)
ds->bts_index = ds->bts_buffer_base; ds->bts_index = ds->bts_buffer_base;
perf_sample_data_init(&data, 0);
data.period = event->hw.last_period; data.period = event->hw.last_period;
data.addr = 0;
data.raw = NULL;
regs.ip = 0; regs.ip = 0;
/* /*
...@@ -732,8 +741,7 @@ static int intel_pmu_handle_irq(struct pt_regs *regs) ...@@ -732,8 +741,7 @@ static int intel_pmu_handle_irq(struct pt_regs *regs)
int bit, loops; int bit, loops;
u64 ack, status; u64 ack, status;
data.addr = 0; perf_sample_data_init(&data, 0);
data.raw = NULL;
cpuc = &__get_cpu_var(cpu_hw_events); cpuc = &__get_cpu_var(cpu_hw_events);
...@@ -935,7 +943,7 @@ static __init int intel_pmu_init(void) ...@@ -935,7 +943,7 @@ static __init int intel_pmu_init(void)
x86_pmu.event_constraints = intel_nehalem_event_constraints; x86_pmu.event_constraints = intel_nehalem_event_constraints;
pr_cont("Nehalem/Corei7 events, "); pr_cont("Nehalem/Corei7 events, ");
break; break;
case 28: case 28: /* Atom */
memcpy(hw_cache_event_ids, atom_hw_cache_event_ids, memcpy(hw_cache_event_ids, atom_hw_cache_event_ids,
sizeof(hw_cache_event_ids)); sizeof(hw_cache_event_ids));
...@@ -951,6 +959,7 @@ static __init int intel_pmu_init(void) ...@@ -951,6 +959,7 @@ static __init int intel_pmu_init(void)
x86_pmu.event_constraints = intel_westmere_event_constraints; x86_pmu.event_constraints = intel_westmere_event_constraints;
pr_cont("Westmere events, "); pr_cont("Westmere events, ");
break; break;
default: default:
/* /*
* default constraints for v2 and up * default constraints for v2 and up
......
...@@ -62,7 +62,7 @@ static void p6_pmu_disable_all(void) ...@@ -62,7 +62,7 @@ static void p6_pmu_disable_all(void)
/* p6 only has one enable register */ /* p6 only has one enable register */
rdmsrl(MSR_P6_EVNTSEL0, val); rdmsrl(MSR_P6_EVNTSEL0, val);
val &= ~ARCH_PERFMON_EVENTSEL0_ENABLE; val &= ~ARCH_PERFMON_EVENTSEL_ENABLE;
wrmsrl(MSR_P6_EVNTSEL0, val); wrmsrl(MSR_P6_EVNTSEL0, val);
} }
...@@ -72,7 +72,7 @@ static void p6_pmu_enable_all(void) ...@@ -72,7 +72,7 @@ static void p6_pmu_enable_all(void)
/* p6 only has one enable register */ /* p6 only has one enable register */
rdmsrl(MSR_P6_EVNTSEL0, val); rdmsrl(MSR_P6_EVNTSEL0, val);
val |= ARCH_PERFMON_EVENTSEL0_ENABLE; val |= ARCH_PERFMON_EVENTSEL_ENABLE;
wrmsrl(MSR_P6_EVNTSEL0, val); wrmsrl(MSR_P6_EVNTSEL0, val);
} }
...@@ -83,7 +83,7 @@ p6_pmu_disable_event(struct hw_perf_event *hwc, int idx) ...@@ -83,7 +83,7 @@ p6_pmu_disable_event(struct hw_perf_event *hwc, int idx)
u64 val = P6_NOP_EVENT; u64 val = P6_NOP_EVENT;
if (cpuc->enabled) if (cpuc->enabled)
val |= ARCH_PERFMON_EVENTSEL0_ENABLE; val |= ARCH_PERFMON_EVENTSEL_ENABLE;
(void)checking_wrmsrl(hwc->config_base + idx, val); (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) ...@@ -95,7 +95,7 @@ static void p6_pmu_enable_event(struct hw_perf_event *hwc, int idx)
val = hwc->config; val = hwc->config;
if (cpuc->enabled) if (cpuc->enabled)
val |= ARCH_PERFMON_EVENTSEL0_ENABLE; val |= ARCH_PERFMON_EVENTSEL_ENABLE;
(void)checking_wrmsrl(hwc->config_base + idx, val); (void)checking_wrmsrl(hwc->config_base + idx, val);
} }
......
...@@ -680,7 +680,7 @@ static int setup_intel_arch_watchdog(unsigned nmi_hz) ...@@ -680,7 +680,7 @@ static int setup_intel_arch_watchdog(unsigned nmi_hz)
cpu_nmi_set_wd_enabled(); cpu_nmi_set_wd_enabled();
apic_write(APIC_LVTPC, APIC_DM_NMI); apic_write(APIC_LVTPC, APIC_DM_NMI);
evntsel |= ARCH_PERFMON_EVENTSEL0_ENABLE; evntsel |= ARCH_PERFMON_EVENTSEL_ENABLE;
wrmsr(evntsel_msr, evntsel, 0); wrmsr(evntsel_msr, evntsel, 0);
intel_arch_wd_ops.checkbit = 1ULL << (eax.split.bit_width - 1); intel_arch_wd_ops.checkbit = 1ULL << (eax.split.bit_width - 1);
return 1; return 1;
......
...@@ -120,9 +120,15 @@ fixup_bp_irq_link(unsigned long bp, unsigned long *stack, ...@@ -120,9 +120,15 @@ fixup_bp_irq_link(unsigned long bp, unsigned long *stack,
{ {
#ifdef CONFIG_FRAME_POINTER #ifdef CONFIG_FRAME_POINTER
struct stack_frame *frame = (struct stack_frame *)bp; struct stack_frame *frame = (struct stack_frame *)bp;
unsigned long next;
if (!in_irq_stack(stack, irq_stack, irq_stack_end)) if (!in_irq_stack(stack, irq_stack, irq_stack_end)) {
return (unsigned long)frame->next_frame; 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 #endif
return bp; return bp;
} }
......
...@@ -343,13 +343,6 @@ int arch_validate_hwbkpt_settings(struct perf_event *bp, ...@@ -343,13 +343,6 @@ int arch_validate_hwbkpt_settings(struct perf_event *bp,
return ret; return ret;
} }
/*
* 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 * Check that the low-order bits of the address are appropriate
* for the alignment implied by len. * for the alignment implied by len.
...@@ -535,8 +528,3 @@ void hw_breakpoint_pmu_read(struct perf_event *bp) ...@@ -535,8 +528,3 @@ void hw_breakpoint_pmu_read(struct perf_event *bp)
{ {
/* TODO */ /* TODO */
} }
void hw_breakpoint_pmu_unthrottle(struct perf_event *bp)
{
/* TODO */
}
...@@ -46,17 +46,6 @@ ...@@ -46,17 +46,6 @@
static unsigned long reset_value[NUM_VIRT_COUNTERS]; 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_FETCH_SIZE 6
#define IBS_OP_SIZE 12 #define IBS_OP_SIZE 12
...@@ -182,7 +171,7 @@ static void op_amd_setup_ctrs(struct op_x86_model_spec const *model, ...@@ -182,7 +171,7 @@ static void op_amd_setup_ctrs(struct op_x86_model_spec const *model,
continue; continue;
} }
rdmsrl(msrs->controls[i].addr, val); rdmsrl(msrs->controls[i].addr, val);
if (val & ARCH_PERFMON_EVENTSEL0_ENABLE) if (val & ARCH_PERFMON_EVENTSEL_ENABLE)
op_x86_warn_in_use(i); op_x86_warn_in_use(i);
val &= model->reserved; val &= model->reserved;
wrmsrl(msrs->controls[i].addr, val); wrmsrl(msrs->controls[i].addr, val);
...@@ -290,7 +279,7 @@ op_amd_handle_ibs(struct pt_regs * const regs, ...@@ -290,7 +279,7 @@ op_amd_handle_ibs(struct pt_regs * const regs,
oprofile_write_commit(&entry); oprofile_write_commit(&entry);
/* reenable the IRQ */ /* reenable the IRQ */
ctl &= ~(IBS_FETCH_VAL | IBS_FETCH_CNT_MASK); ctl &= ~(IBS_FETCH_VAL | IBS_FETCH_CNT);
ctl |= IBS_FETCH_ENABLE; ctl |= IBS_FETCH_ENABLE;
wrmsrl(MSR_AMD64_IBSFETCHCTL, ctl); wrmsrl(MSR_AMD64_IBSFETCHCTL, ctl);
} }
...@@ -330,7 +319,7 @@ static inline void op_amd_start_ibs(void) ...@@ -330,7 +319,7 @@ static inline void op_amd_start_ibs(void)
return; return;
if (ibs_config.fetch_enabled) { 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_config.rand_en ? IBS_FETCH_RAND_EN : 0;
val |= IBS_FETCH_ENABLE; val |= IBS_FETCH_ENABLE;
wrmsrl(MSR_AMD64_IBSFETCHCTL, val); wrmsrl(MSR_AMD64_IBSFETCHCTL, val);
...@@ -352,7 +341,7 @@ static inline void op_amd_start_ibs(void) ...@@ -352,7 +341,7 @@ static inline void op_amd_start_ibs(void)
* avoid underflows. * avoid underflows.
*/ */
ibs_op_ctl = min(ibs_op_ctl + IBS_RANDOM_MAXCNT_OFFSET, 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) if (ibs_caps & IBS_CAPS_OPCNT && ibs_config.dispatched_ops)
ibs_op_ctl |= IBS_OP_CNT_CTL; ibs_op_ctl |= IBS_OP_CNT_CTL;
...@@ -409,7 +398,7 @@ static void op_amd_start(struct op_msrs const * const msrs) ...@@ -409,7 +398,7 @@ static void op_amd_start(struct op_msrs const * const msrs)
if (!reset_value[op_x86_phys_to_virt(i)]) if (!reset_value[op_x86_phys_to_virt(i)])
continue; continue;
rdmsrl(msrs->controls[i].addr, val); rdmsrl(msrs->controls[i].addr, val);
val |= ARCH_PERFMON_EVENTSEL0_ENABLE; val |= ARCH_PERFMON_EVENTSEL_ENABLE;
wrmsrl(msrs->controls[i].addr, val); wrmsrl(msrs->controls[i].addr, val);
} }
...@@ -429,7 +418,7 @@ static void op_amd_stop(struct op_msrs const * const msrs) ...@@ -429,7 +418,7 @@ static void op_amd_stop(struct op_msrs const * const msrs)
if (!reset_value[op_x86_phys_to_virt(i)]) if (!reset_value[op_x86_phys_to_virt(i)])
continue; continue;
rdmsrl(msrs->controls[i].addr, val); rdmsrl(msrs->controls[i].addr, val);
val &= ~ARCH_PERFMON_EVENTSEL0_ENABLE; val &= ~ARCH_PERFMON_EVENTSEL_ENABLE;
wrmsrl(msrs->controls[i].addr, val); wrmsrl(msrs->controls[i].addr, val);
} }
......
...@@ -88,7 +88,7 @@ static void ppro_setup_ctrs(struct op_x86_model_spec const *model, ...@@ -88,7 +88,7 @@ static void ppro_setup_ctrs(struct op_x86_model_spec const *model,
continue; continue;
} }
rdmsrl(msrs->controls[i].addr, val); rdmsrl(msrs->controls[i].addr, val);
if (val & ARCH_PERFMON_EVENTSEL0_ENABLE) if (val & ARCH_PERFMON_EVENTSEL_ENABLE)
op_x86_warn_in_use(i); op_x86_warn_in_use(i);
val &= model->reserved; val &= model->reserved;
wrmsrl(msrs->controls[i].addr, val); wrmsrl(msrs->controls[i].addr, val);
...@@ -166,7 +166,7 @@ static void ppro_start(struct op_msrs const * const msrs) ...@@ -166,7 +166,7 @@ static void ppro_start(struct op_msrs const * const msrs)
for (i = 0; i < num_counters; ++i) { for (i = 0; i < num_counters; ++i) {
if (reset_value[i]) { if (reset_value[i]) {
rdmsrl(msrs->controls[i].addr, val); rdmsrl(msrs->controls[i].addr, val);
val |= ARCH_PERFMON_EVENTSEL0_ENABLE; val |= ARCH_PERFMON_EVENTSEL_ENABLE;
wrmsrl(msrs->controls[i].addr, val); wrmsrl(msrs->controls[i].addr, val);
} }
} }
...@@ -184,7 +184,7 @@ static void ppro_stop(struct op_msrs const * const msrs) ...@@ -184,7 +184,7 @@ static void ppro_stop(struct op_msrs const * const msrs)
if (!reset_value[i]) if (!reset_value[i])
continue; continue;
rdmsrl(msrs->controls[i].addr, val); rdmsrl(msrs->controls[i].addr, val);
val &= ~ARCH_PERFMON_EVENTSEL0_ENABLE; val &= ~ARCH_PERFMON_EVENTSEL_ENABLE;
wrmsrl(msrs->controls[i].addr, val); wrmsrl(msrs->controls[i].addr, val);
} }
} }
......
...@@ -66,14 +66,14 @@ register_wide_hw_breakpoint_cpu(struct perf_event_attr *attr, ...@@ -66,14 +66,14 @@ register_wide_hw_breakpoint_cpu(struct perf_event_attr *attr,
perf_overflow_handler_t triggered, perf_overflow_handler_t triggered,
int cpu); int cpu);
extern struct perf_event ** extern struct perf_event * __percpu *
register_wide_hw_breakpoint(struct perf_event_attr *attr, register_wide_hw_breakpoint(struct perf_event_attr *attr,
perf_overflow_handler_t triggered); 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 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_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_reserve_bp_slot(struct perf_event *bp);
extern int dbg_release_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 * ...@@ -100,7 +100,7 @@ static inline struct perf_event *
register_wide_hw_breakpoint_cpu(struct perf_event_attr *attr, register_wide_hw_breakpoint_cpu(struct perf_event_attr *attr,
perf_overflow_handler_t triggered, perf_overflow_handler_t triggered,
int cpu) { return NULL; } int cpu) { return NULL; }
static inline struct perf_event ** static inline struct perf_event * __percpu *
register_wide_hw_breakpoint(struct perf_event_attr *attr, register_wide_hw_breakpoint(struct perf_event_attr *attr,
perf_overflow_handler_t triggered) { return NULL; } perf_overflow_handler_t triggered) { return NULL; }
static inline int static inline int
...@@ -109,7 +109,7 @@ static inline int ...@@ -109,7 +109,7 @@ static inline int
__register_perf_hw_breakpoint(struct perf_event *bp) { return -ENOSYS; } __register_perf_hw_breakpoint(struct perf_event *bp) { return -ENOSYS; }
static inline void unregister_hw_breakpoint(struct perf_event *bp) { } static inline void unregister_hw_breakpoint(struct perf_event *bp) { }
static inline void 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 static inline int
reserve_bp_slot(struct perf_event *bp) {return -ENOSYS; } reserve_bp_slot(struct perf_event *bp) {return -ENOSYS; }
static inline void release_bp_slot(struct perf_event *bp) { } static inline void release_bp_slot(struct perf_event *bp) { }
......
...@@ -487,9 +487,8 @@ struct hw_perf_event { ...@@ -487,9 +487,8 @@ struct hw_perf_event {
struct hrtimer hrtimer; struct hrtimer hrtimer;
}; };
#ifdef CONFIG_HAVE_HW_BREAKPOINT #ifdef CONFIG_HAVE_HW_BREAKPOINT
union { /* breakpoint */ /* breakpoint */
struct arch_hw_breakpoint info; struct arch_hw_breakpoint info;
};
#endif #endif
}; };
atomic64_t prev_count; atomic64_t prev_count;
...@@ -802,6 +801,13 @@ struct perf_sample_data { ...@@ -802,6 +801,13 @@ struct perf_sample_data {
struct perf_raw_record *raw; struct perf_raw_record *raw;
}; };
static inline
void perf_sample_data_init(struct perf_sample_data *data, u64 addr)
{
data->addr = addr;
data->raw = NULL;
}
extern void perf_output_sample(struct perf_output_handle *handle, extern void perf_output_sample(struct perf_output_handle *handle,
struct perf_event_header *header, struct perf_event_header *header,
struct perf_sample_data *data, struct perf_sample_data *data,
...@@ -858,6 +864,21 @@ extern int sysctl_perf_event_paranoid; ...@@ -858,6 +864,21 @@ extern int sysctl_perf_event_paranoid;
extern int sysctl_perf_event_mlock; extern int sysctl_perf_event_mlock;
extern int sysctl_perf_event_sample_rate; 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_event_init(void);
extern void perf_tp_event(int event_id, u64 addr, u64 count, void *record, int entry_size); 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); extern void perf_bp_event(struct perf_event *event, void *data);
......
...@@ -413,17 +413,17 @@ EXPORT_SYMBOL_GPL(unregister_hw_breakpoint); ...@@ -413,17 +413,17 @@ EXPORT_SYMBOL_GPL(unregister_hw_breakpoint);
* *
* @return a set of per_cpu pointers to perf events * @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, register_wide_hw_breakpoint(struct perf_event_attr *attr,
perf_overflow_handler_t triggered) perf_overflow_handler_t triggered)
{ {
struct perf_event **cpu_events, **pevent, *bp; struct perf_event * __percpu *cpu_events, **pevent, *bp;
long err; long err;
int cpu; int cpu;
cpu_events = alloc_percpu(typeof(*cpu_events)); cpu_events = alloc_percpu(typeof(*cpu_events));
if (!cpu_events) if (!cpu_events)
return ERR_PTR(-ENOMEM); return (void __percpu __force *)ERR_PTR(-ENOMEM);
get_online_cpus(); get_online_cpus();
for_each_online_cpu(cpu) { for_each_online_cpu(cpu) {
...@@ -451,7 +451,7 @@ register_wide_hw_breakpoint(struct perf_event_attr *attr, ...@@ -451,7 +451,7 @@ register_wide_hw_breakpoint(struct perf_event_attr *attr,
put_online_cpus(); put_online_cpus();
free_percpu(cpu_events); free_percpu(cpu_events);
return ERR_PTR(err); return (void __percpu __force *)ERR_PTR(err);
} }
EXPORT_SYMBOL_GPL(register_wide_hw_breakpoint); EXPORT_SYMBOL_GPL(register_wide_hw_breakpoint);
...@@ -459,7 +459,7 @@ 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 * unregister_wide_hw_breakpoint - unregister a wide breakpoint in the kernel
* @cpu_events: the per cpu set of events to unregister * @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; int cpu;
struct perf_event **pevent; struct perf_event **pevent;
...@@ -489,5 +489,4 @@ struct pmu perf_ops_bp = { ...@@ -489,5 +489,4 @@ struct pmu perf_ops_bp = {
.enable = arch_install_hw_breakpoint, .enable = arch_install_hw_breakpoint,
.disable = arch_uninstall_hw_breakpoint, .disable = arch_uninstall_hw_breakpoint,
.read = hw_breakpoint_pmu_read, .read = hw_breakpoint_pmu_read,
.unthrottle = hw_breakpoint_pmu_unthrottle
}; };
...@@ -56,21 +56,6 @@ static atomic_t nr_task_events __read_mostly; ...@@ -56,21 +56,6 @@ static atomic_t nr_task_events __read_mostly;
*/ */
int sysctl_perf_event_paranoid __read_mostly = 1; 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 */ int sysctl_perf_event_mlock __read_mostly = 512; /* 'free' kb per user */
/* /*
...@@ -4123,8 +4108,7 @@ void __perf_sw_event(u32 event_id, u64 nr, int nmi, ...@@ -4123,8 +4108,7 @@ void __perf_sw_event(u32 event_id, u64 nr, int nmi,
if (rctx < 0) if (rctx < 0)
return; return;
data.addr = addr; perf_sample_data_init(&data, addr);
data.raw = NULL;
do_perf_sw_event(PERF_TYPE_SOFTWARE, event_id, nr, nmi, &data, regs); do_perf_sw_event(PERF_TYPE_SOFTWARE, event_id, nr, nmi, &data, regs);
...@@ -4172,8 +4156,7 @@ static enum hrtimer_restart perf_swevent_hrtimer(struct hrtimer *hrtimer) ...@@ -4172,8 +4156,7 @@ static enum hrtimer_restart perf_swevent_hrtimer(struct hrtimer *hrtimer)
event = container_of(hrtimer, struct perf_event, hw.hrtimer); event = container_of(hrtimer, struct perf_event, hw.hrtimer);
event->pmu->read(event); event->pmu->read(event);
data.addr = 0; perf_sample_data_init(&data, 0);
data.raw = NULL;
data.period = event->hw.last_period; data.period = event->hw.last_period;
regs = get_irq_regs(); regs = get_irq_regs();
/* /*
...@@ -4337,17 +4320,15 @@ static const struct pmu perf_ops_task_clock = { ...@@ -4337,17 +4320,15 @@ static const struct pmu perf_ops_task_clock = {
void perf_tp_event(int event_id, u64 addr, u64 count, void *record, void perf_tp_event(int event_id, u64 addr, u64 count, void *record,
int entry_size) int entry_size)
{ {
struct pt_regs *regs = get_irq_regs();
struct perf_sample_data data;
struct perf_raw_record raw = { struct perf_raw_record raw = {
.size = entry_size, .size = entry_size,
.data = record, .data = record,
}; };
struct perf_sample_data data = { perf_sample_data_init(&data, addr);
.addr = addr, data.raw = &raw;
.raw = &raw,
};
struct pt_regs *regs = get_irq_regs();
if (!regs) if (!regs)
regs = task_pt_regs(current); regs = task_pt_regs(current);
...@@ -4463,8 +4444,7 @@ void perf_bp_event(struct perf_event *bp, void *data) ...@@ -4463,8 +4444,7 @@ void perf_bp_event(struct perf_event *bp, void *data)
struct perf_sample_data sample; struct perf_sample_data sample;
struct pt_regs *regs = data; struct pt_regs *regs = data;
sample.raw = NULL; perf_sample_data_init(&sample, bp->attr.bp_addr);
sample.addr = bp->attr.bp_addr;
if (!perf_exclude_event(bp, regs)) if (!perf_exclude_event(bp, regs))
perf_swevent_add(bp, 1, 1, &sample, regs); perf_swevent_add(bp, 1, 1, &sample, regs);
......
...@@ -532,6 +532,14 @@ config LOCK_STAT ...@@ -532,6 +532,14 @@ config LOCK_STAT
For more details, see Documentation/lockstat.txt 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 config DEBUG_LOCKDEP
bool "Lock dependency engine debugging" bool "Lock dependency engine debugging"
depends on DEBUG_KERNEL && LOCKDEP depends on DEBUG_KERNEL && LOCKDEP
......
...@@ -34,7 +34,7 @@ ...@@ -34,7 +34,7 @@
#include <linux/perf_event.h> #include <linux/perf_event.h>
#include <linux/hw_breakpoint.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"; static char ksym_name[KSYM_NAME_LEN] = "pid_max";
module_param_string(ksym, ksym_name, KSYM_NAME_LEN, S_IRUGO); module_param_string(ksym, ksym_name, KSYM_NAME_LEN, S_IRUGO);
...@@ -61,8 +61,8 @@ static int __init hw_break_module_init(void) ...@@ -61,8 +61,8 @@ static int __init hw_break_module_init(void)
attr.bp_type = HW_BREAKPOINT_W | HW_BREAKPOINT_R; attr.bp_type = HW_BREAKPOINT_W | HW_BREAKPOINT_R;
sample_hbp = register_wide_hw_breakpoint(&attr, sample_hbp_handler); sample_hbp = register_wide_hw_breakpoint(&attr, sample_hbp_handler);
if (IS_ERR(sample_hbp)) { if (IS_ERR((void __force *)sample_hbp)) {
ret = PTR_ERR(sample_hbp); ret = PTR_ERR((void __force *)sample_hbp);
goto fail; goto fail;
} }
......
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]
...@@ -460,6 +460,150 @@ process_raw_event(void *data, int cpu, ...@@ -460,6 +460,150 @@ process_raw_event(void *data, int cpu,
process_lock_release_event(data, event, cpu, timestamp, thread); 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) static int process_sample_event(event_t *event, struct perf_session *session)
{ {
struct thread *thread; struct thread *thread;
...@@ -480,7 +624,7 @@ static int process_sample_event(event_t *event, struct perf_session *session) ...@@ -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) if (profile_cpu != -1 && profile_cpu != (int) data.cpu)
return 0; 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; return 0;
} }
...@@ -576,6 +720,7 @@ static void __cmd_report(void) ...@@ -576,6 +720,7 @@ static void __cmd_report(void)
setup_pager(); setup_pager();
select_key(); select_key();
read_events(); read_events();
flush_raw_event_queue(ULLONG_MAX);
sort_result(); sort_result();
print_result(); print_result();
} }
...@@ -608,7 +753,6 @@ static const char *record_args[] = { ...@@ -608,7 +753,6 @@ static const char *record_args[] = {
"record", "record",
"-a", "-a",
"-R", "-R",
"-M",
"-f", "-f",
"-m", "1024", "-m", "1024",
"-c", "1", "-c", "1",
......
...@@ -573,6 +573,7 @@ int cmd_trace(int argc, const char **argv, const char *prefix __used) ...@@ -573,6 +573,7 @@ int cmd_trace(int argc, const char **argv, const char *prefix __used)
if (symbol__init() < 0) if (symbol__init() < 0)
return -1; return -1;
if (!script_name)
setup_pager(); setup_pager();
session = perf_session__new(input_name, O_RDONLY, 0); session = perf_session__new(input_name, O_RDONLY, 0);
...@@ -608,7 +609,6 @@ int cmd_trace(int argc, const char **argv, const char *prefix __used) ...@@ -608,7 +609,6 @@ int cmd_trace(int argc, const char **argv, const char *prefix __used)
return -1; return -1;
} }
perf_header__read(&session->header, input);
err = scripting_ops->generate_script("perf-trace"); err = scripting_ops->generate_script("perf-trace");
goto out; goto out;
} }
......
...@@ -18,3 +18,4 @@ perf-top mainporcelain common ...@@ -18,3 +18,4 @@ perf-top mainporcelain common
perf-trace mainporcelain common perf-trace mainporcelain common
perf-probe mainporcelain common perf-probe mainporcelain common
perf-kmem mainporcelain common perf-kmem mainporcelain common
perf-lock mainporcelain common
...@@ -9,8 +9,9 @@ fi ...@@ -9,8 +9,9 @@ fi
DEBUGDIR=~/.debug/ DEBUGDIR=~/.debug/
BUILDIDS=$(mktemp /tmp/perf-archive-buildids.XXXXXX) 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 if [ ! -s $BUILDIDS ] ; then
echo "perf archive: no build-ids found" echo "perf archive: no build-ids found"
rm -f $BUILDIDS rm -f $BUILDIDS
......
...@@ -65,9 +65,7 @@ ...@@ -65,9 +65,7 @@
* Use the __kuser_memory_barrier helper in the CPU helper page. See * Use the __kuser_memory_barrier helper in the CPU helper page. See
* arch/arm/kernel/entry-armv.S in the kernel source for details. * arch/arm/kernel/entry-armv.S in the kernel source for details.
*/ */
#define rmb() asm volatile("mov r0, #0xffff0fff; mov lr, pc;" \ #define rmb() ((void(*)(void))0xffff0fa0)()
"sub pc, r0, #95" ::: "r0", "lr", "cc", \
"memory")
#define cpu_relax() asm volatile("":::"memory") #define cpu_relax() asm volatile("":::"memory")
#endif #endif
......
...@@ -508,8 +508,8 @@ void show_perf_probe_events(void) ...@@ -508,8 +508,8 @@ void show_perf_probe_events(void)
struct str_node *ent; struct str_node *ent;
setup_pager(); setup_pager();
memset(&pp, 0, sizeof(pp)); memset(&pp, 0, sizeof(pp));
fd = open_kprobe_events(O_RDONLY, 0); fd = open_kprobe_events(O_RDONLY, 0);
rawlist = get_trace_kprobe_event_rawlist(fd); rawlist = get_trace_kprobe_event_rawlist(fd);
close(fd); close(fd);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment