at master 9.6 kB view raw
1// SPDX-License-Identifier: GPL-2.0-only 2#include <linux/module.h> 3#include <linux/kthread.h> 4#include <linux/ftrace.h> 5#if !defined(CONFIG_ARM64) && !defined(CONFIG_PPC32) 6#include <asm/asm-offsets.h> 7#endif 8 9extern void my_direct_func1(unsigned long ip); 10extern void my_direct_func2(unsigned long ip); 11 12void my_direct_func1(unsigned long ip) 13{ 14 trace_printk("my direct func1 ip %lx\n", ip); 15} 16 17void my_direct_func2(unsigned long ip) 18{ 19 trace_printk("my direct func2 ip %lx\n", ip); 20} 21 22extern void my_tramp1(void *); 23extern void my_tramp2(void *); 24 25#ifdef CONFIG_RISCV 26#include <asm/asm.h> 27 28asm ( 29" .pushsection .text, \"ax\", @progbits\n" 30" .type my_tramp1, @function\n" 31" .globl my_tramp1\n" 32" my_tramp1:\n" 33" addi sp,sp,-3*"SZREG"\n" 34" "REG_S" a0,0*"SZREG"(sp)\n" 35" "REG_S" t0,1*"SZREG"(sp)\n" 36" "REG_S" ra,2*"SZREG"(sp)\n" 37" mv a0,t0\n" 38" call my_direct_func1\n" 39" "REG_L" a0,0*"SZREG"(sp)\n" 40" "REG_L" t0,1*"SZREG"(sp)\n" 41" "REG_L" ra,2*"SZREG"(sp)\n" 42" addi sp,sp,3*"SZREG"\n" 43" jr t0\n" 44" .size my_tramp1, .-my_tramp1\n" 45 46" .type my_tramp2, @function\n" 47" .globl my_tramp2\n" 48" my_tramp2:\n" 49" addi sp,sp,-3*"SZREG"\n" 50" "REG_S" a0,0*"SZREG"(sp)\n" 51" "REG_S" t0,1*"SZREG"(sp)\n" 52" "REG_S" ra,2*"SZREG"(sp)\n" 53" mv a0,t0\n" 54" call my_direct_func2\n" 55" "REG_L" a0,0*"SZREG"(sp)\n" 56" "REG_L" t0,1*"SZREG"(sp)\n" 57" "REG_L" ra,2*"SZREG"(sp)\n" 58" addi sp,sp,3*"SZREG"\n" 59" jr t0\n" 60" .size my_tramp2, .-my_tramp2\n" 61" .popsection\n" 62); 63 64#endif /* CONFIG_RISCV */ 65 66#ifdef CONFIG_X86_64 67 68#include <asm/ibt.h> 69#include <asm/nospec-branch.h> 70 71asm ( 72" .pushsection .text, \"ax\", @progbits\n" 73" .type my_tramp1, @function\n" 74" .globl my_tramp1\n" 75" my_tramp1:" 76 ASM_ENDBR 77" pushq %rbp\n" 78" movq %rsp, %rbp\n" 79 CALL_DEPTH_ACCOUNT 80" pushq %rdi\n" 81" movq 8(%rbp), %rdi\n" 82" call my_direct_func1\n" 83" popq %rdi\n" 84" leave\n" 85 ASM_RET 86" .size my_tramp1, .-my_tramp1\n" 87 88" .type my_tramp2, @function\n" 89" .globl my_tramp2\n" 90" my_tramp2:" 91 ASM_ENDBR 92" pushq %rbp\n" 93" movq %rsp, %rbp\n" 94 CALL_DEPTH_ACCOUNT 95" pushq %rdi\n" 96" movq 8(%rbp), %rdi\n" 97" call my_direct_func2\n" 98" popq %rdi\n" 99" leave\n" 100 ASM_RET 101" .size my_tramp2, .-my_tramp2\n" 102" .popsection\n" 103); 104 105#endif /* CONFIG_X86_64 */ 106 107#ifdef CONFIG_S390 108 109asm ( 110" .pushsection .text, \"ax\", @progbits\n" 111" .type my_tramp1, @function\n" 112" .globl my_tramp1\n" 113" my_tramp1:" 114" lgr %r1,%r15\n" 115" stmg %r0,%r5,"__stringify(__SF_GPRS)"(%r15)\n" 116" stg %r14,"__stringify(__SF_GPRS+8*8)"(%r15)\n" 117" aghi %r15,"__stringify(-STACK_FRAME_OVERHEAD)"\n" 118" stg %r1,"__stringify(__SF_BACKCHAIN)"(%r15)\n" 119" lgr %r2,%r0\n" 120" brasl %r14,my_direct_func1\n" 121" aghi %r15,"__stringify(STACK_FRAME_OVERHEAD)"\n" 122" lmg %r0,%r5,"__stringify(__SF_GPRS)"(%r15)\n" 123" lg %r14,"__stringify(__SF_GPRS+8*8)"(%r15)\n" 124" lgr %r1,%r0\n" 125" br %r1\n" 126" .size my_tramp1, .-my_tramp1\n" 127"\n" 128" .type my_tramp2, @function\n" 129" .globl my_tramp2\n" 130" my_tramp2:" 131" lgr %r1,%r15\n" 132" stmg %r0,%r5,"__stringify(__SF_GPRS)"(%r15)\n" 133" stg %r14,"__stringify(__SF_GPRS+8*8)"(%r15)\n" 134" aghi %r15,"__stringify(-STACK_FRAME_OVERHEAD)"\n" 135" stg %r1,"__stringify(__SF_BACKCHAIN)"(%r15)\n" 136" lgr %r2,%r0\n" 137" brasl %r14,my_direct_func2\n" 138" aghi %r15,"__stringify(STACK_FRAME_OVERHEAD)"\n" 139" lmg %r0,%r5,"__stringify(__SF_GPRS)"(%r15)\n" 140" lg %r14,"__stringify(__SF_GPRS+8*8)"(%r15)\n" 141" lgr %r1,%r0\n" 142" br %r1\n" 143" .size my_tramp2, .-my_tramp2\n" 144" .popsection\n" 145); 146 147#endif /* CONFIG_S390 */ 148 149#ifdef CONFIG_ARM64 150 151asm ( 152" .pushsection .text, \"ax\", @progbits\n" 153" .type my_tramp1, @function\n" 154" .globl my_tramp1\n" 155" my_tramp1:" 156" hint 34\n" // bti c 157" sub sp, sp, #32\n" 158" stp x9, x30, [sp]\n" 159" str x0, [sp, #16]\n" 160" mov x0, x30\n" 161" bl my_direct_func1\n" 162" ldp x30, x9, [sp]\n" 163" ldr x0, [sp, #16]\n" 164" add sp, sp, #32\n" 165" ret x9\n" 166" .size my_tramp1, .-my_tramp1\n" 167 168" .type my_tramp2, @function\n" 169" .globl my_tramp2\n" 170" my_tramp2:" 171" hint 34\n" // bti c 172" sub sp, sp, #32\n" 173" stp x9, x30, [sp]\n" 174" str x0, [sp, #16]\n" 175" mov x0, x30\n" 176" bl my_direct_func2\n" 177" ldp x30, x9, [sp]\n" 178" ldr x0, [sp, #16]\n" 179" add sp, sp, #32\n" 180" ret x9\n" 181" .size my_tramp2, .-my_tramp2\n" 182" .popsection\n" 183); 184 185#endif /* CONFIG_ARM64 */ 186 187#ifdef CONFIG_LOONGARCH 188#include <asm/asm.h> 189 190asm ( 191" .pushsection .text, \"ax\", @progbits\n" 192" .type my_tramp1, @function\n" 193" .globl my_tramp1\n" 194" my_tramp1:\n" 195" addi.d $sp, $sp, -32\n" 196" st.d $a0, $sp, 0\n" 197" st.d $t0, $sp, 8\n" 198" st.d $ra, $sp, 16\n" 199" move $a0, $t0\n" 200" bl my_direct_func1\n" 201" ld.d $a0, $sp, 0\n" 202" ld.d $ra, $sp, 8\n" 203" ld.d $t0, $sp, 16\n" 204" addi.d $sp, $sp, 32\n" 205" jr $t0\n" 206" .size my_tramp1, .-my_tramp1\n" 207 208" .type my_tramp2, @function\n" 209" .globl my_tramp2\n" 210" my_tramp2:\n" 211" addi.d $sp, $sp, -32\n" 212" st.d $a0, $sp, 0\n" 213" st.d $t0, $sp, 8\n" 214" st.d $ra, $sp, 16\n" 215" move $a0, $t0\n" 216" bl my_direct_func2\n" 217" ld.d $a0, $sp, 0\n" 218" ld.d $ra, $sp, 8\n" 219" ld.d $t0, $sp, 16\n" 220" addi.d $sp, $sp, 32\n" 221" jr $t0\n" 222" .size my_tramp2, .-my_tramp2\n" 223" .popsection\n" 224); 225 226#endif /* CONFIG_LOONGARCH */ 227 228#ifdef CONFIG_PPC 229#include <asm/ppc_asm.h> 230 231#ifdef CONFIG_PPC64 232#define STACK_FRAME_SIZE 48 233#else 234#define STACK_FRAME_SIZE 24 235#endif 236 237#if defined(CONFIG_PPC64_ELF_ABI_V2) && !defined(CONFIG_PPC_KERNEL_PCREL) 238#define PPC64_TOC_SAVE_AND_UPDATE \ 239" std 2, 24(1)\n" \ 240" bcl 20, 31, 1f\n" \ 241" 1: mflr 12\n" \ 242" ld 2, (99f - 1b)(12)\n" 243#define PPC64_TOC_RESTORE \ 244" ld 2, 24(1)\n" 245#define PPC64_TOC \ 246" 99: .quad .TOC.@tocbase\n" 247#else 248#define PPC64_TOC_SAVE_AND_UPDATE "" 249#define PPC64_TOC_RESTORE "" 250#define PPC64_TOC "" 251#endif 252 253#ifdef CONFIG_PPC_FTRACE_OUT_OF_LINE 254#define PPC_FTRACE_RESTORE_LR \ 255 PPC_LL" 0, "__stringify(PPC_LR_STKOFF)"(1)\n" \ 256" mtlr 0\n" 257#define PPC_FTRACE_RET \ 258" blr\n" 259#define PPC_FTRACE_RECOVER_IP \ 260" lwz 8, 4(3)\n" \ 261" li 9, 6\n" \ 262" slw 8, 8, 9\n" \ 263" sraw 8, 8, 9\n" \ 264" add 3, 3, 8\n" \ 265" addi 3, 3, 4\n" 266#else 267#define PPC_FTRACE_RESTORE_LR \ 268 PPC_LL" 0, "__stringify(PPC_LR_STKOFF)"(1)\n" \ 269" mtctr 0\n" 270#define PPC_FTRACE_RET \ 271" mtlr 0\n" \ 272" bctr\n" 273#define PPC_FTRACE_RECOVER_IP "" 274#endif 275 276asm ( 277" .pushsection .text, \"ax\", @progbits\n" 278" .type my_tramp1, @function\n" 279" .globl my_tramp1\n" 280" my_tramp1:\n" 281 PPC_STL" 0, "__stringify(PPC_LR_STKOFF)"(1)\n" 282 PPC_STLU" 1, -"__stringify(STACK_FRAME_MIN_SIZE)"(1)\n" 283" mflr 0\n" 284 PPC_STL" 0, "__stringify(PPC_LR_STKOFF)"(1)\n" 285 PPC_STLU" 1, -"__stringify(STACK_FRAME_SIZE)"(1)\n" 286 PPC64_TOC_SAVE_AND_UPDATE 287 PPC_STL" 3, "__stringify(STACK_FRAME_MIN_SIZE)"(1)\n" 288" mr 3, 0\n" 289 PPC_FTRACE_RECOVER_IP 290" bl my_direct_func1\n" 291 PPC_LL" 3, "__stringify(STACK_FRAME_MIN_SIZE)"(1)\n" 292 PPC64_TOC_RESTORE 293" addi 1, 1, "__stringify(STACK_FRAME_SIZE)"\n" 294 PPC_FTRACE_RESTORE_LR 295" addi 1, 1, "__stringify(STACK_FRAME_MIN_SIZE)"\n" 296 PPC_LL" 0, "__stringify(PPC_LR_STKOFF)"(1)\n" 297 PPC_FTRACE_RET 298" .size my_tramp1, .-my_tramp1\n" 299 300" .type my_tramp2, @function\n" 301" .globl my_tramp2\n" 302" my_tramp2:\n" 303 PPC_STL" 0, "__stringify(PPC_LR_STKOFF)"(1)\n" 304 PPC_STLU" 1, -"__stringify(STACK_FRAME_MIN_SIZE)"(1)\n" 305" mflr 0\n" 306 PPC_STL" 0, "__stringify(PPC_LR_STKOFF)"(1)\n" 307 PPC_STLU" 1, -"__stringify(STACK_FRAME_SIZE)"(1)\n" 308 PPC64_TOC_SAVE_AND_UPDATE 309 PPC_STL" 3, "__stringify(STACK_FRAME_MIN_SIZE)"(1)\n" 310" mr 3, 0\n" 311 PPC_FTRACE_RECOVER_IP 312" bl my_direct_func2\n" 313 PPC_LL" 3, "__stringify(STACK_FRAME_MIN_SIZE)"(1)\n" 314 PPC64_TOC_RESTORE 315" addi 1, 1, "__stringify(STACK_FRAME_SIZE)"\n" 316 PPC_FTRACE_RESTORE_LR 317" addi 1, 1, "__stringify(STACK_FRAME_MIN_SIZE)"\n" 318 PPC_LL" 0, "__stringify(PPC_LR_STKOFF)"(1)\n" 319 PPC_FTRACE_RET 320 PPC64_TOC 321 " .size my_tramp2, .-my_tramp2\n" 322" .popsection\n" 323); 324 325#endif /* CONFIG_PPC */ 326 327static unsigned long my_tramp = (unsigned long)my_tramp1; 328static unsigned long tramps[2] = { 329 (unsigned long)my_tramp1, 330 (unsigned long)my_tramp2, 331}; 332 333static struct ftrace_ops direct; 334 335static int simple_thread(void *arg) 336{ 337 static int t; 338 int ret = 0; 339 340 while (!kthread_should_stop()) { 341 set_current_state(TASK_INTERRUPTIBLE); 342 schedule_timeout(2 * HZ); 343 344 if (ret) 345 continue; 346 t ^= 1; 347 ret = modify_ftrace_direct(&direct, tramps[t]); 348 if (!ret) 349 my_tramp = tramps[t]; 350 WARN_ON_ONCE(ret); 351 } 352 353 return 0; 354} 355 356static struct task_struct *simple_tsk; 357 358static int __init ftrace_direct_multi_init(void) 359{ 360 int ret; 361 362 ftrace_set_filter_ip(&direct, (unsigned long) wake_up_process, 0, 0); 363 ftrace_set_filter_ip(&direct, (unsigned long) schedule, 0, 0); 364 365 ret = register_ftrace_direct(&direct, my_tramp); 366 367 if (!ret) 368 simple_tsk = kthread_run(simple_thread, NULL, "event-sample-fn"); 369 return ret; 370} 371 372static void __exit ftrace_direct_multi_exit(void) 373{ 374 kthread_stop(simple_tsk); 375 unregister_ftrace_direct(&direct, my_tramp, true); 376} 377 378module_init(ftrace_direct_multi_init); 379module_exit(ftrace_direct_multi_exit); 380 381MODULE_AUTHOR("Jiri Olsa"); 382MODULE_DESCRIPTION("Example use case of using modify_ftrace_direct()"); 383MODULE_LICENSE("GPL");