Merge branch 'perf-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull perf fixes from Ingo Molnar: "Misc fixes: - AMD IBS data corruptor fix (uncovered by UBSAN) - an Intel PEBS entry unwind error fix - a HW-tracing crash fix - a MAINTAINERS update" * 'perf-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: perf/core: Fix crash when using HW tracing kernel filters perf/x86/intel: Fix unwind errors from PEBS entries (mk-II) MAINTAINERS: Add Naveen N. Rao as kprobes co-maintainer perf/x86/amd/ibs: Don't access non-started event
This commit is contained in:
commit
0634922a78
@ -7985,7 +7985,7 @@ F: lib/test_kmod.c
|
|||||||
F: tools/testing/selftests/kmod/
|
F: tools/testing/selftests/kmod/
|
||||||
|
|
||||||
KPROBES
|
KPROBES
|
||||||
M: Ananth N Mavinakayanahalli <ananth@linux.vnet.ibm.com>
|
M: Naveen N. Rao <naveen.n.rao@linux.vnet.ibm.com>
|
||||||
M: Anil S Keshavamurthy <anil.s.keshavamurthy@intel.com>
|
M: Anil S Keshavamurthy <anil.s.keshavamurthy@intel.com>
|
||||||
M: "David S. Miller" <davem@davemloft.net>
|
M: "David S. Miller" <davem@davemloft.net>
|
||||||
M: Masami Hiramatsu <mhiramat@kernel.org>
|
M: Masami Hiramatsu <mhiramat@kernel.org>
|
||||||
|
@ -579,7 +579,7 @@ static int perf_ibs_handle_irq(struct perf_ibs *perf_ibs, struct pt_regs *iregs)
|
|||||||
{
|
{
|
||||||
struct cpu_perf_ibs *pcpu = this_cpu_ptr(perf_ibs->pcpu);
|
struct cpu_perf_ibs *pcpu = this_cpu_ptr(perf_ibs->pcpu);
|
||||||
struct perf_event *event = pcpu->event;
|
struct perf_event *event = pcpu->event;
|
||||||
struct hw_perf_event *hwc = &event->hw;
|
struct hw_perf_event *hwc;
|
||||||
struct perf_sample_data data;
|
struct perf_sample_data data;
|
||||||
struct perf_raw_record raw;
|
struct perf_raw_record raw;
|
||||||
struct pt_regs regs;
|
struct pt_regs regs;
|
||||||
@ -602,6 +602,10 @@ static int perf_ibs_handle_irq(struct perf_ibs *perf_ibs, struct pt_regs *iregs)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (WARN_ON_ONCE(!event))
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
hwc = &event->hw;
|
||||||
msr = hwc->config_base;
|
msr = hwc->config_base;
|
||||||
buf = ibs_data.regs;
|
buf = ibs_data.regs;
|
||||||
rdmsrl(msr, *buf);
|
rdmsrl(msr, *buf);
|
||||||
|
@ -2997,6 +2997,9 @@ static int intel_pmu_hw_config(struct perf_event *event)
|
|||||||
}
|
}
|
||||||
if (x86_pmu.pebs_aliases)
|
if (x86_pmu.pebs_aliases)
|
||||||
x86_pmu.pebs_aliases(event);
|
x86_pmu.pebs_aliases(event);
|
||||||
|
|
||||||
|
if (event->attr.sample_type & PERF_SAMPLE_CALLCHAIN)
|
||||||
|
event->attr.sample_type |= __PERF_SAMPLE_CALLCHAIN_EARLY;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (needs_branch_stack(event)) {
|
if (needs_branch_stack(event)) {
|
||||||
|
@ -1185,17 +1185,21 @@ static void setup_pebs_sample_data(struct perf_event *event,
|
|||||||
data->data_src.val = val;
|
data->data_src.val = val;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We must however always use iregs for the unwinder to stay sane; the
|
||||||
|
* record BP,SP,IP can point into thin air when the record is from a
|
||||||
|
* previous PMI context or an (I)RET happend between the record and
|
||||||
|
* PMI.
|
||||||
|
*/
|
||||||
|
if (sample_type & PERF_SAMPLE_CALLCHAIN)
|
||||||
|
data->callchain = perf_callchain(event, iregs);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We use the interrupt regs as a base because the PEBS record does not
|
* We use the interrupt regs as a base because the PEBS record does not
|
||||||
* contain a full regs set, specifically it seems to lack segment
|
* contain a full regs set, specifically it seems to lack segment
|
||||||
* descriptors, which get used by things like user_mode().
|
* descriptors, which get used by things like user_mode().
|
||||||
*
|
*
|
||||||
* In the simple case fix up only the IP for PERF_SAMPLE_IP.
|
* In the simple case fix up only the IP for PERF_SAMPLE_IP.
|
||||||
*
|
|
||||||
* We must however always use BP,SP from iregs for the unwinder to stay
|
|
||||||
* sane; the record BP,SP can point into thin air when the record is
|
|
||||||
* from a previous PMI context or an (I)RET happend between the record
|
|
||||||
* and PMI.
|
|
||||||
*/
|
*/
|
||||||
*regs = *iregs;
|
*regs = *iregs;
|
||||||
|
|
||||||
@ -1214,15 +1218,8 @@ static void setup_pebs_sample_data(struct perf_event *event,
|
|||||||
regs->si = pebs->si;
|
regs->si = pebs->si;
|
||||||
regs->di = pebs->di;
|
regs->di = pebs->di;
|
||||||
|
|
||||||
/*
|
regs->bp = pebs->bp;
|
||||||
* Per the above; only set BP,SP if we don't need callchains.
|
regs->sp = pebs->sp;
|
||||||
*
|
|
||||||
* XXX: does this make sense?
|
|
||||||
*/
|
|
||||||
if (!(sample_type & PERF_SAMPLE_CALLCHAIN)) {
|
|
||||||
regs->bp = pebs->bp;
|
|
||||||
regs->sp = pebs->sp;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifndef CONFIG_X86_32
|
#ifndef CONFIG_X86_32
|
||||||
regs->r8 = pebs->r8;
|
regs->r8 = pebs->r8;
|
||||||
|
@ -1130,6 +1130,7 @@ extern void perf_callchain_kernel(struct perf_callchain_entry_ctx *entry, struct
|
|||||||
extern struct perf_callchain_entry *
|
extern struct perf_callchain_entry *
|
||||||
get_perf_callchain(struct pt_regs *regs, u32 init_nr, bool kernel, bool user,
|
get_perf_callchain(struct pt_regs *regs, u32 init_nr, bool kernel, bool user,
|
||||||
u32 max_stack, bool crosstask, bool add_mark);
|
u32 max_stack, bool crosstask, bool add_mark);
|
||||||
|
extern struct perf_callchain_entry *perf_callchain(struct perf_event *event, struct pt_regs *regs);
|
||||||
extern int get_callchain_buffers(int max_stack);
|
extern int get_callchain_buffers(int max_stack);
|
||||||
extern void put_callchain_buffers(void);
|
extern void put_callchain_buffers(void);
|
||||||
|
|
||||||
|
@ -143,6 +143,8 @@ enum perf_event_sample_format {
|
|||||||
PERF_SAMPLE_PHYS_ADDR = 1U << 19,
|
PERF_SAMPLE_PHYS_ADDR = 1U << 19,
|
||||||
|
|
||||||
PERF_SAMPLE_MAX = 1U << 20, /* non-ABI */
|
PERF_SAMPLE_MAX = 1U << 20, /* non-ABI */
|
||||||
|
|
||||||
|
__PERF_SAMPLE_CALLCHAIN_EARLY = 1ULL << 63,
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -6343,7 +6343,7 @@ static u64 perf_virt_to_phys(u64 virt)
|
|||||||
|
|
||||||
static struct perf_callchain_entry __empty_callchain = { .nr = 0, };
|
static struct perf_callchain_entry __empty_callchain = { .nr = 0, };
|
||||||
|
|
||||||
static struct perf_callchain_entry *
|
struct perf_callchain_entry *
|
||||||
perf_callchain(struct perf_event *event, struct pt_regs *regs)
|
perf_callchain(struct perf_event *event, struct pt_regs *regs)
|
||||||
{
|
{
|
||||||
bool kernel = !event->attr.exclude_callchain_kernel;
|
bool kernel = !event->attr.exclude_callchain_kernel;
|
||||||
@ -6382,7 +6382,9 @@ void perf_prepare_sample(struct perf_event_header *header,
|
|||||||
if (sample_type & PERF_SAMPLE_CALLCHAIN) {
|
if (sample_type & PERF_SAMPLE_CALLCHAIN) {
|
||||||
int size = 1;
|
int size = 1;
|
||||||
|
|
||||||
data->callchain = perf_callchain(event, regs);
|
if (!(sample_type & __PERF_SAMPLE_CALLCHAIN_EARLY))
|
||||||
|
data->callchain = perf_callchain(event, regs);
|
||||||
|
|
||||||
size += data->callchain->nr;
|
size += data->callchain->nr;
|
||||||
|
|
||||||
header->size += size * sizeof(u64);
|
header->size += size * sizeof(u64);
|
||||||
@ -7335,6 +7337,10 @@ static bool perf_addr_filter_match(struct perf_addr_filter *filter,
|
|||||||
struct file *file, unsigned long offset,
|
struct file *file, unsigned long offset,
|
||||||
unsigned long size)
|
unsigned long size)
|
||||||
{
|
{
|
||||||
|
/* d_inode(NULL) won't be equal to any mapped user-space file */
|
||||||
|
if (!filter->path.dentry)
|
||||||
|
return false;
|
||||||
|
|
||||||
if (d_inode(filter->path.dentry) != file_inode(file))
|
if (d_inode(filter->path.dentry) != file_inode(file))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user