Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 9960e9e8 authored by David S. Miller's avatar David S. Miller
Browse files

sparc64: Add function graph tracer support.

parent a71d1d6b
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -37,6 +37,8 @@ config SPARC64
	def_bool 64BIT
	select ARCH_SUPPORTS_MSI
	select HAVE_FUNCTION_TRACER
	select HAVE_FUNCTION_GRAPH_TRACER
	select HAVE_FUNCTION_GRAPH_FP_TEST
	select HAVE_FUNCTION_TRACE_MCOUNT_TEST
	select HAVE_KRETPROBES
	select HAVE_KPROBES
+1 −0
Original line number Diff line number Diff line
@@ -93,6 +93,7 @@ obj-$(CONFIG_KGDB) += kgdb_$(BITS).o


obj-$(CONFIG_DYNAMIC_FTRACE) += ftrace.o
obj-$(CONFIG_FUNCTION_GRAPH_TRACER) += ftrace.o

obj-$(CONFIG_EARLYFB) += btext.o
obj-$(CONFIG_STACKTRACE)     += stacktrace.o
+58 −0
Original line number Diff line number Diff line
@@ -91,3 +91,61 @@ int __init ftrace_dyn_arch_init(void *data)
	return 0;
}
#endif

#ifdef CONFIG_FUNCTION_GRAPH_TRACER

#ifdef CONFIG_DYNAMIC_FTRACE
extern void ftrace_graph_call(void);

int ftrace_enable_ftrace_graph_caller(void)
{
	unsigned long ip = (unsigned long)(&ftrace_graph_call);
	u32 old, new;

	old = *(u32 *) &ftrace_graph_call;
	new = ftrace_call_replace(ip, (unsigned long) &ftrace_graph_caller);
	return ftrace_modify_code(ip, old, new);
}

int ftrace_disable_ftrace_graph_caller(void)
{
	unsigned long ip = (unsigned long)(&ftrace_graph_call);
	u32 old, new;

	old = *(u32 *) &ftrace_graph_call;
	new = ftrace_call_replace(ip, (unsigned long) &ftrace_stub);

	return ftrace_modify_code(ip, old, new);
}

#endif /* !CONFIG_DYNAMIC_FTRACE */

/*
 * Hook the return address and push it in the stack of return addrs
 * in current thread info.
 */
unsigned long prepare_ftrace_return(unsigned long parent,
				    unsigned long self_addr,
				    unsigned long frame_pointer)
{
	unsigned long return_hooker = (unsigned long) &return_to_handler;
	struct ftrace_graph_ent trace;

	if (unlikely(atomic_read(&current->tracing_graph_pause)))
		return parent + 8UL;

	if (ftrace_push_return_trace(parent, self_addr, &trace.depth,
				     frame_pointer) == -EBUSY)
		return parent + 8UL;

	trace.func = self_addr;

	/* Only trace if the calling function expects to */
	if (!ftrace_graph_entry(&trace)) {
		current->curr_ret_stack--;
		return parent + 8UL;
	}

	return return_hooker;
}
#endif /* CONFIG_FUNCTION_GRAPH_TRACER */
+2 −1
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@
#include <linux/delay.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <linux/ftrace.h>
#include <linux/irq.h>

#include <asm/ptrace.h>
@@ -721,7 +722,7 @@ static __attribute__((always_inline)) void restore_hardirq_stack(void *orig_sp)
	__asm__ __volatile__("mov %0, %%sp" : : "r" (orig_sp));
}

void handler_irq(int irq, struct pt_regs *regs)
void __irq_entry handler_irq(int irq, struct pt_regs *regs)
{
	unsigned long pstate, bucket_pa;
	struct pt_regs *old_regs;
+2 −1
Original line number Diff line number Diff line
@@ -5,6 +5,7 @@

#include <linux/kgdb.h>
#include <linux/kdebug.h>
#include <linux/ftrace.h>

#include <asm/kdebug.h>
#include <asm/ptrace.h>
@@ -108,7 +109,7 @@ void gdb_regs_to_pt_regs(unsigned long *gdb_regs, struct pt_regs *regs)
}

#ifdef CONFIG_SMP
void smp_kgdb_capture_client(int irq, struct pt_regs *regs)
void __irq_entry smp_kgdb_capture_client(int irq, struct pt_regs *regs)
{
	unsigned long flags;

Loading