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_RISCV 20#include <asm/asm.h> 21 22asm ( 23" .pushsection .text, \"ax\", @progbits\n" 24" .type my_tramp, @function\n" 25" .globl my_tramp\n" 26" my_tramp:\n" 27" addi sp,sp,-3*"SZREG"\n" 28" "REG_S" a0,0*"SZREG"(sp)\n" 29" "REG_S" t0,1*"SZREG"(sp)\n" 30" "REG_S" ra,2*"SZREG"(sp)\n" 31" call my_direct_func\n" 32" "REG_L" a0,0*"SZREG"(sp)\n" 33" "REG_L" t0,1*"SZREG"(sp)\n" 34" "REG_L" ra,2*"SZREG"(sp)\n" 35" addi sp,sp,3*"SZREG"\n" 36" jr t0\n" 37" .size my_tramp, .-my_tramp\n" 38" .popsection\n" 39); 40 41#endif /* CONFIG_RISCV */ 42 43#ifdef CONFIG_X86_64 44 45#include <asm/ibt.h> 46#include <asm/nospec-branch.h> 47 48asm ( 49" .pushsection .text, \"ax\", @progbits\n" 50" .type my_tramp, @function\n" 51" .globl my_tramp\n" 52" my_tramp:" 53 ASM_ENDBR 54" pushq %rbp\n" 55" movq %rsp, %rbp\n" 56 CALL_DEPTH_ACCOUNT 57" pushq %rdi\n" 58" call my_direct_func\n" 59" popq %rdi\n" 60" leave\n" 61 ASM_RET 62" .size my_tramp, .-my_tramp\n" 63" .popsection\n" 64); 65 66#endif /* CONFIG_X86_64 */ 67 68#ifdef CONFIG_S390 69 70asm ( 71" .pushsection .text, \"ax\", @progbits\n" 72" .type my_tramp, @function\n" 73" .globl my_tramp\n" 74" my_tramp:" 75" lgr %r1,%r15\n" 76" stmg %r0,%r5,"__stringify(__SF_GPRS)"(%r15)\n" 77" stg %r14,"__stringify(__SF_GPRS+8*8)"(%r15)\n" 78" aghi %r15,"__stringify(-STACK_FRAME_OVERHEAD)"\n" 79" stg %r1,"__stringify(__SF_BACKCHAIN)"(%r15)\n" 80" brasl %r14,my_direct_func\n" 81" aghi %r15,"__stringify(STACK_FRAME_OVERHEAD)"\n" 82" lmg %r0,%r5,"__stringify(__SF_GPRS)"(%r15)\n" 83" lg %r14,"__stringify(__SF_GPRS+8*8)"(%r15)\n" 84" lgr %r1,%r0\n" 85" br %r1\n" 86" .size my_tramp, .-my_tramp\n" 87" .popsection\n" 88); 89 90#endif /* CONFIG_S390 */ 91 92#ifdef CONFIG_ARM64 93 94asm ( 95" .pushsection .text, \"ax\", @progbits\n" 96" .type my_tramp, @function\n" 97" .globl my_tramp\n" 98" my_tramp:" 99" hint 34\n" // bti c 100" sub sp, sp, #32\n" 101" stp x9, x30, [sp]\n" 102" str x0, [sp, #16]\n" 103" bl my_direct_func\n" 104" ldp x30, x9, [sp]\n" 105" ldr x0, [sp, #16]\n" 106" add sp, sp, #32\n" 107" ret x9\n" 108" .size my_tramp, .-my_tramp\n" 109" .popsection\n" 110); 111 112#endif /* CONFIG_ARM64 */ 113 114#ifdef CONFIG_LOONGARCH 115 116asm ( 117" .pushsection .text, \"ax\", @progbits\n" 118" .type my_tramp, @function\n" 119" .globl my_tramp\n" 120" my_tramp:\n" 121" addi.d $sp, $sp, -32\n" 122" st.d $a0, $sp, 0\n" 123" st.d $t0, $sp, 8\n" 124" st.d $ra, $sp, 16\n" 125" bl my_direct_func\n" 126" ld.d $a0, $sp, 0\n" 127" ld.d $t0, $sp, 8\n" 128" ld.d $ra, $sp, 16\n" 129" addi.d $sp, $sp, 32\n" 130" jr $t0\n" 131" .size my_tramp, .-my_tramp\n" 132" .popsection\n" 133); 134 135#endif /* CONFIG_LOONGARCH */ 136 137static struct ftrace_ops direct; 138 139static int __init ftrace_direct_init(void) 140{ 141 ftrace_set_filter_ip(&direct, (unsigned long) wake_up_process, 0, 0); 142 143 return register_ftrace_direct(&direct, (unsigned long) my_tramp); 144} 145 146static void __exit ftrace_direct_exit(void) 147{ 148 unregister_ftrace_direct(&direct, (unsigned long)my_tramp, true); 149} 150 151module_init(ftrace_direct_init); 152module_exit(ftrace_direct_exit); 153 154MODULE_AUTHOR("Steven Rostedt"); 155MODULE_DESCRIPTION("Example use case of using register_ftrace_direct()"); 156MODULE_LICENSE("GPL"); 157