1// SPDX-License-Identifier: GPL-2.0-only 2#include <linux/module.h> 3 4#include <linux/sched.h> /* for wake_up_process() */ 5#include <linux/ftrace.h> 6#ifndef CONFIG_ARM64 7#include <asm/asm-offsets.h> 8#endif 9 10extern void my_direct_func(struct task_struct *p); 11 12void my_direct_func(struct task_struct *p) 13{ 14 trace_printk("waking up %s-%d\n", p->comm, p->pid); 15} 16 17extern void my_tramp(void *); 18 19#ifdef CONFIG_X86_64 20 21#include <asm/ibt.h> 22#include <asm/nospec-branch.h> 23 24asm ( 25" .pushsection .text, \"ax\", @progbits\n" 26" .type my_tramp, @function\n" 27" .globl my_tramp\n" 28" my_tramp:" 29 ASM_ENDBR 30" pushq %rbp\n" 31" movq %rsp, %rbp\n" 32 CALL_DEPTH_ACCOUNT 33" pushq %rdi\n" 34" call my_direct_func\n" 35" popq %rdi\n" 36" leave\n" 37 ASM_RET 38" .size my_tramp, .-my_tramp\n" 39" .popsection\n" 40); 41 42#endif /* CONFIG_X86_64 */ 43 44#ifdef CONFIG_S390 45 46asm ( 47" .pushsection .text, \"ax\", @progbits\n" 48" .type my_tramp, @function\n" 49" .globl my_tramp\n" 50" my_tramp:" 51" lgr %r1,%r15\n" 52" stmg %r0,%r5,"__stringify(__SF_GPRS)"(%r15)\n" 53" stg %r14,"__stringify(__SF_GPRS+8*8)"(%r15)\n" 54" aghi %r15,"__stringify(-STACK_FRAME_OVERHEAD)"\n" 55" stg %r1,"__stringify(__SF_BACKCHAIN)"(%r15)\n" 56" brasl %r14,my_direct_func\n" 57" aghi %r15,"__stringify(STACK_FRAME_OVERHEAD)"\n" 58" lmg %r0,%r5,"__stringify(__SF_GPRS)"(%r15)\n" 59" lg %r14,"__stringify(__SF_GPRS+8*8)"(%r15)\n" 60" lgr %r1,%r0\n" 61" br %r1\n" 62" .size my_tramp, .-my_tramp\n" 63" .popsection\n" 64); 65 66#endif /* CONFIG_S390 */ 67 68#ifdef CONFIG_ARM64 69 70asm ( 71" .pushsection .text, \"ax\", @progbits\n" 72" .type my_tramp, @function\n" 73" .globl my_tramp\n" 74" my_tramp:" 75" hint 34\n" // bti c 76" sub sp, sp, #32\n" 77" stp x9, x30, [sp]\n" 78" str x0, [sp, #16]\n" 79" bl my_direct_func\n" 80" ldp x30, x9, [sp]\n" 81" ldr x0, [sp, #16]\n" 82" add sp, sp, #32\n" 83" ret x9\n" 84" .size my_tramp, .-my_tramp\n" 85" .popsection\n" 86); 87 88#endif /* CONFIG_ARM64 */ 89 90#ifdef CONFIG_LOONGARCH 91 92asm ( 93" .pushsection .text, \"ax\", @progbits\n" 94" .type my_tramp, @function\n" 95" .globl my_tramp\n" 96" my_tramp:\n" 97" addi.d $sp, $sp, -32\n" 98" st.d $a0, $sp, 0\n" 99" st.d $t0, $sp, 8\n" 100" st.d $ra, $sp, 16\n" 101" bl my_direct_func\n" 102" ld.d $a0, $sp, 0\n" 103" ld.d $t0, $sp, 8\n" 104" ld.d $ra, $sp, 16\n" 105" addi.d $sp, $sp, 32\n" 106" jr $t0\n" 107" .size my_tramp, .-my_tramp\n" 108" .popsection\n" 109); 110 111#endif /* CONFIG_LOONGARCH */ 112 113static struct ftrace_ops direct; 114 115static int __init ftrace_direct_init(void) 116{ 117 ftrace_set_filter_ip(&direct, (unsigned long) wake_up_process, 0, 0); 118 119 return register_ftrace_direct(&direct, (unsigned long) my_tramp); 120} 121 122static void __exit ftrace_direct_exit(void) 123{ 124 unregister_ftrace_direct(&direct, (unsigned long)my_tramp, true); 125} 126 127module_init(ftrace_direct_init); 128module_exit(ftrace_direct_exit); 129 130MODULE_AUTHOR("Steven Rostedt"); 131MODULE_DESCRIPTION("Example use case of using register_ftrace_direct()"); 132MODULE_LICENSE("GPL"); 133