Loading...
Note: File does not exist in v3.5.6.
1// SPDX-License-Identifier: GPL-2.0-only
2#include <linux/module.h>
3#include <linux/kthread.h>
4#include <linux/ftrace.h>
5#include <asm/asm-offsets.h>
6#include <asm/nospec-branch.h>
7
8extern void my_direct_func1(void);
9extern void my_direct_func2(void);
10
11void my_direct_func1(void)
12{
13 trace_printk("my direct func1\n");
14}
15
16void my_direct_func2(void)
17{
18 trace_printk("my direct func2\n");
19}
20
21extern void my_tramp1(void *);
22extern void my_tramp2(void *);
23
24static unsigned long my_ip = (unsigned long)schedule;
25
26#ifdef CONFIG_X86_64
27
28#include <asm/ibt.h>
29
30asm (
31" .pushsection .text, \"ax\", @progbits\n"
32" .type my_tramp1, @function\n"
33" .globl my_tramp1\n"
34" my_tramp1:"
35 ASM_ENDBR
36" pushq %rbp\n"
37" movq %rsp, %rbp\n"
38 CALL_DEPTH_ACCOUNT
39" call my_direct_func1\n"
40" leave\n"
41" .size my_tramp1, .-my_tramp1\n"
42 ASM_RET
43
44" .type my_tramp2, @function\n"
45" .globl my_tramp2\n"
46" my_tramp2:"
47 ASM_ENDBR
48" pushq %rbp\n"
49" movq %rsp, %rbp\n"
50 CALL_DEPTH_ACCOUNT
51" call my_direct_func2\n"
52" leave\n"
53 ASM_RET
54" .size my_tramp2, .-my_tramp2\n"
55" .popsection\n"
56);
57
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
99static unsigned long my_tramp = (unsigned long)my_tramp1;
100static unsigned long tramps[2] = {
101 (unsigned long)my_tramp1,
102 (unsigned long)my_tramp2,
103};
104
105static int simple_thread(void *arg)
106{
107 static int t;
108 int ret = 0;
109
110 while (!kthread_should_stop()) {
111 set_current_state(TASK_INTERRUPTIBLE);
112 schedule_timeout(2 * HZ);
113
114 if (ret)
115 continue;
116 t ^= 1;
117 ret = modify_ftrace_direct(my_ip, my_tramp, tramps[t]);
118 if (!ret)
119 my_tramp = tramps[t];
120 WARN_ON_ONCE(ret);
121 }
122
123 return 0;
124}
125
126static struct task_struct *simple_tsk;
127
128static int __init ftrace_direct_init(void)
129{
130 int ret;
131
132 ret = register_ftrace_direct(my_ip, my_tramp);
133 if (!ret)
134 simple_tsk = kthread_run(simple_thread, NULL, "event-sample-fn");
135 return ret;
136}
137
138static void __exit ftrace_direct_exit(void)
139{
140 kthread_stop(simple_tsk);
141 unregister_ftrace_direct(my_ip, my_tramp);
142}
143
144module_init(ftrace_direct_init);
145module_exit(ftrace_direct_exit);
146
147MODULE_AUTHOR("Steven Rostedt");
148MODULE_DESCRIPTION("Example use case of using modify_ftrace_direct()");
149MODULE_LICENSE("GPL");