linux/samples/ftrace/ftrace-direct-multi-modify.c
<<
>>
Prefs
   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
   7extern void my_direct_func1(unsigned long ip);
   8extern void my_direct_func2(unsigned long ip);
   9
  10void my_direct_func1(unsigned long ip)
  11{
  12        trace_printk("my direct func1 ip %lx\n", ip);
  13}
  14
  15void my_direct_func2(unsigned long ip)
  16{
  17        trace_printk("my direct func2 ip %lx\n", ip);
  18}
  19
  20extern void my_tramp1(void *);
  21extern void my_tramp2(void *);
  22
  23#ifdef CONFIG_X86_64
  24
  25asm (
  26"       .pushsection    .text, \"ax\", @progbits\n"
  27"       .type           my_tramp1, @function\n"
  28"       .globl          my_tramp1\n"
  29"   my_tramp1:"
  30"       pushq %rbp\n"
  31"       movq %rsp, %rbp\n"
  32"       pushq %rdi\n"
  33"       movq 8(%rbp), %rdi\n"
  34"       call my_direct_func1\n"
  35"       popq %rdi\n"
  36"       leave\n"
  37"       ret\n"
  38"       .size           my_tramp1, .-my_tramp1\n"
  39"       .type           my_tramp2, @function\n"
  40"\n"
  41"       .globl          my_tramp2\n"
  42"   my_tramp2:"
  43"       pushq %rbp\n"
  44"       movq %rsp, %rbp\n"
  45"       pushq %rdi\n"
  46"       movq 8(%rbp), %rdi\n"
  47"       call my_direct_func2\n"
  48"       popq %rdi\n"
  49"       leave\n"
  50"       ret\n"
  51"       .size           my_tramp2, .-my_tramp2\n"
  52"       .popsection\n"
  53);
  54
  55#endif /* CONFIG_X86_64 */
  56
  57#ifdef CONFIG_S390
  58
  59asm (
  60"       .pushsection    .text, \"ax\", @progbits\n"
  61"       .type           my_tramp1, @function\n"
  62"       .globl          my_tramp1\n"
  63"   my_tramp1:"
  64"       lgr             %r1,%r15\n"
  65"       stmg            %r0,%r5,"__stringify(__SF_GPRS)"(%r15)\n"
  66"       stg             %r14,"__stringify(__SF_GPRS+8*8)"(%r15)\n"
  67"       aghi            %r15,"__stringify(-STACK_FRAME_OVERHEAD)"\n"
  68"       stg             %r1,"__stringify(__SF_BACKCHAIN)"(%r15)\n"
  69"       lgr             %r2,%r0\n"
  70"       brasl           %r14,my_direct_func1\n"
  71"       aghi            %r15,"__stringify(STACK_FRAME_OVERHEAD)"\n"
  72"       lmg             %r0,%r5,"__stringify(__SF_GPRS)"(%r15)\n"
  73"       lg              %r14,"__stringify(__SF_GPRS+8*8)"(%r15)\n"
  74"       lgr             %r1,%r0\n"
  75"       br              %r1\n"
  76"       .size           my_tramp1, .-my_tramp1\n"
  77"\n"
  78"       .type           my_tramp2, @function\n"
  79"       .globl          my_tramp2\n"
  80"   my_tramp2:"
  81"       lgr             %r1,%r15\n"
  82"       stmg            %r0,%r5,"__stringify(__SF_GPRS)"(%r15)\n"
  83"       stg             %r14,"__stringify(__SF_GPRS+8*8)"(%r15)\n"
  84"       aghi            %r15,"__stringify(-STACK_FRAME_OVERHEAD)"\n"
  85"       stg             %r1,"__stringify(__SF_BACKCHAIN)"(%r15)\n"
  86"       lgr             %r2,%r0\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 struct ftrace_ops direct;
 106
 107static int simple_thread(void *arg)
 108{
 109        static int t;
 110        int ret = 0;
 111
 112        while (!kthread_should_stop()) {
 113                set_current_state(TASK_INTERRUPTIBLE);
 114                schedule_timeout(2 * HZ);
 115
 116                if (ret)
 117                        continue;
 118                t ^= 1;
 119                ret = modify_ftrace_direct_multi(&direct, tramps[t]);
 120                if (!ret)
 121                        my_tramp = tramps[t];
 122                WARN_ON_ONCE(ret);
 123        }
 124
 125        return 0;
 126}
 127
 128static struct task_struct *simple_tsk;
 129
 130static int __init ftrace_direct_multi_init(void)
 131{
 132        int ret;
 133
 134        ftrace_set_filter_ip(&direct, (unsigned long) wake_up_process, 0, 0);
 135        ftrace_set_filter_ip(&direct, (unsigned long) schedule, 0, 0);
 136
 137        ret = register_ftrace_direct_multi(&direct, my_tramp);
 138
 139        if (!ret)
 140                simple_tsk = kthread_run(simple_thread, NULL, "event-sample-fn");
 141        return ret;
 142}
 143
 144static void __exit ftrace_direct_multi_exit(void)
 145{
 146        kthread_stop(simple_tsk);
 147        unregister_ftrace_direct_multi(&direct, my_tramp);
 148}
 149
 150module_init(ftrace_direct_multi_init);
 151module_exit(ftrace_direct_multi_exit);
 152
 153MODULE_AUTHOR("Jiri Olsa");
 154MODULE_DESCRIPTION("Example use case of using modify_ftrace_direct_multi()");
 155MODULE_LICENSE("GPL");
 156