Merge tag 's390-5.16-1' of git://git.kernel.org/pub/scm/linux/kernel/git/s390/linux
[sfrench/cifs-2.6.git] / arch / s390 / kernel / ftrace.c
index 5165bf344f95680fb589a24795d7b5a07a66a0ad..5510c7d10ddc31fed07af20d57e793bc4a3ae97a 100644 (file)
@@ -17,6 +17,7 @@
 #include <linux/kprobes.h>
 #include <trace/syscall.h>
 #include <asm/asm-offsets.h>
+#include <asm/text-patching.h>
 #include <asm/cacheflush.h>
 #include <asm/ftrace.lds.h>
 #include <asm/nospec-branch.h>
@@ -80,17 +81,6 @@ asm(
 
 #ifdef CONFIG_MODULES
 static char *ftrace_plt;
-
-asm(
-       "       .data\n"
-       "ftrace_plt_template:\n"
-       "       basr    %r1,%r0\n"
-       "       lg      %r1,0f-.(%r1)\n"
-       "       br      %r1\n"
-       "0:     .quad   ftrace_caller\n"
-       "ftrace_plt_template_end:\n"
-       "       .previous\n"
-);
 #endif /* CONFIG_MODULES */
 
 static const char *ftrace_shared_hotpatch_trampoline(const char **end)
@@ -116,7 +106,7 @@ static const char *ftrace_shared_hotpatch_trampoline(const char **end)
 
 bool ftrace_need_init_nop(void)
 {
-       return ftrace_shared_hotpatch_trampoline(NULL);
+       return true;
 }
 
 int ftrace_init_nop(struct module *mod, struct dyn_ftrace *rec)
@@ -175,28 +165,6 @@ int ftrace_modify_call(struct dyn_ftrace *rec, unsigned long old_addr,
        return 0;
 }
 
-static void ftrace_generate_nop_insn(struct ftrace_insn *insn)
-{
-       /* brcl 0,0 */
-       insn->opc = 0xc004;
-       insn->disp = 0;
-}
-
-static void ftrace_generate_call_insn(struct ftrace_insn *insn,
-                                     unsigned long ip)
-{
-       unsigned long target;
-
-       /* brasl r0,ftrace_caller */
-       target = FTRACE_ADDR;
-#ifdef CONFIG_MODULES
-       if (is_module_addr((void *)ip))
-               target = (unsigned long)ftrace_plt;
-#endif /* CONFIG_MODULES */
-       insn->opc = 0xc005;
-       insn->disp = (target - ip) / 2;
-}
-
 static void brcl_disable(void *brcl)
 {
        u8 op = 0x04; /* set mask field to zero */
@@ -207,23 +175,7 @@ static void brcl_disable(void *brcl)
 int ftrace_make_nop(struct module *mod, struct dyn_ftrace *rec,
                    unsigned long addr)
 {
-       struct ftrace_insn orig, new, old;
-
-       if (ftrace_shared_hotpatch_trampoline(NULL)) {
-               brcl_disable((void *)rec->ip);
-               return 0;
-       }
-
-       if (copy_from_kernel_nofault(&old, (void *) rec->ip, sizeof(old)))
-               return -EFAULT;
-       /* Replace ftrace call with a nop. */
-       ftrace_generate_call_insn(&orig, rec->ip);
-       ftrace_generate_nop_insn(&new);
-
-       /* Verify that the to be replaced code matches what we expect. */
-       if (memcmp(&orig, &old, sizeof(old)))
-               return -EINVAL;
-       s390_kernel_write((void *) rec->ip, &new, sizeof(new));
+       brcl_disable((void *)rec->ip);
        return 0;
 }
 
@@ -236,23 +188,7 @@ static void brcl_enable(void *brcl)
 
 int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr)
 {
-       struct ftrace_insn orig, new, old;
-
-       if (ftrace_shared_hotpatch_trampoline(NULL)) {
-               brcl_enable((void *)rec->ip);
-               return 0;
-       }
-
-       if (copy_from_kernel_nofault(&old, (void *) rec->ip, sizeof(old)))
-               return -EFAULT;
-       /* Replace nop with an ftrace call. */
-       ftrace_generate_nop_insn(&orig);
-       ftrace_generate_call_insn(&new, rec->ip);
-
-       /* Verify that the to be replaced code matches what we expect. */
-       if (memcmp(&orig, &old, sizeof(old)))
-               return -EINVAL;
-       s390_kernel_write((void *) rec->ip, &new, sizeof(new));
+       brcl_enable((void *)rec->ip);
        return 0;
 }
 
@@ -264,22 +200,16 @@ int ftrace_update_ftrace_func(ftrace_func_t func)
 
 void arch_ftrace_update_code(int command)
 {
-       if (ftrace_shared_hotpatch_trampoline(NULL))
-               ftrace_modify_all_code(command);
-       else
-               ftrace_run_stop_machine(command);
-}
-
-static void __ftrace_sync(void *dummy)
-{
+       ftrace_modify_all_code(command);
 }
 
 int ftrace_arch_code_modify_post_process(void)
 {
-       if (ftrace_shared_hotpatch_trampoline(NULL)) {
-               /* Send SIGP to the other CPUs, so they see the new code. */
-               smp_call_function(__ftrace_sync, NULL, 1);
-       }
+       /*
+        * Flush any pre-fetched instructions on all
+        * CPUs to make the new code visible.
+        */
+       text_poke_sync_lock();
        return 0;
 }
 
@@ -294,10 +224,6 @@ static int __init ftrace_plt_init(void)
                panic("cannot allocate ftrace plt\n");
 
        start = ftrace_shared_hotpatch_trampoline(&end);
-       if (!start) {
-               start = ftrace_plt_template;
-               end = ftrace_plt_template_end;
-       }
        memcpy(ftrace_plt, start, end - start);
        set_memory_ro((unsigned long)ftrace_plt, 1);
        return 0;
@@ -337,12 +263,14 @@ NOKPROBE_SYMBOL(prepare_ftrace_return);
 int ftrace_enable_ftrace_graph_caller(void)
 {
        brcl_disable(ftrace_graph_caller);
+       text_poke_sync_lock();
        return 0;
 }
 
 int ftrace_disable_ftrace_graph_caller(void)
 {
        brcl_enable(ftrace_graph_caller);
+       text_poke_sync_lock();
        return 0;
 }