x86/ftrace: Use text_gen_insn()
authorPeter Zijlstra <peterz@infradead.org>
Wed, 9 Oct 2019 10:44:14 +0000 (12:44 +0200)
committerIngo Molnar <mingo@kernel.org>
Wed, 27 Nov 2019 06:44:24 +0000 (07:44 +0100)
Replace the ftrace_code_union with the generic text_gen_insn() helper,
which does exactly this.

Tested-by: Alexei Starovoitov <ast@kernel.org>
Tested-by: Steven Rostedt (VMware) <rostedt@goodmis.org>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Acked-by: Alexei Starovoitov <ast@kernel.org>
Cc: Andy Lutomirski <luto@kernel.org>
Cc: Borislav Petkov <bp@alien8.de>
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Josh Poimboeuf <jpoimboe@redhat.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Link: https://lkml.kernel.org/r/20191111132457.932808000@infradead.org
Signed-off-by: Ingo Molnar <mingo@kernel.org>
arch/x86/include/asm/text-patching.h
arch/x86/kernel/alternative.c
arch/x86/kernel/ftrace.c

index 93e4266cd5a3d7ba44e515acf2a65a1f8729ff18..ad8f9f433a1b2893d935e0c30f62b2503aa56b62 100644 (file)
@@ -80,7 +80,35 @@ static inline int text_opcode_size(u8 opcode)
        return size;
 }
 
-extern void *text_gen_insn(u8 opcode, const void *addr, const void *dest);
+union text_poke_insn {
+       u8 text[POKE_MAX_OPCODE_SIZE];
+       struct {
+               u8 opcode;
+               s32 disp;
+       } __attribute__((packed));
+};
+
+static __always_inline
+void *text_gen_insn(u8 opcode, const void *addr, const void *dest)
+{
+       static union text_poke_insn insn; /* per instance */
+       int size = text_opcode_size(opcode);
+
+       insn.opcode = opcode;
+
+       if (size > 1) {
+               insn.disp = (long)dest - (long)(addr + size);
+               if (size == 2) {
+                       /*
+                        * Ensure that for JMP9 the displacement
+                        * actually fits the signed byte.
+                        */
+                       BUG_ON((insn.disp >> 31) != (insn.disp >> 7));
+               }
+       }
+
+       return &insn.text;
+}
 
 extern int after_bootmem;
 extern __ro_after_init struct mm_struct *poking_mm;
index f8f34f94d13d221d0757bef11b55167ed371ed68..cfcfadf5cc80ff10da8f7a00ea87a4174e712369 100644 (file)
@@ -1247,29 +1247,3 @@ void __ref text_poke_bp(void *addr, const void *opcode, size_t len, const void *
        text_poke_loc_init(&tp, addr, opcode, len, emulate);
        text_poke_bp_batch(&tp, 1);
 }
-
-union text_poke_insn {
-       u8 text[POKE_MAX_OPCODE_SIZE];
-       struct {
-               u8 opcode;
-               s32 disp;
-       } __attribute__((packed));
-};
-
-void *text_gen_insn(u8 opcode, const void *addr, const void *dest)
-{
-       static union text_poke_insn insn; /* text_mutex */
-       int size = text_opcode_size(opcode);
-
-       lockdep_assert_held(&text_mutex);
-
-       insn.opcode = opcode;
-
-       if (size > 1) {
-               insn.disp = (long)dest - (long)(addr + size);
-               if (size == 2)
-                       BUG_ON((insn.disp >> 31) != (insn.disp >> 7));
-       }
-
-       return &insn.text;
-}
index 3d8adeba2651f6972a9d2e568d9b311b79b62b3d..2a179fb35cd188e112eaa8e7bcc6d8bdb27d7d5c 100644 (file)
@@ -63,24 +63,6 @@ int ftrace_arch_code_modify_post_process(void)
        return 0;
 }
 
-union ftrace_code_union {
-       char code[MCOUNT_INSN_SIZE];
-       struct {
-               char op;
-               int offset;
-       } __attribute__((packed));
-};
-
-static const char *ftrace_text_replace(char op, unsigned long ip, unsigned long addr)
-{
-       static union ftrace_code_union calc;
-
-       calc.op = op;
-       calc.offset = (int)(addr - (ip + MCOUNT_INSN_SIZE));
-
-       return calc.code;
-}
-
 static const char *ftrace_nop_replace(void)
 {
        return ideal_nops[NOP_ATOMIC5];
@@ -88,7 +70,7 @@ static const char *ftrace_nop_replace(void)
 
 static const char *ftrace_call_replace(unsigned long ip, unsigned long addr)
 {
-       return ftrace_text_replace(CALL_INSN_OPCODE, ip, addr);
+       return text_gen_insn(CALL_INSN_OPCODE, (void *)ip, (void *)addr);
 }
 
 static int ftrace_verify_code(unsigned long ip, const char *old_code)
@@ -480,20 +462,20 @@ void arch_ftrace_update_trampoline(struct ftrace_ops *ops)
 /* Return the address of the function the trampoline calls */
 static void *addr_from_call(void *ptr)
 {
-       union ftrace_code_union calc;
+       union text_poke_insn call;
        int ret;
 
-       ret = probe_kernel_read(&calc, ptr, MCOUNT_INSN_SIZE);
+       ret = probe_kernel_read(&call, ptr, CALL_INSN_SIZE);
        if (WARN_ON_ONCE(ret < 0))
                return NULL;
 
        /* Make sure this is a call */
-       if (WARN_ON_ONCE(calc.op != 0xe8)) {
-               pr_warn("Expected e8, got %x\n", calc.op);
+       if (WARN_ON_ONCE(call.opcode != CALL_INSN_OPCODE)) {
+               pr_warn("Expected E8, got %x\n", call.opcode);
                return NULL;
        }
 
-       return ptr + MCOUNT_INSN_SIZE + calc.offset;
+       return ptr + CALL_INSN_SIZE + call.disp;
 }
 
 void prepare_ftrace_return(unsigned long self_addr, unsigned long *parent,
@@ -562,7 +544,7 @@ extern void ftrace_graph_call(void);
 
 static const char *ftrace_jmp_replace(unsigned long ip, unsigned long addr)
 {
-       return ftrace_text_replace(JMP32_INSN_OPCODE, ip, addr);
+       return text_gen_insn(JMP32_INSN_OPCODE, (void *)ip, (void *)addr);
 }
 
 static int ftrace_mod_jmp(unsigned long ip, void *func)