Merge tag 'hardening-v6.5-rc1-fixes' of git://git.kernel.org/pub/scm/linux/kernel...
[linux-2.6-block.git] / samples / ftrace / ftrace-direct-modify.c
CommitLineData
ae0cc3b7
SRV
1// SPDX-License-Identifier: GPL-2.0-only
2#include <linux/module.h>
3#include <linux/kthread.h>
4#include <linux/ftrace.h>
1254cfbc 5#include <asm/asm-offsets.h>
ae0cc3b7 6
0daf5cb2
JO
7extern void my_direct_func1(void);
8extern void my_direct_func2(void);
9
ae0cc3b7
SRV
10void my_direct_func1(void)
11{
12 trace_printk("my direct func1\n");
13}
14
15void my_direct_func2(void)
16{
17 trace_printk("my direct func2\n");
18}
19
20extern void my_tramp1(void *);
21extern void my_tramp2(void *);
22
23static unsigned long my_ip = (unsigned long)schedule;
24
1254cfbc
HC
25#ifdef CONFIG_X86_64
26
0aec21cf 27#include <asm/ibt.h>
01678fbc 28#include <asm/nospec-branch.h>
0aec21cf 29
ae0cc3b7
SRV
30asm (
31" .pushsection .text, \"ax\", @progbits\n"
9d907f1a 32" .type my_tramp1, @function\n"
983df5f2 33" .globl my_tramp1\n"
ae0cc3b7 34" my_tramp1:"
0aec21cf 35 ASM_ENDBR
ae0cc3b7
SRV
36" pushq %rbp\n"
37" movq %rsp, %rbp\n"
ee3e2469 38 CALL_DEPTH_ACCOUNT
ae0cc3b7
SRV
39" call my_direct_func1\n"
40" leave\n"
9d907f1a 41" .size my_tramp1, .-my_tramp1\n"
b17c2baa 42 ASM_RET
0aec21cf 43
9d907f1a 44" .type my_tramp2, @function\n"
983df5f2 45" .globl my_tramp2\n"
ae0cc3b7 46" my_tramp2:"
0aec21cf 47 ASM_ENDBR
ae0cc3b7
SRV
48" pushq %rbp\n"
49" movq %rsp, %rbp\n"
ee3e2469 50 CALL_DEPTH_ACCOUNT
ae0cc3b7
SRV
51" call my_direct_func2\n"
52" leave\n"
b17c2baa 53 ASM_RET
9d907f1a 54" .size my_tramp2, .-my_tramp2\n"
ae0cc3b7
SRV
55" .popsection\n"
56);
57
1254cfbc
HC
58#endif /* CONFIG_X86_64 */
59
60#ifdef CONFIG_S390
61
62asm (
63" .pushsection .text, \"ax\", @progbits\n"
64" .type my_tramp1, @function\n"
65" .globl my_tramp1\n"
66" my_tramp1:"
67" lgr %r1,%r15\n"
68" stmg %r0,%r5,"__stringify(__SF_GPRS)"(%r15)\n"
69" stg %r14,"__stringify(__SF_GPRS+8*8)"(%r15)\n"
70" aghi %r15,"__stringify(-STACK_FRAME_OVERHEAD)"\n"
71" stg %r1,"__stringify(__SF_BACKCHAIN)"(%r15)\n"
72" brasl %r14,my_direct_func1\n"
73" aghi %r15,"__stringify(STACK_FRAME_OVERHEAD)"\n"
74" lmg %r0,%r5,"__stringify(__SF_GPRS)"(%r15)\n"
75" lg %r14,"__stringify(__SF_GPRS+8*8)"(%r15)\n"
76" lgr %r1,%r0\n"
77" br %r1\n"
78" .size my_tramp1, .-my_tramp1\n"
79" .type my_tramp2, @function\n"
80" .globl my_tramp2\n"
81" my_tramp2:"
82" lgr %r1,%r15\n"
83" stmg %r0,%r5,"__stringify(__SF_GPRS)"(%r15)\n"
84" stg %r14,"__stringify(__SF_GPRS+8*8)"(%r15)\n"
85" aghi %r15,"__stringify(-STACK_FRAME_OVERHEAD)"\n"
86" stg %r1,"__stringify(__SF_BACKCHAIN)"(%r15)\n"
87" brasl %r14,my_direct_func2\n"
88" aghi %r15,"__stringify(STACK_FRAME_OVERHEAD)"\n"
89" lmg %r0,%r5,"__stringify(__SF_GPRS)"(%r15)\n"
90" lg %r14,"__stringify(__SF_GPRS+8*8)"(%r15)\n"
91" lgr %r1,%r0\n"
92" br %r1\n"
93" .size my_tramp2, .-my_tramp2\n"
94" .popsection\n"
95);
96
97#endif /* CONFIG_S390 */
98
22f367a6
YT
99#ifdef CONFIG_LOONGARCH
100
101asm (
102" .pushsection .text, \"ax\", @progbits\n"
103" .type my_tramp1, @function\n"
104" .globl my_tramp1\n"
105" my_tramp1:\n"
106" addi.d $sp, $sp, -16\n"
107" st.d $t0, $sp, 0\n"
108" st.d $ra, $sp, 8\n"
109" bl my_direct_func1\n"
110" ld.d $t0, $sp, 0\n"
111" ld.d $ra, $sp, 8\n"
112" addi.d $sp, $sp, 16\n"
113" jr $t0\n"
114" .size my_tramp1, .-my_tramp1\n"
115
116" .type my_tramp2, @function\n"
117" .globl my_tramp2\n"
118" my_tramp2:\n"
119" addi.d $sp, $sp, -16\n"
120" st.d $t0, $sp, 0\n"
121" st.d $ra, $sp, 8\n"
122" bl my_direct_func2\n"
123" ld.d $t0, $sp, 0\n"
124" ld.d $ra, $sp, 8\n"
125" addi.d $sp, $sp, 16\n"
126" jr $t0\n"
127" .size my_tramp2, .-my_tramp2\n"
128" .popsection\n"
129);
130
131#endif /* CONFIG_LOONGARCH */
132
23edf483
FR
133static struct ftrace_ops direct;
134
ae0cc3b7
SRV
135static unsigned long my_tramp = (unsigned long)my_tramp1;
136static unsigned long tramps[2] = {
137 (unsigned long)my_tramp1,
138 (unsigned long)my_tramp2,
139};
140
141static int simple_thread(void *arg)
142{
143 static int t;
144 int ret = 0;
145
146 while (!kthread_should_stop()) {
147 set_current_state(TASK_INTERRUPTIBLE);
148 schedule_timeout(2 * HZ);
149
150 if (ret)
151 continue;
152 t ^= 1;
da8bdfbd 153 ret = modify_ftrace_direct(&direct, tramps[t]);
ae0cc3b7
SRV
154 if (!ret)
155 my_tramp = tramps[t];
156 WARN_ON_ONCE(ret);
157 }
158
159 return 0;
160}
161
162static struct task_struct *simple_tsk;
163
164static int __init ftrace_direct_init(void)
165{
166 int ret;
167
23edf483 168 ftrace_set_filter_ip(&direct, (unsigned long) my_ip, 0, 0);
da8bdfbd 169 ret = register_ftrace_direct(&direct, my_tramp);
23edf483 170
ae0cc3b7
SRV
171 if (!ret)
172 simple_tsk = kthread_run(simple_thread, NULL, "event-sample-fn");
173 return ret;
174}
175
176static void __exit ftrace_direct_exit(void)
177{
178 kthread_stop(simple_tsk);
da8bdfbd 179 unregister_ftrace_direct(&direct, my_tramp, true);
ae0cc3b7
SRV
180}
181
182module_init(ftrace_direct_init);
183module_exit(ftrace_direct_exit);
184
185MODULE_AUTHOR("Steven Rostedt");
da8bdfbd 186MODULE_DESCRIPTION("Example use case of using modify_ftrace_direct()");
ae0cc3b7 187MODULE_LICENSE("GPL");