2019-06-04 11:11:33 +03:00
// SPDX-License-Identifier: GPL-2.0-only
2010-10-12 15:37:22 +04:00
/*
* Linux performance counter support for MIPS .
*
* Copyright ( C ) 2010 MIPS Technologies , Inc .
* Author : Deng - Cheng Zhu
*
* This code is based on the implementation for ARM , which is in turn
* based on the sparc64 perf event code and the x86 code . Performance
2010-10-12 15:37:23 +04:00
* counter access is based on the MIPS Oprofile code . And the callchain
* support references the code of MIPS stacktrace . c .
2010-10-12 15:37:22 +04:00
*/
# include <linux/perf_event.h>
2017-02-08 20:51:37 +03:00
# include <linux/sched/task_stack.h>
2010-10-12 15:37:22 +04:00
# include <asm/stacktrace.h>
2010-10-12 15:37:24 +04:00
2010-10-12 15:37:23 +04:00
/* Callchain handling code. */
/*
* Leave userspace callchain empty for now . When we find a way to trace
2011-09-24 04:29:55 +04:00
* the user stack callchains , we will add it here .
2010-10-12 15:37:23 +04:00
*/
2016-04-28 18:30:53 +03:00
static void save_raw_perf_callchain ( struct perf_callchain_entry_ctx * entry ,
unsigned long reg29 )
2010-10-12 15:37:23 +04:00
{
unsigned long * sp = ( unsigned long * ) reg29 ;
unsigned long addr ;
while ( ! kstack_end ( sp ) ) {
addr = * sp + + ;
if ( __kernel_text_address ( addr ) ) {
2011-01-21 11:19:20 +03:00
perf_callchain_store ( entry , addr ) ;
perf core: Add a 'nr' field to perf_event_callchain_context
We will use it to count how many addresses are in the entry->ip[] array,
excluding PERF_CONTEXT_{KERNEL,USER,etc} entries, so that we can really
return the number of entries specified by the user via the relevant
sysctl, kernel.perf_event_max_contexts, or via the per event
perf_event_attr.sample_max_stack knob.
This way we keep the perf_sample->ip_callchain->nr meaning, that is the
number of entries, be it real addresses or PERF_CONTEXT_ entries, while
honouring the max_stack knobs, i.e. the end result will be max_stack
entries if we have at least that many entries in a given stack trace.
Cc: David Ahern <dsahern@gmail.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: http://lkml.kernel.org/n/tip-s8teto51tdqvlfhefndtat9r@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2016-05-11 00:08:32 +03:00
if ( entry - > nr > = entry - > max_stack )
2010-10-12 15:37:23 +04:00
break ;
}
}
}
2016-04-28 18:30:53 +03:00
void perf_callchain_kernel ( struct perf_callchain_entry_ctx * entry ,
struct pt_regs * regs )
2010-10-12 15:37:23 +04:00
{
unsigned long sp = regs - > regs [ 29 ] ;
# ifdef CONFIG_KALLSYMS
unsigned long ra = regs - > regs [ 31 ] ;
unsigned long pc = regs - > cp0_epc ;
if ( raw_show_trace | | ! __kernel_text_address ( pc ) ) {
unsigned long stack_page =
( unsigned long ) task_stack_page ( current ) ;
if ( stack_page & & sp > = stack_page & &
sp < = stack_page + THREAD_SIZE - 32 )
save_raw_perf_callchain ( entry , sp ) ;
return ;
}
do {
2011-01-21 11:19:20 +03:00
perf_callchain_store ( entry , pc ) ;
perf core: Add a 'nr' field to perf_event_callchain_context
We will use it to count how many addresses are in the entry->ip[] array,
excluding PERF_CONTEXT_{KERNEL,USER,etc} entries, so that we can really
return the number of entries specified by the user via the relevant
sysctl, kernel.perf_event_max_contexts, or via the per event
perf_event_attr.sample_max_stack knob.
This way we keep the perf_sample->ip_callchain->nr meaning, that is the
number of entries, be it real addresses or PERF_CONTEXT_ entries, while
honouring the max_stack knobs, i.e. the end result will be max_stack
entries if we have at least that many entries in a given stack trace.
Cc: David Ahern <dsahern@gmail.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: http://lkml.kernel.org/n/tip-s8teto51tdqvlfhefndtat9r@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2016-05-11 00:08:32 +03:00
if ( entry - > nr > = entry - > max_stack )
2010-10-12 15:37:23 +04:00
break ;
pc = unwind_stack ( current , & sp , pc , & ra ) ;
} while ( pc ) ;
# else
save_raw_perf_callchain ( entry , sp ) ;
# endif
}