]>
Commit | Line | Data |
---|---|---|
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> | |
5 | ||
6 | void my_direct_func1(void) | |
7 | { | |
8 | trace_printk("my direct func1\n"); | |
9 | } | |
10 | ||
11 | void my_direct_func2(void) | |
12 | { | |
13 | trace_printk("my direct func2\n"); | |
14 | } | |
15 | ||
16 | extern void my_tramp1(void *); | |
17 | extern void my_tramp2(void *); | |
18 | ||
19 | static unsigned long my_ip = (unsigned long)schedule; | |
20 | ||
21 | asm ( | |
22 | " .pushsection .text, \"ax\", @progbits\n" | |
9d907f1a | 23 | " .type my_tramp1, @function\n" |
ae0cc3b7 SRV |
24 | " my_tramp1:" |
25 | " pushq %rbp\n" | |
26 | " movq %rsp, %rbp\n" | |
27 | " call my_direct_func1\n" | |
28 | " leave\n" | |
9d907f1a | 29 | " .size my_tramp1, .-my_tramp1\n" |
ae0cc3b7 | 30 | " ret\n" |
9d907f1a | 31 | " .type my_tramp2, @function\n" |
ae0cc3b7 SRV |
32 | " my_tramp2:" |
33 | " pushq %rbp\n" | |
34 | " movq %rsp, %rbp\n" | |
35 | " call my_direct_func2\n" | |
36 | " leave\n" | |
37 | " ret\n" | |
9d907f1a | 38 | " .size my_tramp2, .-my_tramp2\n" |
ae0cc3b7 SRV |
39 | " .popsection\n" |
40 | ); | |
41 | ||
42 | static unsigned long my_tramp = (unsigned long)my_tramp1; | |
43 | static unsigned long tramps[2] = { | |
44 | (unsigned long)my_tramp1, | |
45 | (unsigned long)my_tramp2, | |
46 | }; | |
47 | ||
48 | static int simple_thread(void *arg) | |
49 | { | |
50 | static int t; | |
51 | int ret = 0; | |
52 | ||
53 | while (!kthread_should_stop()) { | |
54 | set_current_state(TASK_INTERRUPTIBLE); | |
55 | schedule_timeout(2 * HZ); | |
56 | ||
57 | if (ret) | |
58 | continue; | |
59 | t ^= 1; | |
60 | ret = modify_ftrace_direct(my_ip, my_tramp, tramps[t]); | |
61 | if (!ret) | |
62 | my_tramp = tramps[t]; | |
63 | WARN_ON_ONCE(ret); | |
64 | } | |
65 | ||
66 | return 0; | |
67 | } | |
68 | ||
69 | static struct task_struct *simple_tsk; | |
70 | ||
71 | static int __init ftrace_direct_init(void) | |
72 | { | |
73 | int ret; | |
74 | ||
75 | ret = register_ftrace_direct(my_ip, my_tramp); | |
76 | if (!ret) | |
77 | simple_tsk = kthread_run(simple_thread, NULL, "event-sample-fn"); | |
78 | return ret; | |
79 | } | |
80 | ||
81 | static void __exit ftrace_direct_exit(void) | |
82 | { | |
83 | kthread_stop(simple_tsk); | |
84 | unregister_ftrace_direct(my_ip, my_tramp); | |
85 | } | |
86 | ||
87 | module_init(ftrace_direct_init); | |
88 | module_exit(ftrace_direct_exit); | |
89 | ||
90 | MODULE_AUTHOR("Steven Rostedt"); | |
91 | MODULE_DESCRIPTION("Example use case of using modify_ftrace_direct()"); | |
92 | MODULE_LICENSE("GPL"); |