Merge tag 'v5.7-rc6' into objtool/core, to pick up fixes and resolve semantic conflict
[linux-2.6-microblaze.git] / arch / x86 / kernel / ftrace.c
index 37a0aea..c84d28e 100644 (file)
@@ -282,7 +282,8 @@ static inline void tramp_free(void *tramp) { }
 
 /* Defined as markers to the end of the ftrace default trampolines */
 extern void ftrace_regs_caller_end(void);
-extern void ftrace_epilogue(void);
+extern void ftrace_regs_caller_ret(void);
+extern void ftrace_caller_end(void);
 extern void ftrace_caller_op_ptr(void);
 extern void ftrace_regs_caller_op_ptr(void);
 
@@ -334,7 +335,7 @@ create_trampoline(struct ftrace_ops *ops, unsigned int *tramp_size)
                call_offset = (unsigned long)ftrace_regs_call;
        } else {
                start_offset = (unsigned long)ftrace_caller;
-               end_offset = (unsigned long)ftrace_epilogue;
+               end_offset = (unsigned long)ftrace_caller_end;
                op_offset = (unsigned long)ftrace_caller_op_ptr;
                call_offset = (unsigned long)ftrace_call;
        }
@@ -366,6 +367,13 @@ create_trampoline(struct ftrace_ops *ops, unsigned int *tramp_size)
        if (WARN_ON(ret < 0))
                goto fail;
 
+       if (ops->flags & FTRACE_OPS_FL_SAVE_REGS) {
+               ip = trampoline + (ftrace_regs_caller_ret - ftrace_regs_caller);
+               ret = probe_kernel_read(ip, (void *)retq, RET_SIZE);
+               if (WARN_ON(ret < 0))
+                       goto fail;
+       }
+
        /*
         * The address of the ftrace_ops that is used for this trampoline
         * is stored at the end of the trampoline. This will be used to
@@ -407,7 +415,8 @@ create_trampoline(struct ftrace_ops *ops, unsigned int *tramp_size)
 
        set_vm_flush_reset_perms(trampoline);
 
-       set_memory_ro((unsigned long)trampoline, npages);
+       if (likely(system_state != SYSTEM_BOOTING))
+               set_memory_ro((unsigned long)trampoline, npages);
        set_memory_x((unsigned long)trampoline, npages);
        return (unsigned long)trampoline;
 fail:
@@ -415,6 +424,32 @@ fail:
        return 0;
 }
 
+void set_ftrace_ops_ro(void)
+{
+       struct ftrace_ops *ops;
+       unsigned long start_offset;
+       unsigned long end_offset;
+       unsigned long npages;
+       unsigned long size;
+
+       do_for_each_ftrace_op(ops, ftrace_ops_list) {
+               if (!(ops->flags & FTRACE_OPS_FL_ALLOC_TRAMP))
+                       continue;
+
+               if (ops->flags & FTRACE_OPS_FL_SAVE_REGS) {
+                       start_offset = (unsigned long)ftrace_regs_caller;
+                       end_offset = (unsigned long)ftrace_regs_caller_end;
+               } else {
+                       start_offset = (unsigned long)ftrace_caller;
+                       end_offset = (unsigned long)ftrace_caller_end;
+               }
+               size = end_offset - start_offset;
+               size = size + RET_SIZE + sizeof(void *);
+               npages = DIV_ROUND_UP(size, PAGE_SIZE);
+               set_memory_ro((unsigned long)ops->trampoline, npages);
+       } while_for_each_ftrace_op(ops);
+}
+
 static unsigned long calc_trampoline_call_offset(bool save_regs)
 {
        unsigned long start_offset;