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

Unverified Commit bc1a4c3a authored by Alan Kao's avatar Alan Kao Committed by Palmer Dabbelt
Browse files

riscv/ftrace: Add dynamic function graph tracer support



Once the function_graph tracer is enabled, a filtered function has the
following call sequence:

* ftracer_caller         ==> on/off by ftrace_make_call/ftrace_make_nop
* ftrace_graph_caller
* ftrace_graph_call      ==> on/off by ftrace_en/disable_ftrace_graph_caller
* prepare_ftrace_return

Considering the following DYNAMIC_FTRACE_WITH_REGS feature, it would be
more extendable to have a ftrace_graph_caller function, instead of
calling prepare_ftrace_return directly in ftrace_caller.

Cc: Greentime Hu <greentime@andestech.com>
Signed-off-by: default avatarAlan Kao <alankao@andestech.com>
Signed-off-by: default avatarPalmer Dabbelt <palmer@sifive.com>
parent c15ac4fd
Loading
Loading
Loading
Loading
+54 −1
Original line number Diff line number Diff line
@@ -139,4 +139,57 @@ void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr,
		return;
	*parent = return_hooker;
}
#endif

#ifdef CONFIG_DYNAMIC_FTRACE
extern void ftrace_graph_call(void);
int ftrace_enable_ftrace_graph_caller(void)
{
	unsigned int call[2];
	static int init_graph = 1;
	int ret;

	make_call(&ftrace_graph_call, &ftrace_stub, call);

	/*
	 * When enabling graph tracer for the first time, ftrace_graph_call
	 * should contains a call to ftrace_stub.  Once it has been disabled,
	 * the 8-bytes at the position becomes NOPs.
	 */
	if (init_graph) {
		ret = ftrace_check_current_call((unsigned long)&ftrace_graph_call,
						call);
		init_graph = 0;
	} else {
		ret = ftrace_check_current_call((unsigned long)&ftrace_graph_call,
						NULL);
	}

	if (ret)
		return ret;

	return __ftrace_modify_call((unsigned long)&ftrace_graph_call,
				    (unsigned long)&prepare_ftrace_return, true);
}

int ftrace_disable_ftrace_graph_caller(void)
{
	unsigned int call[2];
	int ret;

	make_call(&ftrace_graph_call, &prepare_ftrace_return, call);

	/*
	 * This is to make sure that ftrace_enable_ftrace_graph_caller
	 * did the right thing.
	 */
	ret = ftrace_check_current_call((unsigned long)&ftrace_graph_call,
					call);

	if (ret)
		return ret;

	return __ftrace_modify_call((unsigned long)&ftrace_graph_call,
				    (unsigned long)&prepare_ftrace_return, false);
}
#endif /* CONFIG_DYNAMIC_FTRACE */
#endif /* CONFIG_FUNCTION_GRAPH_TRACER */
+64 −0
Original line number Diff line number Diff line
@@ -14,18 +14,62 @@
	.text

	.macro SAVE_ABI_STATE
#ifdef CONFIG_FUNCTION_GRAPH_TRACER
	addi    sp, sp, -48
	sd      s0, 32(sp)
	sd      ra, 40(sp)
	addi    s0, sp, 48
	sd      t0, 24(sp)
	sd      t1, 16(sp)
#ifdef HAVE_FUNCTION_GRAPH_FP_TEST
	sd      t2, 8(sp)
#endif
#else
	addi	sp, sp, -16
	sd	s0, 0(sp)
	sd	ra, 8(sp)
	addi	s0, sp, 16
#endif
	.endm

	.macro RESTORE_ABI_STATE
#ifdef CONFIG_FUNCTION_GRAPH_TRACER
	ld	s0, 32(sp)
	ld	ra, 40(sp)
	addi	sp, sp, 48
#else
	ld	ra, 8(sp)
	ld	s0, 0(sp)
	addi	sp, sp, 16
#endif
	.endm

	.macro RESTORE_GRAPH_ARGS
	ld	a0, 24(sp)
	ld	a1, 16(sp)
#ifdef HAVE_FUNCTION_GRAPH_FP_TEST
	ld	a2, 8(sp)
#endif
	.endm

ENTRY(ftrace_graph_caller)
	addi	sp, sp, -16
	sd	s0, 0(sp)
	sd	ra, 8(sp)
	addi	s0, sp, 16
ftrace_graph_call:
	.global ftrace_graph_call
	/*
	 * Calling ftrace_enable/disable_ftrace_graph_caller would overwrite the
	 * call below.  Check ftrace_modify_all_code for details.
	 */
	call	ftrace_stub
	ld	ra, 8(sp)
	ld	s0, 0(sp)
	addi	sp, sp, 16
	ret
ENDPROC(ftrace_graph_caller)

ENTRY(ftrace_caller)
	/*
	 * a0: the address in the caller when calling ftrace_caller
@@ -33,6 +77,20 @@ ENTRY(ftrace_caller)
	 */
	ld	a1, -8(s0)
	addi	a0, ra, -MCOUNT_INSN_SIZE

#ifdef CONFIG_FUNCTION_GRAPH_TRACER
	/*
	 * the graph tracer (specifically, prepare_ftrace_return) needs these
	 * arguments but for now the function tracer occupies the regs, so we
	 * save them in temporary regs to recover later.
	 */
	addi	t0, s0, -8
	mv	t1, a0
#ifdef HAVE_FUNCTION_GRAPH_FP_TEST
	ld	t2, -16(s0)
#endif
#endif

	SAVE_ABI_STATE
ftrace_call:
	.global ftrace_call
@@ -45,6 +103,12 @@ ftrace_call:
	 * Check ftrace_modify_all_code for details.
	 */
	call	ftrace_stub

#ifdef CONFIG_FUNCTION_GRAPH_TRACER
	RESTORE_GRAPH_ARGS
	call	ftrace_graph_caller
#endif

	RESTORE_ABI_STATE
	ret
ENDPROC(ftrace_caller)