* [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 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 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-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