diff options
Diffstat (limited to 'samples/ftrace')
-rw-r--r-- | samples/ftrace/Makefile | 1 | ||||
-rw-r--r-- | samples/ftrace/ftrace-direct-modify.c | 88 |
2 files changed, 89 insertions, 0 deletions
diff --git a/samples/ftrace/Makefile b/samples/ftrace/Makefile index d8217c4e072e..fb0c3ae18295 100644 --- a/samples/ftrace/Makefile +++ b/samples/ftrace/Makefile @@ -2,3 +2,4 @@ obj-$(CONFIG_SAMPLE_FTRACE_DIRECT) += ftrace-direct.o obj-$(CONFIG_SAMPLE_FTRACE_DIRECT) += ftrace-direct-too.o +obj-$(CONFIG_SAMPLE_FTRACE_DIRECT) += ftrace-direct-modify.o diff --git a/samples/ftrace/ftrace-direct-modify.c b/samples/ftrace/ftrace-direct-modify.c new file mode 100644 index 000000000000..e04229d21475 --- /dev/null +++ b/samples/ftrace/ftrace-direct-modify.c @@ -0,0 +1,88 @@ +// SPDX-License-Identifier: GPL-2.0-only +#include <linux/module.h> +#include <linux/kthread.h> +#include <linux/ftrace.h> + +void my_direct_func1(void) +{ + trace_printk("my direct func1\n"); +} + +void my_direct_func2(void) +{ + trace_printk("my direct func2\n"); +} + +extern void my_tramp1(void *); +extern void my_tramp2(void *); + +static unsigned long my_ip = (unsigned long)schedule; + +asm ( +" .pushsection .text, \"ax\", @progbits\n" +" my_tramp1:" +" pushq %rbp\n" +" movq %rsp, %rbp\n" +" call my_direct_func1\n" +" leave\n" +" ret\n" +" my_tramp2:" +" pushq %rbp\n" +" movq %rsp, %rbp\n" +" call my_direct_func2\n" +" leave\n" +" ret\n" +" .popsection\n" +); + +static unsigned long my_tramp = (unsigned long)my_tramp1; +static unsigned long tramps[2] = { + (unsigned long)my_tramp1, + (unsigned long)my_tramp2, +}; + +static int simple_thread(void *arg) +{ + static int t; + int ret = 0; + + while (!kthread_should_stop()) { + set_current_state(TASK_INTERRUPTIBLE); + schedule_timeout(2 * HZ); + + if (ret) + continue; + t ^= 1; + ret = modify_ftrace_direct(my_ip, my_tramp, tramps[t]); + if (!ret) + my_tramp = tramps[t]; + WARN_ON_ONCE(ret); + } + + return 0; +} + +static struct task_struct *simple_tsk; + +static int __init ftrace_direct_init(void) +{ + int ret; + + ret = register_ftrace_direct(my_ip, my_tramp); + if (!ret) + simple_tsk = kthread_run(simple_thread, NULL, "event-sample-fn"); + return ret; +} + +static void __exit ftrace_direct_exit(void) +{ + kthread_stop(simple_tsk); + unregister_ftrace_direct(my_ip, my_tramp); +} + +module_init(ftrace_direct_init); +module_exit(ftrace_direct_exit); + +MODULE_AUTHOR("Steven Rostedt"); +MODULE_DESCRIPTION("Example use case of using modify_ftrace_direct()"); +MODULE_LICENSE("GPL"); |