select HAVE_DMA_CONTIGUOUS
        select HAVE_DYNAMIC_FTRACE
        select HAVE_DYNAMIC_FTRACE_WITH_REGS
+       select HAVE_DYNAMIC_FTRACE_WITH_ARGS    if X86_64
        select HAVE_DYNAMIC_FTRACE_WITH_DIRECT_CALLS
        select HAVE_EBPF_JIT
        select HAVE_EFFICIENT_UNALIGNED_ACCESS
 
        regs->orig_ax = addr;
 }
 
+#ifdef CONFIG_HAVE_DYNAMIC_FTRACE_WITH_ARGS
+struct ftrace_regs {
+       struct pt_regs          regs;
+};
+
+static __always_inline struct pt_regs *
+arch_ftrace_get_regs(struct ftrace_regs *fregs)
+{
+       /* Only when FL_SAVE_REGS is set, cs will be non zero */
+       if (!fregs->regs.cs)
+               return NULL;
+       return &fregs->regs;
+}
+#endif
+
 #ifdef CONFIG_DYNAMIC_FTRACE
 
 struct dyn_arch_ftrace {
 
        /* save_mcount_regs fills in first two parameters */
        save_mcount_regs
 
+       /* Stack - skipping return address of ftrace_caller */
+       leaq MCOUNT_REG_SIZE+8(%rsp), %rcx
+       movq %rcx, RSP(%rsp)
+
 SYM_INNER_LABEL(ftrace_caller_op_ptr, SYM_L_GLOBAL)
        /* Load the ftrace_ops into the 3rd parameter */
        movq function_trace_op(%rip), %rdx
 
-       /* regs go into 4th parameter (but make it NULL) */
-       movq $0, %rcx
+       /* regs go into 4th parameter */
+       leaq (%rsp), %rcx
+
+       /* Only ops with REGS flag set should have CS register set */
+       movq $0, CS(%rsp)
 
 SYM_INNER_LABEL(ftrace_call, SYM_L_GLOBAL)
        call ftrace_stub
 
 
 struct ftrace_ops;
 
+#ifndef CONFIG_HAVE_DYNAMIC_FTRACE_WITH_ARGS
+
 struct ftrace_regs {
        struct pt_regs          regs;
 };
+#define arch_ftrace_get_regs(fregs) (&(fregs)->regs)
+
+#endif /* CONFIG_HAVE_DYNAMIC_FTRACE_WITH_ARGS */
 
 static __always_inline struct pt_regs *ftrace_get_regs(struct ftrace_regs *fregs)
 {
        if (!fregs)
                return NULL;
 
-       return &fregs->regs;
+       return arch_ftrace_get_regs(fregs);
 }
 
 typedef void (*ftrace_func_t)(unsigned long ip, unsigned long parent_ip,
 
 config HAVE_DYNAMIC_FTRACE_WITH_DIRECT_CALLS
        bool
 
+config HAVE_DYNAMIC_FTRACE_WITH_ARGS
+       bool
+       help
+        If this is set, then arguments and stack can be found from
+        the pt_regs passed into the function callback regs parameter
+        by default, even without setting the REGS flag in the ftrace_ops.
+        This allows for use of regs_get_kernel_argument() and
+        kernel_stack_pointer().
+
 config HAVE_FTRACE_MCOUNT_RECORD
        bool
        help