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

Commit 046199ca authored by Wu Zhangjin's avatar Wu Zhangjin Committed by Ralf Baechle
Browse files

MIPS: Tracing: Make ftrace for MIPS work without -fno-omit-frame-pointer



When remove the -fno-omit-frame-pointer, gcc will not save the frame
pointer for us, we need to save one ourselves.

Signed-off-by: default avatarWu Zhangjin <wuzhangjin@gmail.com>
Cc: Steven Rostedt <rostedt@goodmis.org>
Cc: Nicholas Mc Guire <der.herr@hofr.at>
Cc: zhangfx@lemote.com
Cc: Wu Zhangjin <wuzhangjin@gmail.com>
Cc: Ingo Molnar <mingo@elte.hu>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: linux-kernel@vger.kernel.org
Cc: linux-mips@linux-mips.org
Patchwork: http://patchwork.linux-mips.org/patch/679/


Signed-off-by: default avatarRalf Baechle <ralf@linux-mips.org>
parent e17ff5fe
Loading
Loading
Loading
Loading
+57 −0
Original line number Diff line number Diff line
@@ -19,6 +19,62 @@
extern void _mcount(void);
#define mcount _mcount

#define safe_load(load, src, dst, error)		\
do {							\
	asm volatile (					\
		"1: " load " %[" STR(dst) "], 0(%[" STR(src) "])\n"\
		"   li %[" STR(error) "], 0\n"		\
		"2:\n"					\
							\
		".section .fixup, \"ax\"\n"		\
		"3: li %[" STR(error) "], 1\n"		\
		"   j 2b\n"				\
		".previous\n"				\
							\
		".section\t__ex_table,\"a\"\n\t"	\
		STR(PTR) "\t1b, 3b\n\t"			\
		".previous\n"				\
							\
		: [dst] "=&r" (dst), [error] "=r" (error)\
		: [src] "r" (src)			\
		: "memory"				\
	);						\
} while (0)

#define safe_store(store, src, dst, error)	\
do {						\
	asm volatile (				\
		"1: " store " %[" STR(src) "], 0(%[" STR(dst) "])\n"\
		"   li %[" STR(error) "], 0\n"	\
		"2:\n"				\
						\
		".section .fixup, \"ax\"\n"	\
		"3: li %[" STR(error) "], 1\n"	\
		"   j 2b\n"			\
		".previous\n"			\
						\
		".section\t__ex_table,\"a\"\n\t"\
		STR(PTR) "\t1b, 3b\n\t"		\
		".previous\n"			\
						\
		: [error] "=r" (error)		\
		: [dst] "r" (dst), [src] "r" (src)\
		: "memory"			\
	);					\
} while (0)

#define safe_load_code(dst, src, error) \
	safe_load(STR(lw), src, dst, error)
#define safe_store_code(src, dst, error) \
	safe_store(STR(sw), src, dst, error)

#define safe_load_stack(dst, src, error) \
	safe_load(STR(PTR_L), src, dst, error)

#define safe_store_stack(src, dst, error) \
	safe_store(STR(PTR_S), src, dst, error)


#ifdef CONFIG_DYNAMIC_FTRACE
static inline unsigned long ftrace_call_adjust(unsigned long addr)
{
@@ -27,6 +83,7 @@ static inline unsigned long ftrace_call_adjust(unsigned long addr)

struct dyn_arch_ftrace {
};

#endif /*  CONFIG_DYNAMIC_FTRACE */
#endif /* __ASSEMBLY__ */
#endif /* CONFIG_FUNCTION_TRACER */
+41 −15
Original line number Diff line number Diff line
@@ -27,7 +27,13 @@ static unsigned int ftrace_nop = 0x00000000;

static int ftrace_modify_code(unsigned long ip, unsigned int new_code)
{
	*(unsigned int *)ip = new_code;
	int faulted;

	/* *(unsigned int *)ip = new_code; */
	safe_store_code(new_code, ip, faulted);

	if (unlikely(faulted))
		return -EFAULT;

	flush_icache_range(ip, ip + 8);

@@ -41,14 +47,20 @@ int ftrace_make_nop(struct module *mod,
		    struct dyn_ftrace *rec, unsigned long addr)
{
	unsigned int new;
	int faulted;
	unsigned long ip = rec->ip;

	/* We have compiled module with -mlong-calls, but compiled the kernel
	 * without it, we need to cope with them respectively. */
	if (ip & 0x40000000) {
		/* record it for ftrace_make_call */
		if (lui_v1 == 0)
			lui_v1 = *(unsigned int *)ip;
		if (lui_v1 == 0) {
			/* lui_v1 = *(unsigned int *)ip; */
			safe_load_code(lui_v1, ip, faulted);

			if (unlikely(faulted))
				return -EFAULT;
		}

		/* lui v1, hi_16bit_of_mcount        --> b 1f (0x10000004)
		 * addiu v1, v1, low_16bit_of_mcount
@@ -147,6 +159,7 @@ unsigned long ftrace_get_parent_addr(unsigned long self_addr,
{
	unsigned long sp, ip, ra;
	unsigned int code;
	int faulted;

	/* in module or kernel? */
	if (self_addr & 0x40000000) {
@@ -162,8 +175,11 @@ unsigned long ftrace_get_parent_addr(unsigned long self_addr,
	do {
		ip -= 4;

		/* get the code at "ip" */
		code = *(unsigned int *)ip;
		/* get the code at "ip": code = *(unsigned int *)ip; */
		safe_load_code(code, ip, faulted);

		if (unlikely(faulted))
			return 0;

		/* If we hit the non-store instruction before finding where the
		 * ra is stored, then this is a leaf function and it does not
@@ -174,11 +190,14 @@ unsigned long ftrace_get_parent_addr(unsigned long self_addr,
	} while (((code & S_RA_SP) != S_RA_SP));

	sp = fp + (code & OFFSET_MASK);
	ra = *(unsigned long *)sp;

	/* ra = *(unsigned long *)sp; */
	safe_load_stack(ra, sp, faulted);
	if (unlikely(faulted))
		return 0;

	if (ra == parent)
		return sp;

	return 0;
}

@@ -193,6 +212,7 @@ void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr,
	struct ftrace_graph_ent trace;
	unsigned long return_hooker = (unsigned long)
	    &return_to_handler;
	int faulted;

	if (unlikely(atomic_read(&current->tracing_graph_pause)))
		return;
@@ -206,21 +226,23 @@ void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr,
	 * ftrace_get_parent_addr() does it!
	 */

	old = *parent;
	/* old = *parent; */
	safe_load_stack(old, parent, faulted);
	if (unlikely(faulted))
		goto out;

	parent = (unsigned long *)ftrace_get_parent_addr(self_addr, old,
							 (unsigned long)parent,
							 fp);

	/* If fails when getting the stack address of the non-leaf function's
	 * ra, stop function graph tracer and return */
	if (parent == 0) {
		ftrace_graph_stop();
		WARN_ON(1);
		return;
	}
	if (parent == 0)
		goto out;

	*parent = return_hooker;
	/* *parent = return_hooker; */
	safe_store_stack(return_hooker, parent, faulted);
	if (unlikely(faulted))
		goto out;

	if (ftrace_push_return_trace(old, self_addr, &trace.depth, fp) ==
	    -EBUSY) {
@@ -235,5 +257,9 @@ void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr,
		current->curr_ret_stack--;
		*parent = old;
	}
	return;
out:
	ftrace_graph_stop();
	WARN_ON(1);
}
#endif				/* CONFIG_FUNCTION_GRAPH_TRACER */
+8 −0
Original line number Diff line number Diff line
@@ -139,7 +139,15 @@ NESTED(ftrace_graph_caller, PT_SIZE, ra)
#endif
	PTR_LA	a0, PT_R1(sp)	/* arg1: &AT -> a0 */
	jal	prepare_ftrace_return
#ifdef CONFIG_FRAME_POINTER
	 move	a2, fp		/* arg3: frame pointer */
#else
#ifdef CONFIG_64BIT
	 PTR_LA	a2, PT_SIZE(sp)
#else
	 PTR_LA	a2, (PT_SIZE+8)(sp)
#endif
#endif

	MCOUNT_RESTORE_REGS
	RETURN_BACK