Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/samples/ftrace/ftrace-direct-modify.c
26295 views
1
// SPDX-License-Identifier: GPL-2.0-only
2
#include <linux/module.h>
3
#include <linux/kthread.h>
4
#include <linux/ftrace.h>
5
#if !defined(CONFIG_ARM64) && !defined(CONFIG_PPC32)
6
#include <asm/asm-offsets.h>
7
#endif
8
9
extern void my_direct_func1(void);
10
extern void my_direct_func2(void);
11
12
void my_direct_func1(void)
13
{
14
trace_printk("my direct func1\n");
15
}
16
17
void my_direct_func2(void)
18
{
19
trace_printk("my direct func2\n");
20
}
21
22
extern void my_tramp1(void *);
23
extern void my_tramp2(void *);
24
25
static unsigned long my_ip = (unsigned long)schedule;
26
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
62
#ifdef CONFIG_X86_64
63
64
#include <asm/ibt.h>
65
#include <asm/nospec-branch.h>
66
67
asm (
68
" .pushsection .text, \"ax\", @progbits\n"
69
" .type my_tramp1, @function\n"
70
" .globl my_tramp1\n"
71
" my_tramp1:"
72
ASM_ENDBR
73
" pushq %rbp\n"
74
" movq %rsp, %rbp\n"
75
CALL_DEPTH_ACCOUNT
76
" call my_direct_func1\n"
77
" leave\n"
78
" .size my_tramp1, .-my_tramp1\n"
79
ASM_RET
80
81
" .type my_tramp2, @function\n"
82
" .globl my_tramp2\n"
83
" my_tramp2:"
84
ASM_ENDBR
85
" pushq %rbp\n"
86
" movq %rsp, %rbp\n"
87
CALL_DEPTH_ACCOUNT
88
" call my_direct_func2\n"
89
" leave\n"
90
ASM_RET
91
" .size my_tramp2, .-my_tramp2\n"
92
" .popsection\n"
93
);
94
95
#endif /* CONFIG_X86_64 */
96
97
#ifdef CONFIG_S390
98
99
asm (
100
" .pushsection .text, \"ax\", @progbits\n"
101
" .type my_tramp1, @function\n"
102
" .globl my_tramp1\n"
103
" my_tramp1:"
104
" lgr %r1,%r15\n"
105
" stmg %r0,%r5,"__stringify(__SF_GPRS)"(%r15)\n"
106
" stg %r14,"__stringify(__SF_GPRS+8*8)"(%r15)\n"
107
" aghi %r15,"__stringify(-STACK_FRAME_OVERHEAD)"\n"
108
" stg %r1,"__stringify(__SF_BACKCHAIN)"(%r15)\n"
109
" brasl %r14,my_direct_func1\n"
110
" aghi %r15,"__stringify(STACK_FRAME_OVERHEAD)"\n"
111
" lmg %r0,%r5,"__stringify(__SF_GPRS)"(%r15)\n"
112
" lg %r14,"__stringify(__SF_GPRS+8*8)"(%r15)\n"
113
" lgr %r1,%r0\n"
114
" br %r1\n"
115
" .size my_tramp1, .-my_tramp1\n"
116
" .type my_tramp2, @function\n"
117
" .globl my_tramp2\n"
118
" my_tramp2:"
119
" lgr %r1,%r15\n"
120
" stmg %r0,%r5,"__stringify(__SF_GPRS)"(%r15)\n"
121
" stg %r14,"__stringify(__SF_GPRS+8*8)"(%r15)\n"
122
" aghi %r15,"__stringify(-STACK_FRAME_OVERHEAD)"\n"
123
" stg %r1,"__stringify(__SF_BACKCHAIN)"(%r15)\n"
124
" brasl %r14,my_direct_func2\n"
125
" aghi %r15,"__stringify(STACK_FRAME_OVERHEAD)"\n"
126
" lmg %r0,%r5,"__stringify(__SF_GPRS)"(%r15)\n"
127
" lg %r14,"__stringify(__SF_GPRS+8*8)"(%r15)\n"
128
" lgr %r1,%r0\n"
129
" br %r1\n"
130
" .size my_tramp2, .-my_tramp2\n"
131
" .popsection\n"
132
);
133
134
#endif /* CONFIG_S390 */
135
136
#ifdef CONFIG_ARM64
137
138
asm (
139
" .pushsection .text, \"ax\", @progbits\n"
140
" .type my_tramp1, @function\n"
141
" .globl my_tramp1\n"
142
" my_tramp1:"
143
" hint 34\n" // bti c
144
" sub sp, sp, #16\n"
145
" stp x9, x30, [sp]\n"
146
" bl my_direct_func1\n"
147
" ldp x30, x9, [sp]\n"
148
" add sp, sp, #16\n"
149
" ret x9\n"
150
" .size my_tramp1, .-my_tramp1\n"
151
152
" .type my_tramp2, @function\n"
153
" .globl my_tramp2\n"
154
" my_tramp2:"
155
" hint 34\n" // bti c
156
" sub sp, sp, #16\n"
157
" stp x9, x30, [sp]\n"
158
" bl my_direct_func2\n"
159
" ldp x30, x9, [sp]\n"
160
" add sp, sp, #16\n"
161
" ret x9\n"
162
" .size my_tramp2, .-my_tramp2\n"
163
" .popsection\n"
164
);
165
166
#endif /* CONFIG_ARM64 */
167
168
#ifdef CONFIG_LOONGARCH
169
170
asm (
171
" .pushsection .text, \"ax\", @progbits\n"
172
" .type my_tramp1, @function\n"
173
" .globl my_tramp1\n"
174
" my_tramp1:\n"
175
" addi.d $sp, $sp, -16\n"
176
" st.d $t0, $sp, 0\n"
177
" st.d $ra, $sp, 8\n"
178
" bl my_direct_func1\n"
179
" ld.d $t0, $sp, 0\n"
180
" ld.d $ra, $sp, 8\n"
181
" addi.d $sp, $sp, 16\n"
182
" jr $t0\n"
183
" .size my_tramp1, .-my_tramp1\n"
184
185
" .type my_tramp2, @function\n"
186
" .globl my_tramp2\n"
187
" my_tramp2:\n"
188
" addi.d $sp, $sp, -16\n"
189
" st.d $t0, $sp, 0\n"
190
" st.d $ra, $sp, 8\n"
191
" bl my_direct_func2\n"
192
" ld.d $t0, $sp, 0\n"
193
" ld.d $ra, $sp, 8\n"
194
" addi.d $sp, $sp, 16\n"
195
" jr $t0\n"
196
" .size my_tramp2, .-my_tramp2\n"
197
" .popsection\n"
198
);
199
200
#endif /* CONFIG_LOONGARCH */
201
202
#ifdef CONFIG_PPC
203
#include <asm/ppc_asm.h>
204
205
#ifdef CONFIG_PPC64
206
#define STACK_FRAME_SIZE 48
207
#else
208
#define STACK_FRAME_SIZE 24
209
#endif
210
211
#if defined(CONFIG_PPC64_ELF_ABI_V2) && !defined(CONFIG_PPC_KERNEL_PCREL)
212
#define PPC64_TOC_SAVE_AND_UPDATE \
213
" std 2, 24(1)\n" \
214
" bcl 20, 31, 1f\n" \
215
" 1: mflr 12\n" \
216
" ld 2, (99f - 1b)(12)\n"
217
#define PPC64_TOC_RESTORE \
218
" ld 2, 24(1)\n"
219
#define PPC64_TOC \
220
" 99: .quad .TOC.@tocbase\n"
221
#else
222
#define PPC64_TOC_SAVE_AND_UPDATE ""
223
#define PPC64_TOC_RESTORE ""
224
#define PPC64_TOC ""
225
#endif
226
227
#ifdef CONFIG_PPC_FTRACE_OUT_OF_LINE
228
#define PPC_FTRACE_RESTORE_LR \
229
PPC_LL" 0, "__stringify(PPC_LR_STKOFF)"(1)\n" \
230
" mtlr 0\n"
231
#define PPC_FTRACE_RET \
232
" blr\n"
233
#else
234
#define PPC_FTRACE_RESTORE_LR \
235
PPC_LL" 0, "__stringify(PPC_LR_STKOFF)"(1)\n" \
236
" mtctr 0\n"
237
#define PPC_FTRACE_RET \
238
" mtlr 0\n" \
239
" bctr\n"
240
#endif
241
242
asm (
243
" .pushsection .text, \"ax\", @progbits\n"
244
" .type my_tramp1, @function\n"
245
" .globl my_tramp1\n"
246
" my_tramp1:\n"
247
PPC_STL" 0, "__stringify(PPC_LR_STKOFF)"(1)\n"
248
PPC_STLU" 1, -"__stringify(STACK_FRAME_MIN_SIZE)"(1)\n"
249
" mflr 0\n"
250
PPC_STL" 0, "__stringify(PPC_LR_STKOFF)"(1)\n"
251
PPC_STLU" 1, -"__stringify(STACK_FRAME_SIZE)"(1)\n"
252
PPC64_TOC_SAVE_AND_UPDATE
253
" bl my_direct_func1\n"
254
PPC64_TOC_RESTORE
255
" addi 1, 1, "__stringify(STACK_FRAME_SIZE)"\n"
256
PPC_FTRACE_RESTORE_LR
257
" addi 1, 1, "__stringify(STACK_FRAME_MIN_SIZE)"\n"
258
PPC_LL" 0, "__stringify(PPC_LR_STKOFF)"(1)\n"
259
PPC_FTRACE_RET
260
" .size my_tramp1, .-my_tramp1\n"
261
262
" .type my_tramp2, @function\n"
263
" .globl my_tramp2\n"
264
" my_tramp2:\n"
265
PPC_STL" 0, "__stringify(PPC_LR_STKOFF)"(1)\n"
266
PPC_STLU" 1, -"__stringify(STACK_FRAME_MIN_SIZE)"(1)\n"
267
" mflr 0\n"
268
PPC_STL" 0, "__stringify(PPC_LR_STKOFF)"(1)\n"
269
PPC_STLU" 1, -"__stringify(STACK_FRAME_SIZE)"(1)\n"
270
PPC64_TOC_SAVE_AND_UPDATE
271
" bl my_direct_func2\n"
272
PPC64_TOC_RESTORE
273
" addi 1, 1, "__stringify(STACK_FRAME_SIZE)"\n"
274
PPC_FTRACE_RESTORE_LR
275
" addi 1, 1, "__stringify(STACK_FRAME_MIN_SIZE)"\n"
276
PPC_LL" 0, "__stringify(PPC_LR_STKOFF)"(1)\n"
277
PPC_FTRACE_RET
278
PPC64_TOC
279
" .size my_tramp2, .-my_tramp2\n"
280
" .popsection\n"
281
);
282
283
#endif /* CONFIG_PPC */
284
285
static struct ftrace_ops direct;
286
287
static unsigned long my_tramp = (unsigned long)my_tramp1;
288
static unsigned long tramps[2] = {
289
(unsigned long)my_tramp1,
290
(unsigned long)my_tramp2,
291
};
292
293
static int simple_thread(void *arg)
294
{
295
static int t;
296
int ret = 0;
297
298
while (!kthread_should_stop()) {
299
set_current_state(TASK_INTERRUPTIBLE);
300
schedule_timeout(2 * HZ);
301
302
if (ret)
303
continue;
304
t ^= 1;
305
ret = modify_ftrace_direct(&direct, tramps[t]);
306
if (!ret)
307
my_tramp = tramps[t];
308
WARN_ON_ONCE(ret);
309
}
310
311
return 0;
312
}
313
314
static struct task_struct *simple_tsk;
315
316
static int __init ftrace_direct_init(void)
317
{
318
int ret;
319
320
ftrace_set_filter_ip(&direct, (unsigned long) my_ip, 0, 0);
321
ret = register_ftrace_direct(&direct, my_tramp);
322
323
if (!ret)
324
simple_tsk = kthread_run(simple_thread, NULL, "event-sample-fn");
325
return ret;
326
}
327
328
static void __exit ftrace_direct_exit(void)
329
{
330
kthread_stop(simple_tsk);
331
unregister_ftrace_direct(&direct, my_tramp, true);
332
}
333
334
module_init(ftrace_direct_init);
335
module_exit(ftrace_direct_exit);
336
337
MODULE_AUTHOR("Steven Rostedt");
338
MODULE_DESCRIPTION("Example use case of using modify_ftrace_direct()");
339
MODULE_LICENSE("GPL");
340
341