Skip to content

Commit 3074e8b

Browse files
Merge patch series "riscv: ftrace: Miscellaneous ftrace improvements"
Björn Töpel <bjorn@kernel.org> says: This series includes a three ftrace improvements for RISC-V: 1. Do not require to run recordmcount at build time (patch 1) 2. Simplification of the function graph functionality (patch 2) 3. Enable DYNAMIC_FTRACE_WITH_DIRECT_CALLS (patch 3 and 4) The series has been tested on Qemu/rv64 virt/Debian sid with the following test configs: CONFIG_FTRACE_SELFTEST=y CONFIG_FTRACE_STARTUP_TEST=y CONFIG_SAMPLE_FTRACE_DIRECT=m CONFIG_SAMPLE_FTRACE_DIRECT_MULTI=m CONFIG_SAMPLE_FTRACE_OPS=m All tests pass. * b4-shazam-merge: samples: ftrace: Add RISC-V support for SAMPLE_FTRACE_DIRECT[_MULTI] riscv: ftrace: Add DYNAMIC_FTRACE_WITH_DIRECT_CALLS support riscv: ftrace: Make function graph use ftrace directly riscv: select FTRACE_MCOUNT_USE_PATCHABLE_FUNCTION_ENTRY Link: https://lore.kernel.org/r/20231130121531.1178502-1-bjorn@kernel.org Signed-off-by: Palmer Dabbelt <palmer@rivosinc.com>
2 parents 448857e + 629291d commit 3074e8b

File tree

9 files changed

+348
-55
lines changed

9 files changed

+348
-55
lines changed

arch/riscv/Kconfig

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ config RISCV
7070
select CPU_PM if CPU_IDLE || HIBERNATION || SUSPEND
7171
select EDAC_SUPPORT
7272
select FRAME_POINTER if PERF_EVENTS || (FUNCTION_TRACER && !DYNAMIC_FTRACE)
73+
select FTRACE_MCOUNT_USE_PATCHABLE_FUNCTION_ENTRY if DYNAMIC_FTRACE
7374
select GENERIC_ARCH_TOPOLOGY
7475
select GENERIC_ATOMIC64 if !64BIT
7576
select GENERIC_CLOCKEVENTS_BROADCAST if SMP
@@ -115,6 +116,7 @@ config RISCV
115116
select HAVE_DEBUG_KMEMLEAK
116117
select HAVE_DMA_CONTIGUOUS if MMU
117118
select HAVE_DYNAMIC_FTRACE if !XIP_KERNEL && MMU && (CLANG_SUPPORTS_DYNAMIC_FTRACE || GCC_SUPPORTS_DYNAMIC_FTRACE)
119+
select HAVE_DYNAMIC_FTRACE_WITH_DIRECT_CALLS
118120
select HAVE_DYNAMIC_FTRACE_WITH_REGS if HAVE_DYNAMIC_FTRACE
119121
select HAVE_FTRACE_MCOUNT_RECORD if !XIP_KERNEL
120122
select HAVE_FUNCTION_GRAPH_TRACER
@@ -142,6 +144,8 @@ config RISCV
142144
select HAVE_REGS_AND_STACK_ACCESS_API
143145
select HAVE_RETHOOK if !XIP_KERNEL
144146
select HAVE_RSEQ
147+
select HAVE_SAMPLE_FTRACE_DIRECT
148+
select HAVE_SAMPLE_FTRACE_DIRECT_MULTI
145149
select HAVE_STACKPROTECTOR
146150
select HAVE_SYSCALL_TRACEPOINTS
147151
select HOTPLUG_CORE_SYNC_DEAD if HOTPLUG_CPU

arch/riscv/include/asm/ftrace.h

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,23 @@ 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+
139+
static inline void __arch_ftrace_set_direct_caller(struct pt_regs *regs, unsigned long addr)
140+
{
141+
regs->t1 = addr;
142+
}
143+
#define arch_ftrace_set_direct_caller(fregs, addr) \
144+
__arch_ftrace_set_direct_caller(&(fregs)->regs, addr)
145+
#endif /* CONFIG_DYNAMIC_FTRACE_WITH_REGS */
146+
147+
#endif /* __ASSEMBLY__ */
132148

133149
#endif /* CONFIG_DYNAMIC_FTRACE */
134150

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: 161 additions & 37 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
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)
80161

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,39 @@ 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+
mv t1, zero
233+
SAVE_ABI_REGS 1
234+
PREPARE_ARGS
120235

121236
SYM_INNER_LABEL(ftrace_regs_call, SYM_L_GLOBAL)
122237
call ftrace_stub
123238

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)
239+
RESTORE_ABI_REGS 1
240+
bnez t1, .Ldirect
241+
jr t0
242+
.Ldirect:
243+
jr t1
244+
SYM_FUNC_END(ftrace_regs_caller)
245+
246+
SYM_FUNC_START(ftrace_caller)
247+
SAVE_ABI_REGS 0
248+
PREPARE_ARGS
249+
250+
SYM_INNER_LABEL(ftrace_call, SYM_L_GLOBAL)
132251
call ftrace_stub
133-
#endif
134252

135-
RESTORE_ALL
136-
jr t0
137-
SYM_FUNC_END(ftrace_regs_caller)
253+
RESTORE_ABI_REGS 0
254+
jr t0
255+
SYM_FUNC_END(ftrace_caller)
138256
#endif /* CONFIG_DYNAMIC_FTRACE_WITH_REGS */
257+
258+
#ifdef CONFIG_DYNAMIC_FTRACE_WITH_DIRECT_CALLS
259+
SYM_CODE_START(ftrace_stub_direct_tramp)
260+
jr t0
261+
SYM_CODE_END(ftrace_stub_direct_tramp)
262+
#endif /* CONFIG_DYNAMIC_FTRACE_WITH_DIRECT_CALLS */

samples/ftrace/ftrace-direct-modify.c

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,41 @@ extern void my_tramp2(void *);
2424

2525
static unsigned long my_ip = (unsigned long)schedule;
2626

27+
#ifdef CONFIG_RISCV
28+
#include <asm/asm.h>
29+
30+
asm (
31+
" .pushsection .text, \"ax\", @progbits\n"
32+
" .type my_tramp1, @function\n"
33+
" .globl my_tramp1\n"
34+
" my_tramp1:\n"
35+
" addi sp,sp,-2*"SZREG"\n"
36+
" "REG_S" t0,0*"SZREG"(sp)\n"
37+
" "REG_S" ra,1*"SZREG"(sp)\n"
38+
" call my_direct_func1\n"
39+
" "REG_L" t0,0*"SZREG"(sp)\n"
40+
" "REG_L" ra,1*"SZREG"(sp)\n"
41+
" addi sp,sp,2*"SZREG"\n"
42+
" jr t0\n"
43+
" .size my_tramp1, .-my_tramp1\n"
44+
" .type my_tramp2, @function\n"
45+
" .globl my_tramp2\n"
46+
47+
" my_tramp2:\n"
48+
" addi sp,sp,-2*"SZREG"\n"
49+
" "REG_S" t0,0*"SZREG"(sp)\n"
50+
" "REG_S" ra,1*"SZREG"(sp)\n"
51+
" call my_direct_func2\n"
52+
" "REG_L" t0,0*"SZREG"(sp)\n"
53+
" "REG_L" ra,1*"SZREG"(sp)\n"
54+
" addi sp,sp,2*"SZREG"\n"
55+
" jr t0\n"
56+
" .size my_tramp2, .-my_tramp2\n"
57+
" .popsection\n"
58+
);
59+
60+
#endif /* CONFIG_RISCV */
61+
2762
#ifdef CONFIG_X86_64
2863

2964
#include <asm/ibt.h>

0 commit comments

Comments
 (0)