Path: blob/master/samples/ftrace/ftrace-direct-multi-modify.c
26282 views
// SPDX-License-Identifier: GPL-2.0-only1#include <linux/module.h>2#include <linux/kthread.h>3#include <linux/ftrace.h>4#if !defined(CONFIG_ARM64) && !defined(CONFIG_PPC32)5#include <asm/asm-offsets.h>6#endif78extern void my_direct_func1(unsigned long ip);9extern void my_direct_func2(unsigned long ip);1011void my_direct_func1(unsigned long ip)12{13trace_printk("my direct func1 ip %lx\n", ip);14}1516void my_direct_func2(unsigned long ip)17{18trace_printk("my direct func2 ip %lx\n", ip);19}2021extern void my_tramp1(void *);22extern void my_tramp2(void *);2324#ifdef CONFIG_RISCV25#include <asm/asm.h>2627asm (28" .pushsection .text, \"ax\", @progbits\n"29" .type my_tramp1, @function\n"30" .globl my_tramp1\n"31" my_tramp1:\n"32" addi sp,sp,-3*"SZREG"\n"33" "REG_S" a0,0*"SZREG"(sp)\n"34" "REG_S" t0,1*"SZREG"(sp)\n"35" "REG_S" ra,2*"SZREG"(sp)\n"36" mv a0,t0\n"37" call my_direct_func1\n"38" "REG_L" a0,0*"SZREG"(sp)\n"39" "REG_L" t0,1*"SZREG"(sp)\n"40" "REG_L" ra,2*"SZREG"(sp)\n"41" addi sp,sp,3*"SZREG"\n"42" jr t0\n"43" .size my_tramp1, .-my_tramp1\n"4445" .type my_tramp2, @function\n"46" .globl my_tramp2\n"47" my_tramp2:\n"48" addi sp,sp,-3*"SZREG"\n"49" "REG_S" a0,0*"SZREG"(sp)\n"50" "REG_S" t0,1*"SZREG"(sp)\n"51" "REG_S" ra,2*"SZREG"(sp)\n"52" mv a0,t0\n"53" call my_direct_func2\n"54" "REG_L" a0,0*"SZREG"(sp)\n"55" "REG_L" t0,1*"SZREG"(sp)\n"56" "REG_L" ra,2*"SZREG"(sp)\n"57" addi sp,sp,3*"SZREG"\n"58" jr t0\n"59" .size my_tramp2, .-my_tramp2\n"60" .popsection\n"61);6263#endif /* CONFIG_RISCV */6465#ifdef CONFIG_X86_646667#include <asm/ibt.h>68#include <asm/nospec-branch.h>6970asm (71" .pushsection .text, \"ax\", @progbits\n"72" .type my_tramp1, @function\n"73" .globl my_tramp1\n"74" my_tramp1:"75ASM_ENDBR76" pushq %rbp\n"77" movq %rsp, %rbp\n"78CALL_DEPTH_ACCOUNT79" pushq %rdi\n"80" movq 8(%rbp), %rdi\n"81" call my_direct_func1\n"82" popq %rdi\n"83" leave\n"84ASM_RET85" .size my_tramp1, .-my_tramp1\n"8687" .type my_tramp2, @function\n"88" .globl my_tramp2\n"89" my_tramp2:"90ASM_ENDBR91" pushq %rbp\n"92" movq %rsp, %rbp\n"93CALL_DEPTH_ACCOUNT94" pushq %rdi\n"95" movq 8(%rbp), %rdi\n"96" call my_direct_func2\n"97" popq %rdi\n"98" leave\n"99ASM_RET100" .size my_tramp2, .-my_tramp2\n"101" .popsection\n"102);103104#endif /* CONFIG_X86_64 */105106#ifdef CONFIG_S390107108asm (109" .pushsection .text, \"ax\", @progbits\n"110" .type my_tramp1, @function\n"111" .globl my_tramp1\n"112" my_tramp1:"113" lgr %r1,%r15\n"114" stmg %r0,%r5,"__stringify(__SF_GPRS)"(%r15)\n"115" stg %r14,"__stringify(__SF_GPRS+8*8)"(%r15)\n"116" aghi %r15,"__stringify(-STACK_FRAME_OVERHEAD)"\n"117" stg %r1,"__stringify(__SF_BACKCHAIN)"(%r15)\n"118" lgr %r2,%r0\n"119" brasl %r14,my_direct_func1\n"120" aghi %r15,"__stringify(STACK_FRAME_OVERHEAD)"\n"121" lmg %r0,%r5,"__stringify(__SF_GPRS)"(%r15)\n"122" lg %r14,"__stringify(__SF_GPRS+8*8)"(%r15)\n"123" lgr %r1,%r0\n"124" br %r1\n"125" .size my_tramp1, .-my_tramp1\n"126"\n"127" .type my_tramp2, @function\n"128" .globl my_tramp2\n"129" my_tramp2:"130" lgr %r1,%r15\n"131" stmg %r0,%r5,"__stringify(__SF_GPRS)"(%r15)\n"132" stg %r14,"__stringify(__SF_GPRS+8*8)"(%r15)\n"133" aghi %r15,"__stringify(-STACK_FRAME_OVERHEAD)"\n"134" stg %r1,"__stringify(__SF_BACKCHAIN)"(%r15)\n"135" lgr %r2,%r0\n"136" brasl %r14,my_direct_func2\n"137" aghi %r15,"__stringify(STACK_FRAME_OVERHEAD)"\n"138" lmg %r0,%r5,"__stringify(__SF_GPRS)"(%r15)\n"139" lg %r14,"__stringify(__SF_GPRS+8*8)"(%r15)\n"140" lgr %r1,%r0\n"141" br %r1\n"142" .size my_tramp2, .-my_tramp2\n"143" .popsection\n"144);145146#endif /* CONFIG_S390 */147148#ifdef CONFIG_ARM64149150asm (151" .pushsection .text, \"ax\", @progbits\n"152" .type my_tramp1, @function\n"153" .globl my_tramp1\n"154" my_tramp1:"155" hint 34\n" // bti c156" sub sp, sp, #32\n"157" stp x9, x30, [sp]\n"158" str x0, [sp, #16]\n"159" mov x0, x30\n"160" bl my_direct_func1\n"161" ldp x30, x9, [sp]\n"162" ldr x0, [sp, #16]\n"163" add sp, sp, #32\n"164" ret x9\n"165" .size my_tramp1, .-my_tramp1\n"166167" .type my_tramp2, @function\n"168" .globl my_tramp2\n"169" my_tramp2:"170" hint 34\n" // bti c171" sub sp, sp, #32\n"172" stp x9, x30, [sp]\n"173" str x0, [sp, #16]\n"174" mov x0, x30\n"175" bl my_direct_func2\n"176" ldp x30, x9, [sp]\n"177" ldr x0, [sp, #16]\n"178" add sp, sp, #32\n"179" ret x9\n"180" .size my_tramp2, .-my_tramp2\n"181" .popsection\n"182);183184#endif /* CONFIG_ARM64 */185186#ifdef CONFIG_LOONGARCH187#include <asm/asm.h>188189asm (190" .pushsection .text, \"ax\", @progbits\n"191" .type my_tramp1, @function\n"192" .globl my_tramp1\n"193" my_tramp1:\n"194" addi.d $sp, $sp, -32\n"195" st.d $a0, $sp, 0\n"196" st.d $t0, $sp, 8\n"197" st.d $ra, $sp, 16\n"198" move $a0, $t0\n"199" bl my_direct_func1\n"200" ld.d $a0, $sp, 0\n"201" ld.d $t0, $sp, 8\n"202" ld.d $ra, $sp, 16\n"203" addi.d $sp, $sp, 32\n"204" jr $t0\n"205" .size my_tramp1, .-my_tramp1\n"206207" .type my_tramp2, @function\n"208" .globl my_tramp2\n"209" my_tramp2:\n"210" addi.d $sp, $sp, -32\n"211" st.d $a0, $sp, 0\n"212" st.d $t0, $sp, 8\n"213" st.d $ra, $sp, 16\n"214" move $a0, $t0\n"215" bl my_direct_func2\n"216" ld.d $a0, $sp, 0\n"217" ld.d $t0, $sp, 8\n"218" ld.d $ra, $sp, 16\n"219" addi.d $sp, $sp, 32\n"220" jr $t0\n"221" .size my_tramp2, .-my_tramp2\n"222" .popsection\n"223);224225#endif /* CONFIG_LOONGARCH */226227#ifdef CONFIG_PPC228#include <asm/ppc_asm.h>229230#ifdef CONFIG_PPC64231#define STACK_FRAME_SIZE 48232#else233#define STACK_FRAME_SIZE 24234#endif235236#if defined(CONFIG_PPC64_ELF_ABI_V2) && !defined(CONFIG_PPC_KERNEL_PCREL)237#define PPC64_TOC_SAVE_AND_UPDATE \238" std 2, 24(1)\n" \239" bcl 20, 31, 1f\n" \240" 1: mflr 12\n" \241" ld 2, (99f - 1b)(12)\n"242#define PPC64_TOC_RESTORE \243" ld 2, 24(1)\n"244#define PPC64_TOC \245" 99: .quad .TOC.@tocbase\n"246#else247#define PPC64_TOC_SAVE_AND_UPDATE ""248#define PPC64_TOC_RESTORE ""249#define PPC64_TOC ""250#endif251252#ifdef CONFIG_PPC_FTRACE_OUT_OF_LINE253#define PPC_FTRACE_RESTORE_LR \254PPC_LL" 0, "__stringify(PPC_LR_STKOFF)"(1)\n" \255" mtlr 0\n"256#define PPC_FTRACE_RET \257" blr\n"258#define PPC_FTRACE_RECOVER_IP \259" lwz 8, 4(3)\n" \260" li 9, 6\n" \261" slw 8, 8, 9\n" \262" sraw 8, 8, 9\n" \263" add 3, 3, 8\n" \264" addi 3, 3, 4\n"265#else266#define PPC_FTRACE_RESTORE_LR \267PPC_LL" 0, "__stringify(PPC_LR_STKOFF)"(1)\n" \268" mtctr 0\n"269#define PPC_FTRACE_RET \270" mtlr 0\n" \271" bctr\n"272#define PPC_FTRACE_RECOVER_IP ""273#endif274275asm (276" .pushsection .text, \"ax\", @progbits\n"277" .type my_tramp1, @function\n"278" .globl my_tramp1\n"279" my_tramp1:\n"280PPC_STL" 0, "__stringify(PPC_LR_STKOFF)"(1)\n"281PPC_STLU" 1, -"__stringify(STACK_FRAME_MIN_SIZE)"(1)\n"282" mflr 0\n"283PPC_STL" 0, "__stringify(PPC_LR_STKOFF)"(1)\n"284PPC_STLU" 1, -"__stringify(STACK_FRAME_SIZE)"(1)\n"285PPC64_TOC_SAVE_AND_UPDATE286PPC_STL" 3, "__stringify(STACK_FRAME_MIN_SIZE)"(1)\n"287" mr 3, 0\n"288PPC_FTRACE_RECOVER_IP289" bl my_direct_func1\n"290PPC_LL" 3, "__stringify(STACK_FRAME_MIN_SIZE)"(1)\n"291PPC64_TOC_RESTORE292" addi 1, 1, "__stringify(STACK_FRAME_SIZE)"\n"293PPC_FTRACE_RESTORE_LR294" addi 1, 1, "__stringify(STACK_FRAME_MIN_SIZE)"\n"295PPC_LL" 0, "__stringify(PPC_LR_STKOFF)"(1)\n"296PPC_FTRACE_RET297" .size my_tramp1, .-my_tramp1\n"298299" .type my_tramp2, @function\n"300" .globl my_tramp2\n"301" my_tramp2:\n"302PPC_STL" 0, "__stringify(PPC_LR_STKOFF)"(1)\n"303PPC_STLU" 1, -"__stringify(STACK_FRAME_MIN_SIZE)"(1)\n"304" mflr 0\n"305PPC_STL" 0, "__stringify(PPC_LR_STKOFF)"(1)\n"306PPC_STLU" 1, -"__stringify(STACK_FRAME_SIZE)"(1)\n"307PPC64_TOC_SAVE_AND_UPDATE308PPC_STL" 3, "__stringify(STACK_FRAME_MIN_SIZE)"(1)\n"309" mr 3, 0\n"310PPC_FTRACE_RECOVER_IP311" bl my_direct_func2\n"312PPC_LL" 3, "__stringify(STACK_FRAME_MIN_SIZE)"(1)\n"313PPC64_TOC_RESTORE314" addi 1, 1, "__stringify(STACK_FRAME_SIZE)"\n"315PPC_FTRACE_RESTORE_LR316" addi 1, 1, "__stringify(STACK_FRAME_MIN_SIZE)"\n"317PPC_LL" 0, "__stringify(PPC_LR_STKOFF)"(1)\n"318PPC_FTRACE_RET319PPC64_TOC320" .size my_tramp2, .-my_tramp2\n"321" .popsection\n"322);323324#endif /* CONFIG_PPC */325326static unsigned long my_tramp = (unsigned long)my_tramp1;327static unsigned long tramps[2] = {328(unsigned long)my_tramp1,329(unsigned long)my_tramp2,330};331332static struct ftrace_ops direct;333334static int simple_thread(void *arg)335{336static int t;337int ret = 0;338339while (!kthread_should_stop()) {340set_current_state(TASK_INTERRUPTIBLE);341schedule_timeout(2 * HZ);342343if (ret)344continue;345t ^= 1;346ret = modify_ftrace_direct(&direct, tramps[t]);347if (!ret)348my_tramp = tramps[t];349WARN_ON_ONCE(ret);350}351352return 0;353}354355static struct task_struct *simple_tsk;356357static int __init ftrace_direct_multi_init(void)358{359int ret;360361ftrace_set_filter_ip(&direct, (unsigned long) wake_up_process, 0, 0);362ftrace_set_filter_ip(&direct, (unsigned long) schedule, 0, 0);363364ret = register_ftrace_direct(&direct, my_tramp);365366if (!ret)367simple_tsk = kthread_run(simple_thread, NULL, "event-sample-fn");368return ret;369}370371static void __exit ftrace_direct_multi_exit(void)372{373kthread_stop(simple_tsk);374unregister_ftrace_direct(&direct, my_tramp, true);375}376377module_init(ftrace_direct_multi_init);378module_exit(ftrace_direct_multi_exit);379380MODULE_AUTHOR("Jiri Olsa");381MODULE_DESCRIPTION("Example use case of using modify_ftrace_direct()");382MODULE_LICENSE("GPL");383384385