18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
28c2ecf20Sopenharmony_ci#include <linux/module.h>
38c2ecf20Sopenharmony_ci
48c2ecf20Sopenharmony_ci#include <linux/mm.h> /* for handle_mm_fault() */
58c2ecf20Sopenharmony_ci#include <linux/ftrace.h>
68c2ecf20Sopenharmony_ci
78c2ecf20Sopenharmony_ciextern void my_direct_func(struct vm_area_struct *vma, unsigned long address,
88c2ecf20Sopenharmony_ci			   unsigned int flags, struct pt_regs *regs);
98c2ecf20Sopenharmony_ci
108c2ecf20Sopenharmony_civoid my_direct_func(struct vm_area_struct *vma, unsigned long address,
118c2ecf20Sopenharmony_ci		    unsigned int flags, struct pt_regs *regs)
128c2ecf20Sopenharmony_ci{
138c2ecf20Sopenharmony_ci	trace_printk("handle mm fault vma=%p address=%lx flags=%x regs=%p\n",
148c2ecf20Sopenharmony_ci		     vma, address, flags, regs);
158c2ecf20Sopenharmony_ci}
168c2ecf20Sopenharmony_ci
178c2ecf20Sopenharmony_ciextern void my_tramp(void *);
188c2ecf20Sopenharmony_ci
198c2ecf20Sopenharmony_ciasm (
208c2ecf20Sopenharmony_ci"	.pushsection    .text, \"ax\", @progbits\n"
218c2ecf20Sopenharmony_ci"	.type		my_tramp, @function\n"
228c2ecf20Sopenharmony_ci"	.globl		my_tramp\n"
238c2ecf20Sopenharmony_ci"   my_tramp:"
248c2ecf20Sopenharmony_ci"	pushq %rbp\n"
258c2ecf20Sopenharmony_ci"	movq %rsp, %rbp\n"
268c2ecf20Sopenharmony_ci"	pushq %rdi\n"
278c2ecf20Sopenharmony_ci"	pushq %rsi\n"
288c2ecf20Sopenharmony_ci"	pushq %rdx\n"
298c2ecf20Sopenharmony_ci"	pushq %rcx\n"
308c2ecf20Sopenharmony_ci"	call my_direct_func\n"
318c2ecf20Sopenharmony_ci"	popq %rcx\n"
328c2ecf20Sopenharmony_ci"	popq %rdx\n"
338c2ecf20Sopenharmony_ci"	popq %rsi\n"
348c2ecf20Sopenharmony_ci"	popq %rdi\n"
358c2ecf20Sopenharmony_ci"	leave\n"
368c2ecf20Sopenharmony_ci	ASM_RET
378c2ecf20Sopenharmony_ci"	.size		my_tramp, .-my_tramp\n"
388c2ecf20Sopenharmony_ci"	.popsection\n"
398c2ecf20Sopenharmony_ci);
408c2ecf20Sopenharmony_ci
418c2ecf20Sopenharmony_ci
428c2ecf20Sopenharmony_cistatic int __init ftrace_direct_init(void)
438c2ecf20Sopenharmony_ci{
448c2ecf20Sopenharmony_ci	return register_ftrace_direct((unsigned long)handle_mm_fault,
458c2ecf20Sopenharmony_ci				     (unsigned long)my_tramp);
468c2ecf20Sopenharmony_ci}
478c2ecf20Sopenharmony_ci
488c2ecf20Sopenharmony_cistatic void __exit ftrace_direct_exit(void)
498c2ecf20Sopenharmony_ci{
508c2ecf20Sopenharmony_ci	unregister_ftrace_direct((unsigned long)handle_mm_fault,
518c2ecf20Sopenharmony_ci				 (unsigned long)my_tramp);
528c2ecf20Sopenharmony_ci}
538c2ecf20Sopenharmony_ci
548c2ecf20Sopenharmony_cimodule_init(ftrace_direct_init);
558c2ecf20Sopenharmony_cimodule_exit(ftrace_direct_exit);
568c2ecf20Sopenharmony_ci
578c2ecf20Sopenharmony_ciMODULE_AUTHOR("Steven Rostedt");
588c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("Another example use case of using register_ftrace_direct()");
598c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL");
60