Merge tag 'block-5.14-2021-08-07' of git://git.kernel.dk/linux-block
[linux-2.6-microblaze.git] / arch / arm / kernel / ftrace.c
index 9a79ef6..3c83b5d 100644 (file)
@@ -68,9 +68,10 @@ int ftrace_arch_code_modify_post_process(void)
        return 0;
 }
 
-static unsigned long ftrace_call_replace(unsigned long pc, unsigned long addr)
+static unsigned long ftrace_call_replace(unsigned long pc, unsigned long addr,
+                                        bool warn)
 {
-       return arm_gen_branch_link(pc, addr);
+       return arm_gen_branch_link(pc, addr, warn);
 }
 
 static int ftrace_modify_code(unsigned long pc, unsigned long old,
@@ -104,14 +105,14 @@ int ftrace_update_ftrace_func(ftrace_func_t func)
        int ret;
 
        pc = (unsigned long)&ftrace_call;
-       new = ftrace_call_replace(pc, (unsigned long)func);
+       new = ftrace_call_replace(pc, (unsigned long)func, true);
 
        ret = ftrace_modify_code(pc, 0, new, false);
 
 #ifdef CONFIG_DYNAMIC_FTRACE_WITH_REGS
        if (!ret) {
                pc = (unsigned long)&ftrace_regs_call;
-               new = ftrace_call_replace(pc, (unsigned long)func);
+               new = ftrace_call_replace(pc, (unsigned long)func, true);
 
                ret = ftrace_modify_code(pc, 0, new, false);
        }
@@ -124,10 +125,22 @@ int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr)
 {
        unsigned long new, old;
        unsigned long ip = rec->ip;
+       unsigned long aaddr = adjust_address(rec, addr);
+       struct module *mod = NULL;
+
+#ifdef CONFIG_ARM_MODULE_PLTS
+       mod = rec->arch.mod;
+#endif
 
        old = ftrace_nop_replace(rec);
 
-       new = ftrace_call_replace(ip, adjust_address(rec, addr));
+       new = ftrace_call_replace(ip, aaddr, !mod);
+#ifdef CONFIG_ARM_MODULE_PLTS
+       if (!new && mod) {
+               aaddr = get_module_plt(mod, ip, aaddr);
+               new = ftrace_call_replace(ip, aaddr, true);
+       }
+#endif
 
        return ftrace_modify_code(rec->ip, old, new, true);
 }
@@ -140,9 +153,9 @@ int ftrace_modify_call(struct dyn_ftrace *rec, unsigned long old_addr,
        unsigned long new, old;
        unsigned long ip = rec->ip;
 
-       old = ftrace_call_replace(ip, adjust_address(rec, old_addr));
+       old = ftrace_call_replace(ip, adjust_address(rec, old_addr), true);
 
-       new = ftrace_call_replace(ip, adjust_address(rec, addr));
+       new = ftrace_call_replace(ip, adjust_address(rec, addr), true);
 
        return ftrace_modify_code(rec->ip, old, new, true);
 }
@@ -152,12 +165,29 @@ int ftrace_modify_call(struct dyn_ftrace *rec, unsigned long old_addr,
 int ftrace_make_nop(struct module *mod,
                    struct dyn_ftrace *rec, unsigned long addr)
 {
+       unsigned long aaddr = adjust_address(rec, addr);
        unsigned long ip = rec->ip;
        unsigned long old;
        unsigned long new;
        int ret;
 
-       old = ftrace_call_replace(ip, adjust_address(rec, addr));
+#ifdef CONFIG_ARM_MODULE_PLTS
+       /* mod is only supplied during module loading */
+       if (!mod)
+               mod = rec->arch.mod;
+       else
+               rec->arch.mod = mod;
+#endif
+
+       old = ftrace_call_replace(ip, aaddr,
+                                 !IS_ENABLED(CONFIG_ARM_MODULE_PLTS) || !mod);
+#ifdef CONFIG_ARM_MODULE_PLTS
+       if (!old && mod) {
+               aaddr = get_module_plt(mod, ip, aaddr);
+               old = ftrace_call_replace(ip, aaddr, true);
+       }
+#endif
+
        new = ftrace_nop_replace(rec);
        ret = ftrace_modify_code(ip, old, new, true);