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