* [PATCH 0/7] riscv: Various text patching improvements @ 2024-02-12 2:55 Samuel Holland 2024-02-12 2:55 ` [PATCH 5/7] riscv: Pass patch_text() the length in bytes Samuel Holland 2024-02-13 12:58 ` [PATCH 0/7] riscv: Various text patching improvements Andrea Parri 0 siblings, 2 replies; 7+ messages in thread From: Samuel Holland @ 2024-02-12 2:55 UTC (permalink / raw) To: Palmer Dabbelt Cc: linux-riscv, linux-kernel, Samuel Holland, Ard Biesheuvel, Daniel Borkmann, Jason Baron, Josh Poimboeuf, Peter Zijlstra, Steven Rostedt, bpf Here are a few changes to minimize calls to stop_machine() and flush_icache_*() in the various text patching functions, as well as to simplify the code. Samuel Holland (7): riscv: jump_label: Batch icache maintenance riscv: jump_label: Simplify assembly syntax riscv: kprobes: Use patch_text_nosync() for insn slots riscv: Simplify text patching loops riscv: Pass patch_text() the length in bytes riscv: Use offset_in_page() in text patching functions riscv: Remove extra variable in patch_text_nosync() arch/riscv/include/asm/jump_label.h | 4 ++- arch/riscv/include/asm/patch.h | 3 +- arch/riscv/kernel/jump_label.c | 16 ++++++--- arch/riscv/kernel/patch.c | 56 +++++++++++++---------------- arch/riscv/kernel/probes/kprobes.c | 20 ++++++----- arch/riscv/net/bpf_jit_comp64.c | 7 ++-- 6 files changed, 56 insertions(+), 50 deletions(-) -- 2.43.0 ^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH 5/7] riscv: Pass patch_text() the length in bytes 2024-02-12 2:55 [PATCH 0/7] riscv: Various text patching improvements Samuel Holland @ 2024-02-12 2:55 ` Samuel Holland 2024-02-19 13:04 ` Björn Töpel 2024-02-13 12:58 ` [PATCH 0/7] riscv: Various text patching improvements Andrea Parri 1 sibling, 1 reply; 7+ messages in thread From: Samuel Holland @ 2024-02-12 2:55 UTC (permalink / raw) To: Palmer Dabbelt Cc: linux-riscv, linux-kernel, Samuel Holland, Daniel Borkmann, bpf patch_text_nosync() already handles an arbitrary length of code, so this removes a superfluous loop and reduces the number of icache flushes. Signed-off-by: Samuel Holland <samuel.holland@sifive.com> --- arch/riscv/include/asm/patch.h | 2 +- arch/riscv/kernel/patch.c | 15 +++++---------- arch/riscv/kernel/probes/kprobes.c | 20 +++++++++++--------- arch/riscv/net/bpf_jit_comp64.c | 7 ++++--- 4 files changed, 21 insertions(+), 23 deletions(-) diff --git a/arch/riscv/include/asm/patch.h b/arch/riscv/include/asm/patch.h index 9f5d6e14c405..7228e266b9a1 100644 --- a/arch/riscv/include/asm/patch.h +++ b/arch/riscv/include/asm/patch.h @@ -9,7 +9,7 @@ int patch_insn_write(void *addr, const void *insn, size_t len); int patch_text_nosync(void *addr, const void *insns, size_t len); int patch_text_set_nosync(void *addr, u8 c, size_t len); -int patch_text(void *addr, u32 *insns, int ninsns); +int patch_text(void *addr, u32 *insns, size_t len); extern int riscv_patch_in_stop_machine; diff --git a/arch/riscv/kernel/patch.c b/arch/riscv/kernel/patch.c index 7f030b46eae5..9aa0050225c0 100644 --- a/arch/riscv/kernel/patch.c +++ b/arch/riscv/kernel/patch.c @@ -19,7 +19,7 @@ struct patch_insn { void *addr; u32 *insns; - int ninsns; + size_t len; atomic_t cpu_count; }; @@ -227,15 +227,10 @@ NOKPROBE_SYMBOL(patch_text_nosync); static int patch_text_cb(void *data) { struct patch_insn *patch = data; - unsigned long len; - int i, ret = 0; + int ret = 0; if (atomic_inc_return(&patch->cpu_count) == num_online_cpus()) { - for (i = 0; ret == 0 && i < patch->ninsns; i++) { - len = GET_INSN_LENGTH(patch->insns[i]); - ret = patch_text_nosync(patch->addr + i * len, - &patch->insns[i], len); - } + ret = patch_text_nosync(patch->addr, patch->insns, patch->len); atomic_inc(&patch->cpu_count); } else { while (atomic_read(&patch->cpu_count) <= num_online_cpus()) @@ -247,13 +242,13 @@ static int patch_text_cb(void *data) } NOKPROBE_SYMBOL(patch_text_cb); -int patch_text(void *addr, u32 *insns, int ninsns) +int patch_text(void *addr, u32 *insns, size_t len) { int ret; struct patch_insn patch = { .addr = addr, .insns = insns, - .ninsns = ninsns, + .len = len, .cpu_count = ATOMIC_INIT(0), }; diff --git a/arch/riscv/kernel/probes/kprobes.c b/arch/riscv/kernel/probes/kprobes.c index cbf8197072bf..a64461fa715c 100644 --- a/arch/riscv/kernel/probes/kprobes.c +++ b/arch/riscv/kernel/probes/kprobes.c @@ -23,14 +23,14 @@ post_kprobe_handler(struct kprobe *, struct kprobe_ctlblk *, struct pt_regs *); static void __kprobes arch_prepare_ss_slot(struct kprobe *p) { + size_t len = GET_INSN_LENGTH(p->opcode); u32 insn = __BUG_INSN_32; - unsigned long offset = GET_INSN_LENGTH(p->opcode); - p->ainsn.api.restore = (unsigned long)p->addr + offset; + p->ainsn.api.restore = (unsigned long)p->addr + len; - patch_text_nosync(p->ainsn.api.insn, &p->opcode, 1); - patch_text_nosync(p->ainsn.api.insn + offset, - &insn, 1); + patch_text_nosync(p->ainsn.api.insn, &p->opcode, len); + patch_text_nosync(p->ainsn.api.insn + len, + &insn, GET_INSN_LENGTH(insn)); } static void __kprobes arch_prepare_simulate(struct kprobe *p) @@ -117,16 +117,18 @@ void *alloc_insn_page(void) /* install breakpoint in text */ void __kprobes arch_arm_kprobe(struct kprobe *p) { - u32 insn = (p->opcode & __INSN_LENGTH_MASK) == __INSN_LENGTH_32 ? - __BUG_INSN_32 : __BUG_INSN_16; + size_t len = GET_INSN_LENGTH(p->opcode); + u32 insn = len == 4 ? __BUG_INSN_32 : __BUG_INSN_16; - patch_text(p->addr, &insn, 1); + patch_text(p->addr, &insn, len); } /* remove breakpoint from text */ void __kprobes arch_disarm_kprobe(struct kprobe *p) { - patch_text(p->addr, &p->opcode, 1); + size_t len = GET_INSN_LENGTH(p->opcode); + + patch_text(p->addr, &p->opcode, len); } void __kprobes arch_remove_kprobe(struct kprobe *p) diff --git a/arch/riscv/net/bpf_jit_comp64.c b/arch/riscv/net/bpf_jit_comp64.c index 719a97e7edb2..43be2585f0d4 100644 --- a/arch/riscv/net/bpf_jit_comp64.c +++ b/arch/riscv/net/bpf_jit_comp64.c @@ -14,6 +14,7 @@ #include "bpf_jit.h" #define RV_FENTRY_NINSNS 2 +#define RV_FENTRY_NBYTES (RV_FENTRY_NINSNS * 4) #define RV_REG_TCC RV_REG_A6 #define RV_REG_TCC_SAVED RV_REG_S6 /* Store A6 in S6 if program do calls */ @@ -681,7 +682,7 @@ int bpf_arch_text_poke(void *ip, enum bpf_text_poke_type poke_type, if (ret) return ret; - if (memcmp(ip, old_insns, RV_FENTRY_NINSNS * 4)) + if (memcmp(ip, old_insns, RV_FENTRY_NBYTES)) return -EFAULT; ret = gen_jump_or_nops(new_addr, ip, new_insns, is_call); @@ -690,8 +691,8 @@ int bpf_arch_text_poke(void *ip, enum bpf_text_poke_type poke_type, cpus_read_lock(); mutex_lock(&text_mutex); - if (memcmp(ip, new_insns, RV_FENTRY_NINSNS * 4)) - ret = patch_text(ip, new_insns, RV_FENTRY_NINSNS); + if (memcmp(ip, new_insns, RV_FENTRY_NBYTES)) + ret = patch_text(ip, new_insns, RV_FENTRY_NBYTES); mutex_unlock(&text_mutex); cpus_read_unlock(); -- 2.43.0 ^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [PATCH 5/7] riscv: Pass patch_text() the length in bytes 2024-02-12 2:55 ` [PATCH 5/7] riscv: Pass patch_text() the length in bytes Samuel Holland @ 2024-02-19 13:04 ` Björn Töpel 0 siblings, 0 replies; 7+ messages in thread From: Björn Töpel @ 2024-02-19 13:04 UTC (permalink / raw) To: Samuel Holland, Palmer Dabbelt Cc: linux-riscv, linux-kernel, Samuel Holland, Daniel Borkmann, bpf Samuel Holland <samuel.holland@sifive.com> writes: > patch_text_nosync() already handles an arbitrary length of code, so this > removes a superfluous loop and reduces the number of icache flushes. > > Signed-off-by: Samuel Holland <samuel.holland@sifive.com> Nice! Nit: 100 chars lines, please. Reviewed-by: Björn Töpel <bjorn@rivosinc.com> ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH 0/7] riscv: Various text patching improvements 2024-02-12 2:55 [PATCH 0/7] riscv: Various text patching improvements Samuel Holland 2024-02-12 2:55 ` [PATCH 5/7] riscv: Pass patch_text() the length in bytes Samuel Holland @ 2024-02-13 12:58 ` Andrea Parri 2024-02-19 12:25 ` Björn Töpel 2024-03-27 15:32 ` Samuel Holland 1 sibling, 2 replies; 7+ messages in thread From: Andrea Parri @ 2024-02-13 12:58 UTC (permalink / raw) To: Samuel Holland Cc: Palmer Dabbelt, linux-riscv, linux-kernel, Ard Biesheuvel, Daniel Borkmann, Jason Baron, Josh Poimboeuf, Peter Zijlstra, Steven Rostedt, bpf, Alexandre Ghiti, Björn Töpel Hi Samuel, On Sun, Feb 11, 2024 at 06:55:11PM -0800, Samuel Holland wrote: > Here are a few changes to minimize calls to stop_machine() and > flush_icache_*() in the various text patching functions, as well as > to simplify the code. > > > Samuel Holland (7): > riscv: jump_label: Batch icache maintenance > riscv: jump_label: Simplify assembly syntax > riscv: kprobes: Use patch_text_nosync() for insn slots > riscv: Simplify text patching loops > riscv: Pass patch_text() the length in bytes > riscv: Use offset_in_page() in text patching functions > riscv: Remove extra variable in patch_text_nosync() This does look like a nice clean-up. Just curious (a "teach me"-like question), how did you test these changes? kselftests, micro-benchmarks, other? BTW, I recall a parallel work from Alex and Bjorn [1] that might have some minor conflict with these changes; + both of them to Cc: for further sync. Andrea [1] https://lore.kernel.org/lkml/20240206204607.527195-1-alexghiti@rivosinc.com/ ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH 0/7] riscv: Various text patching improvements 2024-02-13 12:58 ` [PATCH 0/7] riscv: Various text patching improvements Andrea Parri @ 2024-02-19 12:25 ` Björn Töpel 2024-02-20 22:11 ` Alexandre Ghiti 2024-03-27 15:32 ` Samuel Holland 1 sibling, 1 reply; 7+ messages in thread From: Björn Töpel @ 2024-02-19 12:25 UTC (permalink / raw) To: Andrea Parri, Samuel Holland Cc: Palmer Dabbelt, linux-riscv, linux-kernel, Ard Biesheuvel, Daniel Borkmann, Jason Baron, Josh Poimboeuf, Peter Zijlstra, Steven Rostedt, bpf, Alexandre Ghiti, Björn Töpel Andrea Parri <parri.andrea@gmail.com> writes: > Hi Samuel, > > On Sun, Feb 11, 2024 at 06:55:11PM -0800, Samuel Holland wrote: >> Here are a few changes to minimize calls to stop_machine() and >> flush_icache_*() in the various text patching functions, as well as >> to simplify the code. >> >> >> Samuel Holland (7): >> riscv: jump_label: Batch icache maintenance >> riscv: jump_label: Simplify assembly syntax >> riscv: kprobes: Use patch_text_nosync() for insn slots >> riscv: Simplify text patching loops >> riscv: Pass patch_text() the length in bytes >> riscv: Use offset_in_page() in text patching functions >> riscv: Remove extra variable in patch_text_nosync() > > This does look like a nice clean-up. Just curious (a "teach me"-like question), > how did you test these changes? kselftests, micro-benchmarks, other? > > BTW, I recall a parallel work from Alex and Bjorn [1] that might have some minor > conflict with these changes; + both of them to Cc: for further sync. Indeed! I think Alex is still working on the v2. ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH 0/7] riscv: Various text patching improvements 2024-02-19 12:25 ` Björn Töpel @ 2024-02-20 22:11 ` Alexandre Ghiti 0 siblings, 0 replies; 7+ messages in thread From: Alexandre Ghiti @ 2024-02-20 22:11 UTC (permalink / raw) To: Björn Töpel Cc: Andrea Parri, Samuel Holland, Palmer Dabbelt, linux-riscv, linux-kernel, Ard Biesheuvel, Daniel Borkmann, Jason Baron, Josh Poimboeuf, Peter Zijlstra, Steven Rostedt, bpf, Björn Töpel On Mon, Feb 19, 2024 at 1:25 PM Björn Töpel <bjorn@kernel.org> wrote: > > Andrea Parri <parri.andrea@gmail.com> writes: > > > Hi Samuel, > > > > On Sun, Feb 11, 2024 at 06:55:11PM -0800, Samuel Holland wrote: > >> Here are a few changes to minimize calls to stop_machine() and > >> flush_icache_*() in the various text patching functions, as well as > >> to simplify the code. > >> > >> > >> Samuel Holland (7): > >> riscv: jump_label: Batch icache maintenance > >> riscv: jump_label: Simplify assembly syntax > >> riscv: kprobes: Use patch_text_nosync() for insn slots > >> riscv: Simplify text patching loops > >> riscv: Pass patch_text() the length in bytes > >> riscv: Use offset_in_page() in text patching functions > >> riscv: Remove extra variable in patch_text_nosync() > > > > This does look like a nice clean-up. Just curious (a "teach me"-like question), > > how did you test these changes? kselftests, micro-benchmarks, other? > > > > BTW, I recall a parallel work from Alex and Bjorn [1] that might have some minor > > conflict with these changes; + both of them to Cc: for further sync. > > Indeed! I think Alex is still working on the v2. Actually I was blocked by Andrea's comment about patch_map(), but it's not related so I can spin another version soon. I'd say mine should land first because AIA support may get into 6.9 (?) and then this patch would be needed. In case you re-spin another version, can you rebase on top of it? Unless you have another solution of course. Thanks, Alex ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH 0/7] riscv: Various text patching improvements 2024-02-13 12:58 ` [PATCH 0/7] riscv: Various text patching improvements Andrea Parri 2024-02-19 12:25 ` Björn Töpel @ 2024-03-27 15:32 ` Samuel Holland 1 sibling, 0 replies; 7+ messages in thread From: Samuel Holland @ 2024-03-27 15:32 UTC (permalink / raw) To: Andrea Parri Cc: Palmer Dabbelt, linux-riscv, linux-kernel, Ard Biesheuvel, Daniel Borkmann, Jason Baron, Josh Poimboeuf, Peter Zijlstra, Steven Rostedt, bpf, Alexandre Ghiti, Björn Töpel Hi Andrea, On 2024-02-13 6:58 AM, Andrea Parri wrote: > On Sun, Feb 11, 2024 at 06:55:11PM -0800, Samuel Holland wrote: >> Here are a few changes to minimize calls to stop_machine() and >> flush_icache_*() in the various text patching functions, as well as >> to simplify the code. >> >> >> Samuel Holland (7): >> riscv: jump_label: Batch icache maintenance >> riscv: jump_label: Simplify assembly syntax >> riscv: kprobes: Use patch_text_nosync() for insn slots >> riscv: Simplify text patching loops >> riscv: Pass patch_text() the length in bytes >> riscv: Use offset_in_page() in text patching functions >> riscv: Remove extra variable in patch_text_nosync() > > This does look like a nice clean-up. Just curious (a "teach me"-like question), > how did you test these changes? kselftests, micro-benchmarks, other? For all my patches, I do boot testing on various physical boards (Unmatched, D1, some internal hardware), plus some standard internal workloads. For performance-related patches, I run microbenchmarks or whole-system benchmarks (e.g. UnixBench). For this series specifically, I didn't do any extra benchmarking, as all of the functional changes should be as fast or faster by virtue of simply doing less work. > BTW, I recall a parallel work from Alex and Bjorn [1] that might have some minor > conflict with these changes; + both of them to Cc: for further sync. As suggested by Alex, v2 of this series will be based on the latest version of that patch. Regards, Samuel > > Andrea > > [1] https://lore.kernel.org/lkml/20240206204607.527195-1-alexghiti@rivosinc.com/ ^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2024-03-27 15:32 UTC | newest] Thread overview: 7+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2024-02-12 2:55 [PATCH 0/7] riscv: Various text patching improvements Samuel Holland 2024-02-12 2:55 ` [PATCH 5/7] riscv: Pass patch_text() the length in bytes Samuel Holland 2024-02-19 13:04 ` Björn Töpel 2024-02-13 12:58 ` [PATCH 0/7] riscv: Various text patching improvements Andrea Parri 2024-02-19 12:25 ` Björn Töpel 2024-02-20 22:11 ` Alexandre Ghiti 2024-03-27 15:32 ` Samuel Holland
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox