Skip to content

Commit 5fcfad3

Browse files
zhangqingmychenhuacai
authored andcommitted
LoongArch/ftrace: Add dynamic function graph tracer support
Once the function_graph tracer is enabled, a filtered function has the following call sequence: 1) ftracer_caller ==> on/off by ftrace_make_call/ftrace_make_nop 2) ftrace_graph_caller 3) ftrace_graph_call ==> on/off by ftrace_en/disable_ftrace_graph_caller 4) 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. Co-developed-by: Jinyang He <[email protected]> Signed-off-by: Jinyang He <[email protected]> Signed-off-by: Qing Zhang <[email protected]> Signed-off-by: Huacai Chen <[email protected]>
1 parent 4733f09 commit 5fcfad3

File tree

3 files changed

+101
-0
lines changed

3 files changed

+101
-0
lines changed

arch/loongarch/kernel/ftrace_dyn.c

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,3 +108,47 @@ int __init ftrace_dyn_arch_init(void)
108108
{
109109
return 0;
110110
}
111+
112+
#ifdef CONFIG_FUNCTION_GRAPH_TRACER
113+
void prepare_ftrace_return(unsigned long self_addr, unsigned long *parent)
114+
{
115+
unsigned long old;
116+
unsigned long return_hooker = (unsigned long)&return_to_handler;
117+
118+
if (unlikely(atomic_read(&current->tracing_graph_pause)))
119+
return;
120+
121+
old = *parent;
122+
123+
if (!function_graph_enter(old, self_addr, 0, NULL))
124+
*parent = return_hooker;
125+
}
126+
127+
static int ftrace_modify_graph_caller(bool enable)
128+
{
129+
u32 branch, nop;
130+
unsigned long pc, func;
131+
extern void ftrace_graph_call(void);
132+
133+
pc = (unsigned long)&ftrace_graph_call;
134+
func = (unsigned long)&ftrace_graph_caller;
135+
136+
nop = larch_insn_gen_nop();
137+
branch = larch_insn_gen_b(pc, func);
138+
139+
if (enable)
140+
return ftrace_modify_code(pc, nop, branch, true);
141+
else
142+
return ftrace_modify_code(pc, branch, nop, true);
143+
}
144+
145+
int ftrace_enable_ftrace_graph_caller(void)
146+
{
147+
return ftrace_modify_graph_caller(true);
148+
}
149+
150+
int ftrace_disable_ftrace_graph_caller(void)
151+
{
152+
return ftrace_modify_graph_caller(false);
153+
}
154+
#endif /* CONFIG_FUNCTION_GRAPH_TRACER */

arch/loongarch/kernel/inst.c

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,30 @@ u32 larch_insn_gen_nop(void)
5555
return INSN_NOP;
5656
}
5757

58+
u32 larch_insn_gen_b(unsigned long pc, unsigned long dest)
59+
{
60+
long offset = dest - pc;
61+
unsigned int immediate_l, immediate_h;
62+
union loongarch_instruction insn;
63+
64+
if ((offset & 3) || offset < -SZ_128M || offset >= SZ_128M) {
65+
pr_warn("The generated b instruction is out of range.\n");
66+
return INSN_BREAK;
67+
}
68+
69+
offset >>= 2;
70+
71+
immediate_l = offset & 0xffff;
72+
offset >>= 16;
73+
immediate_h = offset & 0x3ff;
74+
75+
insn.reg0i26_format.opcode = b_op;
76+
insn.reg0i26_format.immediate_l = immediate_l;
77+
insn.reg0i26_format.immediate_h = immediate_h;
78+
79+
return insn.word;
80+
}
81+
5882
u32 larch_insn_gen_bl(unsigned long pc, unsigned long dest)
5983
{
6084
long offset = dest - pc;

arch/loongarch/kernel/mcount_dyn.S

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,11 @@ SYM_CODE_START(ftrace_common)
5757

5858
SYM_INNER_LABEL(ftrace_call, SYM_L_GLOBAL)
5959
bl ftrace_stub
60+
#ifdef CONFIG_FUNCTION_GRAPH_TRACER
61+
SYM_INNER_LABEL(ftrace_graph_call, SYM_L_GLOBAL)
62+
nop /* b ftrace_graph_caller */
63+
#endif
64+
6065
/*
6166
* As we didn't use S series regs in this assmembly code and all calls
6267
* are C function which will save S series regs by themselves, there is
@@ -83,3 +88,31 @@ SYM_CODE_START(ftrace_caller)
8388
ftrace_regs_entry
8489
b ftrace_common
8590
SYM_CODE_END(ftrace_caller)
91+
92+
#ifdef CONFIG_FUNCTION_GRAPH_TRACER
93+
SYM_CODE_START(ftrace_graph_caller)
94+
PTR_L a0, sp, PT_ERA
95+
PTR_ADDI a0, a0, -8 /* arg0: self_addr */
96+
PTR_ADDI a1, sp, PT_R1 /* arg1: parent */
97+
bl prepare_ftrace_return
98+
b ftrace_common_return
99+
SYM_CODE_END(ftrace_graph_caller)
100+
101+
SYM_CODE_START(return_to_handler)
102+
/* Save return value regs */
103+
PTR_ADDI sp, sp, -2 * SZREG
104+
PTR_S a0, sp, 0
105+
PTR_S a1, sp, SZREG
106+
107+
move a0, zero
108+
bl ftrace_return_to_handler
109+
move ra, a0
110+
111+
/* Restore return value regs */
112+
PTR_L a0, sp, 0
113+
PTR_L a1, sp, SZREG
114+
PTR_ADDI sp, sp, 2 * SZREG
115+
116+
jr ra
117+
SYM_CODE_END(return_to_handler)
118+
#endif

0 commit comments

Comments
 (0)