mirror of https://gitee.com/openkylin/linux.git
x86/ftrace: Use text_gen_insn()
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>
This commit is contained in:
parent
254d2c0451
commit
67c1d4a280
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in New Issue