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" 23 " my_tramp1:" 24 " pushq %rbp\n" 25 " movq %rsp, %rbp\n" 26 " call my_direct_func1\n" 27 " leave\n" 28 " ret\n" 29 " my_tramp2:" 30 " pushq %rbp\n" 31 " movq %rsp, %rbp\n" 32 " call my_direct_func2\n" 33 " leave\n" 34 " ret\n" 35 " .popsection\n" 36 ); 37 38 static unsigned long my_tramp = (unsigned long)my_tramp1; 39 static unsigned long tramps[2] = { 40 (unsigned long)my_tramp1, 41 (unsigned long)my_tramp2, 42 }; 43 44 static int simple_thread(void *arg) 45 { 46 static int t; 47 int ret = 0; 48 49 while (!kthread_should_stop()) { 50 set_current_state(TASK_INTERRUPTIBLE); 51 schedule_timeout(2 * HZ); 52 53 if (ret) 54 continue; 55 t ^= 1; 56 ret = modify_ftrace_direct(my_ip, my_tramp, tramps[t]); 57 if (!ret) 58 my_tramp = tramps[t]; 59 WARN_ON_ONCE(ret); 60 } 61 62 return 0; 63 } 64 65 static struct task_struct *simple_tsk; 66 67 static int __init ftrace_direct_init(void) 68 { 69 int ret; 70 71 ret = register_ftrace_direct(my_ip, my_tramp); 72 if (!ret) 73 simple_tsk = kthread_run(simple_thread, NULL, "event-sample-fn"); 74 return ret; 75 } 76 77 static void __exit ftrace_direct_exit(void) 78 { 79 kthread_stop(simple_tsk); 80 unregister_ftrace_direct(my_ip, my_tramp); 81 } 82 83 module_init(ftrace_direct_init); 84 module_exit(ftrace_direct_exit); 85 86 MODULE_AUTHOR("Steven Rostedt"); 87 MODULE_DESCRIPTION("Example use case of using modify_ftrace_direct()"); 88 MODULE_LICENSE("GPL"); 89