Skip to content

Commit

Permalink
Merge branch 'perf-core-for-linus' of git://git.kernel.org/pub/scm/li…
Browse files Browse the repository at this point in the history
…nux/kernel/git/tip/tip

Pull perf updates from Ingo Molnar:
 "Kernel side changes:

   - AMD range breakpoints support:

     Extend breakpoint tools and core to support address range through
     perf event with initial backend support for AMD extended
     breakpoints.

     The syntax is:

         perf record -e mem:addr/len:type

     For example set write breakpoint from 0x1000 to 0x1200 (0x1000 + 512)

         perf record -e mem:0x1000/512:w

   - event throttling/rotating fixes

   - various event group handling fixes, cleanups and general paranoia
     code to be more robust against bugs in the future.

    - kernel stack overhead fixes

  User-visible tooling side changes:

   - Show precise number of samples in at the end of a 'record' session,
     if processing build ids, since we will then traverse the whole
     perf.data file and see all the PERF_RECORD_SAMPLE records,
     otherwise stop showing the previous off-base heuristicly counted
     number of "samples" (Namhyung Kim).

   - Support to read compressed module from build-id cache (Namhyung
     Kim)

   - Enable sampling loads and stores simultaneously in 'perf mem'
     (Stephane Eranian)

   - 'perf diff' output improvements (Namhyung Kim)

   - Fix error reporting for evsel pgfault constructor (Arnaldo Carvalho
     de Melo)

  Tooling side infrastructure changes:

   - Cache eh/debug frame offset for dwarf unwind (Namhyung Kim)

   - Support parsing parameterized events (Cody P Schafer)

   - Add support for IP address formats in libtraceevent (David Ahern)

  Plus other misc fixes"

* 'perf-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: (48 commits)
  perf: Decouple unthrottling and rotating
  perf: Drop module reference on event init failure
  perf: Use POLLIN instead of POLL_IN for perf poll data in flag
  perf: Fix put_event() ctx lock
  perf: Fix move_group() order
  perf: Fix event->ctx locking
  perf: Add a bit of paranoia
  perf symbols: Convert lseek + read to pread
  perf tools: Use perf_data_file__fd() consistently
  perf symbols: Support to read compressed module from build-id cache
  perf evsel: Set attr.task bit for a tracking event
  perf header: Set header version correctly
  perf record: Show precise number of samples
  perf tools: Do not use __perf_session__process_events() directly
  perf callchain: Cache eh/debug frame offset for dwarf unwind
  perf tools: Provide stub for missing pthread_attr_setaffinity_np
  perf evsel: Don't rely on malloc working for sz 0
  tools lib traceevent: Add support for IP address formats
  perf ui/tui: Show fatal error message only if exists
  perf tests: Fix typo in sample-parsing.c
  ...
  • Loading branch information
Linus Torvalds committed Feb 9, 2015
2 parents 8308756 + 2fde4f9 commit a4cbbf5
Show file tree
Hide file tree
Showing 76 changed files with 1,611 additions and 666 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -52,12 +52,18 @@ Description: Per-pmu performance monitoring events specific to the running syste
event=0x2abc
event=0x423,inv,cmask=0x3
domain=0x1,offset=0x8,starting_index=0xffff
domain=0x1,offset=0x8,core=?

Each of the assignments indicates a value to be assigned to a
particular set of bits (as defined by the format file
corresponding to the <term>) in the perf_event structure passed
to the perf_open syscall.

In the case of the last example, a value replacing "?" would
need to be provided by the user selecting the particular event.
This is referred to as "event parameterization". Event
parameters have the format 'param=?'.

What: /sys/bus/event_source/devices/<pmu>/events/<event>.unit
Date: 2014/02/24
Contact: Linux kernel mailing list <linux-kernel@vger.kernel.org>
Expand Down
2 changes: 2 additions & 0 deletions arch/x86/include/asm/cpufeature.h
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,7 @@
#define X86_FEATURE_TOPOEXT ( 6*32+22) /* topology extensions CPUID leafs */
#define X86_FEATURE_PERFCTR_CORE ( 6*32+23) /* core performance counter extensions */
#define X86_FEATURE_PERFCTR_NB ( 6*32+24) /* NB performance counter extensions */
#define X86_FEATURE_BPEXT (6*32+26) /* data breakpoint extension */
#define X86_FEATURE_PERFCTR_L2 ( 6*32+28) /* L2 performance counter extensions */

/*
Expand Down Expand Up @@ -388,6 +389,7 @@ extern const char * const x86_bug_flags[NBUGINTS*32];
#define cpu_has_cx16 boot_cpu_has(X86_FEATURE_CX16)
#define cpu_has_eager_fpu boot_cpu_has(X86_FEATURE_EAGER_FPU)
#define cpu_has_topoext boot_cpu_has(X86_FEATURE_TOPOEXT)
#define cpu_has_bpext boot_cpu_has(X86_FEATURE_BPEXT)

#if __GNUC__ >= 4
extern void warn_pre_alternatives(void);
Expand Down
5 changes: 5 additions & 0 deletions arch/x86/include/asm/debugreg.h
Original file line number Diff line number Diff line change
Expand Up @@ -114,5 +114,10 @@ static inline void debug_stack_usage_inc(void) { }
static inline void debug_stack_usage_dec(void) { }
#endif /* X86_64 */

#ifdef CONFIG_CPU_SUP_AMD
extern void set_dr_addr_mask(unsigned long mask, int dr);
#else
static inline void set_dr_addr_mask(unsigned long mask, int dr) { }
#endif

#endif /* _ASM_X86_DEBUGREG_H */
1 change: 1 addition & 0 deletions arch/x86/include/asm/hw_breakpoint.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
*/
struct arch_hw_breakpoint {
unsigned long address;
unsigned long mask;
u8 len;
u8 type;
};
Expand Down
4 changes: 4 additions & 0 deletions arch/x86/include/uapi/asm/msr-index.h
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,10 @@
/* Fam 16h MSRs */
#define MSR_F16H_L2I_PERF_CTL 0xc0010230
#define MSR_F16H_L2I_PERF_CTR 0xc0010231
#define MSR_F16H_DR1_ADDR_MASK 0xc0011019
#define MSR_F16H_DR2_ADDR_MASK 0xc001101a
#define MSR_F16H_DR3_ADDR_MASK 0xc001101b
#define MSR_F16H_DR0_ADDR_MASK 0xc0011027

/* Fam 15h MSRs */
#define MSR_F15H_PERF_CTL 0xc0010200
Expand Down
19 changes: 19 additions & 0 deletions arch/x86/kernel/cpu/amd.c
Original file line number Diff line number Diff line change
Expand Up @@ -869,3 +869,22 @@ static bool cpu_has_amd_erratum(struct cpuinfo_x86 *cpu, const int *erratum)

return false;
}

void set_dr_addr_mask(unsigned long mask, int dr)
{
if (!cpu_has_bpext)
return;

switch (dr) {
case 0:
wrmsr(MSR_F16H_DR0_ADDR_MASK, mask, 0);
break;
case 1:
case 2:
case 3:
wrmsr(MSR_F16H_DR1_ADDR_MASK - 1 + dr, mask, 0);
break;
default:
break;
}
}
45 changes: 17 additions & 28 deletions arch/x86/kernel/hw_breakpoint.c
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,8 @@ int arch_install_hw_breakpoint(struct perf_event *bp)
*dr7 |= encode_dr7(i, info->len, info->type);

set_debugreg(*dr7, 7);
if (info->mask)
set_dr_addr_mask(info->mask, i);

return 0;
}
Expand Down Expand Up @@ -161,29 +163,8 @@ void arch_uninstall_hw_breakpoint(struct perf_event *bp)
*dr7 &= ~__encode_dr7(i, info->len, info->type);

set_debugreg(*dr7, 7);
}

static int get_hbp_len(u8 hbp_len)
{
unsigned int len_in_bytes = 0;

switch (hbp_len) {
case X86_BREAKPOINT_LEN_1:
len_in_bytes = 1;
break;
case X86_BREAKPOINT_LEN_2:
len_in_bytes = 2;
break;
case X86_BREAKPOINT_LEN_4:
len_in_bytes = 4;
break;
#ifdef CONFIG_X86_64
case X86_BREAKPOINT_LEN_8:
len_in_bytes = 8;
break;
#endif
}
return len_in_bytes;
if (info->mask)
set_dr_addr_mask(0, i);
}

/*
Expand All @@ -196,7 +177,7 @@ int arch_check_bp_in_kernelspace(struct perf_event *bp)
struct arch_hw_breakpoint *info = counter_arch_bp(bp);

va = info->address;
len = get_hbp_len(info->len);
len = bp->attr.bp_len;

return (va >= TASK_SIZE) && ((va + len - 1) >= TASK_SIZE);
}
Expand Down Expand Up @@ -277,6 +258,8 @@ static int arch_build_bp_info(struct perf_event *bp)
}

/* Len */
info->mask = 0;

switch (bp->attr.bp_len) {
case HW_BREAKPOINT_LEN_1:
info->len = X86_BREAKPOINT_LEN_1;
Expand All @@ -293,11 +276,17 @@ static int arch_build_bp_info(struct perf_event *bp)
break;
#endif
default:
return -EINVAL;
if (!is_power_of_2(bp->attr.bp_len))
return -EINVAL;
if (!cpu_has_bpext)
return -EOPNOTSUPP;
info->mask = bp->attr.bp_len - 1;
info->len = X86_BREAKPOINT_LEN_1;
}

return 0;
}

/*
* Validate the arch-specific HW Breakpoint register settings
*/
Expand All @@ -312,11 +301,11 @@ int arch_validate_hwbkpt_settings(struct perf_event *bp)
if (ret)
return ret;

ret = -EINVAL;

switch (info->len) {
case X86_BREAKPOINT_LEN_1:
align = 0;
if (info->mask)
align = info->mask;
break;
case X86_BREAKPOINT_LEN_2:
align = 1;
Expand All @@ -330,7 +319,7 @@ int arch_validate_hwbkpt_settings(struct perf_event *bp)
break;
#endif
default:
return ret;
WARN_ON_ONCE(1);
}

/*
Expand Down
2 changes: 1 addition & 1 deletion include/linux/ftrace_event.h
Original file line number Diff line number Diff line change
Expand Up @@ -595,7 +595,7 @@ extern int ftrace_profile_set_filter(struct perf_event *event, int event_id,
char *filter_str);
extern void ftrace_profile_free_filter(struct perf_event *event);
extern void *perf_trace_buf_prepare(int size, unsigned short type,
struct pt_regs *regs, int *rctxp);
struct pt_regs **regs, int *rctxp);

static inline void
perf_trace_buf_submit(void *raw_data, int size, int rctx, u64 addr,
Expand Down
30 changes: 22 additions & 8 deletions include/linux/perf_event.h
Original file line number Diff line number Diff line change
Expand Up @@ -469,6 +469,7 @@ struct perf_event_context {
*/
struct mutex mutex;

struct list_head active_ctx_list;
struct list_head pinned_groups;
struct list_head flexible_groups;
struct list_head event_list;
Expand Down Expand Up @@ -519,7 +520,6 @@ struct perf_cpu_context {
int exclusive;
struct hrtimer hrtimer;
ktime_t hrtimer_interval;
struct list_head rotation_list;
struct pmu *unique_pmu;
struct perf_cgroup *cgrp;
};
Expand Down Expand Up @@ -659,6 +659,7 @@ static inline int is_software_event(struct perf_event *event)

extern struct static_key perf_swevent_enabled[PERF_COUNT_SW_MAX];

extern void ___perf_sw_event(u32, u64, struct pt_regs *, u64);
extern void __perf_sw_event(u32, u64, struct pt_regs *, u64);

#ifndef perf_arch_fetch_caller_regs
Expand All @@ -683,14 +684,25 @@ static inline void perf_fetch_caller_regs(struct pt_regs *regs)
static __always_inline void
perf_sw_event(u32 event_id, u64 nr, struct pt_regs *regs, u64 addr)
{
struct pt_regs hot_regs;
if (static_key_false(&perf_swevent_enabled[event_id]))
__perf_sw_event(event_id, nr, regs, addr);
}

DECLARE_PER_CPU(struct pt_regs, __perf_regs[4]);

/*
* 'Special' version for the scheduler, it hard assumes no recursion,
* which is guaranteed by us not actually scheduling inside other swevents
* because those disable preemption.
*/
static __always_inline void
perf_sw_event_sched(u32 event_id, u64 nr, u64 addr)
{
if (static_key_false(&perf_swevent_enabled[event_id])) {
if (!regs) {
perf_fetch_caller_regs(&hot_regs);
regs = &hot_regs;
}
__perf_sw_event(event_id, nr, regs, addr);
struct pt_regs *regs = this_cpu_ptr(&__perf_regs[0]);

perf_fetch_caller_regs(regs);
___perf_sw_event(event_id, nr, regs, addr);
}
}

Expand All @@ -706,7 +718,7 @@ static inline void perf_event_task_sched_in(struct task_struct *prev,
static inline void perf_event_task_sched_out(struct task_struct *prev,
struct task_struct *next)
{
perf_sw_event(PERF_COUNT_SW_CONTEXT_SWITCHES, 1, NULL, 0);
perf_sw_event_sched(PERF_COUNT_SW_CONTEXT_SWITCHES, 1, 0);

if (static_key_false(&perf_sched_events.key))
__perf_event_task_sched_out(prev, next);
Expand Down Expand Up @@ -817,6 +829,8 @@ static inline int perf_event_refresh(struct perf_event *event, int refresh)
static inline void
perf_sw_event(u32 event_id, u64 nr, struct pt_regs *regs, u64 addr) { }
static inline void
perf_sw_event_sched(u32 event_id, u64 nr, u64 addr) { }
static inline void
perf_bp_event(struct perf_event *event, void *data) { }

static inline int perf_register_guest_info_callbacks
Expand Down
7 changes: 4 additions & 3 deletions include/trace/ftrace.h
Original file line number Diff line number Diff line change
Expand Up @@ -763,7 +763,7 @@ perf_trace_##call(void *__data, proto) \
struct ftrace_event_call *event_call = __data; \
struct ftrace_data_offsets_##call __maybe_unused __data_offsets;\
struct ftrace_raw_##call *entry; \
struct pt_regs __regs; \
struct pt_regs *__regs; \
u64 __addr = 0, __count = 1; \
struct task_struct *__task = NULL; \
struct hlist_head *head; \
Expand All @@ -782,18 +782,19 @@ perf_trace_##call(void *__data, proto) \
sizeof(u64)); \
__entry_size -= sizeof(u32); \
\
perf_fetch_caller_regs(&__regs); \
entry = perf_trace_buf_prepare(__entry_size, \
event_call->event.type, &__regs, &rctx); \
if (!entry) \
return; \
\
perf_fetch_caller_regs(__regs); \
\
tstruct \
\
{ assign; } \
\
perf_trace_buf_submit(entry, __entry_size, rctx, __addr, \
__count, &__regs, head, __task); \
__count, __regs, head, __task); \
}

/*
Expand Down
Loading

0 comments on commit a4cbbf5

Please sign in to comment.