diff options
author | Peter Zijlstra <peterz@infradead.org> | 2019-10-03 14:50:42 +0200 |
---|---|---|
committer | Ingo Molnar <mingo@kernel.org> | 2019-11-27 07:44:24 +0100 |
commit | 63f62addb88ec4b358cf4574789bc3180c689e9a (patch) | |
tree | 251af1ec2b3fc9ebfaee7fe2a89cb9201dd18750 /arch/x86/kernel/alternative.c | |
parent | x86/alternatives, jump_label: Provide better text_poke() batching interface (diff) | |
download | linux-63f62addb88ec4b358cf4574789bc3180c689e9a.tar.xz linux-63f62addb88ec4b358cf4574789bc3180c689e9a.zip |
x86/alternatives: Add and use text_gen_insn() helper
Provide a simple helper function to create common instruction
encodings.
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: Daniel Bristot de Oliveira <bristot@redhat.com>
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Josh Poimboeuf <jpoimboe@redhat.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Masami Hiramatsu <mhiramat@kernel.org>
Cc: Steven Rostedt <rostedt@goodmis.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Link: https://lkml.kernel.org/r/20191111132457.703538332@infradead.org
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Diffstat (limited to 'arch/x86/kernel/alternative.c')
-rw-r--r-- | arch/x86/kernel/alternative.c | 36 |
1 files changed, 36 insertions, 0 deletions
diff --git a/arch/x86/kernel/alternative.c b/arch/x86/kernel/alternative.c index 42e7f0af88da..714b4a2a6f81 100644 --- a/arch/x86/kernel/alternative.c +++ b/arch/x86/kernel/alternative.c @@ -1237,3 +1237,39 @@ void text_poke_bp(void *addr, const void *opcode, size_t len, const void *emulat 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 = 0; + + 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) + BUG_ON((insn.disp >> 31) != (insn.disp >> 7)); + } + + return &insn.text; +} |