Add a simple powerpc trampoline to demonstrate use of ftrace direct on powerpc.
Signed-off-by: Naveen N. Rao <naveen.n....@linux.vnet.ibm.com> --- samples/Kconfig | 2 +- samples/ftrace/ftrace-direct-modify.c | 58 +++++++++++++++++++++++++++ samples/ftrace/ftrace-direct-too.c | 48 ++++++++++++++++++++-- samples/ftrace/ftrace-direct.c | 45 +++++++++++++++++++-- 4 files changed, 144 insertions(+), 9 deletions(-) diff --git a/samples/Kconfig b/samples/Kconfig index 0ed6e4d71d87b1..fdc9e44dba3b95 100644 --- a/samples/Kconfig +++ b/samples/Kconfig @@ -26,7 +26,7 @@ config SAMPLE_TRACE_PRINTK config SAMPLE_FTRACE_DIRECT tristate "Build register_ftrace_direct() example" depends on DYNAMIC_FTRACE_WITH_DIRECT_CALLS && m - depends on X86_64 # has x86_64 inlined asm + depends on X86_64 || PPC64 # has inlined asm help This builds an ftrace direct function example that hooks to wake_up_process and prints the parameters. diff --git a/samples/ftrace/ftrace-direct-modify.c b/samples/ftrace/ftrace-direct-modify.c index c13a5bc5095bea..89d66a12d300e1 100644 --- a/samples/ftrace/ftrace-direct-modify.c +++ b/samples/ftrace/ftrace-direct-modify.c @@ -2,6 +2,7 @@ #include <linux/module.h> #include <linux/kthread.h> #include <linux/ftrace.h> +#include <linux/kprobes.h> void my_direct_func1(void) { @@ -18,6 +19,7 @@ extern void my_tramp2(void *); static unsigned long my_ip = (unsigned long)schedule; +#ifdef CONFIG_X86 asm ( " .pushsection .text, \"ax\", @progbits\n" " .type my_tramp1, @function\n" @@ -38,6 +40,58 @@ asm ( " .size my_tramp2, .-my_tramp2\n" " .popsection\n" ); +#elif CONFIG_PPC64 +asm ( +" .pushsection .text, \"ax\", @progbits\n" +" .type my_tramp1, @function\n" +" .global my_tramp1\n" +" my_tramp1:\n" +" std 0, 16(1)\n" +" stdu 1, -480(1)\n" +" std 2, 24(1)\n" +" mflr 7\n" +" std 7, 368(1)\n" +" bcl 20, 31, 1f\n" +"1: mflr 12\n" +" ld 2, (3f - 1b)(12)\n" +" bl my_direct_func1\n" +" nop\n" +" ld 2, 24(1)\n" +" ld 7, 368(1)\n" +" mtctr 7\n" +" addi 1, 1, 480\n" +" ld 0, 16(1)\n" +" mtlr 0\n" +" bctr\n" +" .size my_tramp1, .-my_tramp1\n" +" nop\n" +" .type my_tramp2, @function\n" +" .global my_tramp2\n" +" my_tramp2:\n" +" std 0, 16(1)\n" +" stdu 1, -480(1)\n" +" std 2, 24(1)\n" +" mflr 7\n" +" std 7, 368(1)\n" +" bcl 20, 31, 2f\n" +"2: mflr 12\n" +" ld 2, (3f - 2b)(12)\n" +" bl my_direct_func2\n" +" nop\n" +" ld 2, 24(1)\n" +" ld 7, 368(1)\n" +" mtctr 7\n" +" addi 1, 1, 480\n" +" ld 0, 16(1)\n" +" mtlr 0\n" +" bctr\n" +" .size my_tramp2, .-my_tramp2\n" +"3:\n" +" .quad .TOC.@tocbase\n" +" .popsection\n" +); +#endif + static unsigned long my_tramp = (unsigned long)my_tramp1; static unsigned long tramps[2] = { @@ -72,6 +126,10 @@ static int __init ftrace_direct_init(void) { int ret; +#ifdef CONFIG_PPC64 + my_ip = ppc_function_entry((void *)my_ip) + 4; +#endif + ret = register_ftrace_direct(my_ip, my_tramp); if (!ret) simple_tsk = kthread_run(simple_thread, NULL, "event-sample-fn"); diff --git a/samples/ftrace/ftrace-direct-too.c b/samples/ftrace/ftrace-direct-too.c index d5c5022be66429..9a82abecbe0dcc 100644 --- a/samples/ftrace/ftrace-direct-too.c +++ b/samples/ftrace/ftrace-direct-too.c @@ -3,6 +3,7 @@ #include <linux/mm.h> /* for handle_mm_fault() */ #include <linux/ftrace.h> +#include <linux/kprobes.h> void my_direct_func(struct vm_area_struct *vma, unsigned long address, unsigned int flags) @@ -13,6 +14,9 @@ void my_direct_func(struct vm_area_struct *vma, extern void my_tramp(void *); +static unsigned long my_ip = (unsigned long)handle_mm_fault; + +#ifdef CONFIG_X86 asm ( " .pushsection .text, \"ax\", @progbits\n" " .type my_tramp, @function\n" @@ -31,18 +35,54 @@ asm ( " .size my_tramp, .-my_tramp\n" " .popsection\n" ); +#elif CONFIG_PPC64 +asm ( +" .pushsection .text, \"ax\", @progbits\n" +" .type my_tramp, @function\n" +" .global my_tramp\n" +" my_tramp:\n" +" std 0, 16(1)\n" +" stdu 1, -480(1)\n" +" std 2, 24(1)\n" +" std 3, 136(1)\n" +" std 4, 144(1)\n" +" std 5, 152(1)\n" +" mflr 7\n" +" std 7, 368(1)\n" +" bcl 20, 31, 1f\n" +"1: mflr 12\n" +" ld 2, (2f - 1b)(12)\n" +" bl my_direct_func\n" +" nop\n" +" ld 5, 152(1)\n" +" ld 4, 144(1)\n" +" ld 3, 136(1)\n" +" ld 2, 24(1)\n" +" ld 7, 368(1)\n" +" mtctr 7\n" +" addi 1, 1, 480\n" +" ld 0, 16(1)\n" +" mtlr 0\n" +" bctr\n" +" .size my_tramp, .-my_tramp\n" +"2:\n" +" .quad .TOC.@tocbase\n" +" .popsection\n" +); +#endif static int __init ftrace_direct_init(void) { - return register_ftrace_direct((unsigned long)handle_mm_fault, - (unsigned long)my_tramp); +#ifdef CONFIG_PPC64 + my_ip = ppc_function_entry((void *)my_ip) + 4; +#endif + return register_ftrace_direct(my_ip, (unsigned long)my_tramp); } static void __exit ftrace_direct_exit(void) { - unregister_ftrace_direct((unsigned long)handle_mm_fault, - (unsigned long)my_tramp); + unregister_ftrace_direct(my_ip, (unsigned long)my_tramp); } module_init(ftrace_direct_init); diff --git a/samples/ftrace/ftrace-direct.c b/samples/ftrace/ftrace-direct.c index 63ca06d42c803f..da67b6217f91d2 100644 --- a/samples/ftrace/ftrace-direct.c +++ b/samples/ftrace/ftrace-direct.c @@ -3,6 +3,7 @@ #include <linux/sched.h> /* for wake_up_process() */ #include <linux/ftrace.h> +#include <linux/kprobes.h> /* for ppc_function_entry() */ void my_direct_func(struct task_struct *p) { @@ -11,6 +12,9 @@ void my_direct_func(struct task_struct *p) extern void my_tramp(void *); +static unsigned long my_ip = (unsigned long)wake_up_process; + +#ifdef CONFIG_X86 asm ( " .pushsection .text, \"ax\", @progbits\n" " .type my_tramp, @function\n" @@ -25,18 +29,51 @@ asm ( " .size my_tramp, .-my_tramp\n" " .popsection\n" ); +#elif CONFIG_PPC64 +asm ( +" .pushsection .text, \"ax\", @progbits\n" +" .type my_tramp, @function\n" +" .global my_tramp\n" +" my_tramp:\n" +" std 0, 16(1)\n" +" stdu 1, -480(1)\n" +" std 2, 24(1)\n" +" std 3, 136(1)\n" +" mflr 7\n" +" std 7, 368(1)\n" +" bcl 20, 31, 1f\n" +"1: mflr 12\n" +" ld 2, (2f - 1b)(12)\n" +" bl my_direct_func\n" +" nop\n" +" ld 3, 136(1)\n" +" ld 2, 24(1)\n" +" ld 7, 368(1)\n" +" mtctr 7\n" +" addi 1, 1, 480\n" +" ld 0, 16(1)\n" +" mtlr 0\n" +" bctr\n" +" .size my_tramp, .-my_tramp\n" +"2:\n" +" .quad .TOC.@tocbase\n" +" .popsection\n" +); +#endif static int __init ftrace_direct_init(void) { - return register_ftrace_direct((unsigned long)wake_up_process, - (unsigned long)my_tramp); +#ifdef CONFIG_PPC64 + /* Ftrace location is (usually) the second instruction at a function's local entry point */ + my_ip = ppc_function_entry((void *)my_ip) + 4; +#endif + return register_ftrace_direct(my_ip, (unsigned long)my_tramp); } static void __exit ftrace_direct_exit(void) { - unregister_ftrace_direct((unsigned long)wake_up_process, - (unsigned long)my_tramp); + unregister_ftrace_direct(my_ip, (unsigned long)my_tramp); } module_init(ftrace_direct_init); -- 2.25.4