From: Peter Zijlstra Date: Wed, 9 Oct 2019 10:44:17 +0000 (+0200) Subject: x86/alternative: Add text_opcode_size() X-Git-Url: http://git.maquefel.me/?a=commitdiff_plain;h=254d2c04515ea4532a503cc5d8649e1513042e56;p=linux.git x86/alternative: Add text_opcode_size() Introduce a common helper to map *_INSN_OPCODE to *_INSN_SIZE. Tested-by: Alexei Starovoitov Tested-by: Steven Rostedt (VMware) Signed-off-by: Peter Zijlstra (Intel) Acked-by: Alexei Starovoitov Cc: Andy Lutomirski Cc: Borislav Petkov Cc: H. Peter Anvin Cc: Josh Poimboeuf Cc: Linus Torvalds Cc: Thomas Gleixner Link: https://lkml.kernel.org/r/20191111132457.875666061@infradead.org Signed-off-by: Ingo Molnar --- diff --git a/arch/x86/include/asm/text-patching.h b/arch/x86/include/asm/text-patching.h index 95beb85aef65a..93e4266cd5a3d 100644 --- a/arch/x86/include/asm/text-patching.h +++ b/arch/x86/include/asm/text-patching.h @@ -49,18 +49,6 @@ extern void text_poke_bp(void *addr, const void *opcode, size_t len, const void extern void text_poke_queue(void *addr, const void *opcode, size_t len, const void *emulate); extern void text_poke_finish(void); -extern void *text_gen_insn(u8 opcode, const void *addr, const void *dest); - -extern int after_bootmem; -extern __ro_after_init struct mm_struct *poking_mm; -extern __ro_after_init unsigned long poking_addr; - -#ifndef CONFIG_UML_X86 -static inline void int3_emulate_jmp(struct pt_regs *regs, unsigned long ip) -{ - regs->ip = ip; -} - #define INT3_INSN_SIZE 1 #define INT3_INSN_OPCODE 0xCC @@ -73,6 +61,37 @@ static inline void int3_emulate_jmp(struct pt_regs *regs, unsigned long ip) #define JMP8_INSN_SIZE 2 #define JMP8_INSN_OPCODE 0xEB +static inline int text_opcode_size(u8 opcode) +{ + int size = 0; + +#define __CASE(insn) \ + case insn##_INSN_OPCODE: size = insn##_INSN_SIZE; break + + switch(opcode) { + __CASE(INT3); + __CASE(CALL); + __CASE(JMP32); + __CASE(JMP8); + } + +#undef __CASE + + return size; +} + +extern void *text_gen_insn(u8 opcode, const void *addr, const void *dest); + +extern int after_bootmem; +extern __ro_after_init struct mm_struct *poking_mm; +extern __ro_after_init unsigned long poking_addr; + +#ifndef CONFIG_UML_X86 +static inline void int3_emulate_jmp(struct pt_regs *regs, unsigned long ip) +{ + regs->ip = ip; +} + static inline void int3_emulate_push(struct pt_regs *regs, unsigned long val) { /* diff --git a/arch/x86/kernel/alternative.c b/arch/x86/kernel/alternative.c index ce737f1da834f..f8f34f94d13d2 100644 --- a/arch/x86/kernel/alternative.c +++ b/arch/x86/kernel/alternative.c @@ -1259,22 +1259,12 @@ union text_poke_insn { void *text_gen_insn(u8 opcode, const void *addr, const void *dest) { static union text_poke_insn insn; /* text_mutex */ - int size = 0; + int size = text_opcode_size(opcode); lockdep_assert_held(&text_mutex); insn.opcode = opcode; -#define __CASE(insn) \ - case insn##_INSN_OPCODE: size = insn##_INSN_SIZE; break - - switch(opcode) { - __CASE(INT3); - __CASE(CALL); - __CASE(JMP32); - __CASE(JMP8); - } - if (size > 1) { insn.disp = (long)dest - (long)(addr + size); if (size == 2)