Skip to content

Commit 35e61e8

Browse files
Song Shuaipalmer-dabbelt
authored andcommitted
riscv: ftrace: Make function graph use ftrace directly
Similar to commit 0c0593b ("x86/ftrace: Make function graph use ftrace directly") and commit c4a0ebf ("arm64/ftrace: Make function graph use ftrace directly"), RISC-V has no need for a special graph tracer hook. The graph_ops::func function can be used to install the return_hooker. This cleanup only changes the FTRACE_WITH_REGS implementation, leaving the mcount-based implementation is unaffected. Perform the simplification, and also cleanup the register save/restore macros. Signed-off-by: Song Shuai <suagrfillet@gmail.com> Tested-by: Guo Ren <guoren@kernel.org> Signed-off-by: Guo Ren <guoren@kernel.org> Acked-by: Björn Töpel <bjorn@rivosinc.com> Link: https://lore.kernel.org/r/20231130121531.1178502-3-bjorn@kernel.org Signed-off-by: Palmer Dabbelt <palmer@rivosinc.com>
1 parent b546d63 commit 35e61e8

File tree

3 files changed

+175
-56
lines changed

3 files changed

+175
-56
lines changed

arch/riscv/include/asm/ftrace.h

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,16 @@ do { \
128128
struct dyn_ftrace;
129129
int ftrace_init_nop(struct module *mod, struct dyn_ftrace *rec);
130130
#define ftrace_init_nop ftrace_init_nop
131-
#endif
131+
132+
#ifdef CONFIG_DYNAMIC_FTRACE_WITH_REGS
133+
struct ftrace_ops;
134+
struct ftrace_regs;
135+
void ftrace_graph_func(unsigned long ip, unsigned long parent_ip,
136+
struct ftrace_ops *op, struct ftrace_regs *fregs);
137+
#define ftrace_graph_func ftrace_graph_func
138+
#endif /* CONFIG_DYNAMIC_FTRACE_WITH_REGS */
139+
140+
#endif /* __ASSEMBLY__ */
132141

133142
#endif /* CONFIG_DYNAMIC_FTRACE */
134143

arch/riscv/kernel/ftrace.c

Lines changed: 13 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -178,32 +178,28 @@ void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr,
178178
}
179179

180180
#ifdef CONFIG_DYNAMIC_FTRACE
181+
#ifdef CONFIG_DYNAMIC_FTRACE_WITH_REGS
182+
void ftrace_graph_func(unsigned long ip, unsigned long parent_ip,
183+
struct ftrace_ops *op, struct ftrace_regs *fregs)
184+
{
185+
struct pt_regs *regs = arch_ftrace_get_regs(fregs);
186+
unsigned long *parent = (unsigned long *)&regs->ra;
187+
188+
prepare_ftrace_return(parent, ip, frame_pointer(regs));
189+
}
190+
#else /* CONFIG_DYNAMIC_FTRACE_WITH_REGS */
181191
extern void ftrace_graph_call(void);
182-
extern void ftrace_graph_regs_call(void);
183192
int ftrace_enable_ftrace_graph_caller(void)
184193
{
185-
int ret;
186-
187-
ret = __ftrace_modify_call((unsigned long)&ftrace_graph_call,
188-
(unsigned long)&prepare_ftrace_return, true, true);
189-
if (ret)
190-
return ret;
191-
192-
return __ftrace_modify_call((unsigned long)&ftrace_graph_regs_call,
194+
return __ftrace_modify_call((unsigned long)&ftrace_graph_call,
193195
(unsigned long)&prepare_ftrace_return, true, true);
194196
}
195197

196198
int ftrace_disable_ftrace_graph_caller(void)
197199
{
198-
int ret;
199-
200-
ret = __ftrace_modify_call((unsigned long)&ftrace_graph_call,
201-
(unsigned long)&prepare_ftrace_return, false, true);
202-
if (ret)
203-
return ret;
204-
205-
return __ftrace_modify_call((unsigned long)&ftrace_graph_regs_call,
200+
return __ftrace_modify_call((unsigned long)&ftrace_graph_call,
206201
(unsigned long)&prepare_ftrace_return, false, true);
207202
}
203+
#endif /* CONFIG_DYNAMIC_FTRACE_WITH_REGS */
208204
#endif /* CONFIG_DYNAMIC_FTRACE */
209205
#endif /* CONFIG_FUNCTION_GRAPH_TRACER */

arch/riscv/kernel/mcount-dyn.S

Lines changed: 152 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -57,31 +57,150 @@
5757
.endm
5858

5959
#ifdef CONFIG_DYNAMIC_FTRACE_WITH_REGS
60-
.macro SAVE_ALL
60+
61+
/**
62+
* SAVE_ABI_REGS - save regs against the pt_regs struct
63+
*
64+
* @all: tell if saving all the regs
65+
*
66+
* If all is set, all the regs will be saved, otherwise only ABI
67+
* related regs (a0-a7,epc,ra and optional s0) will be saved.
68+
*
69+
* After the stack is established,
70+
*
71+
* 0(sp) stores the PC of the traced function which can be accessed
72+
* by &(fregs)->regs->epc in tracing function. Note that the real
73+
* function entry address should be computed with -FENTRY_RA_OFFSET.
74+
*
75+
* 8(sp) stores the function return address (i.e. parent IP) that
76+
* can be accessed by &(fregs)->regs->ra in tracing function.
77+
*
78+
* The other regs are saved at the respective localtion and accessed
79+
* by the respective pt_regs member.
80+
*
81+
* Here is the layout of stack for your reference.
82+
*
83+
* PT_SIZE_ON_STACK -> +++++++++
84+
* + ..... +
85+
* + t3-t6 +
86+
* + s2-s11+
87+
* + a0-a7 + --++++-> ftrace_caller saved
88+
* + s1 + +
89+
* + s0 + --+
90+
* + t0-t2 + +
91+
* + tp + +
92+
* + gp + +
93+
* + sp + +
94+
* + ra + --+ // parent IP
95+
* sp -> + epc + --+ // PC
96+
* +++++++++
97+
**/
98+
.macro SAVE_ABI_REGS, all=0
6199
addi sp, sp, -PT_SIZE_ON_STACK
62100

63-
REG_S t0, PT_EPC(sp)
64-
REG_S x1, PT_RA(sp)
65-
REG_S x2, PT_SP(sp)
66-
REG_S x3, PT_GP(sp)
67-
REG_S x4, PT_TP(sp)
68-
REG_S x5, PT_T0(sp)
69-
save_from_x6_to_x31
101+
REG_S t0, PT_EPC(sp)
102+
REG_S x1, PT_RA(sp)
103+
104+
// save the ABI regs
105+
106+
REG_S x10, PT_A0(sp)
107+
REG_S x11, PT_A1(sp)
108+
REG_S x12, PT_A2(sp)
109+
REG_S x13, PT_A3(sp)
110+
REG_S x14, PT_A4(sp)
111+
REG_S x15, PT_A5(sp)
112+
REG_S x16, PT_A6(sp)
113+
REG_S x17, PT_A7(sp)
114+
115+
// save the leftover regs
116+
117+
.if \all == 1
118+
REG_S x2, PT_SP(sp)
119+
REG_S x3, PT_GP(sp)
120+
REG_S x4, PT_TP(sp)
121+
REG_S x5, PT_T0(sp)
122+
REG_S x6, PT_T1(sp)
123+
REG_S x7, PT_T2(sp)
124+
REG_S x8, PT_S0(sp)
125+
REG_S x9, PT_S1(sp)
126+
REG_S x18, PT_S2(sp)
127+
REG_S x19, PT_S3(sp)
128+
REG_S x20, PT_S4(sp)
129+
REG_S x21, PT_S5(sp)
130+
REG_S x22, PT_S6(sp)
131+
REG_S x23, PT_S7(sp)
132+
REG_S x24, PT_S8(sp)
133+
REG_S x25, PT_S9(sp)
134+
REG_S x26, PT_S10(sp)
135+
REG_S x27, PT_S11(sp)
136+
REG_S x28, PT_T3(sp)
137+
REG_S x29, PT_T4(sp)
138+
REG_S x30, PT_T5(sp)
139+
REG_S x31, PT_T6(sp)
140+
141+
// save s0 if FP_TEST defined
142+
143+
.else
144+
#ifdef HAVE_FUNCTION_GRAPH_FP_TEST
145+
REG_S x8, PT_S0(sp)
146+
#endif
147+
.endif
70148
.endm
71149

72-
.macro RESTORE_ALL
73-
REG_L x1, PT_RA(sp)
74-
REG_L x2, PT_SP(sp)
75-
REG_L x3, PT_GP(sp)
76-
REG_L x4, PT_TP(sp)
77-
/* Restore t0 with PT_EPC */
78-
REG_L x5, PT_EPC(sp)
79-
restore_from_x6_to_x31
80-
150+
.macro RESTORE_ABI_REGS, all=0
151+
REG_L t0, PT_EPC(sp)
152+
REG_L x1, PT_RA(sp)
153+
REG_L x10, PT_A0(sp)
154+
REG_L x11, PT_A1(sp)
155+
REG_L x12, PT_A2(sp)
156+
REG_L x13, PT_A3(sp)
157+
REG_L x14, PT_A4(sp)
158+
REG_L x15, PT_A5(sp)
159+
REG_L x16, PT_A6(sp)
160+
REG_L x17, PT_A7(sp)
161+
162+
.if \all == 1
163+
REG_L x2, PT_SP(sp)
164+
REG_L x3, PT_GP(sp)
165+
REG_L x4, PT_TP(sp)
166+
REG_L x6, PT_T1(sp)
167+
REG_L x7, PT_T2(sp)
168+
REG_L x8, PT_S0(sp)
169+
REG_L x9, PT_S1(sp)
170+
REG_L x18, PT_S2(sp)
171+
REG_L x19, PT_S3(sp)
172+
REG_L x20, PT_S4(sp)
173+
REG_L x21, PT_S5(sp)
174+
REG_L x22, PT_S6(sp)
175+
REG_L x23, PT_S7(sp)
176+
REG_L x24, PT_S8(sp)
177+
REG_L x25, PT_S9(sp)
178+
REG_L x26, PT_S10(sp)
179+
REG_L x27, PT_S11(sp)
180+
REG_L x28, PT_T3(sp)
181+
REG_L x29, PT_T4(sp)
182+
REG_L x30, PT_T5(sp)
183+
REG_L x31, PT_T6(sp)
184+
185+
.else
186+
#ifdef HAVE_FUNCTION_GRAPH_FP_TEST
187+
REG_L x8, PT_S0(sp)
188+
#endif
189+
.endif
81190
addi sp, sp, PT_SIZE_ON_STACK
82191
.endm
192+
193+
.macro PREPARE_ARGS
194+
addi a0, t0, -FENTRY_RA_OFFSET
195+
la a1, function_trace_op
196+
REG_L a2, 0(a1)
197+
mv a1, ra
198+
mv a3, sp
199+
.endm
200+
83201
#endif /* CONFIG_DYNAMIC_FTRACE_WITH_REGS */
84202

203+
#ifndef CONFIG_DYNAMIC_FTRACE_WITH_REGS
85204
SYM_FUNC_START(ftrace_caller)
86205
SAVE_ABI
87206

@@ -105,34 +224,29 @@ SYM_INNER_LABEL(ftrace_graph_call, SYM_L_GLOBAL)
105224
call ftrace_stub
106225
#endif
107226
RESTORE_ABI
108-
jr t0
227+
jr t0
109228
SYM_FUNC_END(ftrace_caller)
110229

111-
#ifdef CONFIG_DYNAMIC_FTRACE_WITH_REGS
230+
#else /* CONFIG_DYNAMIC_FTRACE_WITH_REGS */
112231
SYM_FUNC_START(ftrace_regs_caller)
113-
SAVE_ALL
114-
115-
addi a0, t0, -FENTRY_RA_OFFSET
116-
la a1, function_trace_op
117-
REG_L a2, 0(a1)
118-
mv a1, ra
119-
mv a3, sp
232+
SAVE_ABI_REGS 1
233+
PREPARE_ARGS
120234

121235
SYM_INNER_LABEL(ftrace_regs_call, SYM_L_GLOBAL)
122236
call ftrace_stub
123237

124-
#ifdef CONFIG_FUNCTION_GRAPH_TRACER
125-
addi a0, sp, PT_RA
126-
REG_L a1, PT_EPC(sp)
127-
addi a1, a1, -FENTRY_RA_OFFSET
128-
#ifdef HAVE_FUNCTION_GRAPH_FP_TEST
129-
mv a2, s0
130-
#endif
131-
SYM_INNER_LABEL(ftrace_graph_regs_call, SYM_L_GLOBAL)
238+
RESTORE_ABI_REGS 1
239+
jr t0
240+
SYM_FUNC_END(ftrace_regs_caller)
241+
242+
SYM_FUNC_START(ftrace_caller)
243+
SAVE_ABI_REGS 0
244+
PREPARE_ARGS
245+
246+
SYM_INNER_LABEL(ftrace_call, SYM_L_GLOBAL)
132247
call ftrace_stub
133-
#endif
134248

135-
RESTORE_ALL
136-
jr t0
137-
SYM_FUNC_END(ftrace_regs_caller)
249+
RESTORE_ABI_REGS 0
250+
jr t0
251+
SYM_FUNC_END(ftrace_caller)
138252
#endif /* CONFIG_DYNAMIC_FTRACE_WITH_REGS */

0 commit comments

Comments
 (0)