From: Ankur Arora <ankur.a.arora@oracle.com> To: linux-kernel@vger.kernel.org, x86@kernel.org Cc: peterz@infradead.org, hpa@zytor.com, jpoimboe@redhat.com, namit@vmware.com, mhiramat@kernel.org, jgross@suse.com, bp@alien8.de, vkuznets@redhat.com, pbonzini@redhat.com, boris.ostrovsky@oracle.com, mihai.carabas@oracle.com, kvm@vger.kernel.org, xen-devel@lists.xenproject.org, virtualization@lists.linux-foundation.org, Ankur Arora <ankur.a.arora@oracle.com> Subject: [RFC PATCH 14/26] x86/alternatives: Handle native insns in text_poke_loc*() Date: Tue, 7 Apr 2020 22:03:11 -0700 [thread overview] Message-ID: <20200408050323.4237-15-ankur.a.arora@oracle.com> (raw) In-Reply-To: <20200408050323.4237-1-ankur.a.arora@oracle.com> Intended to handle scenarios where we might want to patch arbitrary instructions (ex. inlined opcodes in pv_lock_ops.) Users for native mode (as opposed to emulated) are introduced in later patches. Signed-off-by: Ankur Arora <ankur.a.arora@oracle.com> --- arch/x86/include/asm/text-patching.h | 4 +- arch/x86/kernel/alternative.c | 61 ++++++++++++++++++++-------- 2 files changed, 45 insertions(+), 20 deletions(-) diff --git a/arch/x86/include/asm/text-patching.h b/arch/x86/include/asm/text-patching.h index 04778c2bc34e..c4b2814f2f9d 100644 --- a/arch/x86/include/asm/text-patching.h +++ b/arch/x86/include/asm/text-patching.h @@ -25,10 +25,10 @@ static inline void apply_paravirt(struct paravirt_patch_site *start, /* * Currently, the max observed size in the kernel code is - * JUMP_LABEL_NOP_SIZE/RELATIVEJUMP_SIZE, which are 5. + * NOP7 for indirect call, which is 7. * Raise it if needed. */ -#define POKE_MAX_OPCODE_SIZE 5 +#define POKE_MAX_OPCODE_SIZE 7 extern void text_poke_early(void *addr, const void *opcode, size_t len); diff --git a/arch/x86/kernel/alternative.c b/arch/x86/kernel/alternative.c index 337aad8c2521..004fe86f463f 100644 --- a/arch/x86/kernel/alternative.c +++ b/arch/x86/kernel/alternative.c @@ -981,8 +981,15 @@ void text_poke_sync(void) struct text_poke_loc { s32 rel_addr; /* addr := _stext + rel_addr */ - s32 rel32; - u8 opcode; + union { + struct { + s32 rel32; + u8 opcode; + } emulated; + struct { + u8 len; + } native; + }; const u8 text[POKE_MAX_OPCODE_SIZE]; }; @@ -990,6 +997,7 @@ struct bp_patching_desc { struct text_poke_loc *vec; int nr_entries; atomic_t refs; + bool native; }; static struct bp_patching_desc *bp_desc; @@ -1071,10 +1079,13 @@ int notrace poke_int3_handler(struct pt_regs *regs) goto out_put; } - len = text_opcode_size(tp->opcode); + if (desc->native) + BUG(); + + len = text_opcode_size(tp->emulated.opcode); ip += len; - switch (tp->opcode) { + switch (tp->emulated.opcode) { case INT3_INSN_OPCODE: /* * Someone poked an explicit INT3, they'll want to handle it, @@ -1083,12 +1094,12 @@ int notrace poke_int3_handler(struct pt_regs *regs) goto out_put; case CALL_INSN_OPCODE: - int3_emulate_call(regs, (long)ip + tp->rel32); + int3_emulate_call(regs, (long)ip + tp->emulated.rel32); break; case JMP32_INSN_OPCODE: case JMP8_INSN_OPCODE: - int3_emulate_jmp(regs, (long)ip + tp->rel32); + int3_emulate_jmp(regs, (long)ip + tp->emulated.rel32); break; default: @@ -1134,6 +1145,7 @@ static void text_poke_bp_batch(struct text_poke_loc *tp, unsigned int nr_entries .vec = tp, .nr_entries = nr_entries, .refs = ATOMIC_INIT(1), + .native = false, }; unsigned char int3 = INT3_INSN_OPCODE; unsigned int i; @@ -1161,7 +1173,7 @@ static void text_poke_bp_batch(struct text_poke_loc *tp, unsigned int nr_entries * Second step: update all but the first byte of the patched range. */ for (do_sync = 0, i = 0; i < nr_entries; i++) { - int len = text_opcode_size(tp[i].opcode); + int len = text_opcode_size(tp[i].emulated.opcode); if (len - INT3_INSN_SIZE > 0) { text_poke(text_poke_addr(&tp[i]) + INT3_INSN_SIZE, @@ -1205,11 +1217,25 @@ static void text_poke_bp_batch(struct text_poke_loc *tp, unsigned int nr_entries } static void text_poke_loc_init(struct text_poke_loc *tp, void *addr, - const void *opcode, size_t len, const void *emulate) + const void *opcode, size_t len, + const void *emulate, bool native) { struct insn insn; + memset((void *)tp, 0, sizeof(*tp)); memcpy((void *)tp->text, opcode, len); + + tp->rel_addr = addr - (void *)_stext; + + /* + * Native mode: when we might be poking + * arbitrary (perhaps) multiple instructions. + */ + if (native) { + tp->native.len = (u8)len; + return; + } + if (!emulate) emulate = opcode; @@ -1219,31 +1245,30 @@ static void text_poke_loc_init(struct text_poke_loc *tp, void *addr, BUG_ON(!insn_complete(&insn)); BUG_ON(len != insn.length); - tp->rel_addr = addr - (void *)_stext; - tp->opcode = insn.opcode.bytes[0]; + tp->emulated.opcode = insn.opcode.bytes[0]; - switch (tp->opcode) { + switch (tp->emulated.opcode) { case INT3_INSN_OPCODE: break; case CALL_INSN_OPCODE: case JMP32_INSN_OPCODE: case JMP8_INSN_OPCODE: - tp->rel32 = insn.immediate.value; + tp->emulated.rel32 = insn.immediate.value; break; default: /* assume NOP */ switch (len) { case 2: /* NOP2 -- emulate as JMP8+0 */ BUG_ON(memcmp(emulate, ideal_nops[len], len)); - tp->opcode = JMP8_INSN_OPCODE; - tp->rel32 = 0; + tp->emulated.opcode = JMP8_INSN_OPCODE; + tp->emulated.rel32 = 0; break; case 5: /* NOP5 -- emulate as JMP32+0 */ BUG_ON(memcmp(emulate, ideal_nops[NOP_ATOMIC5], len)); - tp->opcode = JMP32_INSN_OPCODE; - tp->rel32 = 0; + tp->emulated.opcode = JMP32_INSN_OPCODE; + tp->emulated.rel32 = 0; break; default: /* unknown instruction */ @@ -1299,7 +1324,7 @@ void __ref text_poke_queue(void *addr, const void *opcode, size_t len, const voi text_poke_flush(addr); tp = &tp_vec[tp_vec_nr++]; - text_poke_loc_init(tp, addr, opcode, len, emulate); + text_poke_loc_init(tp, addr, opcode, len, emulate, false); } /** @@ -1322,7 +1347,7 @@ void __ref text_poke_bp(void *addr, const void *opcode, size_t len, const void * return; } - text_poke_loc_init(&tp, addr, opcode, len, emulate); + text_poke_loc_init(&tp, addr, opcode, len, emulate, false); text_poke_bp_batch(&tp, 1); } -- 2.20.1
WARNING: multiple messages have this Message-ID (diff)
From: Ankur Arora <ankur.a.arora@oracle.com> To: linux-kernel@vger.kernel.org, x86@kernel.org Cc: jgross@suse.com, xen-devel@lists.xenproject.org, kvm@vger.kernel.org, peterz@infradead.org, hpa@zytor.com, Ankur Arora <ankur.a.arora@oracle.com>, virtualization@lists.linux-foundation.org, pbonzini@redhat.com, namit@vmware.com, mhiramat@kernel.org, jpoimboe@redhat.com, mihai.carabas@oracle.com, bp@alien8.de, vkuznets@redhat.com, boris.ostrovsky@oracle.com Subject: [RFC PATCH 14/26] x86/alternatives: Handle native insns in text_poke_loc*() Date: Tue, 7 Apr 2020 22:03:11 -0700 [thread overview] Message-ID: <20200408050323.4237-15-ankur.a.arora@oracle.com> (raw) In-Reply-To: <20200408050323.4237-1-ankur.a.arora@oracle.com> Intended to handle scenarios where we might want to patch arbitrary instructions (ex. inlined opcodes in pv_lock_ops.) Users for native mode (as opposed to emulated) are introduced in later patches. Signed-off-by: Ankur Arora <ankur.a.arora@oracle.com> --- arch/x86/include/asm/text-patching.h | 4 +- arch/x86/kernel/alternative.c | 61 ++++++++++++++++++++-------- 2 files changed, 45 insertions(+), 20 deletions(-) diff --git a/arch/x86/include/asm/text-patching.h b/arch/x86/include/asm/text-patching.h index 04778c2bc34e..c4b2814f2f9d 100644 --- a/arch/x86/include/asm/text-patching.h +++ b/arch/x86/include/asm/text-patching.h @@ -25,10 +25,10 @@ static inline void apply_paravirt(struct paravirt_patch_site *start, /* * Currently, the max observed size in the kernel code is - * JUMP_LABEL_NOP_SIZE/RELATIVEJUMP_SIZE, which are 5. + * NOP7 for indirect call, which is 7. * Raise it if needed. */ -#define POKE_MAX_OPCODE_SIZE 5 +#define POKE_MAX_OPCODE_SIZE 7 extern void text_poke_early(void *addr, const void *opcode, size_t len); diff --git a/arch/x86/kernel/alternative.c b/arch/x86/kernel/alternative.c index 337aad8c2521..004fe86f463f 100644 --- a/arch/x86/kernel/alternative.c +++ b/arch/x86/kernel/alternative.c @@ -981,8 +981,15 @@ void text_poke_sync(void) struct text_poke_loc { s32 rel_addr; /* addr := _stext + rel_addr */ - s32 rel32; - u8 opcode; + union { + struct { + s32 rel32; + u8 opcode; + } emulated; + struct { + u8 len; + } native; + }; const u8 text[POKE_MAX_OPCODE_SIZE]; }; @@ -990,6 +997,7 @@ struct bp_patching_desc { struct text_poke_loc *vec; int nr_entries; atomic_t refs; + bool native; }; static struct bp_patching_desc *bp_desc; @@ -1071,10 +1079,13 @@ int notrace poke_int3_handler(struct pt_regs *regs) goto out_put; } - len = text_opcode_size(tp->opcode); + if (desc->native) + BUG(); + + len = text_opcode_size(tp->emulated.opcode); ip += len; - switch (tp->opcode) { + switch (tp->emulated.opcode) { case INT3_INSN_OPCODE: /* * Someone poked an explicit INT3, they'll want to handle it, @@ -1083,12 +1094,12 @@ int notrace poke_int3_handler(struct pt_regs *regs) goto out_put; case CALL_INSN_OPCODE: - int3_emulate_call(regs, (long)ip + tp->rel32); + int3_emulate_call(regs, (long)ip + tp->emulated.rel32); break; case JMP32_INSN_OPCODE: case JMP8_INSN_OPCODE: - int3_emulate_jmp(regs, (long)ip + tp->rel32); + int3_emulate_jmp(regs, (long)ip + tp->emulated.rel32); break; default: @@ -1134,6 +1145,7 @@ static void text_poke_bp_batch(struct text_poke_loc *tp, unsigned int nr_entries .vec = tp, .nr_entries = nr_entries, .refs = ATOMIC_INIT(1), + .native = false, }; unsigned char int3 = INT3_INSN_OPCODE; unsigned int i; @@ -1161,7 +1173,7 @@ static void text_poke_bp_batch(struct text_poke_loc *tp, unsigned int nr_entries * Second step: update all but the first byte of the patched range. */ for (do_sync = 0, i = 0; i < nr_entries; i++) { - int len = text_opcode_size(tp[i].opcode); + int len = text_opcode_size(tp[i].emulated.opcode); if (len - INT3_INSN_SIZE > 0) { text_poke(text_poke_addr(&tp[i]) + INT3_INSN_SIZE, @@ -1205,11 +1217,25 @@ static void text_poke_bp_batch(struct text_poke_loc *tp, unsigned int nr_entries } static void text_poke_loc_init(struct text_poke_loc *tp, void *addr, - const void *opcode, size_t len, const void *emulate) + const void *opcode, size_t len, + const void *emulate, bool native) { struct insn insn; + memset((void *)tp, 0, sizeof(*tp)); memcpy((void *)tp->text, opcode, len); + + tp->rel_addr = addr - (void *)_stext; + + /* + * Native mode: when we might be poking + * arbitrary (perhaps) multiple instructions. + */ + if (native) { + tp->native.len = (u8)len; + return; + } + if (!emulate) emulate = opcode; @@ -1219,31 +1245,30 @@ static void text_poke_loc_init(struct text_poke_loc *tp, void *addr, BUG_ON(!insn_complete(&insn)); BUG_ON(len != insn.length); - tp->rel_addr = addr - (void *)_stext; - tp->opcode = insn.opcode.bytes[0]; + tp->emulated.opcode = insn.opcode.bytes[0]; - switch (tp->opcode) { + switch (tp->emulated.opcode) { case INT3_INSN_OPCODE: break; case CALL_INSN_OPCODE: case JMP32_INSN_OPCODE: case JMP8_INSN_OPCODE: - tp->rel32 = insn.immediate.value; + tp->emulated.rel32 = insn.immediate.value; break; default: /* assume NOP */ switch (len) { case 2: /* NOP2 -- emulate as JMP8+0 */ BUG_ON(memcmp(emulate, ideal_nops[len], len)); - tp->opcode = JMP8_INSN_OPCODE; - tp->rel32 = 0; + tp->emulated.opcode = JMP8_INSN_OPCODE; + tp->emulated.rel32 = 0; break; case 5: /* NOP5 -- emulate as JMP32+0 */ BUG_ON(memcmp(emulate, ideal_nops[NOP_ATOMIC5], len)); - tp->opcode = JMP32_INSN_OPCODE; - tp->rel32 = 0; + tp->emulated.opcode = JMP32_INSN_OPCODE; + tp->emulated.rel32 = 0; break; default: /* unknown instruction */ @@ -1299,7 +1324,7 @@ void __ref text_poke_queue(void *addr, const void *opcode, size_t len, const voi text_poke_flush(addr); tp = &tp_vec[tp_vec_nr++]; - text_poke_loc_init(tp, addr, opcode, len, emulate); + text_poke_loc_init(tp, addr, opcode, len, emulate, false); } /** @@ -1322,7 +1347,7 @@ void __ref text_poke_bp(void *addr, const void *opcode, size_t len, const void * return; } - text_poke_loc_init(&tp, addr, opcode, len, emulate); + text_poke_loc_init(&tp, addr, opcode, len, emulate, false); text_poke_bp_batch(&tp, 1); } -- 2.20.1
next prev parent reply other threads:[~2020-04-08 5:06 UTC|newest] Thread overview: 93+ messages / expand[flat|nested] mbox.gz Atom feed top 2020-04-08 5:02 [RFC PATCH 00/26] Runtime paravirt patching Ankur Arora 2020-04-08 5:02 ` Ankur Arora 2020-04-08 5:02 ` [RFC PATCH 01/26] x86/paravirt: Specify subsection in PVOP macros Ankur Arora 2020-04-08 5:02 ` Ankur Arora 2020-04-08 5:02 ` [RFC PATCH 02/26] x86/paravirt: Allow paravirt patching post-init Ankur Arora 2020-04-08 5:02 ` Ankur Arora 2020-04-08 5:03 ` [RFC PATCH 03/26] x86/paravirt: PVRTOP macros for PARAVIRT_RUNTIME Ankur Arora 2020-04-08 5:03 ` Ankur Arora 2020-04-08 5:03 ` [RFC PATCH 04/26] x86/alternatives: Refactor alternatives_smp_module* Ankur Arora 2020-04-08 5:03 ` Ankur Arora 2020-04-08 5:03 ` [RFC PATCH 05/26] x86/alternatives: Rename alternatives_smp*, smp_alt_module Ankur Arora 2020-04-08 5:03 ` Ankur Arora 2020-04-08 5:03 ` [RFC PATCH 06/26] x86/alternatives: Remove stale symbols Ankur Arora 2020-04-08 5:03 ` Ankur Arora 2020-04-08 5:03 ` [RFC PATCH 07/26] x86/paravirt: Persist .parainstructions.runtime Ankur Arora 2020-04-08 5:03 ` Ankur Arora 2020-04-08 5:03 ` [RFC PATCH 08/26] x86/paravirt: Stash native pv-ops Ankur Arora 2020-04-08 5:03 ` Ankur Arora 2020-04-08 5:03 ` [RFC PATCH 09/26] x86/paravirt: Add runtime_patch() Ankur Arora 2020-04-08 5:03 ` Ankur Arora 2020-04-08 11:05 ` Peter Zijlstra 2020-04-08 11:05 ` Peter Zijlstra 2020-04-08 11:05 ` Peter Zijlstra 2020-04-08 5:03 ` [RFC PATCH 10/26] x86/paravirt: Add primitives to stage pv-ops Ankur Arora 2020-04-08 5:03 ` Ankur Arora 2020-04-08 5:03 ` [RFC PATCH 11/26] x86/alternatives: Remove return value of text_poke*() Ankur Arora 2020-04-08 5:03 ` Ankur Arora 2020-04-08 5:03 ` [RFC PATCH 12/26] x86/alternatives: Use __get_unlocked_pte() in text_poke() Ankur Arora 2020-04-08 5:03 ` Ankur Arora 2020-04-08 5:03 ` [RFC PATCH 13/26] x86/alternatives: Split __text_poke() Ankur Arora 2020-04-08 5:03 ` Ankur Arora 2020-04-08 5:03 ` Ankur Arora [this message] 2020-04-08 5:03 ` [RFC PATCH 14/26] x86/alternatives: Handle native insns in text_poke_loc*() Ankur Arora 2020-04-08 11:11 ` Peter Zijlstra 2020-04-08 11:11 ` Peter Zijlstra 2020-04-08 11:11 ` Peter Zijlstra 2020-04-08 11:17 ` Peter Zijlstra 2020-04-08 11:17 ` Peter Zijlstra 2020-04-08 11:17 ` Peter Zijlstra 2020-04-08 5:03 ` [RFC PATCH 15/26] x86/alternatives: Non-emulated text poking Ankur Arora 2020-04-08 5:03 ` Ankur Arora 2020-04-08 11:13 ` Peter Zijlstra 2020-04-08 11:13 ` Peter Zijlstra 2020-04-08 11:13 ` Peter Zijlstra 2020-04-08 11:23 ` Peter Zijlstra 2020-04-08 11:23 ` Peter Zijlstra 2020-04-08 11:23 ` Peter Zijlstra 2020-04-08 5:03 ` [RFC PATCH 16/26] x86/alternatives: Add paravirt patching at runtime Ankur Arora 2020-04-08 5:03 ` Ankur Arora 2020-04-08 5:03 ` [RFC PATCH 17/26] x86/alternatives: Add patching logic in text_poke_site() Ankur Arora 2020-04-08 5:03 ` Ankur Arora 2020-04-08 5:03 ` [RFC PATCH 18/26] x86/alternatives: Handle BP in non-emulated text poking Ankur Arora 2020-04-08 5:03 ` Ankur Arora 2020-04-08 5:03 ` [RFC PATCH 19/26] x86/alternatives: NMI safe runtime patching Ankur Arora 2020-04-08 5:03 ` Ankur Arora 2020-04-08 11:36 ` Peter Zijlstra 2020-04-08 11:36 ` Peter Zijlstra 2020-04-08 11:36 ` Peter Zijlstra 2020-04-08 5:03 ` [RFC PATCH 20/26] x86/paravirt: Enable pv-spinlocks in runtime_patch() Ankur Arora 2020-04-08 5:03 ` Ankur Arora 2020-04-08 5:03 ` [RFC PATCH 21/26] x86/alternatives: Paravirt runtime selftest Ankur Arora 2020-04-08 5:03 ` Ankur Arora 2020-04-08 5:03 ` [RFC PATCH 22/26] kvm/paravirt: Encapsulate KVM pv switching logic Ankur Arora 2020-04-08 5:03 ` Ankur Arora 2020-04-08 5:03 ` [RFC PATCH 23/26] x86/kvm: Add worker to trigger runtime patching Ankur Arora 2020-04-08 5:03 ` Ankur Arora 2020-04-08 5:03 ` [RFC PATCH 24/26] x86/kvm: Support dynamic CPUID hints Ankur Arora 2020-04-08 5:03 ` Ankur Arora 2020-04-08 5:03 ` [RFC PATCH 25/26] x86/kvm: Guest support for dynamic hints Ankur Arora 2020-04-08 5:03 ` Ankur Arora 2020-04-08 5:03 ` [RFC PATCH 26/26] x86/kvm: Add hint change notifier for KVM_HINT_REALTIME Ankur Arora 2020-04-08 5:03 ` Ankur Arora 2020-04-08 12:08 ` [RFC PATCH 00/26] Runtime paravirt patching Peter Zijlstra 2020-04-08 12:08 ` Peter Zijlstra 2020-04-08 12:08 ` Peter Zijlstra 2020-04-08 13:33 ` Jürgen Groß 2020-04-08 13:33 ` Jürgen Groß 2020-04-08 14:49 ` Peter Zijlstra 2020-04-08 14:49 ` Peter Zijlstra 2020-04-08 14:49 ` Peter Zijlstra 2020-04-10 9:18 ` Ankur Arora 2020-04-10 9:18 ` Ankur Arora 2020-04-08 12:28 ` Jürgen Groß 2020-04-08 12:28 ` Jürgen Groß 2020-04-10 7:56 ` Ankur Arora 2020-04-10 7:56 ` Ankur Arora 2020-04-10 9:32 ` Ankur Arora 2020-04-10 9:32 ` Ankur Arora 2020-04-08 14:12 ` Thomas Gleixner 2020-04-08 14:12 ` Thomas Gleixner 2020-04-08 14:12 ` Thomas Gleixner 2020-04-10 9:55 ` Ankur Arora 2020-04-10 9:55 ` Ankur Arora
Reply instructions: You may reply publicly to this message via plain-text email using any one of the following methods: * Save the following mbox file, import it into your mail client, and reply-to-all from there: mbox Avoid top-posting and favor interleaved quoting: https://en.wikipedia.org/wiki/Posting_style#Interleaved_style * Reply using the --to, --cc, and --in-reply-to switches of git-send-email(1): git send-email \ --in-reply-to=20200408050323.4237-15-ankur.a.arora@oracle.com \ --to=ankur.a.arora@oracle.com \ --cc=boris.ostrovsky@oracle.com \ --cc=bp@alien8.de \ --cc=hpa@zytor.com \ --cc=jgross@suse.com \ --cc=jpoimboe@redhat.com \ --cc=kvm@vger.kernel.org \ --cc=linux-kernel@vger.kernel.org \ --cc=mhiramat@kernel.org \ --cc=mihai.carabas@oracle.com \ --cc=namit@vmware.com \ --cc=pbonzini@redhat.com \ --cc=peterz@infradead.org \ --cc=virtualization@lists.linux-foundation.org \ --cc=vkuznets@redhat.com \ --cc=x86@kernel.org \ --cc=xen-devel@lists.xenproject.org \ /path/to/YOUR_REPLY https://kernel.org/pub/software/scm/git/docs/git-send-email.html * If your mail client supports setting the In-Reply-To header via mailto: links, try the mailto: linkBe sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.