MIPS, Perf-events: Work with the new callchain interface
This is the MIPS part of the following commits by Frederic Weisbecker: -f72c1a931e
perf: Factorize callchain context handling Store the kernel and user contexts from the generic layer instead of archs, this gathers some repetitive code. -56962b4449
perf: Generalize some arch callchain code - Most archs use one callchain buffer per cpu, except x86 that needs to deal with NMIs. Provide a default perf_callchain_buffer() implementation that x86 overrides. - Centralize all the kernel/user regs handling and invoke new arch handlers from there: perf_callchain_user() / perf_callchain_kernel() That avoid all the user_mode(), current->mm checks and so... - Invert some parameters in perf_callchain_*() helpers: entry to the left, regs to the right, following the traditional (dst, src). -70791ce9ba
perf: Generalize callchain_store() callchain_store() is the same on every archs, inline it in perf_event.h and rename it to perf_callchain_store() to avoid any collision. This removes repetitive code. -c1a65932fd
perf: Drop unappropriate tests on arch callchains Drop the TASK_RUNNING test on user tasks for callchains as this check doesn't seem to make any sense. Also remove the tests for !current that is not supposed to happen and current->pid as this should be handled at the generic level, with exclude_idle attribute. Reported-by: Wu Zhangjin <wuzhangjin@gmail.com> Acked-by: Frederic Weisbecker <fweisbec@gmail.com> Acked-by: David Daney <ddaney@caviumnetworks.com> Signed-off-by: Deng-Cheng Zhu <dengcheng.zhu@gmail.com> To: a.p.zijlstra@chello.nl To: will.deacon@arm.com Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Cc: paulus@samba.org Cc: mingo@elte.hu Cc: acme@redhat.com Cc: dengcheng.zhu@gmail.com Cc: matt@console-pimps.org Cc: sshtylyov@mvista.com Patchwork: http://patchwork.linux-mips.org/patch/2014/ Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
This commit is contained in:
parent
c049b6a5f2
commit
98f92f2f9e
|
@ -534,21 +534,13 @@ handle_associated_event(struct cpu_hw_events *cpuc,
|
|||
#include "perf_event_mipsxx.c"
|
||||
|
||||
/* Callchain handling code. */
|
||||
static inline void
|
||||
callchain_store(struct perf_callchain_entry *entry,
|
||||
u64 ip)
|
||||
{
|
||||
if (entry->nr < PERF_MAX_STACK_DEPTH)
|
||||
entry->ip[entry->nr++] = ip;
|
||||
}
|
||||
|
||||
/*
|
||||
* Leave userspace callchain empty for now. When we find a way to trace
|
||||
* the user stack callchains, we add here.
|
||||
*/
|
||||
static void
|
||||
perf_callchain_user(struct pt_regs *regs,
|
||||
struct perf_callchain_entry *entry)
|
||||
void perf_callchain_user(struct perf_callchain_entry *entry,
|
||||
struct pt_regs *regs)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -561,23 +553,21 @@ static void save_raw_perf_callchain(struct perf_callchain_entry *entry,
|
|||
while (!kstack_end(sp)) {
|
||||
addr = *sp++;
|
||||
if (__kernel_text_address(addr)) {
|
||||
callchain_store(entry, addr);
|
||||
perf_callchain_store(entry, addr);
|
||||
if (entry->nr >= PERF_MAX_STACK_DEPTH)
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
perf_callchain_kernel(struct pt_regs *regs,
|
||||
struct perf_callchain_entry *entry)
|
||||
void perf_callchain_kernel(struct perf_callchain_entry *entry,
|
||||
struct pt_regs *regs)
|
||||
{
|
||||
unsigned long sp = regs->regs[29];
|
||||
#ifdef CONFIG_KALLSYMS
|
||||
unsigned long ra = regs->regs[31];
|
||||
unsigned long pc = regs->cp0_epc;
|
||||
|
||||
callchain_store(entry, PERF_CONTEXT_KERNEL);
|
||||
if (raw_show_trace || !__kernel_text_address(pc)) {
|
||||
unsigned long stack_page =
|
||||
(unsigned long)task_stack_page(current);
|
||||
|
@ -587,53 +577,12 @@ perf_callchain_kernel(struct pt_regs *regs,
|
|||
return;
|
||||
}
|
||||
do {
|
||||
callchain_store(entry, pc);
|
||||
perf_callchain_store(entry, pc);
|
||||
if (entry->nr >= PERF_MAX_STACK_DEPTH)
|
||||
break;
|
||||
pc = unwind_stack(current, &sp, pc, &ra);
|
||||
} while (pc);
|
||||
#else
|
||||
callchain_store(entry, PERF_CONTEXT_KERNEL);
|
||||
save_raw_perf_callchain(entry, sp);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
perf_do_callchain(struct pt_regs *regs,
|
||||
struct perf_callchain_entry *entry)
|
||||
{
|
||||
int is_user;
|
||||
|
||||
if (!regs)
|
||||
return;
|
||||
|
||||
is_user = user_mode(regs);
|
||||
|
||||
if (!current || !current->pid)
|
||||
return;
|
||||
|
||||
if (is_user && current->state != TASK_RUNNING)
|
||||
return;
|
||||
|
||||
if (!is_user) {
|
||||
perf_callchain_kernel(regs, entry);
|
||||
if (current->mm)
|
||||
regs = task_pt_regs(current);
|
||||
else
|
||||
regs = NULL;
|
||||
}
|
||||
if (regs)
|
||||
perf_callchain_user(regs, entry);
|
||||
}
|
||||
|
||||
static DEFINE_PER_CPU(struct perf_callchain_entry, pmc_irq_entry);
|
||||
|
||||
struct perf_callchain_entry *
|
||||
perf_callchain(struct pt_regs *regs)
|
||||
{
|
||||
struct perf_callchain_entry *entry = &__get_cpu_var(pmc_irq_entry);
|
||||
|
||||
entry->nr = 0;
|
||||
perf_do_callchain(regs, entry);
|
||||
return entry;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue